copy_output_result.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_RESULT_H_
  5. #define COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_RESULT_H_
  6. #include <array>
  7. #include <vector>
  8. #include "base/threading/thread_checker.h"
  9. #include "components/viz/common/resources/release_callback.h"
  10. #include "components/viz/common/viz_common_export.h"
  11. #include "gpu/command_buffer/common/mailbox_holder.h"
  12. #include "third_party/skia/include/core/SkBitmap.h"
  13. #include "ui/gfx/color_space.h"
  14. #include "ui/gfx/geometry/rect.h"
  15. class SkBitmap;
  16. namespace viz {
  17. // Base class for providing the result of a CopyOutputRequest. Implementations
  18. // that execute CopyOutputRequests will use a subclass implementation to define
  19. // data storage, access and ownership semantics relative to the lifetime of the
  20. // CopyOutputResult instance.
  21. class VIZ_COMMON_EXPORT CopyOutputResult {
  22. public:
  23. enum class Format : uint8_t {
  24. // A normal bitmap. When the results are returned in system memory, the
  25. // AsSkBitmap() will return a bitmap in "N32Premul" form. When the results
  26. // are returned in a texture, it will be an GL_RGBA texture referred to by
  27. // a gpu::Mailbox. Client code can optionally take ownership of the texture
  28. // (via a call to |TakeTextureOwnership()|) if it is needed beyond the
  29. // lifetime of the CopyOutputResult.
  30. RGBA,
  31. // I420 format planes. This is intended to be used internally within the VIZ
  32. // component to support video capture. When requesting this format, results
  33. // can only be delivered on the same task runner sequence that runs the
  34. // DirectRenderer implementation. For now, I420 format can be requested only
  35. // for system memory.
  36. I420_PLANES,
  37. // NV12 format planes. This is intended to be used internally within the VIZ
  38. // component to support video capture. When requesting this format, results
  39. // can only be delivered on the same task runner sequence that runs the
  40. // DirectRenderer implementation. For now, NV12 format can be requested only
  41. // for system memory.
  42. NV12_PLANES,
  43. };
  44. // Specifies how the results are delivered to the issuer of the request.
  45. // This should usually (but not always!) correspond to the value found in
  46. // CopyOutputRequest::result_destination() of the request that caused this
  47. // result to be produced. For details, see the comment on
  48. // CopyOutputRequest::ResultDestination.
  49. enum class Destination : uint8_t {
  50. // Place the results in system memory.
  51. kSystemMemory,
  52. // Place the results in native textures. The GPU textures are returned via a
  53. // mailbox. The caller can use |GetTextureResult()| and
  54. // |TakeTextureOwnership()| to access the results.
  55. kNativeTextures,
  56. };
  57. // Maximum number of planes allowed when returning results in native textures.
  58. // We need at most 3 planes to support the formats we're interested in (RGBA
  59. // format requires 1 plane, NV12 requires 2, I420 requires 3 planes).
  60. static constexpr size_t kMaxPlanes = 3;
  61. static constexpr size_t kRGBAMaxPlanes = 1;
  62. static constexpr size_t kNV12MaxPlanes = 2;
  63. static constexpr size_t kI420MaxPlanes = 3;
  64. CopyOutputResult(Format format,
  65. Destination destination,
  66. const gfx::Rect& rect,
  67. bool needs_lock_for_bitmap);
  68. CopyOutputResult(const CopyOutputResult&) = delete;
  69. CopyOutputResult& operator=(const CopyOutputResult&) = delete;
  70. virtual ~CopyOutputResult();
  71. // Returns false if the request succeeded and the data accessors will return
  72. // valid references.
  73. bool IsEmpty() const;
  74. // Returns the format of this result.
  75. Format format() const { return format_; }
  76. // Returns the destination of this result.
  77. Destination destination() const { return destination_; }
  78. // Returns the result Rect, which is the position and size of the image data
  79. // within the surface/layer (see CopyOutputRequest::set_area()). If a scale
  80. // ratio was set in the request, this will be in the scaled, NOT the original,
  81. // coordinate space.
  82. const gfx::Rect& rect() const { return rect_; }
  83. const gfx::Size& size() const { return rect_.size(); }
  84. class ScopedSkBitmap;
  85. // Return a ScopedSkBitmap object. The scoped_sk_bitmap.bitmap() can be used
  86. // to access the SkBitmap. The API user should not keep a copy of
  87. // scoped_sk_bitmap.bitmap(), since the content SkBitmap could become invalid
  88. // after ScopedSkBitmap is released.
  89. ScopedSkBitmap ScopedAccessSkBitmap() const;
  90. // Returns a pointer with a set of gpu::MailboxHolders referencing a
  91. // texture-backed result, or null if this is not a texture-backed result.
  92. // Clients can either:
  93. // 1. Let CopyOutputResult retain ownership and the texture will only be
  94. // valid for use during CopyOutputResult's lifetime.
  95. // 2. Take over ownership of the texture by calling TakeTextureOwnership(),
  96. // and the client must guarantee all the release callbacks will be run at
  97. // some point.
  98. // Even when the returned pointer is non-null, the object that it points to
  99. // can be default-constructed (the resulting mailboxes can be empty) in the
  100. // case of a failed reply, in which case IsEmpty() would report true.
  101. struct VIZ_COMMON_EXPORT TextureResult {
  102. // |texture_target| is guaranteed to be GL_TEXTURE_2D for each returned
  103. // plane. The planes are placed continuously from the beginning of the array
  104. // - i.e. if k planes are valid, indices from 0 (inclusive), to k
  105. // (exclusive) will contain the data. If the result is not empty, at least
  106. // one plane must be filled out (non-zero).
  107. std::array<gpu::MailboxHolder, kMaxPlanes> planes;
  108. gfx::ColorSpace color_space;
  109. // Single plane variant:
  110. TextureResult(const gpu::Mailbox& mailbox,
  111. const gpu::SyncToken& sync_token,
  112. const gfx::ColorSpace& color_space);
  113. // General purpose variant:
  114. TextureResult(const std::array<gpu::MailboxHolder, kMaxPlanes>& planes,
  115. const gfx::ColorSpace& color_space);
  116. TextureResult(const TextureResult& other);
  117. TextureResult& operator=(const TextureResult& other);
  118. };
  119. virtual const TextureResult* GetTextureResult() const;
  120. using ReleaseCallbacks = std::vector<ReleaseCallback>;
  121. // Returns a vector of release callbacks for the textures in |planes| array of
  122. // TextureResult. `i`th element in this collection is a release callback for
  123. // the `i`th element in |planes| array.
  124. // The size of the collection must match the number of valid entries in
  125. // |planes| array. The vector will be empty iff the CopyOutputResult
  126. // |IsEmpty()| is true.
  127. virtual ReleaseCallbacks TakeTextureOwnership();
  128. //
  129. // Subsampled YUV format result description
  130. // (valid for I420 and for NV12 formats)
  131. //
  132. // Since I420 and NV12 pixel formats subsample chroma planes and the results
  133. // are returned in a planar manner, care must be taken when interpreting the
  134. // results and when calculating sizes of memory regions for `ReadI420Planes()`
  135. // and `ReadNV12()` methods.
  136. //
  137. // Callers should follow the memory region size requirements specified in
  138. // `ReadI420Planes()` and `ReadNV12()` methods, and are advised to call
  139. // `set_result_selection()` with an even-sized, even-offset gfx::Rect
  140. // if they intend to "stitch" the results into a subregion of an existing
  141. // buffer by copying them. Memory region size calculation helpers are
  142. // available in copy_output_util.h.
  143. //
  144. // Copies the image planes of an I420_PLANES result to the caller-provided
  145. // memory. Returns true if successful, or false if: 1) this result is empty,
  146. // or 2) the result format is not I420_PLANES and does not provide a
  147. // conversion implementation.
  148. //
  149. // |y_out|, |u_out| and |v_out| point to the start of the memory regions to
  150. // receive each plane. These memory regions must have the following sizes:
  151. //
  152. // Y plane: y_out_stride * size().height() bytes, with
  153. // y_out_stride >= size().width()
  154. // U plane: u_out_stride * CEIL(size().height() / 2) bytes, with
  155. // u_out_stride >= CEIL(size().width() / 2)
  156. // V plane: v_out_stride * CEIL(size().height() / 2) bytes, with
  157. // v_out_stride >= CEIL(size().width() / 2)
  158. //
  159. // The color space is always Rec.709 (see gfx::ColorSpace::CreateREC709()).
  160. virtual bool ReadI420Planes(uint8_t* y_out,
  161. int y_out_stride,
  162. uint8_t* u_out,
  163. int u_out_stride,
  164. uint8_t* v_out,
  165. int v_out_stride) const;
  166. // Copies the image planes of an NV12_PLANES result to the caller-provided
  167. // memory. Returns true if successful, or false if: 1) this result is empty,
  168. // or 2) the result format is not NV12_PLANES and does not provide a
  169. // conversion implementation.
  170. //
  171. // |y_out| and |uv_out| point to the start of the memory regions to
  172. // receive each plane. These memory regions must have the following sizes:
  173. //
  174. // Y plane: y_out_stride * size().height() bytes, with
  175. // y_out_stride >= size().width()
  176. // UV plane: uv_out_stride * CEIL(size().height() / 2) bytes, with
  177. // uv_out_stride >= 2 * CEIL(size().width() / 2)
  178. //
  179. // The color space is always Rec.709 (see gfx::ColorSpace::CreateREC709()).
  180. virtual bool ReadNV12Planes(uint8_t* y_out,
  181. int y_out_stride,
  182. uint8_t* uv_out,
  183. int uv_out_stride) const;
  184. // Copies the result into |dest|. The result is in N32Premul form. Returns
  185. // true if successful, or false if: 1) the result is empty, or 2) the result
  186. // format is not RGBA and conversion is not implemented.
  187. virtual bool ReadRGBAPlane(uint8_t* dest, int stride) const;
  188. // Returns the color space of the image data returned by ReadRGBAPlane().
  189. virtual gfx::ColorSpace GetRGBAColorSpace() const;
  190. protected:
  191. // Lock the content of SkBitmap returned from AsSkBitmap() call.
  192. // Return true, if lock operation is successful, implementations should
  193. // keep SkBitmap content validate until UnlockSkBitmap() is called.
  194. virtual bool LockSkBitmap() const;
  195. // Unlock the content of SkBitmap returned from AsSkBitmap() call.
  196. virtual void UnlockSkBitmap() const;
  197. // Convenience to provide this result in SkBitmap form. Returns a
  198. // !readyToDraw() bitmap if this result is empty or if a conversion is not
  199. // possible in the current implementation. The returned SkBitmap also carries
  200. // its color space information.
  201. virtual const SkBitmap& AsSkBitmap() const;
  202. // Accessor for subclasses to initialize the cached SkBitmap.
  203. SkBitmap* cached_bitmap() const { return &cached_bitmap_; }
  204. private:
  205. const Format format_;
  206. const Destination destination_;
  207. const gfx::Rect rect_;
  208. const bool needs_lock_for_bitmap_;
  209. // Cached bitmap returned by the default implementation of AsSkBitmap().
  210. mutable SkBitmap cached_bitmap_;
  211. };
  212. // Subclass of CopyOutputResult that provides a RGBA result from an
  213. // SkBitmap (or an I420_PLANES result based on a SkBitmap). Implies that the
  214. // destination is kSystemMemory.
  215. class VIZ_COMMON_EXPORT CopyOutputSkBitmapResult : public CopyOutputResult {
  216. public:
  217. CopyOutputSkBitmapResult(Format format,
  218. const gfx::Rect& rect,
  219. SkBitmap bitmap);
  220. CopyOutputSkBitmapResult(const gfx::Rect& rect, SkBitmap bitmap);
  221. CopyOutputSkBitmapResult(const CopyOutputSkBitmapResult&) = delete;
  222. CopyOutputSkBitmapResult& operator=(const CopyOutputSkBitmapResult&) = delete;
  223. ~CopyOutputSkBitmapResult() override;
  224. const SkBitmap& AsSkBitmap() const override;
  225. };
  226. // Subclass of CopyOutputResult that holds references to textures (via
  227. // mailboxes). The owner of the result must take ownership of the textures if it
  228. // wants to use them by calling |TakeTextureOwnership()|, and then call the
  229. // ReleaseCallbacks when the textures will no longer be used to release
  230. // ownership and allow the textures to be reused or destroyed. If ownership is
  231. // not claimed, it will be released when this class is destroyed.
  232. class VIZ_COMMON_EXPORT CopyOutputTextureResult : public CopyOutputResult {
  233. public:
  234. // Construct a non-empty texture result:
  235. CopyOutputTextureResult(Format format,
  236. const gfx::Rect& rect,
  237. TextureResult texture_result,
  238. ReleaseCallbacks release_callbacks);
  239. CopyOutputTextureResult(const CopyOutputTextureResult&) = delete;
  240. CopyOutputTextureResult& operator=(const CopyOutputTextureResult&) = delete;
  241. ~CopyOutputTextureResult() override;
  242. const TextureResult* GetTextureResult() const override;
  243. ReleaseCallbacks TakeTextureOwnership() override;
  244. private:
  245. TextureResult texture_result_;
  246. ReleaseCallbacks release_callbacks_;
  247. };
  248. // Scoped class for accessing SkBitmap in CopyOutputRequest.
  249. // It cannot be used across threads.
  250. class VIZ_COMMON_EXPORT CopyOutputResult::ScopedSkBitmap {
  251. public:
  252. ScopedSkBitmap();
  253. ScopedSkBitmap(ScopedSkBitmap&& other);
  254. ~ScopedSkBitmap();
  255. ScopedSkBitmap& operator=(ScopedSkBitmap&& other);
  256. void reset();
  257. // Accesses SkBitmap which can only be used in the scope of the
  258. // ScopedSkBitmap.
  259. const SkBitmap bitmap() const {
  260. return result_ ? result_->AsSkBitmap() : SkBitmap();
  261. }
  262. // Returns a SkBitmap which can be used out the scope of the ScopedSkBitmap.
  263. // It makes a copy of the content in CopyOutputResult if it is needed.
  264. SkBitmap GetOutScopedBitmap() const;
  265. private:
  266. friend class CopyOutputResult;
  267. explicit ScopedSkBitmap(const CopyOutputResult* result);
  268. const CopyOutputResult* result_ = nullptr;
  269. THREAD_CHECKER(thread_checker_);
  270. };
  271. } // namespace viz
  272. #endif // COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_RESULT_H_