| Index: cc/paint/paint_op_buffer.h
|
| diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
|
| index c400f51735799e7d7f3e092f54e2c8537f38954f..10be38069186b249e4f801d8c0a95eacf1a1fb4a 100644
|
| --- a/cc/paint/paint_op_buffer.h
|
| +++ b/cc/paint/paint_op_buffer.h
|
| @@ -72,6 +72,29 @@ enum class PaintOpType : uint8_t {
|
| LastPaintOpType = Translate,
|
| };
|
|
|
| +// It is a requirement for every field in a PaintOp that we can memcpy it to
|
| +// another place in memory and free the only one (without calling any
|
| +// constructors or destructors). std::is_trivially_copyable<> would guarantee
|
| +// this, but is a superset of the guarantees that we need. For instance sk_sp<>
|
| +// works correctly when we memcpy+free it, but it has a non-trivial move
|
| +// constructor and destructor, which would make it fail a check for
|
| +// std::is_trivially_copyable. std::is_trivially_move_constructible<> also
|
| +// provides enough as we are moving the objects from one address to another
|
| +// conceptually, but also is not satisfied by sk_sp<> since it modifies the
|
| +// moved-from type.
|
| +// TODO(danakj): std::is_trivially_move_constructible is not always available
|
| +// for us yet, but we could use it when it is.
|
| +// For every field in a PaintOp, then, provide either a static_assert or a
|
| +// comment explaining why this field satisfies the ability to memcpy+free
|
| +// its data.
|
| +// sk_sp<T> pointers behave if their memory address is changed because there is
|
| +// never a pointer back to the sk_sp<T> itself from inside the T. This is true
|
| +// because multiple sk_sp<> may point to the same T and they are transient
|
| +// compared to the lifetime of any T. Additionally, the move constructor doesn't
|
| +// change any state that needs to be reflected in the new object.
|
| +// NOTABLY std::vector does *not* satisfy this, as implementations can (and do)
|
| +// sometimes have a pointer back to the vector from its internals, so running
|
| +// its move-assignment operator is required.
|
| struct CC_PAINT_EXPORT PaintOp {
|
| uint32_t type : 8;
|
| uint32_t skip : 24;
|
| @@ -124,9 +147,17 @@ struct CC_PAINT_EXPORT PaintOpWithFlags : PaintOp {
|
| // provide a modified PaintFlags. The RasterWithFlags() method is static with
|
| // a const PaintOpWithFlags* parameter so that it can be used as a function
|
| // pointer.
|
| + // PaintFlags is a collection of trivial data types and sk_sp<> ref pointers.
|
| + // The trivial data types satisfy std::is_trivially_copyable, and sk_sp<> is
|
| + // valid to have its memory address changed for reasons decribed at the top of
|
| + // PaintOp.
|
| PaintFlags flags;
|
| };
|
|
|
| +// A PaintOp with an additional block of memory with variable size. The
|
| +// additional data held in the PaintOpWithData must be able to be moved in
|
| +// memory without consequences. As such it must not (directly or indirectly)
|
| +// contain any pointers back to itself or to the PaintOp.
|
| struct CC_PAINT_EXPORT PaintOpWithData : PaintOpWithFlags {
|
| // Having data is just a helper for ops that have a varying amount of data and
|
| // want a way to store that inline. This is for ops that pass in a
|
| @@ -168,8 +199,16 @@ struct CC_PAINT_EXPORT PaintOpWithArrayBase : PaintOpWithFlags {
|
| : PaintOpWithFlags(flags) {}
|
| };
|
|
|
| +// A PaintOp with an additional block of memory with variable size that is
|
| +// an array of a known type. The types held in the array must be able to be
|
| +// moved in memory without consequences. As such it must not (directly or
|
| +// indirectly) contain any pointers back to itself or to the PaintOp. We use
|
| +// std::is_trivially_copyable() to verify this (it is more strict but satisfies
|
| +// our needs).
|
| template <typename M>
|
| struct CC_PAINT_EXPORT PaintOpWithArray : PaintOpWithArrayBase {
|
| + static_assert(base::is_trivially_copyable<M>::value, "");
|
| +
|
| // Paint op that has a M[count] and a char[bytes].
|
| // Array data is stored first so that it can be aligned with T's alignment
|
| // with the arbitrary unaligned char data after it.
|
| @@ -239,48 +278,66 @@ struct CC_PAINT_EXPORT AnnotateOp final : PaintOp {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| - PaintCanvas::AnnotationType annotation_type;
|
| + // uint8_t is a trivial type.
|
| + uint8_t annotation_type;
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect rect;
|
| + // sk_sp<> satisfies our data requirements as described at the top of PaintOp.
|
| sk_sp<SkData> data;
|
| };
|
|
|
| struct CC_PAINT_EXPORT ClipPathOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::ClipPath;
|
| ClipPathOp(SkPath path, SkClipOp op, bool antialias)
|
| - : path(path), op(op), antialias(antialias) {}
|
| + : path(path), op(static_cast<uint8_t>(op)), antialias(antialias) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
| int CountSlowPaths() const;
|
|
|
| + // ThreadsafePath is an SkPath which contains trivial types, sk_sp<>, and
|
| + // SkAtomic<uint8_t>. sk_sp<> is valid as described at the top of PaintOp.
|
| + // SkAtomic<uint8_t> stores a trivial type internally, and takes its address
|
| + // but does not store it.
|
| ThreadsafePath path;
|
| - SkClipOp op;
|
| + // uint8_t is a trivial type.
|
| + uint8_t op;
|
| + // bool is a trivial type.
|
| bool antialias;
|
| };
|
|
|
| struct CC_PAINT_EXPORT ClipRectOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::ClipRect;
|
| ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias)
|
| - : rect(rect), op(op), antialias(antialias) {}
|
| + : rect(rect), op(static_cast<uint8_t>(op)), antialias(antialias) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect rect;
|
| - SkClipOp op;
|
| + // uint8_t is a trivial type.
|
| + uint8_t op;
|
| + // bool is a trivial type.
|
| bool antialias;
|
| };
|
|
|
| struct CC_PAINT_EXPORT ClipRRectOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::ClipRRect;
|
| ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias)
|
| - : rrect(rrect), op(op), antialias(antialias) {}
|
| + : rrect(rrect), op(static_cast<uint8_t>(op)), antialias(antialias) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRRect>::value, "");
|
| SkRRect rrect;
|
| - SkClipOp op;
|
| + // uint8_t is a trivial type.
|
| + uint8_t op;
|
| + // bool is a trivial type.
|
| bool antialias;
|
| };
|
|
|
| @@ -291,6 +348,8 @@ struct CC_PAINT_EXPORT ConcatOp final : PaintOp {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that ThreadsafeMatrix can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<ThreadsafeMatrix>::value, "");
|
| ThreadsafeMatrix matrix;
|
| };
|
|
|
| @@ -298,8 +357,8 @@ struct CC_PAINT_EXPORT DrawArcOp final : PaintOpWithFlags {
|
| static constexpr PaintOpType kType = PaintOpType::DrawArc;
|
| static constexpr bool kIsDrawOp = true;
|
| DrawArcOp(const SkRect& oval,
|
| - SkScalar start_angle,
|
| - SkScalar sweep_angle,
|
| + float start_angle,
|
| + float sweep_angle,
|
| bool use_center,
|
| const PaintFlags& flags)
|
| : PaintOpWithFlags(flags),
|
| @@ -318,19 +377,21 @@ struct CC_PAINT_EXPORT DrawArcOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect oval;
|
| - SkScalar start_angle;
|
| - SkScalar sweep_angle;
|
| + // float is a trivial type.
|
| + float start_angle;
|
| + // float is a trivial type.
|
| + float sweep_angle;
|
| + // bool is a trivial type.
|
| bool use_center;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawCircleOp final : PaintOpWithFlags {
|
| static constexpr PaintOpType kType = PaintOpType::DrawCircle;
|
| static constexpr bool kIsDrawOp = true;
|
| - DrawCircleOp(SkScalar cx,
|
| - SkScalar cy,
|
| - SkScalar radius,
|
| - const PaintFlags& flags)
|
| + DrawCircleOp(float cx, float cy, float radius, const PaintFlags& flags)
|
| : PaintOpWithFlags(flags), cx(cx), cy(cy), radius(radius) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| @@ -343,21 +404,27 @@ struct CC_PAINT_EXPORT DrawCircleOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| - SkScalar cx;
|
| - SkScalar cy;
|
| - SkScalar radius;
|
| + // float is a trivial type.
|
| + float cx;
|
| + // float is a trivial type.
|
| + float cy;
|
| + // float is a trivial type.
|
| + float radius;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawColorOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::DrawColor;
|
| static constexpr bool kIsDrawOp = true;
|
| - DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {}
|
| + DrawColorOp(SkColor color, SkBlendMode mode)
|
| + : color(static_cast<uint32_t>(color)), mode(static_cast<uint8_t>(mode)) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| - SkColor color;
|
| - SkBlendMode mode;
|
| + // uint32_t is a trivial type.
|
| + uint32_t color;
|
| + // uint8_t is a trivial type.
|
| + uint8_t mode;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawDisplayItemListOp final : PaintOp {
|
| @@ -377,6 +444,8 @@ struct CC_PAINT_EXPORT DrawDisplayItemListOp final : PaintOp {
|
| bool HasDiscardableImages() const;
|
| // TODO(enne): DisplayItemList should know number of slow paths.
|
|
|
| + // scoped_refptr<> is able to be moved in memory for the same reasons as
|
| + // sk_sp<> which is described at the top of PaintOp.
|
| scoped_refptr<DisplayItemList> list;
|
| };
|
|
|
| @@ -398,7 +467,10 @@ struct CC_PAINT_EXPORT DrawDRRectOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRRect>::value, "");
|
| SkRRect outer;
|
| + // The above verifies SkRRect can be moved trivially.
|
| SkRRect inner;
|
| };
|
|
|
| @@ -406,8 +478,8 @@ struct CC_PAINT_EXPORT DrawImageOp final : PaintOpWithFlags {
|
| static constexpr PaintOpType kType = PaintOpType::DrawImage;
|
| static constexpr bool kIsDrawOp = true;
|
| DrawImageOp(const PaintImage& image,
|
| - SkScalar left,
|
| - SkScalar top,
|
| + float left,
|
| + float top,
|
| const PaintFlags* flags);
|
| ~DrawImageOp();
|
| static void Raster(const PaintOp* op,
|
| @@ -422,9 +494,14 @@ struct CC_PAINT_EXPORT DrawImageOp final : PaintOpWithFlags {
|
| const SkMatrix& original_ctm);
|
| bool HasDiscardableImages() const;
|
|
|
| + // PaintImage is a set of trivial types and an sk_sp<> which is able to be
|
| + // moved in memory as described at the top of PaintOp. PaintImage does not
|
| + // hold any pointers back to itself directly or indirectly.
|
| PaintImage image;
|
| - SkScalar left;
|
| - SkScalar top;
|
| + // float is a trivial type.
|
| + float left;
|
| + // float is a trivial type.
|
| + float top;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawImageRectOp final : PaintOpWithFlags {
|
| @@ -448,10 +525,17 @@ struct CC_PAINT_EXPORT DrawImageRectOp final : PaintOpWithFlags {
|
| const SkMatrix& original_ctm);
|
| bool HasDiscardableImages() const;
|
|
|
| + // PaintImage is a set of trivial types and an sk_sp<> which is able to be
|
| + // moved in memory as described at the top of PaintOp. PaintImage does not
|
| + // hold any pointers back to itself directly or indirectly.
|
| PaintImage image;
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect src;
|
| + // The above verifies that SkRect can be moved trivially.
|
| SkRect dst;
|
| - PaintCanvas::SrcRectConstraint constraint;
|
| + // uint8_t is a trivial type.
|
| + uint8_t constraint;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawIRectOp final : PaintOpWithFlags {
|
| @@ -470,17 +554,15 @@ struct CC_PAINT_EXPORT DrawIRectOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkIRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkIRect>::value, "");
|
| SkIRect rect;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawLineOp final : PaintOpWithFlags {
|
| static constexpr PaintOpType kType = PaintOpType::DrawLine;
|
| static constexpr bool kIsDrawOp = true;
|
| - DrawLineOp(SkScalar x0,
|
| - SkScalar y0,
|
| - SkScalar x1,
|
| - SkScalar y1,
|
| - const PaintFlags& flags)
|
| + DrawLineOp(float x0, float y0, float x1, float y1, const PaintFlags& flags)
|
| : PaintOpWithFlags(flags), x0(x0), y0(y0), x1(x1), y1(y1) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| @@ -495,10 +577,14 @@ struct CC_PAINT_EXPORT DrawLineOp final : PaintOpWithFlags {
|
|
|
| int CountSlowPaths() const;
|
|
|
| - SkScalar x0;
|
| - SkScalar y0;
|
| - SkScalar x1;
|
| - SkScalar y1;
|
| + // float is a trivial type.
|
| + float x0;
|
| + // float is a trivial type.
|
| + float y0;
|
| + // float is a trivial type.
|
| + float x1;
|
| + // float is a trivial type.
|
| + float y1;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawOvalOp final : PaintOpWithFlags {
|
| @@ -517,6 +603,8 @@ struct CC_PAINT_EXPORT DrawOvalOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect oval;
|
| };
|
|
|
| @@ -537,6 +625,10 @@ struct CC_PAINT_EXPORT DrawPathOp final : PaintOpWithFlags {
|
| const SkMatrix& original_ctm);
|
| int CountSlowPaths() const;
|
|
|
| + // ThreadsafePath is an SkPath which contains trivial types, sk_sp<>, and
|
| + // SkAtomic<uint8_t>. sk_sp<> is valid as described at the top of PaintOp.
|
| + // SkAtomic<uint8_t> stores a trivial type internally, and takes its address
|
| + // but does not store it.
|
| ThreadsafePath path;
|
| };
|
|
|
| @@ -574,6 +666,7 @@ struct CC_PAINT_EXPORT DrawRecordOp final : PaintOp {
|
| bool HasDiscardableImages() const;
|
| int CountSlowPaths() const;
|
|
|
| + // sk_sp<> can be moved in memory as decribed at the top of PaintOp.
|
| sk_sp<const PaintRecord> record;
|
| };
|
|
|
| @@ -593,6 +686,8 @@ struct CC_PAINT_EXPORT DrawRectOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect rect;
|
| };
|
|
|
| @@ -612,13 +707,15 @@ struct CC_PAINT_EXPORT DrawRRectOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRRect>::value, "");
|
| SkRRect rrect;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawTextOp final : PaintOpWithData {
|
| static constexpr PaintOpType kType = PaintOpType::DrawText;
|
| static constexpr bool kIsDrawOp = true;
|
| - DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags)
|
| + DrawTextOp(size_t bytes, float x, float y, const PaintFlags& flags)
|
| : PaintOpWithData(flags, bytes), x(x), y(y) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| @@ -634,16 +731,18 @@ struct CC_PAINT_EXPORT DrawTextOp final : PaintOpWithData {
|
| void* GetData() { return GetDataForThis(this); }
|
| const void* GetData() const { return GetDataForThis(this); }
|
|
|
| - SkScalar x;
|
| - SkScalar y;
|
| + // float is a trivial type.
|
| + float x;
|
| + // float is a trivial type.
|
| + float y;
|
| };
|
|
|
| struct CC_PAINT_EXPORT DrawTextBlobOp final : PaintOpWithFlags {
|
| static constexpr PaintOpType kType = PaintOpType::DrawTextBlob;
|
| static constexpr bool kIsDrawOp = true;
|
| DrawTextBlobOp(sk_sp<SkTextBlob> blob,
|
| - SkScalar x,
|
| - SkScalar y,
|
| + float x,
|
| + float y,
|
| const PaintFlags& flags);
|
| ~DrawTextBlobOp();
|
| static void Raster(const PaintOp* op,
|
| @@ -657,9 +756,12 @@ struct CC_PAINT_EXPORT DrawTextBlobOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // sk_sp<> can be moved in memory as decribed at the top of PaintOp.
|
| sk_sp<SkTextBlob> blob;
|
| - SkScalar x;
|
| - SkScalar y;
|
| + // float is a trivial type.
|
| + float x;
|
| + // float is a trivial type.
|
| + float y;
|
| };
|
|
|
| struct CC_PAINT_EXPORT NoopOp final : PaintOp {
|
| @@ -678,12 +780,13 @@ struct CC_PAINT_EXPORT RestoreOp final : PaintOp {
|
|
|
| struct CC_PAINT_EXPORT RotateOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::Rotate;
|
| - explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
|
| + explicit RotateOp(float degrees) : degrees(degrees) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| - SkScalar degrees;
|
| + // float is a trivial type.
|
| + float degrees;
|
| };
|
|
|
| struct CC_PAINT_EXPORT SaveOp final : PaintOp {
|
| @@ -709,6 +812,8 @@ struct CC_PAINT_EXPORT SaveLayerOp final : PaintOpWithFlags {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect bounds;
|
| };
|
|
|
| @@ -720,19 +825,24 @@ struct CC_PAINT_EXPORT SaveLayerAlphaOp final : PaintOp {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that SkRect can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<SkRect>::value, "");
|
| SkRect bounds;
|
| + // uint8_t is a trivial type.
|
| uint8_t alpha;
|
| };
|
|
|
| struct CC_PAINT_EXPORT ScaleOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::Scale;
|
| - ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
|
| + ScaleOp(float sx, float sy) : sx(sx), sy(sy) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| - SkScalar sx;
|
| - SkScalar sy;
|
| + // float is a trivial type.
|
| + float sx;
|
| + // float is a trivial type.
|
| + float sy;
|
| };
|
|
|
| struct CC_PAINT_EXPORT SetMatrixOp final : PaintOp {
|
| @@ -748,18 +858,22 @@ struct CC_PAINT_EXPORT SetMatrixOp final : PaintOp {
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| + // Verify that ThreadsafeMatrix can be moved trivially.
|
| + static_assert(base::is_trivially_copyable<ThreadsafeMatrix>::value, "");
|
| ThreadsafeMatrix matrix;
|
| };
|
|
|
| struct CC_PAINT_EXPORT TranslateOp final : PaintOp {
|
| static constexpr PaintOpType kType = PaintOpType::Translate;
|
| - TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
|
| + TranslateOp(float dx, float dy) : dx(dx), dy(dy) {}
|
| static void Raster(const PaintOp* op,
|
| SkCanvas* canvas,
|
| const SkMatrix& original_ctm);
|
|
|
| - SkScalar dx;
|
| - SkScalar dy;
|
| + // float is a trivial type.
|
| + float dx;
|
| + // float is a trivial type.
|
| + float dy;
|
| };
|
|
|
| using LargestPaintOp = DrawDRRectOp;
|
|
|