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