diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index b3bb258f3faad..7ba3273d60c11 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -36,14 +36,6 @@ FILE: ../../../flutter/flow/compositor_context.cc FILE: ../../../flutter/flow/compositor_context.h FILE: ../../../flutter/flow/diff_context.cc FILE: ../../../flutter/flow/diff_context.h -FILE: ../../../flutter/flow/display_list.cc -FILE: ../../../flutter/flow/display_list.h -FILE: ../../../flutter/flow/display_list_canvas.cc -FILE: ../../../flutter/flow/display_list_canvas.h -FILE: ../../../flutter/flow/display_list_canvas_unittests.cc -FILE: ../../../flutter/flow/display_list_unittests.cc -FILE: ../../../flutter/flow/display_list_utils.cc -FILE: ../../../flutter/flow/display_list_utils.h FILE: ../../../flutter/flow/embedded_view_params_unittests.cc FILE: ../../../flutter/flow/embedded_views.cc FILE: ../../../flutter/flow/embedded_views.h @@ -75,9 +67,6 @@ FILE: ../../../flutter/flow/layers/color_filter_layer_unittests.cc FILE: ../../../flutter/flow/layers/container_layer.cc FILE: ../../../flutter/flow/layers/container_layer.h FILE: ../../../flutter/flow/layers/container_layer_unittests.cc -FILE: ../../../flutter/flow/layers/display_list_layer.cc -FILE: ../../../flutter/flow/layers/display_list_layer.h -FILE: ../../../flutter/flow/layers/display_list_layer_unittests.cc FILE: ../../../flutter/flow/layers/image_filter_layer.cc FILE: ../../../flutter/flow/layers/image_filter_layer.h FILE: ../../../flutter/flow/layers/image_filter_layer_unittests.cc diff --git a/common/settings.h b/common/settings.h index 89310ed07df27..b4a4980575e0b 100644 --- a/common/settings.h +++ b/common/settings.h @@ -165,9 +165,6 @@ struct Settings { // Selects the SkParagraph implementation of the text layout engine. bool enable_skparagraph = false; - // Selects the DisplayList for storage of rendering operations. - bool enable_display_list = false; - // All shells in the process share the same VM. The last shell to shutdown // should typically shut down the VM as well. However, applications depend on // the behavior of "warming-up" the VM by creating a shell that does not do diff --git a/flow/BUILD.gn b/flow/BUILD.gn index b6c881f902f7d..29df9651107a5 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -12,12 +12,6 @@ source_set("flow") { "compositor_context.h", "diff_context.cc", "diff_context.h", - "display_list.cc", - "display_list.h", - "display_list_canvas.cc", - "display_list_canvas.h", - "display_list_utils.cc", - "display_list_utils.h", "embedded_views.cc", "embedded_views.h", "frame_timings.cc", @@ -36,8 +30,6 @@ source_set("flow") { "layers/color_filter_layer.h", "layers/container_layer.cc", "layers/container_layer.h", - "layers/display_list_layer.cc", - "layers/display_list_layer.h", "layers/image_filter_layer.cc", "layers/image_filter_layer.h", "layers/layer.cc", @@ -131,8 +123,6 @@ if (enable_unittests) { testonly = true sources = [ - "display_list_canvas_unittests.cc", - "display_list_unittests.cc", "embedded_view_params_unittests.cc", "flow_run_all_unittests.cc", "flow_test_utils.cc", @@ -146,7 +136,6 @@ if (enable_unittests) { "layers/clip_rrect_layer_unittests.cc", "layers/color_filter_layer_unittests.cc", "layers/container_layer_unittests.cc", - "layers/display_list_layer_unittests.cc", "layers/image_filter_layer_unittests.cc", "layers/layer_tree_unittests.cc", "layers/opacity_layer_unittests.cc", diff --git a/flow/display_list.cc b/flow/display_list.cc deleted file mode 100644 index 1390a161f90e5..0000000000000 --- a/flow/display_list.cc +++ /dev/null @@ -1,1368 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include "flutter/flow/display_list.h" -#include "flutter/flow/display_list_canvas.h" -#include "flutter/flow/display_list_utils.h" -#include "flutter/fml/logging.h" - -#include "third_party/skia/include/core/SkImageFilter.h" -#include "third_party/skia/include/core/SkMaskFilter.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkRSXform.h" -#include "third_party/skia/include/core/SkTextBlob.h" - -namespace flutter { - -const SkSamplingOptions DisplayList::NearestSampling = - SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone); -const SkSamplingOptions DisplayList::LinearSampling = - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone); -const SkSamplingOptions DisplayList::MipmapSampling = - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); -const SkSamplingOptions DisplayList::CubicSampling = - SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}); - -// Most Ops can be bulk compared using memcmp because they contain -// only numeric values or constructs that are constructed from numeric -// values. -// -// Some contain sk_sp<> references which can also be bulk compared -// to see if they are pointing to the same reference. (Note that -// two sk_sp<> that refer to the same object are themselves ==.) -// -// Only a DLOp that wants to do a deep compare needs to override the -// DLOp::equals() method and return a value of kEqual or kNotEqual. -enum class DisplayListCompare { - // The Op is deferring comparisons to a bulk memcmp performed lazily - // across all bulk-comparable ops. - kUseBulkCompare, - - // The Op provided a specific equals method that spotted a difference - kNotEqual, - - // The Op provided a specific equals method that saw no differences - kEqual, -}; - -#pragma pack(push, DLOp_Alignment, 8) - -// Assuming a 64-bit platform (most of our platforms at this time?) -// the following comments are a "worst case" assessment of how well -// these structures pack into memory. They may be packed more tightly -// on some of the 32-bit platforms that we see in older phones. -// -// Struct allocation in the DL memory is aligned to a void* boundary -// which means that the minimum (aligned) struct size will be 8 bytes. -// The DLOp base uses 4 bytes so each Op-specific struct gets 4 bytes -// of data for "free" and works best when it packs well into an 8-byte -// aligned size. -struct DLOp { - DisplayListOpType type : 8; - uint32_t size : 24; - - DisplayListCompare equals(const DLOp* other) const { - return DisplayListCompare::kUseBulkCompare; - } -}; - -// 4 byte header + 4 byte payload packs into minimum 8 bytes -#define DEFINE_SET_BOOL_OP(name) \ - struct Set##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kSet##name; \ - \ - Set##name##Op(bool value) : value(value) {} \ - \ - const bool value; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.set##name(value); \ - } \ - }; -DEFINE_SET_BOOL_OP(AA) -DEFINE_SET_BOOL_OP(Dither) -DEFINE_SET_BOOL_OP(InvertColors) -#undef DEFINE_SET_BOOL_OP - -// 4 byte header + 4 byte payload packs into minimum 8 bytes -#define DEFINE_SET_ENUM_OP(name) \ - struct Set##name##s##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kSet##name##s; \ - \ - Set##name##s##Op(SkPaint::name value) : value(value) {} \ - \ - const SkPaint::name value; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.set##name##s(value); \ - } \ - }; -DEFINE_SET_ENUM_OP(Cap) -DEFINE_SET_ENUM_OP(Join) -#undef DEFINE_SET_ENUM_OP - -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SetDrawStyleOp final : DLOp { - static const auto kType = DisplayListOpType::kSetDrawStyle; - - SetDrawStyleOp(SkPaint::Style style) : style(style) {} - - const SkPaint::Style style; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.setDrawStyle(style); - } -}; -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SetStrokeWidthOp final : DLOp { - static const auto kType = DisplayListOpType::kSetStrokeWidth; - - SetStrokeWidthOp(SkScalar width) : width(width) {} - - const SkScalar width; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.setStrokeWidth(width); - } -}; -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SetMiterLimitOp final : DLOp { - static const auto kType = DisplayListOpType::kSetMiterLimit; - - SetMiterLimitOp(SkScalar limit) : limit(limit) {} - - const SkScalar limit; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.setMiterLimit(limit); - } -}; - -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SetColorOp final : DLOp { - static const auto kType = DisplayListOpType::kSetColor; - - SetColorOp(SkColor color) : color(color) {} - - const SkColor color; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.setColor(color); } -}; -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SetBlendModeOp final : DLOp { - static const auto kType = DisplayListOpType::kSetBlendMode; - - SetBlendModeOp(SkBlendMode mode) : mode(mode) {} - - const SkBlendMode mode; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.setBlendMode(mode); } -}; - -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SetFilterQualityOp final : DLOp { - static const auto kType = DisplayListOpType::kSetFilterQuality; - - SetFilterQualityOp(SkFilterQuality quality) : quality(quality) {} - - const SkFilterQuality quality; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.setFilterQuality(quality); - } -}; - -// Clear: 4 byte header + unused 4 byte payload uses 8 bytes -// (4 bytes unused) -// Set: 4 byte header + an sk_sp (ptr) uses 16 bytes due to the -// alignment of the ptr. -// (4 bytes unused) -#define DEFINE_SET_CLEAR_SKREF_OP(name, field) \ - struct Clear##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kClear##name; \ - \ - Clear##name##Op() {} \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.set##name(nullptr); \ - } \ - }; \ - struct Set##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kSet##name; \ - \ - Set##name##Op(sk_sp field) : field(std::move(field)) {} \ - \ - sk_sp field; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.set##name(field); \ - } \ - }; -DEFINE_SET_CLEAR_SKREF_OP(Shader, shader) -DEFINE_SET_CLEAR_SKREF_OP(ImageFilter, filter) -DEFINE_SET_CLEAR_SKREF_OP(ColorFilter, filter) -DEFINE_SET_CLEAR_SKREF_OP(MaskFilter, filter) -#undef DEFINE_SET_CLEAR_SKREF_OP - -// 4 byte header + 4 byte payload packs into minimum 8 bytes -// Note that the "blur style" is packed into the OpType to prevent -// needing an additional 8 bytes for a 4-value enum. -#define DEFINE_MASK_BLUR_FILTER_OP(name, style) \ - struct SetMaskBlurFilter##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kSetMaskBlurFilter##name; \ - \ - SetMaskBlurFilter##name##Op(SkScalar sigma) : sigma(sigma) {} \ - \ - SkScalar sigma; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.setMaskBlurFilter(style, sigma); \ - } \ - }; -DEFINE_MASK_BLUR_FILTER_OP(Normal, kNormal_SkBlurStyle) -DEFINE_MASK_BLUR_FILTER_OP(Solid, kSolid_SkBlurStyle) -DEFINE_MASK_BLUR_FILTER_OP(Inner, kInner_SkBlurStyle) -DEFINE_MASK_BLUR_FILTER_OP(Outer, kOuter_SkBlurStyle) -#undef DEFINE_MASK_BLUR_FILTER_OP - -// 4 byte header + no payload uses minimum 8 bytes (4 bytes unused) -struct SaveOp final : DLOp { - static const auto kType = DisplayListOpType::kSave; - - SaveOp() {} - - void dispatch(Dispatcher& dispatcher) const { dispatcher.save(); } -}; -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct SaveLayerOp final : DLOp { - static const auto kType = DisplayListOpType::kSaveLayer; - - SaveLayerOp(bool with_paint) : with_paint(with_paint) {} - - bool with_paint; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.saveLayer(nullptr, with_paint); - } -}; -// 4 byte header + 20 byte payload packs evenly into 24 bytes -struct SaveLayerBoundsOp final : DLOp { - static const auto kType = DisplayListOpType::kSaveLayerBounds; - - SaveLayerBoundsOp(SkRect rect, bool with_paint) - : with_paint(with_paint), rect(rect) {} - - bool with_paint; - const SkRect rect; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.saveLayer(&rect, with_paint); - } -}; -// 4 byte header + no payload uses minimum 8 bytes (4 bytes unused) -struct RestoreOp final : DLOp { - static const auto kType = DisplayListOpType::kRestore; - - RestoreOp() {} - - void dispatch(Dispatcher& dispatcher) const { dispatcher.restore(); } -}; - -// 4 byte header + 8 byte payload uses 12 bytes but is rounded up to 16 bytes -// (4 bytes unused) -struct TranslateOp final : DLOp { - static const auto kType = DisplayListOpType::kTranslate; - - TranslateOp(SkScalar tx, SkScalar ty) : tx(tx), ty(ty) {} - - const SkScalar tx; - const SkScalar ty; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.translate(tx, ty); } -}; -// 4 byte header + 8 byte payload uses 12 bytes but is rounded up to 16 bytes -// (4 bytes unused) -struct ScaleOp final : DLOp { - static const auto kType = DisplayListOpType::kScale; - - ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {} - - const SkScalar sx; - const SkScalar sy; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.scale(sx, sy); } -}; -// 4 byte header + 4 byte payload packs into minimum 8 bytes -struct RotateOp final : DLOp { - static const auto kType = DisplayListOpType::kRotate; - - RotateOp(SkScalar degrees) : degrees(degrees) {} - - const SkScalar degrees; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.rotate(degrees); } -}; -// 4 byte header + 8 byte payload uses 12 bytes but is rounded up to 16 bytes -// (4 bytes unused) -struct SkewOp final : DLOp { - static const auto kType = DisplayListOpType::kSkew; - - SkewOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {} - - const SkScalar sx; - const SkScalar sy; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.skew(sx, sy); } -}; -// 4 byte header + 24 byte payload uses 28 bytes but is rounded up to 32 bytes -// (4 bytes unused) -struct Transform2x3Op final : DLOp { - static const auto kType = DisplayListOpType::kTransform2x3; - - Transform2x3Op(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) - : mxx(mxx), mxy(mxy), mxt(mxt), myx(myx), myy(myy), myt(myt) {} - - const SkScalar mxx, mxy, mxt; - const SkScalar myx, myy, myt; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.transform2x3(mxx, mxy, mxt, myx, myy, myt); - } -}; -// 4 byte header + 36 byte payload packs evenly into 40 bytes -struct Transform3x3Op final : DLOp { - static const auto kType = DisplayListOpType::kTransform3x3; - - Transform3x3Op(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) - : mxx(mxx), - mxy(mxy), - mxt(mxt), - myx(myx), - myy(myy), - myt(myt), - px(px), - py(py), - pt(pt) {} - - const SkScalar mxx, mxy, mxt; - const SkScalar myx, myy, myt; - const SkScalar px, py, pt; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.transform3x3(mxx, mxy, mxt, myx, myy, myt, px, py, pt); - } -}; - -// 4 byte header + 4 byte common payload packs into minimum 8 bytes -// SkRect is 16 more bytes, which packs efficiently into 24 bytes total -// SkRRect is 52 more bytes, which rounds up to 56 bytes (4 bytes unused) -// which packs into 64 bytes total -// SkPath is 16 more bytes, which packs efficiently into 24 bytes total -// -// We could pack the clip_op and the bool both into the free 4 bytes after -// the header, but the Windows compiler keeps wanting to expand that -// packing into more bytes than needed (even when they are declared as -// packed bit fields!) -#define DEFINE_CLIP_SHAPE_OP(shapetype, clipop) \ - struct Clip##clipop##shapetype##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kClip##clipop##shapetype; \ - \ - Clip##clipop##shapetype##Op(Sk##shapetype shape, bool is_aa) \ - : is_aa(is_aa), shape(shape) {} \ - \ - const bool is_aa; \ - const Sk##shapetype shape; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.clip##shapetype(shape, is_aa, SkClipOp::k##clipop); \ - } \ - }; -DEFINE_CLIP_SHAPE_OP(Rect, Intersect) -DEFINE_CLIP_SHAPE_OP(RRect, Intersect) -DEFINE_CLIP_SHAPE_OP(Rect, Difference) -DEFINE_CLIP_SHAPE_OP(RRect, Difference) -#undef DEFINE_CLIP_SHAPE_OP - -#define DEFINE_CLIP_PATH_OP(clipop) \ - struct Clip##clipop##PathOp final : DLOp { \ - static const auto kType = DisplayListOpType::kClip##clipop##Path; \ - \ - Clip##clipop##PathOp(SkPath path, bool is_aa) \ - : is_aa(is_aa), path(path) {} \ - \ - const bool is_aa; \ - const SkPath path; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.clipPath(path, is_aa, SkClipOp::k##clipop); \ - } \ - \ - DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \ - return is_aa == other->is_aa && path == other->path \ - ? DisplayListCompare::kEqual \ - : DisplayListCompare::kNotEqual; \ - } \ - }; -DEFINE_CLIP_PATH_OP(Intersect) -DEFINE_CLIP_PATH_OP(Difference) -#undef DEFINE_CLIP_PATH_OP - -// 4 byte header + no payload uses minimum 8 bytes (4 bytes unused) -struct DrawPaintOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawPaint; - - DrawPaintOp() {} - - void dispatch(Dispatcher& dispatcher) const { dispatcher.drawPaint(); } -}; -// 4 byte header + 8 byte payload uses 12 bytes but is rounded up to 16 bytes -// (4 bytes unused) -struct DrawColorOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawColor; - - DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {} - - const SkColor color; - const SkBlendMode mode; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawColor(color, mode); - } -}; - -// The common data is a 4 byte header with an unused 4 bytes -// SkRect is 16 more bytes, using 20 bytes which rounds up to 24 bytes total -// (4 bytes unused) -// SkOval is same as SkRect -// SkRRect is 52 more bytes, which packs efficiently into 56 bytes total -#define DEFINE_DRAW_1ARG_OP(op_name, arg_type, arg_name) \ - struct Draw##op_name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kDraw##op_name; \ - \ - Draw##op_name##Op(arg_type arg_name) : arg_name(arg_name) {} \ - \ - const arg_type arg_name; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.draw##op_name(arg_name); \ - } \ - }; -DEFINE_DRAW_1ARG_OP(Rect, SkRect, rect) -DEFINE_DRAW_1ARG_OP(Oval, SkRect, oval) -DEFINE_DRAW_1ARG_OP(RRect, SkRRect, rrect) -#undef DEFINE_DRAW_1ARG_OP - -// 4 byte header + 16 byte payload uses 20 bytes but is rounded up to 24 bytes -// (4 bytes unused) -struct DrawPathOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawPath; - - DrawPathOp(SkPath path) : path(path) {} - - const SkPath path; - - void dispatch(Dispatcher& dispatcher) const { dispatcher.drawPath(path); } - - DisplayListCompare equals(const DrawPathOp* other) const { - return path == other->path ? DisplayListCompare::kEqual - : DisplayListCompare::kNotEqual; - } -}; - -// The common data is a 4 byte header with an unused 4 bytes -// 2 x SkPoint is 16 more bytes, using 20 bytes rounding up to 24 bytes total -// (4 bytes unused) -// SkPoint + SkScalar is 12 more bytes, packing efficiently into 16 bytes total -// 2 x SkRRect is 104 more bytes, using 108 and rounding up to 112 bytes total -// (4 bytes unused) -#define DEFINE_DRAW_2ARG_OP(op_name, type1, name1, type2, name2) \ - struct Draw##op_name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kDraw##op_name; \ - \ - Draw##op_name##Op(type1 name1, type2 name2) \ - : name1(name1), name2(name2) {} \ - \ - const type1 name1; \ - const type2 name2; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.draw##op_name(name1, name2); \ - } \ - }; -DEFINE_DRAW_2ARG_OP(Line, SkPoint, p0, SkPoint, p1) -DEFINE_DRAW_2ARG_OP(Circle, SkPoint, center, SkScalar, radius) -DEFINE_DRAW_2ARG_OP(DRRect, SkRRect, outer, SkRRect, inner) -#undef DEFINE_DRAW_2ARG_OP - -// 4 byte header + 28 byte payload packs efficiently into 32 bytes -struct DrawArcOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawArc; - - DrawArcOp(SkRect bounds, SkScalar start, SkScalar sweep, bool center) - : bounds(bounds), start(start), sweep(sweep), center(center) {} - - const SkRect bounds; - const SkScalar start; - const SkScalar sweep; - const bool center; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawArc(bounds, start, sweep, center); - } -}; - -// 4 byte header + 4 byte fixed payload packs efficiently into 8 bytes -// But then there is a list of points following the structure which -// is guaranteed to be a multiple of 8 bytes (SkPoint is 8 bytes) -// so this op will always pack efficiently -// The point type is packed into 3 different OpTypes to avoid expanding -// the fixed payload beyond the 8 bytes -#define DEFINE_DRAW_POINTS_OP(name, mode) \ - struct Draw##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kDraw##name; \ - \ - Draw##name##Op(uint32_t count) : count(count) {} \ - \ - const uint32_t count; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - const SkPoint* pts = reinterpret_cast(this + 1); \ - dispatcher.drawPoints(SkCanvas::PointMode::mode, count, pts); \ - } \ - }; -DEFINE_DRAW_POINTS_OP(Points, kPoints_PointMode); -DEFINE_DRAW_POINTS_OP(Lines, kLines_PointMode); -DEFINE_DRAW_POINTS_OP(Polygon, kPolygon_PointMode); -#undef DEFINE_DRAW_POINTS_OP - -// 4 byte header + 12 byte payload packs efficiently into 16 bytes -struct DrawVerticesOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawVertices; - - DrawVerticesOp(sk_sp vertices, SkBlendMode mode) - : mode(mode), vertices(std::move(vertices)) {} - - const SkBlendMode mode; - const sk_sp vertices; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawVertices(vertices, mode); - } -}; - -// 4 byte header + 36 byte payload packs efficiently into 40 bytes -struct DrawImageOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawImage; - - DrawImageOp(const sk_sp image, - const SkPoint& point, - const SkSamplingOptions& sampling) - : point(point), sampling(sampling), image(std::move(image)) {} - - const SkPoint point; - const SkSamplingOptions sampling; - const sk_sp image; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawImage(image, point, sampling); - } -}; - -// 4 byte header + 60 byte payload packs efficiently into 64 bytes -// -// The constraint could be stored in the struct, but it would not pack -// efficiently so 2 variants are defined instead. -#define DEFINE_DRAW_IMAGE_RECT_OP(name, constraint) \ - struct Draw##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kDraw##name; \ - \ - Draw##name##Op(const sk_sp image, \ - const SkRect& src, \ - const SkRect& dst, \ - const SkSamplingOptions& sampling) \ - : src(src), dst(dst), sampling(sampling), image(std::move(image)) {} \ - \ - const SkRect src; \ - const SkRect dst; \ - const SkSamplingOptions sampling; \ - const sk_sp image; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - dispatcher.drawImageRect(image, src, dst, sampling, constraint); \ - } \ - }; -DEFINE_DRAW_IMAGE_RECT_OP(ImageRectStrict, SkCanvas::kStrict_SrcRectConstraint) -DEFINE_DRAW_IMAGE_RECT_OP(ImageRectFast, SkCanvas::kFast_SrcRectConstraint) -#undef DEFINE_DRAW_IMAGE_RECT_OP - -// 4 byte header + 44 byte payload packs efficiently into 48 bytes -struct DrawImageNineOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawImageNine; - - DrawImageNineOp(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) - : center(center), dst(dst), filter(filter), image(std::move(image)) {} - - const SkIRect center; - const SkRect dst; - const SkFilterMode filter; - const sk_sp image; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawImageNine(image, center, dst, filter); - } -}; - -// 4 byte header + 60 byte payload packs evenly into 64 bytes -struct DrawImageLatticeOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawImageLattice; - - DrawImageLatticeOp(const sk_sp image, - int x_count, - int y_count, - int cell_count, - const SkIRect& src, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) - : with_paint(with_paint), - x_count(x_count), - y_count(y_count), - cell_count(cell_count), - filter(filter), - src(src), - dst(dst), - image(std::move(image)) {} - - const bool with_paint; - const int x_count; - const int y_count; - const int cell_count; - const SkFilterMode filter; - const SkIRect src; - const SkRect dst; - const sk_sp image; - - void dispatch(Dispatcher& dispatcher) const { - const int* xDivs = reinterpret_cast(this + 1); - const int* yDivs = reinterpret_cast(xDivs + x_count); - const SkColor* colors = - (cell_count == 0) ? nullptr - : reinterpret_cast(yDivs + y_count); - const SkCanvas::Lattice::RectType* types = - (cell_count == 0) - ? nullptr - : reinterpret_cast(colors + - cell_count); - dispatcher.drawImageLattice( - image, {xDivs, yDivs, types, x_count, y_count, &src, colors}, dst, - filter, with_paint); - } -}; - -#define DRAW_ATLAS_NO_COLORS_ARRAY(tex, count) nullptr -#define DRAW_ATLAS_HAS_COLORS_ARRAY(tex, count) \ - reinterpret_cast(tex + count) - -#define DRAW_ATLAS_NO_CULLING_ARGS \ - const sk_sp atlas, int count, SkBlendMode mode, \ - const SkSamplingOptions &sampling -#define DRAW_ATLAS_NO_CULLING_INIT \ - count(count), mode(mode), sampling(sampling), atlas(std::move(atlas)) -#define DRAW_ATLAS_NO_CULLING_FIELDS \ - const int count; \ - const SkBlendMode mode; \ - const SkSamplingOptions sampling; \ - const sk_sp atlas -#define DRAW_ATLAS_NO_CULLING_P_ARG nullptr - -#define DRAW_ATLAS_HAS_CULLING_ARGS \ - DRAW_ATLAS_NO_CULLING_ARGS, const SkRect& cull -#define DRAW_ATLAS_HAS_CULLING_INIT DRAW_ATLAS_NO_CULLING_INIT, cull(cull) -#define DRAW_ATLAS_HAS_CULLING_FIELDS \ - DRAW_ATLAS_NO_CULLING_FIELDS; \ - const SkRect cull -#define DRAW_ATLAS_HAS_CULLING_P_ARG &cull - -// 4 byte header + 36 byte common payload packs efficiently into 40 bytes -// Culling version has an additional 16 bytes of payload for 56 bytes -// So all 4 versions of the base structure pack well. -// Each of these is then followed by a number of lists. -// SkRSXform list is a multiple of 16 bytes so it is always packed well -// SkRect list is also a multiple of 16 bytes so it also packs well -// SkColor list only packs well if the count is even, otherwise there -// can be 4 unusued bytes at the end. -#define DEFINE_DRAW_ATLAS_OP(name, colors, cull) \ - struct Draw##name##Op final : DLOp { \ - static const auto kType = DisplayListOpType::kDraw##name; \ - \ - Draw##name##Op(DRAW_ATLAS_##cull##_ARGS) : DRAW_ATLAS_##cull##_INIT {} \ - \ - DRAW_ATLAS_##cull##_FIELDS; \ - \ - void dispatch(Dispatcher& dispatcher) const { \ - const SkRSXform* xform = reinterpret_cast(this + 1); \ - const SkRect* tex = reinterpret_cast(xform + count); \ - const SkColor* colors = DRAW_ATLAS_##colors##_ARRAY(tex, count); \ - dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, \ - DRAW_ATLAS_##cull##_P_ARG); \ - } \ - }; -DEFINE_DRAW_ATLAS_OP(Atlas, NO_COLORS, NO_CULLING) -DEFINE_DRAW_ATLAS_OP(AtlasColored, HAS_COLORS, NO_CULLING) -DEFINE_DRAW_ATLAS_OP(AtlasCulled, NO_COLORS, HAS_CULLING) -DEFINE_DRAW_ATLAS_OP(AtlasColoredCulled, HAS_COLORS, HAS_CULLING) -#undef DEFINE_DRAW_ATLAS_OP -#undef DRAW_ATLAS_NO_COLORS_ARRAY -#undef DRAW_ATLAS_HAS_COLORS_ARRAY -#undef DRAW_ATLAS_NO_CULLING_ARGS -#undef DRAW_ATLAS_NO_CULLING_INIT -#undef DRAW_ATLAS_NO_CULLING_FIELDS -#undef DRAW_ATLAS_NO_CULLING_P_ARG -#undef DRAW_ATLAS_HAS_CULLING_ARGS -#undef DRAW_ATLAS_HAS_CULLING_INIT -#undef DRAW_ATLAS_HAS_CULLING_FIELDS -#undef DRAW_ATLAS_HAS_CULLING_P_ARG - -// 4 byte header + 12 byte payload packs evenly into 16 bytes -struct DrawSkPictureOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawSkPicture; - - DrawSkPictureOp(sk_sp picture, bool with_layer) - : with_layer(with_layer), picture(std::move(picture)) {} - - const bool with_layer; - const sk_sp picture; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawPicture(picture, nullptr, with_layer); - } -}; - -// 4 byte header + 52 byte payload packs evenly into 56 bytes -struct DrawSkPictureMatrixOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawSkPictureMatrix; - - DrawSkPictureMatrixOp(sk_sp picture, - const SkMatrix matrix, - bool with_layer) - : with_layer(with_layer), picture(std::move(picture)), matrix(matrix) {} - - const bool with_layer; - const sk_sp picture; - const SkMatrix matrix; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawPicture(picture, &matrix, with_layer); - } -}; - -// 4 byte header + ptr aligned payload uses 12 bytes rounde up to 16 -// (4 bytes unused) -struct DrawDisplayListOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawDisplayList; - - DrawDisplayListOp(const sk_sp display_list) - : display_list(std::move(display_list)) {} - - sk_sp display_list; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawDisplayList(display_list); - } -}; - -// 4 byte header + 8 payload bytes + an aligned pointer take 24 bytes -// (4 unused to align the pointer) -struct DrawTextBlobOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawTextBlob; - - DrawTextBlobOp(const sk_sp blob, SkScalar x, SkScalar y) - : x(x), y(y), blob(std::move(blob)) {} - - const SkScalar x; - const SkScalar y; - const sk_sp blob; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawTextBlob(blob, x, y); - } -}; - -// 4 byte header + 28 byte payload packs evenly into 32 bytes -struct DrawShadowOp final : DLOp { - static const auto kType = DisplayListOpType::kDrawShadow; - - DrawShadowOp(const SkPath& path, - SkColor color, - SkScalar elevation, - bool occludes) - : color(color), elevation(elevation), occludes(occludes), path(path) {} - - const SkColor color; - const SkScalar elevation; - const bool occludes; - const SkPath path; - - void dispatch(Dispatcher& dispatcher) const { - dispatcher.drawShadow(path, color, elevation, occludes); - } -}; - -#pragma pack(pop, DLOp_Alignment) - -void DisplayList::ComputeBounds() { - DisplayListBoundsCalculator calculator(bounds_cull_); - Dispatch(calculator); - bounds_ = calculator.getBounds(); -} - -void DisplayList::Dispatch(Dispatcher& dispatcher, - uint8_t* ptr, - uint8_t* end) const { - while (ptr < end) { - auto op = (const DLOp*)ptr; - ptr += op->size; - FML_DCHECK(ptr <= end); - switch (op->type) { -#define DL_OP_DISPATCH(name) \ - case DisplayListOpType::k##name: \ - static_cast(op)->dispatch(dispatcher); \ - break; - - FOR_EACH_DISPLAY_LIST_OP(DL_OP_DISPATCH) - -#undef DL_OP_DISPATCH - - default: - FML_DCHECK(false); - return; - } - } -} - -static void DisposeOps(uint8_t* ptr, uint8_t* end) { - while (ptr < end) { - auto op = (const DLOp*)ptr; - ptr += op->size; - FML_DCHECK(ptr <= end); - switch (op->type) { -#define DL_OP_DISPOSE(name) \ - case DisplayListOpType::k##name: \ - if (!std::is_trivially_destructible_v) { \ - static_cast(op)->~name##Op(); \ - } \ - break; - - FOR_EACH_DISPLAY_LIST_OP(DL_OP_DISPOSE) - -#undef DL_OP_DISPATCH - - default: - FML_DCHECK(false); - return; - } - } -} - -static bool CompareOps(uint8_t* ptrA, - uint8_t* endA, - uint8_t* ptrB, - uint8_t* endB) { - // These conditions are checked by the caller... - FML_DCHECK((endA - ptrA) == (endB - ptrB)); - FML_DCHECK(ptrA != ptrB); - uint8_t* bulkStartA = ptrA; - uint8_t* bulkStartB = ptrB; - while (ptrA < endA && ptrB < endB) { - auto opA = (const DLOp*)ptrA; - auto opB = (const DLOp*)ptrB; - if (opA->type != opB->type || opA->size != opB->size) { - return false; - } - ptrA += opA->size; - ptrB += opB->size; - FML_DCHECK(ptrA <= endA); - FML_DCHECK(ptrB <= endB); - DisplayListCompare result; - switch (opA->type) { -#define DL_OP_EQUALS(name) \ - case DisplayListOpType::k##name: \ - result = static_cast(opA)->equals( \ - static_cast(opB)); \ - break; - - FOR_EACH_DISPLAY_LIST_OP(DL_OP_EQUALS) - -#undef DL_OP_DISPATCH - - default: - FML_DCHECK(false); - return false; - } - switch (result) { - case DisplayListCompare::kNotEqual: - return false; - case DisplayListCompare::kUseBulkCompare: - break; - case DisplayListCompare::kEqual: - // Check if we have a backlog of bytes to bulk compare and then - // reset the bulk compare pointers to the address following this op - auto bulkBytes = reinterpret_cast(opA) - bulkStartA; - if (bulkBytes > 0) { - if (memcmp(bulkStartA, bulkStartB, bulkBytes) != 0) { - return false; - } - } - bulkStartA = ptrA; - bulkStartB = ptrB; - break; - } - } - if (ptrA != endA || ptrB != endB) { - return false; - } - if (bulkStartA < ptrA) { - // Perform a final bulk compare if we have remaining bytes waiting - if (memcmp(bulkStartA, bulkStartB, ptrA - bulkStartA) != 0) { - return false; - } - } - return true; -} - -void DisplayList::RenderTo(SkCanvas* canvas) const { - DisplayListCanvasDispatcher dispatcher(canvas); - Dispatch(dispatcher); -} - -bool DisplayList::Equals(const DisplayList& other) const { - if (used_ != other.used_ || op_count_ != other.op_count_) { - return false; - } - if (ptr_ == other.ptr_) { - return true; - } - return CompareOps(ptr_, ptr_ + used_, other.ptr_, other.ptr_ + other.used_); -} - -DisplayList::DisplayList(uint8_t* ptr, - size_t used, - int op_count, - const SkRect& cull) - : ptr_(ptr), - used_(used), - op_count_(op_count), - bounds_({0, 0, -1, -1}), - bounds_cull_(cull) { - static std::atomic nextID{1}; - do { - unique_id_ = nextID.fetch_add(+1, std::memory_order_relaxed); - } while (unique_id_ == 0); -} - -DisplayList::~DisplayList() { - DisposeOps(ptr_, ptr_ + used_); -} - -#define DL_BUILDER_PAGE 4096 - -// CopyV(dst, src,n, src,n, ...) copies any number of typed srcs into dst. -static void CopyV(void* dst) {} - -template -static void CopyV(void* dst, const S* src, int n, Rest&&... rest) { - FML_DCHECK(((uintptr_t)dst & (alignof(S) - 1)) == 0) - << "Expected " << dst << " to be aligned for at least " << alignof(S) - << " bytes."; - sk_careful_memcpy(dst, src, n * sizeof(S)); - CopyV(SkTAddOffset(dst, n * sizeof(S)), std::forward(rest)...); -} - -template -void* DisplayListBuilder::Push(size_t pod, Args&&... args) { - size_t size = SkAlignPtr(sizeof(T) + pod); - FML_DCHECK(size < (1 << 24)); - if (used_ + size > allocated_) { - static_assert(SkIsPow2(DL_BUILDER_PAGE), - "This math needs updating for non-pow2."); - // Next greater multiple of DL_BUILDER_PAGE. - allocated_ = (used_ + size + DL_BUILDER_PAGE) & ~(DL_BUILDER_PAGE - 1); - storage_.realloc(allocated_); - FML_DCHECK(storage_.get()); - memset(storage_.get() + used_, 0, allocated_ - used_); - } - FML_DCHECK(used_ + size <= allocated_); - auto op = (T*)(storage_.get() + used_); - used_ += size; - new (op) T{std::forward(args)...}; - op->type = T::kType; - op->size = size; - op_count_++; - return op + 1; -} - -sk_sp DisplayListBuilder::Build() { - while (save_level_ > 0) { - restore(); - } - size_t used = used_; - int count = op_count_; - used_ = allocated_ = op_count_ = 0; - storage_.realloc(used); - return sk_sp( - new DisplayList(storage_.release(), used, count, cull_)); -} - -DisplayListBuilder::DisplayListBuilder(const SkRect& cull) : cull_(cull) {} - -DisplayListBuilder::~DisplayListBuilder() { - uint8_t* ptr = storage_.get(); - if (ptr) { - DisposeOps(ptr, ptr + used_); - } -} - -void DisplayListBuilder::setAA(bool aa) { - Push(0, aa); -} -void DisplayListBuilder::setDither(bool dither) { - Push(0, dither); -} -void DisplayListBuilder::setInvertColors(bool invert) { - Push(0, invert); -} -void DisplayListBuilder::setCaps(SkPaint::Cap cap) { - Push(0, cap); -} -void DisplayListBuilder::setJoins(SkPaint::Join join) { - Push(0, join); -} -void DisplayListBuilder::setDrawStyle(SkPaint::Style style) { - Push(0, style); -} -void DisplayListBuilder::setStrokeWidth(SkScalar width) { - Push(0, width); -} -void DisplayListBuilder::setMiterLimit(SkScalar limit) { - Push(0, limit); -} -void DisplayListBuilder::setColor(SkColor color) { - Push(0, color); -} -void DisplayListBuilder::setBlendMode(SkBlendMode mode) { - Push(0, mode); -} -void DisplayListBuilder::setFilterQuality(SkFilterQuality quality) { - Push(0, quality); -} -void DisplayListBuilder::setShader(sk_sp shader) { - shader // - ? Push(0, std::move(shader)) - : Push(0); -} -void DisplayListBuilder::setImageFilter(sk_sp filter) { - filter // - ? Push(0, std::move(filter)) - : Push(0); -} -void DisplayListBuilder::setColorFilter(sk_sp filter) { - filter // - ? Push(0, std::move(filter)) - : Push(0); -} -void DisplayListBuilder::setMaskFilter(sk_sp filter) { - Push(0, std::move(filter)); -} -void DisplayListBuilder::setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) { - switch (style) { - case kNormal_SkBlurStyle: - Push(0, sigma); - break; - case kSolid_SkBlurStyle: - Push(0, sigma); - break; - case kOuter_SkBlurStyle: - Push(0, sigma); - break; - case kInner_SkBlurStyle: - Push(0, sigma); - break; - } -} - -void DisplayListBuilder::save() { - save_level_++; - Push(0); -} -void DisplayListBuilder::restore() { - if (save_level_ > 0) { - Push(0); - save_level_--; - } -} -void DisplayListBuilder::saveLayer(const SkRect* bounds, bool with_paint) { - save_level_++; - bounds // - ? Push(0, *bounds, with_paint) - : Push(0, with_paint); -} - -void DisplayListBuilder::translate(SkScalar tx, SkScalar ty) { - Push(0, tx, ty); -} -void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) { - Push(0, sx, sy); -} -void DisplayListBuilder::rotate(SkScalar degrees) { - Push(0, degrees); -} -void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) { - Push(0, sx, sy); -} -void DisplayListBuilder::transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) { - Push(0, mxx, mxy, mxt, myx, myy, myt); -} -void DisplayListBuilder::transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) { - Push(0, mxx, mxy, mxt, myx, myy, myt, px, py, pt); -} - -void DisplayListBuilder::clipRect(const SkRect& rect, - bool is_aa, - SkClipOp clip_op) { - clip_op == SkClipOp::kIntersect // - ? Push(0, rect, is_aa) - : Push(0, rect, is_aa); -} -void DisplayListBuilder::clipRRect(const SkRRect& rrect, - bool is_aa, - SkClipOp clip_op) { - if (rrect.isRect()) { - clipRect(rrect.rect(), is_aa, clip_op); - } else { - clip_op == SkClipOp::kIntersect // - ? Push(0, rrect, is_aa) - : Push(0, rrect, is_aa); - } -} -void DisplayListBuilder::clipPath(const SkPath& path, - bool is_aa, - SkClipOp clip_op) { - if (!path.isInverseFillType()) { - SkRect rect; - if (path.isRect(&rect)) { - this->clipRect(rect, is_aa, clip_op); - return; - } - SkRRect rrect; - if (path.isOval(&rect)) { - rrect.setOval(rect); - this->clipRRect(rrect, is_aa, clip_op); - return; - } - if (path.isRRect(&rrect)) { - this->clipRRect(rrect, is_aa, clip_op); - return; - } - } - clip_op == SkClipOp::kIntersect // - ? Push(0, path, is_aa) - : Push(0, path, is_aa); -} - -void DisplayListBuilder::drawPaint() { - Push(0); -} -void DisplayListBuilder::drawColor(SkColor color, SkBlendMode mode) { - Push(0, color, mode); -} -void DisplayListBuilder::drawLine(const SkPoint& p0, const SkPoint& p1) { - Push(0, p0, p1); -} -void DisplayListBuilder::drawRect(const SkRect& rect) { - Push(0, rect); -} -void DisplayListBuilder::drawOval(const SkRect& bounds) { - Push(0, bounds); -} -void DisplayListBuilder::drawCircle(const SkPoint& center, SkScalar radius) { - Push(0, center, radius); -} -void DisplayListBuilder::drawRRect(const SkRRect& rrect) { - if (rrect.isRect()) { - drawRect(rrect.rect()); - } else if (rrect.isOval()) { - drawOval(rrect.rect()); - } else { - Push(0, rrect); - } -} -void DisplayListBuilder::drawDRRect(const SkRRect& outer, - const SkRRect& inner) { - Push(0, outer, inner); -} -void DisplayListBuilder::drawPath(const SkPath& path) { - Push(0, path); -} - -void DisplayListBuilder::drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) { - Push(0, bounds, start, sweep, useCenter); -} -void DisplayListBuilder::drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) { - void* data_ptr; - FML_DCHECK(count < MaxDrawPointsCount); - int bytes = count * sizeof(SkPoint); - switch (mode) { - case SkCanvas::PointMode::kPoints_PointMode: - data_ptr = Push(bytes, count); - break; - case SkCanvas::PointMode::kLines_PointMode: - data_ptr = Push(bytes, count); - break; - case SkCanvas::PointMode::kPolygon_PointMode: - data_ptr = Push(bytes, count); - break; - default: - FML_DCHECK(false); - return; - } - CopyV(data_ptr, pts, count); -} -void DisplayListBuilder::drawVertices(const sk_sp vertices, - SkBlendMode mode) { - Push(0, std::move(vertices), mode); -} - -void DisplayListBuilder::drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) { - Push(0, std::move(image), point, sampling); -} -void DisplayListBuilder::drawImageRect(const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint) { - constraint == SkCanvas::kFast_SrcRectConstraint // - ? Push(0, std::move(image), src, dst, sampling) - : Push(0, std::move(image), src, dst, sampling); -} -void DisplayListBuilder::drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) { - Push(0, std::move(image), center, dst, filter); -} -void DisplayListBuilder::drawImageLattice(const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) { - int xDivCount = lattice.fXCount; - int yDivCount = lattice.fYCount; - FML_DCHECK((lattice.fRectTypes == nullptr) || (lattice.fColors != nullptr)); - int cellCount = lattice.fRectTypes && lattice.fColors - ? (xDivCount + 1) * (yDivCount + 1) - : 0; - size_t bytes = - (xDivCount + yDivCount) * sizeof(int) + - cellCount * (sizeof(SkColor) + sizeof(SkCanvas::Lattice::RectType)); - SkIRect src = lattice.fBounds ? *lattice.fBounds : image->bounds(); - void* pod = this->Push(bytes, std::move(image), xDivCount, - yDivCount, cellCount, src, dst, - filter, with_paint); - CopyV(pod, lattice.fXDivs, xDivCount, lattice.fYDivs, yDivCount, - lattice.fColors, cellCount, lattice.fRectTypes, cellCount); -} -void DisplayListBuilder::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) { - int bytes = count * (sizeof(SkRSXform) + sizeof(SkRect)); - void* data_ptr; - if (colors) { - bytes += count * sizeof(SkColor); - if (cullRect) { - data_ptr = Push(bytes, std::move(atlas), count, - mode, sampling, *cullRect); - } else { - data_ptr = Push(bytes, std::move(atlas), count, mode, - sampling); - } - CopyV(data_ptr, xform, count, tex, count, colors, count); - } else { - if (cullRect) { - data_ptr = Push(bytes, std::move(atlas), count, mode, - sampling, *cullRect); - } else { - data_ptr = - Push(bytes, std::move(atlas), count, mode, sampling); - } - CopyV(data_ptr, xform, count, tex, count); - } -} - -void DisplayListBuilder::drawPicture(const sk_sp picture, - const SkMatrix* matrix, - bool with_layer) { - matrix // - ? Push(0, std::move(picture), *matrix, with_layer) - : Push(0, std::move(picture), with_layer); -} -void DisplayListBuilder::drawDisplayList( - const sk_sp display_list) { - Push(0, std::move(display_list)); -} -void DisplayListBuilder::drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) { - Push(0, std::move(blob), x, y); -} -void DisplayListBuilder::drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) { - Push(0, path, color, elevation, occludes); -} - -} // namespace flutter diff --git a/flow/display_list.h b/flow/display_list.h deleted file mode 100644 index 7fde2a8480728..0000000000000 --- a/flow/display_list.h +++ /dev/null @@ -1,452 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_FLOW_DISPLAY_LIST_H_ -#define FLUTTER_FLOW_DISPLAY_LIST_H_ - -#include "third_party/skia/include/core/SkBlurTypes.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkColorFilter.h" -#include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/core/SkImageFilter.h" -#include "third_party/skia/include/core/SkPicture.h" -#include "third_party/skia/include/core/SkShader.h" -#include "third_party/skia/include/core/SkVertices.h" - -// The Flutter DisplayList mechanism encapsulates a persistent sequence of -// rendering operations. -// -// This file contains the definitions for: -// DisplayList: the base class that holds the information about the -// sequence of operations and can dispatch them to a Dispatcher -// Dispatcher: a pure virtual interface which can be implemented to field -// the requests for purposes such as sending them to an SkCanvas -// or detecting various rendering optimization scenarios -// DisplayListBuilder: a class for constructing a DisplayList from the same -// calls defined in the Dispatcher -// -// Other files include various class definitions for dealing with display -// lists, such as: -// display_list_canvas.h: classes to interact between SkCanvas and DisplayList -// (SkCanvas->DisplayList adapter and vice versa) -// -// display_list_utils.h: various utility classes to ease implementing -// a Dispatcher, including NOP implementations of -// the attribute, clip, and transform methods, -// classes to track attributes, clips, and transforms -// and a class to compute the bounds of a DisplayList -// Any class implementing Dispatcher can inherit from -// these utility classes to simplify its creation -// -// The Flutter DisplayList mechanism can be used in place of the Skia -// SkPicture mechanism. The primary means of communication into and out -// of the DisplayList is through the Dispatcher virtual class which -// provides a nearly 1:1 translation between the records of the DisplayList -// to method calls. -// -// A DisplayList can be created directly using a DisplayListBuilder and -// the Dispatcher methods that it implements, or it can be created from -// a sequence of SkCanvas calls using the DisplayListCanvasRecorder class. -// -// A DisplayList can be read back by implementing the Dispatcher virtual -// methods (with help from some of the classes in the utils file) and -// passing an instance to the dispatch() method, or it can be rendered -// to Skia using a DisplayListCanvasDispatcher or simply by passing an -// SkCanvas pointer to its renderTo() method. -// -// The mechanism is inspired by the SkLiteDL class that is not directly -// supported by Skia, but has been recommended as a basis for custom -// display lists for a number of their customers. - -namespace flutter { - -#define FOR_EACH_DISPLAY_LIST_OP(V) \ - V(SetAA) \ - V(SetDither) \ - V(SetInvertColors) \ - \ - V(SetCaps) \ - V(SetJoins) \ - \ - V(SetDrawStyle) \ - V(SetStrokeWidth) \ - V(SetMiterLimit) \ - \ - V(SetColor) \ - V(SetBlendMode) \ - \ - V(SetFilterQuality) \ - \ - V(SetShader) \ - V(ClearShader) \ - V(SetColorFilter) \ - V(ClearColorFilter) \ - V(SetImageFilter) \ - V(ClearImageFilter) \ - \ - V(ClearMaskFilter) \ - V(SetMaskFilter) \ - V(SetMaskBlurFilterNormal) \ - V(SetMaskBlurFilterSolid) \ - V(SetMaskBlurFilterOuter) \ - V(SetMaskBlurFilterInner) \ - \ - V(Save) \ - V(SaveLayer) \ - V(SaveLayerBounds) \ - V(Restore) \ - \ - V(Translate) \ - V(Scale) \ - V(Rotate) \ - V(Skew) \ - V(Transform2x3) \ - V(Transform3x3) \ - \ - V(ClipIntersectRect) \ - V(ClipIntersectRRect) \ - V(ClipIntersectPath) \ - V(ClipDifferenceRect) \ - V(ClipDifferenceRRect) \ - V(ClipDifferencePath) \ - \ - V(DrawPaint) \ - V(DrawColor) \ - \ - V(DrawLine) \ - V(DrawRect) \ - V(DrawOval) \ - V(DrawCircle) \ - V(DrawRRect) \ - V(DrawDRRect) \ - V(DrawArc) \ - V(DrawPath) \ - \ - V(DrawPoints) \ - V(DrawLines) \ - V(DrawPolygon) \ - V(DrawVertices) \ - \ - V(DrawImage) \ - V(DrawImageRectStrict) \ - V(DrawImageRectFast) \ - V(DrawImageNine) \ - V(DrawImageLattice) \ - V(DrawAtlas) \ - V(DrawAtlasColored) \ - V(DrawAtlasCulled) \ - V(DrawAtlasColoredCulled) \ - \ - V(DrawSkPicture) \ - V(DrawSkPictureMatrix) \ - V(DrawDisplayList) \ - V(DrawTextBlob) \ - \ - V(DrawShadow) - -#define DL_OP_TO_ENUM_VALUE(name) k##name, -enum class DisplayListOpType { FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) }; -#undef DL_OP_TO_ENUM_VALUE - -class Dispatcher; -class DisplayListBuilder; - -// The base class that contains a sequence of rendering operations -// for dispatch to a Dispatcher. These objects must be instantiated -// through an instance of DisplayListBuilder::build(). -class DisplayList : public SkRefCnt { - public: - static const SkSamplingOptions NearestSampling; - static const SkSamplingOptions LinearSampling; - static const SkSamplingOptions MipmapSampling; - static const SkSamplingOptions CubicSampling; - - DisplayList() - : ptr_(nullptr), - used_(0), - op_count_(0), - unique_id_(0), - bounds_({0, 0, 0, 0}), - bounds_cull_({0, 0, 0, 0}) {} - - ~DisplayList(); - - void Dispatch(Dispatcher& ctx) const { Dispatch(ctx, ptr_, ptr_ + used_); } - - void RenderTo(SkCanvas* canvas) const; - - size_t bytes() const { return used_; } - int op_count() const { return op_count_; } - uint32_t unique_id() const { return unique_id_; } - - const SkRect& bounds() { - if (bounds_.width() < 0.0) { - // ComputeBounds() will leave the variable with a - // non-negative width and height - ComputeBounds(); - } - return bounds_; - } - - bool Equals(const DisplayList& other) const; - - private: - DisplayList(uint8_t* ptr, size_t used, int op_count, const SkRect& cull_rect); - - uint8_t* ptr_; - size_t used_; - int op_count_; - - uint32_t unique_id_; - SkRect bounds_; - - // Only used for drawPaint() and drawColor() - SkRect bounds_cull_; - - void ComputeBounds(); - void Dispatch(Dispatcher& ctx, uint8_t* ptr, uint8_t* end) const; - - friend class DisplayListBuilder; -}; - -// The pure virtual interface for interacting with a display list. -// This interface represents the methods used to build a list -// through the DisplayListBuilder and also the methods that will -// be invoked through the DisplayList::dispatch() method. -class Dispatcher { - public: - // MaxDrawPointsCount * sizeof(SkPoint) must be less than 1 << 32 - static constexpr int MaxDrawPointsCount = ((1 << 29) - 1); - - virtual void setAA(bool aa) = 0; - virtual void setDither(bool dither) = 0; - virtual void setInvertColors(bool invert) = 0; - virtual void setCaps(SkPaint::Cap cap) = 0; - virtual void setJoins(SkPaint::Join join) = 0; - virtual void setDrawStyle(SkPaint::Style style) = 0; - virtual void setStrokeWidth(SkScalar width) = 0; - virtual void setMiterLimit(SkScalar limit) = 0; - virtual void setColor(SkColor color) = 0; - virtual void setBlendMode(SkBlendMode mode) = 0; - virtual void setFilterQuality(SkFilterQuality quality) = 0; - virtual void setShader(const sk_sp shader) = 0; - virtual void setImageFilter(const sk_sp filter) = 0; - virtual void setColorFilter(const sk_sp filter) = 0; - virtual void setMaskFilter(const sk_sp filter) = 0; - virtual void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) = 0; - - virtual void save() = 0; - virtual void restore() = 0; - virtual void saveLayer(const SkRect* bounds, bool restoreWithPaint) = 0; - - virtual void translate(SkScalar tx, SkScalar ty) = 0; - virtual void scale(SkScalar sx, SkScalar sy) = 0; - virtual void rotate(SkScalar degrees) = 0; - virtual void skew(SkScalar sx, SkScalar sy) = 0; - virtual void transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) = 0; - virtual void transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) = 0; - - virtual void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) = 0; - virtual void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) = 0; - virtual void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) = 0; - - virtual void drawPaint() = 0; - virtual void drawColor(SkColor color, SkBlendMode mode) = 0; - virtual void drawLine(const SkPoint& p0, const SkPoint& p1) = 0; - virtual void drawRect(const SkRect& rect) = 0; - virtual void drawOval(const SkRect& bounds) = 0; - virtual void drawCircle(const SkPoint& center, SkScalar radius) = 0; - virtual void drawRRect(const SkRRect& rrect) = 0; - virtual void drawDRRect(const SkRRect& outer, const SkRRect& inner) = 0; - virtual void drawPath(const SkPath& path) = 0; - virtual void drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) = 0; - virtual void drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) = 0; - virtual void drawVertices(const sk_sp vertices, - SkBlendMode mode) = 0; - virtual void drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) = 0; - virtual void drawImageRect(const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint) = 0; - virtual void drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) = 0; - virtual void drawImageLattice(const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) = 0; - virtual void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) = 0; - virtual void drawPicture(const sk_sp picture, - const SkMatrix* matrix, - bool with_save_layer) = 0; - virtual void drawDisplayList(const sk_sp display_list) = 0; - virtual void drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) = 0; - virtual void drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) = 0; -}; - -// The primary class used to build a display list. The list of methods -// here matches the list of methods invoked during dispatch(). -// If there is some code that already renders to an SkCanvas object, -// those rendering commands can be captured into a DisplayList using -// the DisplayListCanvasRecorder class. -class DisplayListBuilder final : public virtual Dispatcher, public SkRefCnt { - public: - DisplayListBuilder(const SkRect& cull = SkRect::MakeEmpty()); - ~DisplayListBuilder(); - - void setAA(bool aa) override; - void setDither(bool dither) override; - void setInvertColors(bool invert) override; - void setCaps(SkPaint::Cap cap) override; - void setJoins(SkPaint::Join join) override; - void setDrawStyle(SkPaint::Style style) override; - void setStrokeWidth(SkScalar width) override; - void setMiterLimit(SkScalar limit) override; - void setColor(SkColor color) override; - void setBlendMode(SkBlendMode mode) override; - void setFilterQuality(SkFilterQuality quality) override; - void setShader(sk_sp shader) override; - void setImageFilter(sk_sp filter) override; - void setColorFilter(sk_sp filter) override; - void setMaskFilter(sk_sp filter) override; - void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override; - - void save() override; - void restore() override; - void saveLayer(const SkRect* bounds, bool restoreWithPaint) override; - - void translate(SkScalar tx, SkScalar ty) override; - void scale(SkScalar sx, SkScalar sy) override; - void rotate(SkScalar degrees) override; - void skew(SkScalar sx, SkScalar sy) override; - void transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) override; - void transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) override; - - void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) override; - void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) override; - void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) override; - - void drawPaint() override; - void drawColor(SkColor color, SkBlendMode mode) override; - void drawLine(const SkPoint& p0, const SkPoint& p1) override; - void drawRect(const SkRect& rect) override; - void drawOval(const SkRect& bounds) override; - void drawCircle(const SkPoint& center, SkScalar radius) override; - void drawRRect(const SkRRect& rrect) override; - void drawDRRect(const SkRRect& outer, const SkRRect& inner) override; - void drawPath(const SkPath& path) override; - void drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) override; - void drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) override; - void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; - void drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) override; - void drawImageRect( - const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint = - SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint) override; - void drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) override; - void drawImageLattice(const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) override; - void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) override; - void drawPicture(const sk_sp picture, - const SkMatrix* matrix, - bool with_save_layer) override; - void drawDisplayList(const sk_sp display_list) override; - void drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) override; - void drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) override; - - sk_sp Build(); - - private: - SkAutoTMalloc storage_; - size_t used_ = 0; - size_t allocated_ = 0; - int op_count_ = 0; - int save_level_ = 0; - - SkRect cull_; - - template - void* Push(size_t extra, Args&&... args); -}; - -} // namespace flutter - -#endif // FLUTTER_FLOW_DISPLAY_LIST_H_ diff --git a/flow/display_list_canvas.cc b/flow/display_list_canvas.cc deleted file mode 100644 index c6070df8b198a..0000000000000 --- a/flow/display_list_canvas.cc +++ /dev/null @@ -1,481 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/flow/display_list_canvas.h" - -#include "flutter/flow/layers/physical_shape_layer.h" - -#include "third_party/skia/include/core/SkMaskFilter.h" -#include "third_party/skia/include/core/SkTextBlob.h" - -namespace flutter { - -void DisplayListCanvasDispatcher::save() { - canvas_->save(); -} -void DisplayListCanvasDispatcher::restore() { - canvas_->restore(); -} -void DisplayListCanvasDispatcher::saveLayer(const SkRect* bounds, - bool restore_with_paint) { - canvas_->saveLayer(bounds, restore_with_paint ? &paint() : nullptr); -} - -void DisplayListCanvasDispatcher::translate(SkScalar tx, SkScalar ty) { - canvas_->translate(tx, ty); -} -void DisplayListCanvasDispatcher::scale(SkScalar sx, SkScalar sy) { - canvas_->scale(sx, sy); -} -void DisplayListCanvasDispatcher::rotate(SkScalar degrees) { - canvas_->rotate(degrees); -} -void DisplayListCanvasDispatcher::skew(SkScalar sx, SkScalar sy) { - canvas_->skew(sx, sy); -} -void DisplayListCanvasDispatcher::transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) { - canvas_->concat(SkMatrix::MakeAll(mxx, mxy, mxt, myx, myy, myt, 0, 0, 1)); -} -void DisplayListCanvasDispatcher::transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) { - canvas_->concat(SkMatrix::MakeAll(mxx, mxy, mxt, myx, myy, myt, px, py, pt)); -} - -void DisplayListCanvasDispatcher::clipRect(const SkRect& rect, - bool isAA, - SkClipOp clip_op) { - canvas_->clipRect(rect, clip_op, isAA); -} -void DisplayListCanvasDispatcher::clipRRect(const SkRRect& rrect, - bool isAA, - SkClipOp clip_op) { - canvas_->clipRRect(rrect, clip_op, isAA); -} -void DisplayListCanvasDispatcher::clipPath(const SkPath& path, - bool isAA, - SkClipOp clip_op) { - canvas_->clipPath(path, clip_op, isAA); -} - -void DisplayListCanvasDispatcher::drawPaint() { - canvas_->drawPaint(paint()); -} -void DisplayListCanvasDispatcher::drawColor(SkColor color, SkBlendMode mode) { - canvas_->drawColor(color, mode); -} -void DisplayListCanvasDispatcher::drawLine(const SkPoint& p0, - const SkPoint& p1) { - canvas_->drawLine(p0, p1, paint()); -} -void DisplayListCanvasDispatcher::drawRect(const SkRect& rect) { - canvas_->drawRect(rect, paint()); -} -void DisplayListCanvasDispatcher::drawOval(const SkRect& bounds) { - canvas_->drawOval(bounds, paint()); -} -void DisplayListCanvasDispatcher::drawCircle(const SkPoint& center, - SkScalar radius) { - canvas_->drawCircle(center, radius, paint()); -} -void DisplayListCanvasDispatcher::drawRRect(const SkRRect& rrect) { - canvas_->drawRRect(rrect, paint()); -} -void DisplayListCanvasDispatcher::drawDRRect(const SkRRect& outer, - const SkRRect& inner) { - canvas_->drawDRRect(outer, inner, paint()); -} -void DisplayListCanvasDispatcher::drawPath(const SkPath& path) { - canvas_->drawPath(path, paint()); -} -void DisplayListCanvasDispatcher::drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) { - canvas_->drawArc(bounds, start, sweep, useCenter, paint()); -} -void DisplayListCanvasDispatcher::drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) { - canvas_->drawPoints(mode, count, pts, paint()); -} -void DisplayListCanvasDispatcher::drawVertices(const sk_sp vertices, - SkBlendMode mode) { - canvas_->drawVertices(vertices, mode, paint()); -} -void DisplayListCanvasDispatcher::drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) { - canvas_->drawImage(image, point.fX, point.fY, sampling, &paint()); -} -void DisplayListCanvasDispatcher::drawImageRect( - const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint) { - canvas_->drawImageRect(image, src, dst, sampling, &paint(), constraint); -} -void DisplayListCanvasDispatcher::drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) { - canvas_->drawImageNine(image.get(), center, dst, filter, &paint()); -} -void DisplayListCanvasDispatcher::drawImageLattice( - const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) { - canvas_->drawImageLattice(image.get(), lattice, dst, filter, - with_paint ? &paint() : nullptr); -} -void DisplayListCanvasDispatcher::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) { - canvas_->drawAtlas(atlas.get(), xform, tex, colors, count, mode, sampling, - cullRect, &paint()); -} -void DisplayListCanvasDispatcher::drawPicture(const sk_sp picture, - const SkMatrix* matrix, - bool with_save_layer) { - canvas_->drawPicture(picture, matrix, with_save_layer ? &paint() : nullptr); -} -void DisplayListCanvasDispatcher::drawDisplayList( - const sk_sp display_list) { - int save_count = canvas_->save(); - { - DisplayListCanvasDispatcher dispatcher(canvas_); - display_list->Dispatch(dispatcher); - } - canvas_->restoreToCount(save_count); -} -void DisplayListCanvasDispatcher::drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) { - canvas_->drawTextBlob(blob, x, y, paint()); -} -void DisplayListCanvasDispatcher::drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) { - flutter::PhysicalShapeLayer::DrawShadow(canvas_, path, color, elevation, - occludes, 1.0); -} - -DisplayListCanvasRecorder::DisplayListCanvasRecorder(const SkRect& bounds) - : SkCanvasVirtualEnforcer(bounds.width(), bounds.height()), - builder_(sk_make_sp(bounds)) {} - -sk_sp DisplayListCanvasRecorder::Build() { - sk_sp display_list = builder_->Build(); - builder_.reset(); - return display_list; -} - -void DisplayListCanvasRecorder::didConcat44(const SkM44& m44) { - SkMatrix m = m44.asM33(); - if (m.hasPerspective()) { - builder_->transform3x3(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], - m[8]); - } else { - builder_->transform2x3(m[0], m[1], m[2], m[3], m[4], m[5]); - } -} -void DisplayListCanvasRecorder::didTranslate(SkScalar tx, SkScalar ty) { - builder_->translate(tx, ty); -} -void DisplayListCanvasRecorder::didScale(SkScalar sx, SkScalar sy) { - builder_->scale(sx, sy); -} - -void DisplayListCanvasRecorder::onClipRect(const SkRect& rect, - SkClipOp clip_op, - ClipEdgeStyle edgeStyle) { - builder_->clipRect(rect, edgeStyle == ClipEdgeStyle::kSoft_ClipEdgeStyle, - clip_op); -} -void DisplayListCanvasRecorder::onClipRRect(const SkRRect& rrect, - SkClipOp clip_op, - ClipEdgeStyle edgeStyle) { - builder_->clipRRect(rrect, edgeStyle == ClipEdgeStyle::kSoft_ClipEdgeStyle, - clip_op); -} -void DisplayListCanvasRecorder::onClipPath(const SkPath& path, - SkClipOp clip_op, - ClipEdgeStyle edgeStyle) { - builder_->clipPath(path, edgeStyle == ClipEdgeStyle::kSoft_ClipEdgeStyle, - clip_op); -} - -void DisplayListCanvasRecorder::willSave() { - builder_->save(); -} -SkCanvas::SaveLayerStrategy DisplayListCanvasRecorder::getSaveLayerStrategy( - const SaveLayerRec& rec) { - if (rec.fPaint) { - RecordPaintAttributes(rec.fPaint, DrawType::kSaveLayerOpType); - builder_->saveLayer(rec.fBounds, true); - } else { - builder_->saveLayer(rec.fBounds, false); - } - return SaveLayerStrategy::kNoLayer_SaveLayerStrategy; -} -void DisplayListCanvasRecorder::didRestore() { - builder_->restore(); -} - -void DisplayListCanvasRecorder::onDrawPaint(const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kFillOpType); - builder_->drawPaint(); -} -void DisplayListCanvasRecorder::onDrawRect(const SkRect& rect, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawRect(rect); -} -void DisplayListCanvasRecorder::onDrawRRect(const SkRRect& rrect, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawRRect(rrect); -} -void DisplayListCanvasRecorder::onDrawDRRect(const SkRRect& outer, - const SkRRect& inner, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawDRRect(outer, inner); -} -void DisplayListCanvasRecorder::onDrawOval(const SkRect& rect, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawOval(rect); -} -void DisplayListCanvasRecorder::onDrawArc(const SkRect& rect, - SkScalar startAngle, - SkScalar sweepAngle, - bool useCenter, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawArc(rect, startAngle, sweepAngle, useCenter); -} -void DisplayListCanvasRecorder::onDrawPath(const SkPath& path, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawPath(path); -} - -void DisplayListCanvasRecorder::onDrawPoints(SkCanvas::PointMode mode, - size_t count, - const SkPoint pts[], - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kStrokeOpType); - if (mode == SkCanvas::PointMode::kLines_PointMode && count == 2) { - builder_->drawLine(pts[0], pts[1]); - } else { - uint32_t count32 = static_cast(count); - // TODO(flar): depending on the mode we could break it down into - // multiple calls to drawPoints, but how much do we really want - // to support more than a couple billion points? - FML_DCHECK(count32 == count); - builder_->drawPoints(mode, count32, pts); - } -} -void DisplayListCanvasRecorder::onDrawVerticesObject(const SkVertices* vertices, - SkBlendMode mode, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawVertices(sk_ref_sp(vertices), mode); -} - -void DisplayListCanvasRecorder::onDrawImage2(const SkImage* image, - SkScalar dx, - SkScalar dy, - const SkSamplingOptions& sampling, - const SkPaint* paint) { - RecordPaintAttributes(paint, DrawType::kImageOpType); - builder_->drawImage(sk_ref_sp(image), SkPoint::Make(dx, dy), sampling); -} -void DisplayListCanvasRecorder::onDrawImageRect2( - const SkImage* image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - const SkPaint* paint, - SrcRectConstraint constraint) { - RecordPaintAttributes(paint, DrawType::kImageRectOpType); - builder_->drawImageRect(sk_ref_sp(image), src, dst, sampling, constraint); -} -void DisplayListCanvasRecorder::onDrawImageLattice2(const SkImage* image, - const Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - const SkPaint* paint) { - if (paint != nullptr) { - // SkCanvas will always construct a paint, - // though it is a default paint most of the time - SkPaint default_paint; - if (*paint == default_paint) { - paint = nullptr; - } else { - RecordPaintAttributes(paint, DrawType::kImageOpType); - } - } - builder_->drawImageLattice(sk_ref_sp(image), lattice, dst, filter, - paint != nullptr); -} -void DisplayListCanvasRecorder::onDrawAtlas2(const SkImage* image, - const SkRSXform xform[], - const SkRect src[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cull, - const SkPaint* paint) { - RecordPaintAttributes(paint, DrawType::kImageOpType); - builder_->drawAtlas(sk_ref_sp(image), xform, src, colors, count, mode, - sampling, cull); -} - -void DisplayListCanvasRecorder::onDrawTextBlob(const SkTextBlob* blob, - SkScalar x, - SkScalar y, - const SkPaint& paint) { - RecordPaintAttributes(&paint, DrawType::kDrawOpType); - builder_->drawTextBlob(sk_ref_sp(blob), x, y); -} -void DisplayListCanvasRecorder::onDrawShadowRec(const SkPath& path, - const SkDrawShadowRec& rec) { - // Skia does not expose the SkDrawShadowRec structure in a public - // header file so we cannot record this operation. - // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 - FML_DCHECK(false); -} - -void DisplayListCanvasRecorder::onDrawPicture(const SkPicture* picture, - const SkMatrix* matrix, - const SkPaint* paint) { - if (paint) { - RecordPaintAttributes(paint, DrawType::kSaveLayerOpType); - } - builder_->drawPicture(sk_ref_sp(picture), matrix, paint != nullptr); -} - -void DisplayListCanvasRecorder::RecordPaintAttributes(const SkPaint* paint, - DrawType type) { - int dataNeeded; - switch (type) { - case DrawType::kDrawOpType: - dataNeeded = kDrawMask_; - break; - case DrawType::kFillOpType: - dataNeeded = kPaintMask_; - break; - case DrawType::kStrokeOpType: - dataNeeded = kStrokeMask_; - break; - case DrawType::kImageOpType: - dataNeeded = kImageMask_; - break; - case DrawType::kImageRectOpType: - dataNeeded = kImageRectMask_; - break; - case DrawType::kSaveLayerOpType: - dataNeeded = kSaveLayerMask_; - break; - default: - FML_DCHECK(false); - return; - } - if (paint == nullptr) { - paint = new SkPaint(); - } - if ((dataNeeded & kAaNeeded_) != 0 && current_aa_ != paint->isAntiAlias()) { - builder_->setAA(current_aa_ = paint->isAntiAlias()); - } - if ((dataNeeded & kDitherNeeded_) != 0 && - current_dither_ != paint->isDither()) { - builder_->setDither(current_dither_ = paint->isDither()); - } - if ((dataNeeded & kColorNeeded_) != 0 && - current_color_ != paint->getColor()) { - builder_->setColor(current_color_ = paint->getColor()); - } - if ((dataNeeded & kBlendNeeded_) != 0 && - current_blend_ != paint->getBlendMode()) { - builder_->setBlendMode(current_blend_ = paint->getBlendMode()); - } - // invert colors is a Flutter::Paint thing, not an SkPaint thing - // if ((dataNeeded & invertColorsNeeded_) != 0 && - // currentInvertColors_ != paint->???) { - // currentInvertColors_ = paint->invertColors; - // addOp_(currentInvertColors_ - // ? _CanvasOp.setInvertColors - // : _CanvasOp.clearInvertColors, 0); - // } - if ((dataNeeded & kPaintStyleNeeded_) != 0) { - if (current_style_ != paint->getStyle()) { - builder_->setDrawStyle(current_style_ = paint->getStyle()); - } - if (current_style_ == SkPaint::Style::kStroke_Style) { - dataNeeded |= kStrokeStyleNeeded_; - } - } - if ((dataNeeded & kStrokeStyleNeeded_) != 0) { - if (current_stroke_width_ != paint->getStrokeWidth()) { - builder_->setStrokeWidth(current_stroke_width_ = paint->getStrokeWidth()); - } - if (current_cap_ != paint->getStrokeCap()) { - builder_->setCaps(current_cap_ = paint->getStrokeCap()); - } - if (current_join_ != paint->getStrokeJoin()) { - builder_->setJoins(current_join_ = paint->getStrokeJoin()); - } - if (current_miter_limit_ != paint->getStrokeMiter()) { - builder_->setMiterLimit(current_miter_limit_ = paint->getStrokeMiter()); - } - } - if ((dataNeeded & kFilterQualityNeeded_) != 0 && - current_fq_ != paint->getFilterQuality()) { - builder_->setFilterQuality(current_fq_ = paint->getFilterQuality()); - } - if ((dataNeeded & kShaderNeeded_) != 0 && - current_shader_.get() != paint->getShader()) { - builder_->setShader(current_shader_ = sk_ref_sp(paint->getShader())); - } - if ((dataNeeded & kColorFilterNeeded_) != 0 && - current_color_filter_.get() != paint->getColorFilter()) { - builder_->setColorFilter(current_color_filter_ = - sk_ref_sp(paint->getColorFilter())); - } - if ((dataNeeded & kImageFilterNeeded_) != 0 && - current_image_filter_.get() != paint->getImageFilter()) { - builder_->setImageFilter(current_image_filter_ = - sk_ref_sp(paint->getImageFilter())); - } - if ((dataNeeded & kMaskFilterNeeded_) != 0 && - current_mask_filter_.get() != paint->getMaskFilter()) { - builder_->setMaskFilter(current_mask_filter_ = - sk_ref_sp(paint->getMaskFilter())); - } -} - -} // namespace flutter diff --git a/flow/display_list_canvas.h b/flow/display_list_canvas.h deleted file mode 100644 index da535a7d26635..0000000000000 --- a/flow/display_list_canvas.h +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_FLOW_DISPLAY_LIST_CANVAS_H_ -#define FLUTTER_FLOW_DISPLAY_LIST_CANVAS_H_ - -#include "flutter/flow/display_list.h" -#include "flutter/flow/display_list_utils.h" -#include "flutter/fml/logging.h" - -#include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" -#include "third_party/skia/include/utils/SkNoDrawCanvas.h" - -// Classes to interact between SkCanvas and DisplayList, including: -// DisplayListCanvasDispatcher: -// Can be fed to the dispatch() method of a DisplayList to feed -// the resulting rendering operations to an SkCanvas instance. -// DisplayListCanvasRecorder -// An adapter that implements an SkCanvas interface which can -// then be handed to code that outputs to an SkCanvas to capture -// the output into a Flutter DisplayList. - -namespace flutter { - -// Receives all methods on Dispatcher and sends them to an SkCanvas -class DisplayListCanvasDispatcher : public virtual Dispatcher, - public SkPaintDispatchHelper { - public: - DisplayListCanvasDispatcher(SkCanvas* canvas) : canvas_(canvas) {} - - void save() override; - void restore() override; - void saveLayer(const SkRect* bounds, bool restore_with_paint) override; - - void translate(SkScalar tx, SkScalar ty) override; - void scale(SkScalar sx, SkScalar sy) override; - void rotate(SkScalar degrees) override; - void skew(SkScalar sx, SkScalar sy) override; - void transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) override; - void transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) override; - - void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) override; - void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) override; - void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) override; - - void drawPaint() override; - void drawColor(SkColor color, SkBlendMode mode) override; - void drawLine(const SkPoint& p0, const SkPoint& p1) override; - void drawRect(const SkRect& rect) override; - void drawOval(const SkRect& bounds) override; - void drawCircle(const SkPoint& center, SkScalar radius) override; - void drawRRect(const SkRRect& rrect) override; - void drawDRRect(const SkRRect& outer, const SkRRect& inner) override; - void drawPath(const SkPath& path) override; - void drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) override; - void drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) override; - void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; - void drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) override; - void drawImageRect(const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint) override; - void drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) override; - void drawImageLattice(const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) override; - void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) override; - void drawPicture(const sk_sp picture, - const SkMatrix* matrix, - bool with_save_layer) override; - void drawDisplayList(const sk_sp display_list) override; - void drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) override; - void drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) override; - - private: - SkCanvas* canvas_; -}; - -// Receives all methods on SkCanvas and sends them to a DisplayListBuilder -class DisplayListCanvasRecorder - : public SkCanvasVirtualEnforcer, - public SkRefCnt { - public: - DisplayListCanvasRecorder(const SkRect& bounds); - - const sk_sp builder() { return builder_; } - - sk_sp Build(); - - void didConcat44(const SkM44&) override; - void didSetM44(const SkM44&) override { FML_DCHECK(false); } - void didTranslate(SkScalar, SkScalar) override; - void didScale(SkScalar, SkScalar) override; - - void onClipRect(const SkRect& rect, - SkClipOp op, - ClipEdgeStyle edgeStyle) override; - void onClipRRect(const SkRRect& rrect, - SkClipOp op, - ClipEdgeStyle edgeStyle) override; - void onClipPath(const SkPath& path, - SkClipOp op, - ClipEdgeStyle edgeStyle) override; - - void willSave() override; - SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override; - void didRestore() override; - - void onDrawPaint(const SkPaint& paint) override; - void onDrawBehind(const SkPaint&) override { FML_DCHECK(false); } - void onDrawRect(const SkRect& rect, const SkPaint& paint) override; - void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override; - void onDrawDRRect(const SkRRect& outer, - const SkRRect& inner, - const SkPaint& paint) override; - void onDrawOval(const SkRect& rect, const SkPaint& paint) override; - void onDrawArc(const SkRect& rect, - SkScalar startAngle, - SkScalar sweepAngle, - bool useCenter, - const SkPaint& paint) override; - void onDrawPath(const SkPath& path, const SkPaint& paint) override; - void onDrawRegion(const SkRegion& region, const SkPaint& paint) override { - FML_DCHECK(false); - } - - void onDrawTextBlob(const SkTextBlob* blob, - SkScalar x, - SkScalar y, - const SkPaint& paint) override; - - void onDrawPatch(const SkPoint cubics[12], - const SkColor colors[4], - const SkPoint texCoords[4], - SkBlendMode mode, - const SkPaint& paint) override { - FML_DCHECK(false); - } - void onDrawPoints(SkCanvas::PointMode mode, - size_t count, - const SkPoint pts[], - const SkPaint& paint) override; - void onDrawVerticesObject(const SkVertices* vertices, - SkBlendMode mode, - const SkPaint& paint) override; - - void onDrawImage2(const SkImage*, - SkScalar dx, - SkScalar dy, - const SkSamplingOptions&, - const SkPaint*) override; - void onDrawImageRect2(const SkImage*, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions&, - const SkPaint*, - SrcRectConstraint) override; - void onDrawImageLattice2(const SkImage*, - const Lattice&, - const SkRect& dst, - SkFilterMode, - const SkPaint*) override; - void onDrawAtlas2(const SkImage*, - const SkRSXform[], - const SkRect src[], - const SkColor[], - int count, - SkBlendMode, - const SkSamplingOptions&, - const SkRect* cull, - const SkPaint*) override; - - void onDrawEdgeAAQuad(const SkRect& rect, - const SkPoint clip[4], - SkCanvas::QuadAAFlags aaFlags, - const SkColor4f& color, - SkBlendMode mode) override { - FML_DCHECK(0); - } - - void onDrawAnnotation(const SkRect& rect, - const char key[], - SkData* value) override { - FML_DCHECK(false); - } - void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override; - - void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override { - FML_DCHECK(false); - } - void onDrawPicture(const SkPicture* picture, - const SkMatrix* matrix, - const SkPaint* paint) override; - - enum class DrawType { - // The operation will be an image operation - kImageOpType, - // The operation will be an imageRect operation - kImageRectOpType, - // The operation will be a fill or stroke depending on the paint.style - kDrawOpType, - // The operation will be a fill (ignoring paint.style) - kFillOpType, - // The operation will be a stroke (ignoring paint.style) - kStrokeOpType, - // The operation will be a saveLayer with a paint object - kSaveLayerOpType, - }; - - void RecordPaintAttributes(const SkPaint* paint, DrawType type); - - private: - sk_sp builder_; - - // Mask bits for the various attributes that might be needed for a given - // operation. - // clang-format off - static constexpr int kAaNeeded_ = 1 << 0; - static constexpr int kColorNeeded_ = 1 << 1; - static constexpr int kBlendNeeded_ = 1 << 2; - static constexpr int kInvertColorsNeeded_ = 1 << 3; - static constexpr int kFilterQualityNeeded_ = 1 << 4; - static constexpr int kPaintStyleNeeded_ = 1 << 5; - static constexpr int kStrokeStyleNeeded_ = 1 << 6; - static constexpr int kShaderNeeded_ = 1 << 7; - static constexpr int kColorFilterNeeded_ = 1 << 8; - static constexpr int kImageFilterNeeded_ = 1 << 9; - static constexpr int kMaskFilterNeeded_ = 1 << 10; - static constexpr int kDitherNeeded_ = 1 << 11; - // clang-format on - - // Combinations of the above mask bits that are common to typical "draw" - // calls. - // Note that the strokeStyle_ is handled conditionally depending on whether - // the paintStyle_ attribute value is synchronized. It can also be manually - // specified for operations that will be always stroking, like [drawLine]. - static constexpr int kPaintMask_ = kAaNeeded_ | kColorNeeded_ | - kBlendNeeded_ | kInvertColorsNeeded_ | - kColorFilterNeeded_ | kShaderNeeded_ | - kDitherNeeded_ | kImageFilterNeeded_; - static constexpr int kDrawMask_ = - kPaintMask_ | kPaintStyleNeeded_ | kMaskFilterNeeded_; - static constexpr int kStrokeMask_ = - kPaintMask_ | kStrokeStyleNeeded_ | kMaskFilterNeeded_; - static constexpr int kImageMask_ = - kColorNeeded_ | kBlendNeeded_ | kInvertColorsNeeded_ | - kColorFilterNeeded_ | kDitherNeeded_ | kImageFilterNeeded_ | - kFilterQualityNeeded_ | kMaskFilterNeeded_; - static constexpr int kImageRectMask_ = kImageMask_ | kAaNeeded_; - static constexpr int kSaveLayerMask_ = - kColorNeeded_ | kBlendNeeded_ | kInvertColorsNeeded_ | - kColorFilterNeeded_ | kImageFilterNeeded_; - - bool current_aa_ = false; - bool current_dither_ = false; - SkColor current_color_ = 0xFF000000; - SkBlendMode current_blend_ = SkBlendMode::kSrcOver; - SkPaint::Style current_style_ = SkPaint::Style::kFill_Style; - SkScalar current_stroke_width_ = 0.0; - SkScalar current_miter_limit_ = 4.0; - SkPaint::Cap current_cap_ = SkPaint::Cap::kButt_Cap; - SkPaint::Join current_join_ = SkPaint::Join::kMiter_Join; - SkFilterQuality current_fq_ = SkFilterQuality::kNone_SkFilterQuality; - sk_sp current_shader_; - sk_sp current_color_filter_; - sk_sp current_image_filter_; - sk_sp current_mask_filter_; -}; - -} // namespace flutter - -#endif // FLUTTER_FLOW_DISPLAY_LIST_CANVAS_H_ diff --git a/flow/display_list_canvas_unittests.cc b/flow/display_list_canvas_unittests.cc deleted file mode 100644 index cd2f6ff88e620..0000000000000 --- a/flow/display_list_canvas_unittests.cc +++ /dev/null @@ -1,1296 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/flow/display_list_canvas.h" -#include "flutter/flow/layers/physical_shape_layer.h" - -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkImageInfo.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" -#include "third_party/skia/include/core/SkRRect.h" -#include "third_party/skia/include/core/SkRSXform.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/core/SkTextBlob.h" -#include "third_party/skia/include/core/SkVertices.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "third_party/skia/include/effects/SkImageFilters.h" - -#include - -#include "gtest/gtest.h" - -namespace flutter { -namespace testing { - -constexpr int TestWidth = 200; -constexpr int TestHeight = 200; -constexpr int RenderWidth = 100; -constexpr int RenderHeight = 100; -constexpr int RenderLeft = (TestWidth - RenderWidth) / 2; -constexpr int RenderTop = (TestHeight - RenderHeight) / 2; -constexpr int RenderRight = RenderLeft + RenderWidth; -constexpr int RenderBottom = RenderTop + RenderHeight; -constexpr int RenderCenterX = (RenderLeft + RenderRight) / 2; -constexpr int RenderCenterY = (RenderTop + RenderBottom) / 2; -constexpr SkScalar RenderRadius = std::min(RenderWidth, RenderHeight) / 2.0; -constexpr SkScalar RenderCornerRadius = RenderRadius / 5.0; - -constexpr SkPoint TestCenter = SkPoint::Make(TestWidth / 2, TestHeight / 2); -constexpr SkRect TestBounds = SkRect::MakeWH(TestWidth, TestHeight); -constexpr SkRect RenderBounds = - SkRect::MakeLTRB(RenderLeft, RenderTop, RenderRight, RenderBottom); - -class CanvasCompareTester { - public: - // If a test is using any shadow operations then we cannot currently - // record those in an SkCanvas and play it back into a DisplayList - // because internally the operation gets encapsulated in a Skia - // ShadowRec which is not exposed by their headers. For operations - // that use shadows, we can perform a lot of tests, but not the tests - // that require SkCanvas->DisplayList transfers. - // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 - static bool UsingShadows; - - typedef const std::function CvRenderer; - typedef const std::function DlRenderer; - - static void RenderAll(CvRenderer& cv_renderer, DlRenderer& dl_renderer) { - RenderWithAttributes(cv_renderer, dl_renderer); - RenderWithTransforms(cv_renderer, dl_renderer); - RenderWithClips(cv_renderer, dl_renderer); - } - - static void RenderNoAttributes(CvRenderer& cv_renderer, - DlRenderer& dl_renderer) { - RenderWith([=](SkCanvas*, SkPaint& p) {}, // - [=](DisplayListBuilder& d) {}, // - cv_renderer, dl_renderer, "Base Test"); - RenderWithTransforms(cv_renderer, dl_renderer); - RenderWithClips(cv_renderer, dl_renderer); - } - - static void RenderWithSaveRestore(CvRenderer& cv_renderer, - DlRenderer& dl_renderer) { - SkRect clip = SkRect::MakeLTRB(0, 0, 10, 10); - SkRect rect = SkRect::MakeLTRB(5, 5, 15, 15); - SkColor save_layer_color = SkColorSetARGB(0x7f, 0x00, 0xff, 0xff); - RenderWith( - [=](SkCanvas* cv, SkPaint& p) { - cv->save(); - cv->clipRect(clip, SkClipOp::kIntersect, false); - cv->drawRect(rect, p); - cv->restore(); - }, - [=](DisplayListBuilder& b) { - b.save(); - b.clipRect(clip, false, SkClipOp::kIntersect); - b.drawRect(rect); - b.restore(); - }, - cv_renderer, dl_renderer, "With prior save/clip/restore"); - RenderWith( - [=](SkCanvas* cv, SkPaint& p) { - SkPaint save_p; - save_p.setColor(save_layer_color); - cv->saveLayer(RenderBounds, &save_p); - cv->drawRect(rect, p); - }, - [=](DisplayListBuilder& b) { - b.setColor(save_layer_color); - b.saveLayer(&RenderBounds, true); - b.setColor(SkPaint().getColor()); - b.drawRect(rect); - }, - cv_renderer, dl_renderer, "With saveLayer"); - } - - static void RenderWithAttributes(CvRenderer& cv_renderer, - DlRenderer& dl_renderer) { - RenderWith([=](SkCanvas*, SkPaint& p) {}, // - [=](DisplayListBuilder& d) {}, // - cv_renderer, dl_renderer, "Base Test"); - - RenderWith([=](SkCanvas*, SkPaint& p) { p.setAntiAlias(true); }, // - [=](DisplayListBuilder& b) { b.setAA(true); }, // - cv_renderer, dl_renderer, "AA == True"); - RenderWith([=](SkCanvas*, SkPaint& p) { p.setAntiAlias(false); }, // - [=](DisplayListBuilder& b) { b.setAA(false); }, // - cv_renderer, dl_renderer, "AA == False"); - - RenderWith([=](SkCanvas*, SkPaint& p) { p.setDither(true); }, // - [=](DisplayListBuilder& b) { b.setDither(true); }, // - cv_renderer, dl_renderer, "Dither == True"); - RenderWith([=](SkCanvas*, SkPaint& p) { p.setDither(false); }, // - [=](DisplayListBuilder& b) { b.setDither(false); }, // - cv_renderer, dl_renderer, "Dither = False"); - - RenderWith([=](SkCanvas*, SkPaint& p) { p.setColor(SK_ColorBLUE); }, // - [=](DisplayListBuilder& b) { b.setColor(SK_ColorBLUE); }, // - cv_renderer, dl_renderer, "Color == Blue"); - RenderWith([=](SkCanvas*, SkPaint& p) { p.setColor(SK_ColorGREEN); }, // - [=](DisplayListBuilder& b) { b.setColor(SK_ColorGREEN); }, // - cv_renderer, dl_renderer, "Color == Green"); - - RenderWithStrokes(cv_renderer, dl_renderer); - - // Not testing FilterQuality here because there is no SkPaint version - - { - // half opaque cyan - SkColor blendableColor = SkColorSetARGB(0x7f, 0x00, 0xff, 0xff); - SkColor bg = SK_ColorWHITE; - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setBlendMode(SkBlendMode::kSrcIn); - p.setColor(blendableColor); - }, - [=](DisplayListBuilder& b) { - b.setBlendMode(SkBlendMode::kSrcIn); - b.setColor(blendableColor); - }, - cv_renderer, dl_renderer, "Blend == SrcIn", &bg); - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setBlendMode(SkBlendMode::kDstIn); - p.setColor(blendableColor); - }, - [=](DisplayListBuilder& b) { - b.setBlendMode(SkBlendMode::kDstIn); - b.setColor(blendableColor); - }, - cv_renderer, dl_renderer, "Blend == DstIn", &bg); - } - - { - sk_sp filter = - SkImageFilters::Blur(5.0, 5.0, SkTileMode::kDecal, nullptr, nullptr); - { - RenderWith([=](SkCanvas*, SkPaint& p) { p.setImageFilter(filter); }, - [=](DisplayListBuilder& b) { b.setImageFilter(filter); }, - cv_renderer, dl_renderer, "ImageFilter == Decal Blur 5"); - } - ASSERT_TRUE(filter->unique()) << "ImageFilter Cleanup"; - } - - { - // clang-format off - constexpr float rotate_color_matrix[20] = { - 0, 1, 0, 0, 0, - 0, 0, 1, 0, 0, - 1, 0, 0, 0, 0, - 0, 0, 0, 1, 0, - }; - constexpr float invert_color_matrix[20] = { - -1.0, 0, 0, 1.0, 0, - 0, -1.0, 0, 1.0, 0, - 0, 0, -1.0, 1.0, 0, - 1.0, 1.0, 1.0, 1.0, 0, - }; - // clang-format on - sk_sp filter = SkColorFilters::Matrix(rotate_color_matrix); - { - SkColor bg = SK_ColorWHITE; - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setColor(SK_ColorYELLOW); - p.setColorFilter(filter); - }, - [=](DisplayListBuilder& b) { - b.setColor(SK_ColorYELLOW); - b.setColorFilter(filter); - }, - cv_renderer, dl_renderer, "ColorFilter == RotateRGB", &bg); - } - ASSERT_TRUE(filter->unique()) << "ColorFilter Cleanup"; - filter = SkColorFilters::Matrix(invert_color_matrix); - { - SkColor bg = SK_ColorWHITE; - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setColor(SK_ColorYELLOW); - p.setColorFilter(filter); - }, - [=](DisplayListBuilder& b) { - b.setColor(SK_ColorYELLOW); - b.setInvertColors(true); - }, - cv_renderer, dl_renderer, "ColorFilter == Invert", &bg); - } - ASSERT_TRUE(filter->unique()) << "ColorFilter Cleanup"; - } - - { - sk_sp filter = - SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5.0); - { - RenderWith([=](SkCanvas*, SkPaint& p) { p.setMaskFilter(filter); }, - [=](DisplayListBuilder& b) { b.setMaskFilter(filter); }, - cv_renderer, dl_renderer, "MaskFilter == Blur 5"); - } - ASSERT_TRUE(filter->unique()) << "MaskFilter Cleanup"; - { - RenderWith([=](SkCanvas*, SkPaint& p) { p.setMaskFilter(filter); }, - [=](DisplayListBuilder& b) { - b.setMaskBlurFilter(kNormal_SkBlurStyle, 5.0); - }, - cv_renderer, dl_renderer, "MaskFilter == Blur(Normal, 5.0)"); - } - ASSERT_TRUE(filter->unique()) << "MaskFilter Cleanup"; - } - - { - SkPoint end_points[] = { - SkPoint::Make(RenderBounds.fLeft, RenderBounds.fTop), - SkPoint::Make(RenderBounds.fRight, RenderBounds.fBottom), - }; - SkColor colors[] = { - SK_ColorGREEN, - SK_ColorYELLOW, - SK_ColorBLUE, - }; - float stops[] = { - 0.0, - 0.5, - 1.0, - }; - sk_sp shader = SkGradientShader::MakeLinear( - end_points, colors, stops, 3, SkTileMode::kMirror, 0, nullptr); - { - RenderWith([=](SkCanvas*, SkPaint& p) { p.setShader(shader); }, - [=](DisplayListBuilder& b) { b.setShader(shader); }, - cv_renderer, dl_renderer, "LinearGradient GYB"); - } - ASSERT_TRUE(shader->unique()) << "Shader Cleanup"; - } - } - - static void RenderWithStrokes(CvRenderer& cv_renderer, - DlRenderer& dl_renderer) { - RenderWith( - [=](SkCanvas*, SkPaint& p) { p.setStyle(SkPaint::kFill_Style); }, - [=](DisplayListBuilder& b) { b.setDrawStyle(SkPaint::kFill_Style); }, - cv_renderer, dl_renderer, "Fill"); - RenderWith( - [=](SkCanvas*, SkPaint& p) { p.setStyle(SkPaint::kStroke_Style); }, - [=](DisplayListBuilder& b) { b.setDrawStyle(SkPaint::kStroke_Style); }, - cv_renderer, dl_renderer, "Stroke + defaults"); - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kFill_Style); - p.setStrokeWidth(10.0); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kFill_Style); - b.setStrokeWidth(10.0); - }, - cv_renderer, dl_renderer, "Fill + unnecessary StrokeWidth 10"); - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(10.0); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(10.0); - }, - cv_renderer, dl_renderer, "Stroke Width 10"); - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - }, - cv_renderer, dl_renderer, "Stroke Width 5"); - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - p.setStrokeCap(SkPaint::kButt_Cap); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - b.setCaps(SkPaint::kButt_Cap); - }, - cv_renderer, dl_renderer, "Stroke Width 5, Butt Cap"); - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - p.setStrokeCap(SkPaint::kRound_Cap); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - b.setCaps(SkPaint::kRound_Cap); - }, - cv_renderer, dl_renderer, "Stroke Width 5, Round Cap"); - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - p.setStrokeJoin(SkPaint::kBevel_Join); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - b.setJoins(SkPaint::kBevel_Join); - }, - cv_renderer, dl_renderer, "Stroke Width 5, Bevel Join"); - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - p.setStrokeJoin(SkPaint::kRound_Join); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - b.setJoins(SkPaint::kRound_Join); - }, - cv_renderer, dl_renderer, "Stroke Width 5, Round Join"); - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - p.setStrokeMiter(100.0); - p.setStrokeJoin(SkPaint::kMiter_Join); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - b.setMiterLimit(100.0); - b.setJoins(SkPaint::kMiter_Join); - }, - cv_renderer, dl_renderer, "Stroke Width 5, Miter 100"); - - RenderWith( - [=](SkCanvas*, SkPaint& p) { - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(5.0); - p.setStrokeMiter(0.0); - p.setStrokeJoin(SkPaint::kMiter_Join); - }, - [=](DisplayListBuilder& b) { - b.setDrawStyle(SkPaint::kStroke_Style); - b.setStrokeWidth(5.0); - b.setMiterLimit(0.0); - b.setJoins(SkPaint::kMiter_Join); - }, - cv_renderer, dl_renderer, "Stroke Width 5, Miter 0"); - } - - static void RenderWithTransforms(CvRenderer& cv_renderer, - DlRenderer& dl_renderer) { - RenderWith([=](SkCanvas* c, SkPaint&) { c->translate(5, 10); }, // - [=](DisplayListBuilder& b) { b.translate(5, 10); }, // - cv_renderer, dl_renderer, "Translate 5, 10"); - RenderWith([=](SkCanvas* c, SkPaint&) { c->scale(0.95, 0.95); }, // - [=](DisplayListBuilder& b) { b.scale(0.95, 0.95); }, // - cv_renderer, dl_renderer, "Scale 95%"); - RenderWith([=](SkCanvas* c, SkPaint&) { c->rotate(5); }, // - [=](DisplayListBuilder& b) { b.rotate(5); }, // - cv_renderer, dl_renderer, "Rotate 5 degrees"); - RenderWith([=](SkCanvas* c, SkPaint&) { c->skew(0.05, 0.05); }, // - [=](DisplayListBuilder& b) { b.skew(0.05, 0.05); }, // - cv_renderer, dl_renderer, "Skew 5%"); - { - SkMatrix tx = SkMatrix::MakeAll(1.1, 0.1, 1.05, 0.05, 1, 1, 0, 0, 1); - RenderWith([=](SkCanvas* c, SkPaint&) { c->concat(tx); }, // - [=](DisplayListBuilder& b) { - b.transform2x3(tx[0], tx[1], tx[2], // - tx[3], tx[4], tx[5]); - }, // - cv_renderer, dl_renderer, "Transform 2x3"); - } - { - SkMatrix tx = SkMatrix::MakeAll(1.1, 0.1, 1.05, 0.05, 1, 1, 0, 0, 1.01); - RenderWith([=](SkCanvas* c, SkPaint&) { c->concat(tx); }, // - [=](DisplayListBuilder& b) { - b.transform3x3(tx[0], tx[1], tx[2], // - tx[3], tx[4], tx[5], // - tx[6], tx[7], tx[8]); - }, // - cv_renderer, dl_renderer, "Transform 3x3"); - } - } - - static void RenderWithClips(CvRenderer& cv_renderer, - DlRenderer& dl_renderer) { - SkRect r_clip = RenderBounds.makeInset(15.5, 15.5); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipRect(r_clip, SkClipOp::kIntersect, false); - }, - [=](DisplayListBuilder& b) { - b.clipRect(r_clip, false, SkClipOp::kIntersect); - }, - cv_renderer, dl_renderer, "Hard ClipRect inset by 15.5"); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipRect(r_clip, SkClipOp::kIntersect, true); - }, - [=](DisplayListBuilder& b) { - b.clipRect(r_clip, true, SkClipOp::kIntersect); - }, - cv_renderer, dl_renderer, "AA ClipRect inset by 15.5"); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipRect(r_clip, SkClipOp::kDifference, false); - }, - [=](DisplayListBuilder& b) { - b.clipRect(r_clip, false, SkClipOp::kDifference); - }, - cv_renderer, dl_renderer, "Hard ClipRect Diff, inset by 15.5"); - SkRRect rr_clip = SkRRect::MakeRectXY(r_clip, 1.8, 2.7); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipRRect(rr_clip, SkClipOp::kIntersect, false); - }, - [=](DisplayListBuilder& b) { - b.clipRRect(rr_clip, false, SkClipOp::kIntersect); - }, - cv_renderer, dl_renderer, "Hard ClipRRect inset by 15.5"); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipRRect(rr_clip, SkClipOp::kIntersect, true); - }, - [=](DisplayListBuilder& b) { - b.clipRRect(rr_clip, true, SkClipOp::kIntersect); - }, - cv_renderer, dl_renderer, "AA ClipRRect inset by 15.5"); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipRRect(rr_clip, SkClipOp::kDifference, false); - }, - [=](DisplayListBuilder& b) { - b.clipRRect(rr_clip, false, SkClipOp::kDifference); - }, - cv_renderer, dl_renderer, "Hard ClipRRect Diff, inset by 15.5"); - SkPath path_clip = SkPath(); - path_clip.setFillType(SkPathFillType::kEvenOdd); - path_clip.addRect(r_clip); - path_clip.addCircle(RenderCenterX, RenderCenterY, 1.0); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipPath(path_clip, SkClipOp::kIntersect, false); - }, - [=](DisplayListBuilder& b) { - b.clipPath(path_clip, false, SkClipOp::kIntersect); - }, - cv_renderer, dl_renderer, "Hard ClipPath inset by 15.5"); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipPath(path_clip, SkClipOp::kIntersect, true); - }, - [=](DisplayListBuilder& b) { - b.clipPath(path_clip, true, SkClipOp::kIntersect); - }, - cv_renderer, dl_renderer, "AA ClipPath inset by 15.5"); - RenderWith( - [=](SkCanvas* c, SkPaint&) { - c->clipPath(path_clip, SkClipOp::kDifference, false); - }, - [=](DisplayListBuilder& b) { - b.clipPath(path_clip, false, SkClipOp::kDifference); - }, - cv_renderer, dl_renderer, "Hard ClipPath Diff, inset by 15.5"); - } - - static SkRect getSkBounds(CvRenderer& cv_setup, CvRenderer& cv_render) { - SkPictureRecorder recorder; - SkRTreeFactory rtree_factory; - SkCanvas* cv = recorder.beginRecording(TestBounds, &rtree_factory); - SkPaint p; - cv_setup(cv, p); - cv_render(cv, p); - return recorder.finishRecordingAsPicture()->cullRect(); - } - - static void RenderWith(CvRenderer& cv_setup, - DlRenderer& dl_setup, - CvRenderer& cv_render, - DlRenderer& dl_render, - const std::string info, - const SkColor* bg = nullptr) { - // surface1 is direct rendering via SkCanvas to SkSurface - // DisplayList mechanisms are not involved in this operation - sk_sp ref_surface = makeSurface(bg); - SkPaint paint1; - cv_setup(ref_surface->getCanvas(), paint1); - cv_render(ref_surface->getCanvas(), paint1); - SkRect ref_bounds = getSkBounds(cv_setup, cv_render); - SkPixmap ref_pixels; - ASSERT_TRUE(ref_surface->peekPixels(&ref_pixels)) << info; - ASSERT_EQ(ref_pixels.width(), TestWidth) << info; - ASSERT_EQ(ref_pixels.height(), TestHeight) << info; - ASSERT_EQ(ref_pixels.info().bytesPerPixel(), 4) << info; - checkPixels(&ref_pixels, ref_bounds, info, bg); - - { - // This sequence plays the provided equivalently constructed - // DisplayList onto the SkCanvas of the surface - // DisplayList => direct rendering - sk_sp test_surface = makeSurface(bg); - DisplayListBuilder builder(TestBounds); - dl_setup(builder); - dl_render(builder); - sk_sp display_list = builder.Build(); - SkRect dl_bounds = display_list->bounds(); -#ifdef DISPLAY_LIST_BOUNDS_ACCURACY_CHECKING - if (dl_bounds != ref_bounds) { - FML_LOG(ERROR) << "For " << info; - FML_LOG(ERROR) << "ref: " << ref_bounds.fLeft << ", " << ref_bounds.fTop - << " => " << ref_bounds.fRight << ", " - << ref_bounds.fBottom; - FML_LOG(ERROR) << "dl: " << dl_bounds.fLeft << ", " << dl_bounds.fTop - << " => " << dl_bounds.fRight << ", " - << dl_bounds.fBottom; - if (!dl_bounds.contains(ref_bounds)) { - FML_LOG(ERROR) << "DisplayList bounds are too small!"; - } - } -#endif // DISPLAY_LIST_BOUNDS_ACCURACY_CHECKING - // This sometimes triggers, but when it triggers and I examine - // the ref_bounds, they are always unnecessarily large and - // since the pixel OOB tests in the compare method do not - // trigger, we will trust the DL bounds. - // EXPECT_TRUE(dl_bounds.contains(ref_bounds)) << info; - display_list->RenderTo(test_surface->getCanvas()); - compareToReference(test_surface.get(), &ref_pixels, info + " (DL render)", - &dl_bounds, bg); - } - - // This test cannot work if the rendering is using shadows until - // we can access the Skia ShadowRec via public headers. - if (!UsingShadows) { - // This sequence renders SkCanvas calls to a DisplayList and then - // plays them back on SkCanvas to SkSurface - // SkCanvas calls => DisplayList => rendering - sk_sp test_surface = makeSurface(bg); - DisplayListCanvasRecorder dl_recorder(TestBounds); - SkPaint test_paint; - cv_setup(&dl_recorder, test_paint); - cv_render(&dl_recorder, test_paint); - dl_recorder.builder()->Build()->RenderTo(test_surface->getCanvas()); - compareToReference(test_surface.get(), &ref_pixels, - info + " (Sk->DL render)", nullptr, nullptr); - } - } - - static void checkPixels(SkPixmap* ref_pixels, - SkRect ref_bounds, - const std::string info, - const SkColor* bg) { - SkPMColor untouched = (bg) ? SkPreMultiplyColor(*bg) : 0; - int pixels_touched = 0; - int pixels_oob = 0; - for (int y = 0; y < TestHeight; y++) { - const uint32_t* ref_row = ref_pixels->addr32(0, y); - for (int x = 0; x < TestWidth; x++) { - if (ref_row[x] != untouched) { - pixels_touched++; - if (!ref_bounds.intersects(SkRect::MakeXYWH(x, y, 1, 1))) { - pixels_oob++; - } - } - } - } - ASSERT_EQ(pixels_oob, 0) << info; - ASSERT_GT(pixels_touched, 0) << info; - } - - static void compareToReference(SkSurface* test_surface, - SkPixmap* reference, - const std::string info, - SkRect* bounds, - const SkColor* bg) { - SkPMColor untouched = (bg) ? SkPreMultiplyColor(*bg) : 0; - SkPixmap test_pixels; - ASSERT_TRUE(test_surface->peekPixels(&test_pixels)) << info; - ASSERT_EQ(test_pixels.width(), TestWidth) << info; - ASSERT_EQ(test_pixels.height(), TestHeight) << info; - ASSERT_EQ(test_pixels.info().bytesPerPixel(), 4) << info; - - int pixels_different = 0; - int pixels_oob = 0; - int minX = TestWidth; - int minY = TestWidth; - int maxX = 0; - int maxY = 0; - for (int y = 0; y < TestHeight; y++) { - const uint32_t* ref_row = reference->addr32(0, y); - const uint32_t* test_row = test_pixels.addr32(0, y); - for (int x = 0; x < TestWidth; x++) { - if (bounds && test_row[x] != untouched) { - if (minX > x) - minX = x; - if (minY > y) - minY = y; - if (maxX < x) - maxX = x; - if (maxY < y) - maxY = y; - if (!bounds->intersects(SkRect::MakeXYWH(x, y, 1, 1))) { - pixels_oob++; - } - } - if (test_row[x] != ref_row[x]) { - pixels_different++; - } - } - } -#ifdef DISPLAY_LIST_BOUNDS_ACCURACY_CHECKING - if (bounds && *bounds != SkRect::MakeLTRB(minX, minY, maxX + 1, maxY + 1)) { - FML_LOG(ERROR) << "inaccurate bounds for " << info; - FML_LOG(ERROR) << "dl: " << bounds->fLeft << ", " << bounds->fTop - << " => " << bounds->fRight << ", " << bounds->fBottom; - FML_LOG(ERROR) << "pixels: " << minX << ", " << minY << " => " - << (maxX + 1) << ", " << (maxY + 1); - } -#endif // DISPLAY_LIST_BOUNDS_ACCURACY_CHECKING - ASSERT_EQ(pixels_oob, 0) << info; - ASSERT_EQ(pixels_different, 0) << info; - } - - static sk_sp makeSurface(const SkColor* bg) { - sk_sp surface = - SkSurface::MakeRasterN32Premul(TestWidth, TestHeight); - if (bg) { - surface->getCanvas()->drawColor(*bg); - } - return surface; - } - - static const sk_sp testImage; - static const sk_sp makeTestImage() { - sk_sp surface = - SkSurface::MakeRasterN32Premul(RenderWidth, RenderHeight); - SkCanvas* canvas = surface->getCanvas(); - SkPaint p0, p1; - p0.setStyle(SkPaint::kFill_Style); - p0.setColor(SK_ColorGREEN); - p1.setStyle(SkPaint::kFill_Style); - p1.setColor(SK_ColorBLUE); - // Some pixels need some transparency for DstIn testing - p1.setAlpha(128); - int cbdim = 5; - for (int y = 0; y < RenderHeight; y += cbdim) { - for (int x = 0; x < RenderWidth; x += cbdim) { - SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1; - canvas->drawRect(SkRect::MakeXYWH(x, y, cbdim, cbdim), cellp); - } - } - return surface->makeImageSnapshot(); - } - - static sk_sp MakeTextBlob(std::string string, - SkScalar height = RenderHeight) { - SkFont font(SkTypeface::MakeDefault(), height); - return SkTextBlob::MakeFromText(string.c_str(), string.size(), font, - SkTextEncoding::kUTF8); - } -}; - -bool CanvasCompareTester::UsingShadows = false; -const sk_sp CanvasCompareTester::testImage = - CanvasCompareTester::makeTestImage(); - -TEST(DisplayListCanvas, DrawPaint) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPaint(paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPaint(); - }); -} - -TEST(DisplayListCanvas, DrawColor) { - CanvasCompareTester::RenderNoAttributes( // - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawColor(SK_ColorMAGENTA); - }, - [=](DisplayListBuilder& builder) { // - builder.drawColor(SK_ColorMAGENTA, SkBlendMode::kSrcOver); - }); -} - -TEST(DisplayListCanvas, DrawLine) { - SkRect rect = RenderBounds; - SkPoint p1 = SkPoint::Make(rect.fLeft, rect.fTop); - SkPoint p2 = SkPoint::Make(rect.fRight, rect.fBottom); - - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawLine(p1, p2, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawLine(p1, p2); - }); -} - -TEST(DisplayListCanvas, DrawRect) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawRect(RenderBounds, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawRect(RenderBounds); - }); -} - -TEST(DisplayListCanvas, DrawOval) { - SkRect rect = RenderBounds.makeInset(0, 10); - - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawOval(rect, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawOval(rect); - }); -} - -TEST(DisplayListCanvas, DrawCircle) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawCircle(TestCenter, RenderRadius, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawCircle(TestCenter, RenderRadius); - }); -} - -TEST(DisplayListCanvas, DrawRRect) { - SkRRect rrect = - SkRRect::MakeRectXY(RenderBounds, RenderCornerRadius, RenderCornerRadius); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawRRect(rrect, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawRRect(rrect); - }); -} - -TEST(DisplayListCanvas, DrawDRRect) { - SkRRect outer = - SkRRect::MakeRectXY(RenderBounds, RenderCornerRadius, RenderCornerRadius); - SkRect innerBounds = RenderBounds.makeInset(30.0, 30.0); - SkRRect inner = - SkRRect::MakeRectXY(innerBounds, RenderCornerRadius, RenderCornerRadius); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawDRRect(outer, inner, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawDRRect(outer, inner); - }); -} - -TEST(DisplayListCanvas, DrawPath) { - SkPath path; - path.moveTo(RenderCenterX, RenderTop); - path.lineTo(RenderRight, RenderBottom); - path.lineTo(RenderLeft, RenderCenterY); - path.lineTo(RenderRight, RenderCenterY); - path.lineTo(RenderLeft, RenderBottom); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPath(path, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPath(path); - }); -} - -TEST(DisplayListCanvas, DrawArc) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawArc(RenderBounds, 30, 270, false, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawArc(RenderBounds, 30, 270, false); - }); -} - -TEST(DisplayListCanvas, DrawArcCenter) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawArc(RenderBounds, 30, 270, true, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawArc(RenderBounds, 30, 270, true); - }); -} - -TEST(DisplayListCanvas, DrawPointsAsPoints) { - const SkScalar x0 = RenderLeft; - const SkScalar x1 = (RenderLeft + RenderCenterX) * 0.5; - const SkScalar x2 = RenderCenterX; - const SkScalar x3 = (RenderRight + RenderCenterX) * 0.5; - const SkScalar x4 = RenderRight; - - const SkScalar y0 = RenderTop; - const SkScalar y1 = (RenderTop + RenderCenterY) * 0.5; - const SkScalar y2 = RenderCenterY; - const SkScalar y3 = (RenderBottom + RenderCenterY) * 0.5; - const SkScalar y4 = RenderBottom; - - // clang-format off - const SkPoint points[] = { - {x0, y0}, {x1, y0}, {x2, y0}, {x3, y0}, {x4, y0}, - {x0, y1}, {x1, y1}, {x2, y1}, {x3, y1}, {x4, y1}, - {x0, y2}, {x1, y2}, {x2, y2}, {x3, y2}, {x4, y2}, - {x0, y3}, {x1, y3}, {x2, y3}, {x3, y3}, {x4, y3}, - {x0, y4}, {x1, y4}, {x2, y4}, {x3, y4}, {x4, y4}, - }; - // clang-format on - - const int count = sizeof(points) / sizeof(points[0]); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPoints(SkCanvas::kPoints_PointMode, count, points, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPoints(SkCanvas::kPoints_PointMode, count, points); - }); -} - -TEST(DisplayListCanvas, DrawPointsAsLines) { - const SkScalar x0 = RenderLeft; - const SkScalar x1 = (RenderLeft + RenderCenterX) * 0.5; - const SkScalar x2 = RenderCenterX; - const SkScalar x3 = (RenderRight + RenderCenterX) * 0.5; - const SkScalar x4 = RenderRight; - - const SkScalar y0 = RenderTop; - const SkScalar y1 = (RenderTop + RenderCenterY) * 0.5; - const SkScalar y2 = RenderCenterY; - const SkScalar y3 = (RenderBottom + RenderCenterY) * 0.5; - const SkScalar y4 = RenderBottom; - - // clang-format off - const SkPoint points[] = { - // Diagonals - {x0, y0}, {x4, y4}, {x4, y0}, {x0, y4}, - // Inner box - {x1, y1}, {x3, y1}, - {x3, y1}, {x3, y3}, - {x3, y3}, {x1, y3}, - {x1, y3}, {x1, y1}, - // Middle crosshair - {x2, y1}, {x2, y3}, - {x1, y2}, {x3, y3}, - }; - // clang-format on - - const int count = sizeof(points) / sizeof(points[0]); - ASSERT_TRUE((count & 1) == 0); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPoints(SkCanvas::kLines_PointMode, count, points, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPoints(SkCanvas::kLines_PointMode, count, points); - }); -} - -TEST(DisplayListCanvas, DrawPointsAsPolygon) { - const SkPoint points[] = { - SkPoint::Make(RenderLeft, RenderTop), - SkPoint::Make(RenderRight, RenderBottom), - SkPoint::Make(RenderRight, RenderTop), - SkPoint::Make(RenderLeft, RenderBottom), - SkPoint::Make(RenderLeft, RenderTop), - }; - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, points, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPoints(SkCanvas::kPolygon_PointMode, 4, points); - }); -} - -TEST(DisplayListCanvas, DrawVerticesWithColors) { - const SkPoint pts[3] = { - SkPoint::Make(RenderCenterX, RenderTop), - SkPoint::Make(RenderLeft, RenderBottom), - SkPoint::Make(RenderRight, RenderBottom), - }; - const SkColor colors[3] = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN}; - const sk_sp vertices = SkVertices::MakeCopy( - SkVertices::kTriangles_VertexMode, 3, pts, nullptr, colors); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawVertices(vertices.get(), SkBlendMode::kSrcOver, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawVertices(vertices, SkBlendMode::kSrcOver); - }); - ASSERT_TRUE(vertices->unique()); -} - -TEST(DisplayListCanvas, DrawVerticesWithImage) { - const SkPoint pts[3] = { - SkPoint::Make(RenderCenterX, RenderTop), - SkPoint::Make(RenderLeft, RenderBottom), - SkPoint::Make(RenderRight, RenderBottom), - }; - const SkPoint tex[3] = { - SkPoint::Make(RenderWidth / 2.0, 0), - SkPoint::Make(0, RenderHeight), - SkPoint::Make(RenderWidth, RenderHeight), - }; - const sk_sp vertices = SkVertices::MakeCopy( - SkVertices::kTriangles_VertexMode, 3, pts, tex, nullptr); - const sk_sp shader = CanvasCompareTester::testImage->makeShader( - SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions()); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - paint.setShader(shader); - canvas->drawVertices(vertices.get(), SkBlendMode::kSrcOver, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.setShader(shader); - builder.drawVertices(vertices, SkBlendMode::kSrcOver); - }); - ASSERT_TRUE(vertices->unique()); - ASSERT_TRUE(shader->unique()); -} - -TEST(DisplayListCanvas, DrawImageNearest) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImage(CanvasCompareTester::testImage, RenderLeft, RenderTop, - DisplayList::NearestSampling, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImage(CanvasCompareTester::testImage, - SkPoint::Make(RenderLeft, RenderTop), - DisplayList::NearestSampling); - }); -} - -TEST(DisplayListCanvas, DrawImageLinear) { - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImage(CanvasCompareTester::testImage, RenderLeft, RenderTop, - DisplayList::LinearSampling, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImage(CanvasCompareTester::testImage, - SkPoint::Make(RenderLeft, RenderTop), - DisplayList::LinearSampling); - }); -} - -TEST(DisplayListCanvas, DrawImageRectNearest) { - SkRect src = SkRect::MakeIWH(RenderWidth, RenderHeight).makeInset(5, 5); - SkRect dst = RenderBounds.makeInset(15.5, 10.5); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImageRect(CanvasCompareTester::testImage, src, dst, - DisplayList::NearestSampling, &paint, - SkCanvas::kFast_SrcRectConstraint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImageRect(CanvasCompareTester::testImage, src, dst, - DisplayList::NearestSampling); - }); -} - -TEST(DisplayListCanvas, DrawImageRectLinear) { - SkRect src = SkRect::MakeIWH(RenderWidth, RenderHeight).makeInset(5, 5); - SkRect dst = RenderBounds.makeInset(15.5, 10.5); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImageRect(CanvasCompareTester::testImage, src, dst, - DisplayList::LinearSampling, &paint, - SkCanvas::kFast_SrcRectConstraint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImageRect(CanvasCompareTester::testImage, src, dst, - DisplayList::LinearSampling); - }); -} - -TEST(DisplayListCanvas, DrawImageNineNearest) { - SkIRect src = SkIRect::MakeWH(RenderWidth, RenderHeight).makeInset(5, 5); - SkRect dst = RenderBounds.makeInset(15.5, 10.5); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImageNine(CanvasCompareTester::testImage.get(), src, dst, - SkFilterMode::kNearest, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImageNine(CanvasCompareTester::testImage, src, dst, - SkFilterMode::kNearest); - }); -} - -TEST(DisplayListCanvas, DrawImageNineLinear) { - SkIRect src = SkIRect::MakeWH(RenderWidth, RenderHeight).makeInset(5, 5); - SkRect dst = RenderBounds.makeInset(15.5, 10.5); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImageNine(CanvasCompareTester::testImage.get(), src, dst, - SkFilterMode::kLinear, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImageNine(CanvasCompareTester::testImage, src, dst, - SkFilterMode::kLinear); - }); -} - -TEST(DisplayListCanvas, DrawImageLatticeNearest) { - const SkRect dst = RenderBounds.makeInset(15.5, 10.5); - const int divX[] = { - (RenderLeft + RenderCenterX) / 2, - RenderCenterX, - (RenderRight + RenderCenterX) / 2, - }; - const int divY[] = { - (RenderTop + RenderCenterY) / 2, - RenderCenterY, - (RenderBottom + RenderCenterY) / 2, - }; - SkCanvas::Lattice lattice = { - divX, divY, nullptr, 3, 3, nullptr, nullptr, - }; - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImageLattice(CanvasCompareTester::testImage.get(), lattice, - dst, SkFilterMode::kNearest, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImageLattice(CanvasCompareTester::testImage, lattice, // - dst, SkFilterMode::kNearest, true); - }); -} - -TEST(DisplayListCanvas, DrawImageLatticeLinear) { - const SkRect dst = RenderBounds.makeInset(15.5, 10.5); - const int divX[] = { - (RenderLeft + RenderCenterX) / 2, - RenderCenterX, - (RenderRight + RenderCenterX) / 2, - }; - const int divY[] = { - (RenderTop + RenderCenterY) / 2, - RenderCenterY, - (RenderBottom + RenderCenterY) / 2, - }; - SkCanvas::Lattice lattice = { - divX, divY, nullptr, 3, 3, nullptr, nullptr, - }; - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawImageLattice(CanvasCompareTester::testImage.get(), lattice, - dst, SkFilterMode::kLinear, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawImageLattice(CanvasCompareTester::testImage, lattice, // - dst, SkFilterMode::kLinear, true); - }); -} - -TEST(DisplayListCanvas, DrawAtlasNearest) { - const SkRSXform xform[] = { - {0.5, 0, RenderLeft, RenderRight}, - {0, 0.5, RenderCenterX, RenderCenterY}, - }; - const SkRect tex[] = { - {0, 0, RenderWidth * 0.5, RenderHeight * 0.5}, - {RenderWidth * 0.5, RenderHeight * 0.5, RenderWidth, RenderHeight}, - }; - const SkColor colors[] = { - SK_ColorBLUE, - SK_ColorGREEN, - }; - const sk_sp image = CanvasCompareTester::testImage; - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { - canvas->drawAtlas(image.get(), xform, tex, colors, 2, - SkBlendMode::kSrcOver, DisplayList::NearestSampling, - nullptr, &paint); - }, - [=](DisplayListBuilder& builder) { - builder.drawAtlas(image, xform, tex, colors, 2, // - SkBlendMode::kSrcOver, DisplayList::NearestSampling, - nullptr); - }); -} - -TEST(DisplayListCanvas, DrawAtlasLinear) { - const SkRSXform xform[] = { - {0.5, 0, RenderLeft, RenderRight}, - {0, 0.5, RenderCenterX, RenderCenterY}, - }; - const SkRect tex[] = { - {0, 0, RenderWidth * 0.5, RenderHeight * 0.5}, - {RenderWidth * 0.5, RenderHeight * 0.5, RenderWidth, RenderHeight}, - }; - const SkColor colors[] = { - SK_ColorBLUE, - SK_ColorGREEN, - }; - const sk_sp image = CanvasCompareTester::testImage; - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { - canvas->drawAtlas(image.get(), xform, tex, colors, 2, // - SkBlendMode::kSrcOver, DisplayList::LinearSampling, - nullptr, &paint); - }, - [=](DisplayListBuilder& builder) { - builder.drawAtlas(image, xform, tex, colors, 2, // - SkBlendMode::kSrcOver, DisplayList::LinearSampling, - nullptr); - }); -} - -TEST(DisplayListCanvas, DrawPicture) { - SkPictureRecorder recorder; - SkCanvas* cv = recorder.beginRecording(RenderBounds); - SkPaint p; - p.setStyle(SkPaint::kFill_Style); - p.setColor(SK_ColorBLUE); - cv->drawOval(RenderBounds, p); - sk_sp picture = recorder.finishRecordingAsPicture(); - CanvasCompareTester::RenderNoAttributes( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPicture(picture, nullptr, nullptr); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPicture(picture, nullptr, false); - }); -} - -TEST(DisplayListCanvas, DrawPictureWithMatrix) { - SkPictureRecorder recorder; - SkCanvas* cv = recorder.beginRecording(RenderBounds); - SkPaint p; - p.setStyle(SkPaint::kFill_Style); - p.setColor(SK_ColorBLUE); - cv->drawOval(RenderBounds, p); - sk_sp picture = recorder.finishRecordingAsPicture(); - SkMatrix matrix = SkMatrix::Scale(0.95, 0.95); - CanvasCompareTester::RenderNoAttributes( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPicture(picture, &matrix, nullptr); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPicture(picture, &matrix, false); - }); -} - -TEST(DisplayListCanvas, DrawPictureWithPaint) { - SkPictureRecorder recorder; - SkCanvas* cv = recorder.beginRecording(RenderBounds); - SkPaint p; - p.setStyle(SkPaint::kFill_Style); - p.setColor(SK_ColorBLUE); - cv->drawOval(RenderBounds, p); - sk_sp picture = recorder.finishRecordingAsPicture(); - CanvasCompareTester::RenderAll( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPicture(picture, nullptr, &paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawPicture(picture, nullptr, true); - }); -} - -TEST(DisplayListCanvas, DrawDisplayList) { - DisplayListBuilder builder; - builder.setDrawStyle(SkPaint::kFill_Style); - builder.setColor(SK_ColorBLUE); - builder.drawOval(RenderBounds); - sk_sp display_list = builder.Build(); - CanvasCompareTester::RenderNoAttributes( - [=](SkCanvas* canvas, SkPaint& paint) { // - display_list->RenderTo(canvas); - }, - [=](DisplayListBuilder& builder) { // - builder.drawDisplayList(display_list); - }); -} - -TEST(DisplayListCanvas, DrawTextBlob) { - // TODO(https://github.com/flutter/flutter/issues/82202): Remove once the - // performance overlay can use Fuchsia's font manager instead of the empty - // default. -#if defined(OS_FUCHSIA) - GTEST_SKIP() << "Rendering comparisons require a valid default font manager"; -#endif // OS_FUCHSIA - sk_sp blob = CanvasCompareTester::MakeTextBlob("Test Blob"); - CanvasCompareTester::RenderNoAttributes( - [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawTextBlob(blob, RenderLeft, RenderBottom, paint); - }, - [=](DisplayListBuilder& builder) { // - builder.drawTextBlob(blob, RenderLeft, RenderBottom); - }); -} - -TEST(DisplayListCanvas, DrawShadow) { - CanvasCompareTester::UsingShadows = true; - SkPath path; - path.moveTo(RenderCenterX, RenderTop); - path.lineTo(RenderRight, RenderBottom); - path.lineTo(RenderLeft, RenderCenterY); - path.lineTo(RenderRight, RenderCenterY); - path.lineTo(RenderLeft, RenderBottom); - path.close(); - const SkColor color = SK_ColorDKGRAY; - const SkScalar elevation = 10; - - CanvasCompareTester::RenderNoAttributes( - [=](SkCanvas* canvas, SkPaint& paint) { // - PhysicalShapeLayer::DrawShadow(canvas, path, color, elevation, false, - 1.0); - }, - [=](DisplayListBuilder& builder) { // - builder.drawShadow(path, color, elevation, false); - }); - CanvasCompareTester::UsingShadows = false; -} - -TEST(DisplayListCanvas, DrawOccludingShadow) { - CanvasCompareTester::UsingShadows = true; - SkPath path; - path.moveTo(RenderCenterX, RenderTop); - path.lineTo(RenderRight, RenderBottom); - path.lineTo(RenderLeft, RenderCenterY); - path.lineTo(RenderRight, RenderCenterY); - path.lineTo(RenderLeft, RenderBottom); - path.close(); - const SkColor color = SK_ColorDKGRAY; - const SkScalar elevation = 10; - - CanvasCompareTester::RenderNoAttributes( - [=](SkCanvas* canvas, SkPaint& paint) { // - PhysicalShapeLayer::DrawShadow(canvas, path, color, elevation, true, - 1.0); - }, - [=](DisplayListBuilder& builder) { // - builder.drawShadow(path, color, elevation, true); - }); - CanvasCompareTester::UsingShadows = false; -} - -} // namespace testing -} // namespace flutter diff --git a/flow/display_list_unittests.cc b/flow/display_list_unittests.cc deleted file mode 100644 index eae1815eb047f..0000000000000 --- a/flow/display_list_unittests.cc +++ /dev/null @@ -1,830 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/flow/display_list_canvas.h" - -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkImageInfo.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkPicture.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" -#include "third_party/skia/include/core/SkRRect.h" -#include "third_party/skia/include/core/SkRSXform.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/core/SkTextBlob.h" -#include "third_party/skia/include/core/SkVertices.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "third_party/skia/include/effects/SkImageFilters.h" - -#include - -#include "gtest/gtest.h" - -namespace flutter { -namespace testing { - -constexpr SkPoint end_points[] = { - {0, 0}, - {100, 100}, -}; -constexpr SkColor colors[] = { - SK_ColorGREEN, - SK_ColorYELLOW, - SK_ColorBLUE, -}; -constexpr float stops[] = { - 0.0, - 0.5, - 1.0, -}; -constexpr float rotate_color_matrix[20] = { - 0, 1, 0, 0, 0, // - 0, 0, 1, 0, 0, // - 1, 0, 0, 0, 0, // - 0, 0, 0, 1, 0, // -}; - -constexpr SkPoint TestPoints[] = { - {10, 10}, - {20, 20}, - {10, 20}, - {20, 10}, -}; -#define TestPointCount sizeof(TestPoints) / (sizeof(TestPoints[0])) - -static const sk_sp TestShader1 = - SkGradientShader::MakeLinear(end_points, - colors, - stops, - 3, - SkTileMode::kMirror, - 0, - nullptr); -// TestShader2 is identical to TestShader1 and points out that we cannot -// perform a deep compare over our various sk_sp objects because the -// DisplayLists constructed with the two do not compare == below. -static const sk_sp TestShader2 = - SkGradientShader::MakeLinear(end_points, - colors, - stops, - 3, - SkTileMode::kMirror, - 0, - nullptr); -static const sk_sp TestShader3 = - SkGradientShader::MakeLinear(end_points, - colors, - stops, - 3, - SkTileMode::kDecal, - 0, - nullptr); -static const sk_sp TestImageFilter = - SkImageFilters::Blur(5.0, 5.0, SkTileMode::kDecal, nullptr, nullptr); -static const sk_sp TestColorFilter = - SkColorFilters::Matrix(rotate_color_matrix); -static const sk_sp TestMaskFilter = - SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5.0); -constexpr SkRect TestBounds = SkRect::MakeLTRB(10, 10, 50, 60); -static const SkRRect TestRRect = SkRRect::MakeRectXY(TestBounds, 5, 5); -static const SkRRect TestRRectRect = SkRRect::MakeRect(TestBounds); -static const SkRRect TestInnerRRect = - SkRRect::MakeRectXY(TestBounds.makeInset(5, 5), 2, 2); -static const SkPath TestPathRect = SkPath::Rect(TestBounds); -static const SkPath TestPathOval = SkPath::Oval(TestBounds); -static const SkPath TestPath1 = - SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true); -static const SkPath TestPath2 = - SkPath::Polygon({{0, 0}, {10, 10}, {0, 10}, {10, 0}}, true); -static const SkPath TestPath3 = - SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, false); -static const SkMatrix TestMatrix1 = SkMatrix::Scale(2, 2); -static const SkMatrix TestMatrix2 = SkMatrix::RotateDeg(45); - -static sk_sp MakeTestImage(int w, int h, int checker_size) { - sk_sp surface = SkSurface::MakeRasterN32Premul(w, h); - SkCanvas* canvas = surface->getCanvas(); - SkPaint p0, p1; - p0.setStyle(SkPaint::kFill_Style); - p0.setColor(SK_ColorGREEN); - p1.setStyle(SkPaint::kFill_Style); - p1.setColor(SK_ColorBLUE); - p1.setAlpha(128); - for (int y = 0; y < w; y += checker_size) { - for (int x = 0; x < h; x += checker_size) { - SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1; - canvas->drawRect(SkRect::MakeXYWH(x, y, checker_size, checker_size), - cellp); - } - } - return surface->makeImageSnapshot(); -} -static sk_sp TestImage1 = MakeTestImage(40, 40, 5); -static sk_sp TestImage2 = MakeTestImage(50, 50, 5); - -static sk_sp TestVertices1 = - SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, - 3, - TestPoints, - nullptr, - colors); -static sk_sp TestVertices2 = - SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, - 3, - TestPoints, - nullptr, - colors); - -static constexpr int TestDivs1[] = {10, 20, 30}; -static constexpr int TestDivs2[] = {15, 20, 25}; -static constexpr int TestDivs3[] = {15, 25}; -static constexpr SkCanvas::Lattice::RectType TestRTypes[] = { - SkCanvas::Lattice::RectType::kDefault, - SkCanvas::Lattice::RectType::kTransparent, - SkCanvas::Lattice::RectType::kFixedColor, - SkCanvas::Lattice::RectType::kDefault, - SkCanvas::Lattice::RectType::kTransparent, - SkCanvas::Lattice::RectType::kFixedColor, - SkCanvas::Lattice::RectType::kDefault, - SkCanvas::Lattice::RectType::kTransparent, - SkCanvas::Lattice::RectType::kFixedColor, -}; -static constexpr SkColor TestLatticeColors[] = { - SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, - SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, - SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, -}; -static constexpr SkIRect TestLatticeSrcRect = {1, 1, 39, 39}; - -static sk_sp MakeTestPicture(int w, int h, SkColor color) { - SkPictureRecorder recorder; - SkCanvas* cv = recorder.beginRecording(TestBounds); - SkPaint paint; - paint.setColor(color); - paint.setStyle(SkPaint::kFill_Style); - cv->drawRect(SkRect::MakeWH(w, h), paint); - return recorder.finishRecordingAsPicture(); -} -static sk_sp TestPicture1 = MakeTestPicture(20, 20, SK_ColorGREEN); -static sk_sp TestPicture2 = MakeTestPicture(25, 25, SK_ColorBLUE); - -static sk_sp MakeTestDisplayList(int w, int h, SkColor color) { - DisplayListBuilder builder; - builder.setColor(color); - builder.drawRect(SkRect::MakeWH(w, h)); - return builder.Build(); -} -static sk_sp TestDisplayList1 = - MakeTestDisplayList(20, 20, SK_ColorGREEN); -static sk_sp TestDisplayList2 = - MakeTestDisplayList(25, 25, SK_ColorBLUE); - -static sk_sp MakeTextBlob(std::string string) { - return SkTextBlob::MakeFromText(string.c_str(), string.size(), SkFont(), - SkTextEncoding::kUTF8); -} -static sk_sp TestBlob1 = MakeTextBlob("TestBlob1"); -static sk_sp TestBlob2 = MakeTextBlob("TestBlob2"); - -// --------------- -// Test Suite data -// --------------- - -typedef const std::function DlInvoker; - -struct DisplayListInvocation { - int op_count; - size_t byte_count; - - // in some cases, running the sequence through an SkCanvas will result - // in fewer ops/bytes. Attribute invocations are recorded in an SkPaint - // and not forwarded on, and SkCanvas culls unused save/restore/transforms. - int sk_op_count; - size_t sk_byte_count; - - DlInvoker invoker; - - bool sk_version_matches() { - return (op_count == sk_op_count && byte_count == sk_byte_count); - } - - sk_sp Build() { - DisplayListBuilder builder; - invoker(builder); - return builder.Build(); - } -}; - -struct DisplayListInvocationGroup { - std::string op_name; - std::vector variants; -}; - -std::vector allGroups = { - { "SetAA", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setAA(false);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setAA(true);}}, - } - }, - { "SetDither", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setDither(false);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setDither(true);}}, - } - }, - { "SetInvertColors", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setInvertColors(false);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setInvertColors(true);}}, - } - }, - { "SetStrokeCap", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setCaps(SkPaint::kButt_Cap);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setCaps(SkPaint::kRound_Cap);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setCaps(SkPaint::kSquare_Cap);}}, - } - }, - { "SetStrokeJoin", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setJoins(SkPaint::kBevel_Join);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setJoins(SkPaint::kRound_Join);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setJoins(SkPaint::kMiter_Join);}}, - } - }, - { "SetDrawStyle", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setDrawStyle(SkPaint::kFill_Style);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setDrawStyle(SkPaint::kStroke_Style);}}, - } - }, - { "SetStrokeWidth", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeWidth(0.0);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeWidth(5.0);}}, - } - }, - { "SetMiterLimit", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMiterLimit(0.0);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMiterLimit(5.0);}}, - } - }, - { "SetColor", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setColor(SK_ColorGREEN);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setColor(SK_ColorBLUE);}}, - } - }, - { "SetBlendMode", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kSrcIn);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kDstIn);}}, - } - }, - { "SetFilterQuality", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setFilterQuality(kNone_SkFilterQuality);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setFilterQuality(kLow_SkFilterQuality);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setFilterQuality(kMedium_SkFilterQuality);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setFilterQuality(kHigh_SkFilterQuality);}}, - } - }, - { "SetShader", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setShader(nullptr);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setShader(TestShader1);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setShader(TestShader2);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setShader(TestShader3);}}, - } - }, - { "SetImageFilter", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(nullptr);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(TestImageFilter);}}, - } - }, - { "SetColorFilter", { - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(nullptr);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(TestColorFilter);}}, - } - }, - { "SetMaskFilter", { - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(nullptr);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(TestMaskFilter);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMaskBlurFilter(kNormal_SkBlurStyle, 3.0);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMaskBlurFilter(kNormal_SkBlurStyle, 5.0);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMaskBlurFilter(kSolid_SkBlurStyle, 3.0);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMaskBlurFilter(kInner_SkBlurStyle, 3.0);}}, - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setMaskBlurFilter(kOuter_SkBlurStyle, 3.0);}}, - } - }, - { "Save(Layer)+Restore", { - // cv.save/restore are ignored if there are no draw calls between them - {2, 16, 0, 0, [](DisplayListBuilder& b) {b.save(); b.restore();}}, - {2, 16, 2, 16, [](DisplayListBuilder& b) {b.saveLayer(nullptr, false); b.restore(); }}, - {2, 16, 2, 16, [](DisplayListBuilder& b) {b.saveLayer(nullptr, true); b.restore(); }}, - {2, 32, 2, 32, [](DisplayListBuilder& b) {b.saveLayer(&TestBounds, false); b.restore(); }}, - {2, 32, 2, 32, [](DisplayListBuilder& b) {b.saveLayer(&TestBounds, true); b.restore(); }}, - } - }, - { "Translate", { - // cv.translate(0, 0) is ignored - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.translate(0, 0);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.translate(10, 10);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.translate(10, 15);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.translate(15, 10);}}, - } - }, - { "Scale", { - // cv.scale(1, 1) is ignored - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.scale(1, 1);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.scale(2, 2);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.scale(2, 3);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.scale(3, 2);}}, - } - }, - { "Rotate", { - // cv.rotate(0) is ignored, otherwise expressed as concat(rotmatrix) - {1, 8, 0, 0, [](DisplayListBuilder& b) {b.rotate(0);}}, - {1, 8, 1, 32, [](DisplayListBuilder& b) {b.rotate(30);}}, - {1, 8, 1, 32, [](DisplayListBuilder& b) {b.rotate(45);}}, - } - }, - { "Skew", { - // cv.skew(0, 0) is ignored, otherwise expressed as concat(skewmatrix) - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.skew(0, 0);}}, - {1, 16, 1, 32, [](DisplayListBuilder& b) {b.skew(0.1, 0.1);}}, - {1, 16, 1, 32, [](DisplayListBuilder& b) {b.skew(0.1, 0.2);}}, - {1, 16, 1, 32, [](DisplayListBuilder& b) {b.skew(0.2, 0.1);}}, - } - }, - { "Transform2x3", { - // cv.transform(identity) is ignored - {1, 32, 0, 0, [](DisplayListBuilder& b) {b.transform2x3(1, 0, 0, 0, 1, 0);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.transform2x3(0, 1, 12, 1, 0, 33);}}, - } - }, - { "Transform3x3", { - // cv.transform(identity) is ignored - {1, 40, 0, 0, [](DisplayListBuilder& b) {b.transform3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);}}, - {1, 40, 1, 40, [](DisplayListBuilder& b) {b.transform3x3(0, 1, 12, 1, 0, 33, 0, 0, 12);}}, - } - }, - { "ClipRect", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(TestBounds, true, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(TestBounds.makeOffset(1, 1), - true, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(TestBounds, false, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(TestBounds, true, SkClipOp::kDifference);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(TestBounds, false, SkClipOp::kDifference);}}, - } - }, - { "ClipRRect", { - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(TestRRect, true, SkClipOp::kIntersect);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(TestRRect.makeOffset(1, 1), - true, SkClipOp::kIntersect);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(TestRRect, false, SkClipOp::kIntersect);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(TestRRect, true, SkClipOp::kDifference);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(TestRRect, false, SkClipOp::kDifference);}}, - } - }, - { "ClipPath", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPath1, true, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPath2, true, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPath3, true, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPath1, false, SkClipOp::kIntersect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPath1, true, SkClipOp::kDifference);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPath1, false, SkClipOp::kDifference);}}, - // clipPath(rect) becomes clipRect - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(TestPathRect, true, SkClipOp::kIntersect);}}, - // clipPath(oval) becomes clipRRect - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipPath(TestPathOval, true, SkClipOp::kIntersect);}}, - } - }, - { "DrawPaint", { - {1, 8, 1, 8, [](DisplayListBuilder& b) {b.drawPaint();}}, - } - }, - { "DrawColor", { - // cv.drawColor becomes cv.drawPaint(paint) - {1, 16, 3, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, SkBlendMode::kSrcIn);}}, - {1, 16, 3, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, SkBlendMode::kDstIn);}}, - {1, 16, 3, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorCYAN, SkBlendMode::kSrcIn);}}, - } - }, - { "DrawLine", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 0}, {10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 1}, {10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 0}, {20, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 0}, {10, 20});}}, - } - }, - { "DrawRect", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 0, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 1, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 0, 20, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 0, 10, 20});}}, - } - }, - { "DrawOval", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 0, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 1, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 0, 20, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 0, 10, 20});}}, - } - }, - { "DrawCircle", { - // cv.drawCircle becomes cv.drawOval - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawCircle({0, 0}, 10);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawCircle({0, 5}, 10);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawCircle({0, 0}, 20);}}, - } - }, - { "DrawRRect", { - {1, 56, 1, 56, [](DisplayListBuilder& b) {b.drawRRect(TestRRect);}}, - {1, 56, 1, 56, [](DisplayListBuilder& b) {b.drawRRect(TestRRect.makeOffset(5, 5));}}, - } - }, - { "DrawDRRect", { - {1, 112, 1, 112, [](DisplayListBuilder& b) {b.drawDRRect(TestRRect, TestInnerRRect);}}, - {1, 112, 1, 112, [](DisplayListBuilder& b) {b.drawDRRect(TestRRect.makeOffset(5, 5), - TestInnerRRect.makeOffset(4, 4));}}, - } - }, - { "DrawPath", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(TestPath1);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(TestPath2);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(TestPath3);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(TestPathRect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(TestPathOval);}}, - } - }, - { "DrawArc", { - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(TestBounds, 45, 270, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(TestBounds.makeOffset(1, 1), - 45, 270, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(TestBounds, 30, 270, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(TestBounds, 45, 260, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(TestBounds, 45, 270, true);}}, - } - }, - { "DrawPoints", { - {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kPoints_PointMode, - TestPointCount, - TestPoints);}}, - {1, 8 + (TestPointCount - 1) * 8, 1, 8 + (TestPointCount - 1) * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kPoints_PointMode, - TestPointCount - 1, - TestPoints);}}, - {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kLines_PointMode, - TestPointCount, - TestPoints);}}, - {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kPolygon_PointMode, - TestPointCount, - TestPoints);}}, - } - }, - { "DrawVertices", { - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, SkBlendMode::kSrcIn);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, SkBlendMode::kDstIn);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices2, SkBlendMode::kSrcIn);}}, - } - }, - { "DrawImage", { - {1, 40, 1, 40, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 10}, DisplayList::NearestSampling);}}, - {1, 40, 1, 40, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {20, 10}, DisplayList::NearestSampling);}}, - {1, 40, 1, 40, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 20}, DisplayList::NearestSampling);}}, - {1, 40, 1, 40, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 10}, DisplayList::LinearSampling);}}, - {1, 40, 1, 40, [](DisplayListBuilder& b) {b.drawImage(TestImage2, {10, 10}, DisplayList::NearestSampling);}}, - } - }, - { "DrawImageRect", { - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - DisplayList::NearestSampling);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - DisplayList::NearestSampling, - SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, - DisplayList::NearestSampling);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, - DisplayList::NearestSampling);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - DisplayList::LinearSampling);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, - DisplayList::NearestSampling);}}, - } - }, - { "DrawImageNine", { - // SkVanvas::drawImageNine is immediately converted to drawImageLattice - {1, 48, 1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - SkFilterMode::kNearest);}}, - {1, 48, 1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, - SkFilterMode::kNearest);}}, - {1, 48, 1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, - SkFilterMode::kNearest);}}, - {1, 48, 1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - SkFilterMode::kLinear);}}, - {1, 48, 1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, - SkFilterMode::kNearest);}}, - } - }, - { "DrawImageLattice", { - // Lattice: - // const int* fXDivs; //!< x-axis values dividing bitmap - // const int* fYDivs; //!< y-axis values dividing bitmap - // const RectType* fRectTypes; //!< array of fill types - // int fXCount; //!< number of x-coordinates - // int fYCount; //!< number of y-coordinates - // const SkIRect* fBounds; //!< source bounds to draw from - // const SkColor* fColors; //!< array of colors - // size = 64 + fXCount * 4 + fYCount * 4 - // if fColors and fRectTypes are not null, add (fXCount + 1) * (fYCount + 1) * 5 - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs1, TestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kNearest, false);}}, - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs1, TestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 45}, SkFilterMode::kNearest, false);}}, - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs2, TestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kNearest, false);}}, - // One less yDiv does not change the allocation due to 8-byte alignment - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs1, TestDivs1, nullptr, 3, 2, nullptr, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kNearest, false);}}, - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs1, TestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kLinear, false);}}, - {2, 96, 2, 96, [](DisplayListBuilder& b) {b.setColor(SK_ColorMAGENTA); - b.drawImageLattice(TestImage1, - {TestDivs1, TestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kNearest, true);}}, - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage2, - {TestDivs1, TestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kNearest, false);}}, - // Supplying fBounds does not change size because the Op record always includes it - {1, 88, 1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs1, TestDivs1, nullptr, 3, 3, &TestLatticeSrcRect, nullptr}, - {10, 10, 40, 40}, SkFilterMode::kNearest, false);}}, - {1, 128, 1, 128, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {TestDivs3, TestDivs3, TestRTypes, 2, 2, nullptr, TestLatticeColors}, - {10, 10, 40, 40}, SkFilterMode::kNearest, false);}}, - } - }, - { "DrawAtlas", { - {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, - DisplayList::NearestSampling, nullptr);}}, - {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {0, 1, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, - DisplayList::NearestSampling, nullptr);}}, - {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 25, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, - DisplayList::NearestSampling, nullptr);}}, - {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, - DisplayList::LinearSampling, nullptr);}}, - {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kDstIn, - DisplayList::NearestSampling, nullptr);}}, - {1, 56 + 32 + 32, 1, 56 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - static SkRect cullRect = { 0, 0, 200, 200 }; - b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, - DisplayList::NearestSampling, &cullRect);}}, - {1, 40 + 32 + 32 + 8, 1, 40 + 32 + 32 + 8, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - static SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN }; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, SkBlendMode::kSrcIn, - DisplayList::NearestSampling, nullptr);}}, - {1, 56 + 32 + 32 + 8, 1, 56 + 32 + 32 + 8, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - static SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN }; - static SkRect cullRect = { 0, 0, 200, 200 }; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, SkBlendMode::kSrcIn, - DisplayList::NearestSampling, &cullRect);}}, - } - }, - { "DrawPicture", { - // cv.drawPicture cannot be compared as SkCanvas may inline it - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, nullptr, false);}}, - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawPicture(TestPicture2, nullptr, false);}}, - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, nullptr, true);}}, - {1, 56, -1, 56, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, &TestMatrix1, false);}}, - {1, 56, -1, 56, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, &TestMatrix2, false);}}, - {1, 56, -1, 56, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, &TestMatrix1, true);}}, - } - }, - { "DrawDisplayList", { - // cv.drawDL does not exist - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawDisplayList(TestDisplayList1);}}, - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawDisplayList(TestDisplayList2);}}, - } - }, - { "DrawTextBlob", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob1, 10, 10);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob1, 20, 10);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob1, 10, 20);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob2, 10, 10);}}, - } - }, - // The -1 op counts below are to indicate to the framework not to test - // SkCanvas conversion of these ops as it converts the operation into a - // format that is not exposed publicly and so we cannot recapture the - // operation. - // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 - { "DrawShadow", { - // cv shadows are turned into an opaque ShadowRec which is not exposed - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, false);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath2, SK_ColorGREEN, 1.0, false);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorBLUE, 1.0, false);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 2.0, false);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, true);}}, - } - }, -}; - -TEST(DisplayList, SingleOpSizes) { - for (auto& group : allGroups) { - for (size_t i = 0; i < group.variants.size(); i++) { - auto& invocation = group.variants[i]; - sk_sp dl = invocation.Build(); - auto desc = group.op_name + "(variant " + std::to_string(i + 1) + ")"; - ASSERT_EQ(dl->op_count(), invocation.op_count) << desc; - EXPECT_EQ(dl->bytes(), invocation.byte_count) << desc; - } - } -} - -TEST(DisplayList, SingleOpDisplayListsNotEqualEmpty) { - sk_sp empty = DisplayListBuilder().Build(); - for (auto& group : allGroups) { - for (size_t i = 0; i < group.variants.size(); i++) { - sk_sp dl = group.variants[i].Build(); - auto desc = - group.op_name + "(variant " + std::to_string(i + 1) + " != empty)"; - ASSERT_FALSE(dl->Equals(*empty)) << desc; - ASSERT_FALSE(empty->Equals(*dl)) << desc; - } - } -} - -TEST(DisplayList, SingleOpDisplayListsRecapturedAreEqual) { - for (auto& group : allGroups) { - for (size_t i = 0; i < group.variants.size(); i++) { - sk_sp dl = group.variants[i].Build(); - // Verify recapturing the replay of the display list is Equals() - // when dispatching directly from the DL to another builder - DisplayListBuilder builder; - dl->Dispatch(builder); - sk_sp copy = builder.Build(); - auto desc = - group.op_name + "(variant " + std::to_string(i + 1) + " == copy)"; - ASSERT_EQ(copy->op_count(), dl->op_count()) << desc; - ASSERT_EQ(copy->bytes(), dl->bytes()) << desc; - ASSERT_EQ(copy->bounds(), dl->bounds()) << desc; - ASSERT_TRUE(copy->Equals(*dl)) << desc; - ASSERT_TRUE(dl->Equals(*copy)) << desc; - } - } -} - -TEST(DisplayList, SingleOpDisplayListsRecapturedViaSkCanvasAreEqual) { - for (auto& group : allGroups) { - for (size_t i = 0; i < group.variants.size(); i++) { - if (group.variants[i].sk_op_count < 0) { - // A negative sk_op_count means "do not test this op". - // Used mainly for these cases: - // - we cannot encode a DrawShadowRec (Skia private header) - // - SkCanvas cannot receive a DisplayList - // - SkCanvas may or may not inline an SkPicture - continue; - } - // Verify a DisplayList (re)built by "rendering" it to an - // [SkCanvas->DisplayList] recorder recaptures an equivalent - // sequence. - // Note that sometimes the rendering ops can be optimized out by - // SkCanvas so the transfer is not always 1:1. We control for - // this by having separate op counts and sizes for the sk results - // and changing our expectation of Equals() results accordingly. - sk_sp dl = group.variants[i].Build(); - - DisplayListCanvasRecorder recorder(dl->bounds()); - dl->RenderTo(&recorder); - sk_sp sk_copy = recorder.Build(); - auto desc = group.op_name + "[variant " + std::to_string(i + 1) + "]"; - EXPECT_EQ(sk_copy->op_count(), group.variants[i].sk_op_count) << desc; - EXPECT_EQ(sk_copy->bytes(), group.variants[i].sk_byte_count) << desc; - if (group.variants[i].sk_version_matches()) { - EXPECT_EQ(sk_copy->bounds(), dl->bounds()) << desc; - EXPECT_TRUE(dl->Equals(*sk_copy)) << desc << " == sk_copy"; - EXPECT_TRUE(sk_copy->Equals(*dl)) << "sk_copy == " << desc; - } else { - // No assertion on bounds - // they could be equal, hard to tell - EXPECT_FALSE(dl->Equals(*sk_copy)) << desc << " != sk_copy"; - EXPECT_FALSE(sk_copy->Equals(*dl)) << "sk_copy != " << desc; - } - } - } -} - -TEST(DisplayList, SingleOpDisplayListsCompareToEachOther) { - for (auto& group : allGroups) { - std::vector> listsA; - std::vector> listsB; - for (size_t i = 0; i < group.variants.size(); i++) { - listsA.push_back(group.variants[i].Build()); - listsB.push_back(group.variants[i].Build()); - } - - for (size_t i = 0; i < listsA.size(); i++) { - sk_sp listA = listsA[i]; - for (size_t j = 0; j < listsB.size(); j++) { - sk_sp listB = listsB[j]; - auto desc = group.op_name + "(variant " + std::to_string(i + 1) + - " ==? variant " + std::to_string(j + 1) + ")"; - if (i == j) { - ASSERT_EQ(listA->op_count(), listB->op_count()) << desc; - ASSERT_EQ(listA->bytes(), listB->bytes()) << desc; - ASSERT_EQ(listA->bounds(), listB->bounds()) << desc; - ASSERT_TRUE(listA->Equals(*listB)) << desc; - ASSERT_TRUE(listB->Equals(*listA)) << desc; - } else { - // No assertion on op/byte counts or bounds - // they may or may not be equal between variants - ASSERT_FALSE(listA->Equals(*listB)) << desc; - ASSERT_FALSE(listB->Equals(*listA)) << desc; - } - } - } - } -} - -static sk_sp Build(size_t g_index, size_t v_index) { - DisplayListBuilder builder; - int op_count = 0; - size_t byte_count = 0; - for (size_t i = 0; i < allGroups.size(); i++) { - DisplayListInvocationGroup& group = allGroups[i]; - size_t j = (i == g_index ? v_index : 0); - if (j >= group.variants.size()) - continue; - DisplayListInvocation& invocation = group.variants[j]; - op_count += invocation.op_count; - byte_count += invocation.byte_count; - invocation.invoker(builder); - } - sk_sp dl = builder.Build(); - std::string name; - if (g_index >= allGroups.size()) { - name = "Default"; - } else { - name = allGroups[g_index].op_name; - if (v_index < 0) { - name += " skipped"; - } else { - name += " variant " + std::to_string(v_index + 1); - } - } - EXPECT_EQ(dl->op_count(), op_count) << name; - EXPECT_EQ(dl->bytes(), byte_count) << name; - return dl; -} - -TEST(DisplayList, DisplayListsWithVaryingOpComparisons) { - sk_sp default_dl = Build(allGroups.size(), 0); - ASSERT_TRUE(default_dl->Equals(*default_dl)) << "Default == itself"; - for (size_t gi = 0; gi < allGroups.size(); gi++) { - DisplayListInvocationGroup& group = allGroups[gi]; - sk_sp missing_dl = Build(gi, group.variants.size()); - auto desc = "[Group " + std::to_string(gi + 1) + " omitted]"; - ASSERT_TRUE(missing_dl->Equals(*missing_dl)) << desc << " == itself"; - ASSERT_FALSE(missing_dl->Equals(*default_dl)) << desc << " != Default"; - ASSERT_FALSE(default_dl->Equals(*missing_dl)) << "Default != " << desc; - for (size_t vi = 0; vi < group.variants.size(); vi++) { - auto desc = "[Group " + std::to_string(gi + 1) + " variant " + - std::to_string(vi + 1) + "]"; - sk_sp variant_dl = Build(gi, vi); - ASSERT_TRUE(variant_dl->Equals(*variant_dl)) << desc << " == itself"; - if (vi == 0) { - ASSERT_TRUE(variant_dl->Equals(*default_dl)) << desc << " == Default"; - ASSERT_TRUE(default_dl->Equals(*variant_dl)) << "Default == " << desc; - } else { - ASSERT_FALSE(variant_dl->Equals(*default_dl)) << desc << " != Default"; - ASSERT_FALSE(default_dl->Equals(*variant_dl)) << "Default != " << desc; - } - ASSERT_FALSE(variant_dl->Equals(*missing_dl)) << desc << " != omitted"; - ASSERT_FALSE(missing_dl->Equals(*variant_dl)) << "omitted != " << desc; - } - } -} - -} // namespace testing -} // namespace flutter diff --git a/flow/display_list_utils.cc b/flow/display_list_utils.cc deleted file mode 100644 index 474435b94c992..0000000000000 --- a/flow/display_list_utils.cc +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include - -#include "flutter/flow/display_list_utils.h" -#include "flutter/flow/layers/physical_shape_layer.h" -#include "flutter/fml/logging.h" - -#include "third_party/skia/include/core/SkMaskFilter.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkRSXform.h" -#include "third_party/skia/include/core/SkTextBlob.h" -#include "third_party/skia/include/utils/SkShadowUtils.h" - -namespace flutter { - -// clang-format off -constexpr float invert_color_matrix[20] = { - -1.0, 0, 0, 1.0, 0, - 0, -1.0, 0, 1.0, 0, - 0, 0, -1.0, 1.0, 0, - 1.0, 1.0, 1.0, 1.0, 0 -}; -// clang-format on - -void SkPaintDispatchHelper::setAA(bool aa) { - paint_.setAntiAlias(aa); -} -void SkPaintDispatchHelper::setDither(bool dither) { - paint_.setDither(dither); -} -void SkPaintDispatchHelper::setInvertColors(bool invert) { - invert_colors_ = invert; - paint_.setColorFilter(makeColorFilter()); -} -void SkPaintDispatchHelper::setCaps(SkPaint::Cap cap) { - paint_.setStrokeCap(cap); -} -void SkPaintDispatchHelper::setJoins(SkPaint::Join join) { - paint_.setStrokeJoin(join); -} -void SkPaintDispatchHelper::setDrawStyle(SkPaint::Style style) { - paint_.setStyle(style); -} -void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) { - paint_.setStrokeWidth(width); -} -void SkPaintDispatchHelper::setMiterLimit(SkScalar limit) { - paint_.setStrokeMiter(limit); -} -void SkPaintDispatchHelper::setColor(SkColor color) { - paint_.setColor(color); -} -void SkPaintDispatchHelper::setBlendMode(SkBlendMode mode) { - paint_.setBlendMode(mode); -} -void SkPaintDispatchHelper::setFilterQuality(SkFilterQuality quality) { - paint_.setFilterQuality(quality); -} -void SkPaintDispatchHelper::setShader(sk_sp shader) { - paint_.setShader(shader); -} -void SkPaintDispatchHelper::setImageFilter(sk_sp filter) { - paint_.setImageFilter(filter); -} -void SkPaintDispatchHelper::setColorFilter(sk_sp filter) { - color_filter_ = filter; - paint_.setColorFilter(makeColorFilter()); -} -void SkPaintDispatchHelper::setMaskFilter(sk_sp filter) { - paint_.setMaskFilter(filter); -} -void SkPaintDispatchHelper::setMaskBlurFilter(SkBlurStyle style, - SkScalar sigma) { - paint_.setMaskFilter(SkMaskFilter::MakeBlur(style, sigma)); -} - -sk_sp SkPaintDispatchHelper::makeColorFilter() { - if (!invert_colors_) { - return color_filter_; - } - sk_sp invert_filter = - SkColorFilters::Matrix(invert_color_matrix); - if (color_filter_) { - invert_filter = invert_filter->makeComposed(color_filter_); - } - return invert_filter; -} - -void SkMatrixDispatchHelper::translate(SkScalar tx, SkScalar ty) { - matrix_.preTranslate(tx, ty); -} -void SkMatrixDispatchHelper::scale(SkScalar sx, SkScalar sy) { - matrix_.preScale(sx, sy); -} -void SkMatrixDispatchHelper::rotate(SkScalar degrees) { - matrix_.preRotate(degrees); -} -void SkMatrixDispatchHelper::skew(SkScalar sx, SkScalar sy) { - matrix_.preSkew(sx, sy); -} -void SkMatrixDispatchHelper::transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) { - matrix_.preConcat(SkMatrix::MakeAll(mxx, mxy, mxt, myx, myy, myt, 0, 0, 1)); -} -void SkMatrixDispatchHelper::transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) { - matrix_.preConcat( - SkMatrix::MakeAll(mxx, mxy, mxt, myx, myy, myt, px, py, pt)); -} -void SkMatrixDispatchHelper::save() { - saved_.push_back(matrix_); -} -void SkMatrixDispatchHelper::restore() { - matrix_ = saved_.back(); - saved_.pop_back(); -} -void SkMatrixDispatchHelper::reset() { - matrix_.reset(); -} - -void ClipBoundsDispatchHelper::clipRect(const SkRect& rect, - bool isAA, - SkClipOp clip_op) { - if (clip_op == SkClipOp::kIntersect) { - intersect(rect); - } -} -void ClipBoundsDispatchHelper::clipRRect(const SkRRect& rrect, - bool isAA, - SkClipOp clip_op) { - if (clip_op == SkClipOp::kIntersect) { - intersect(rrect.getBounds()); - } -} -void ClipBoundsDispatchHelper::clipPath(const SkPath& path, - bool isAA, - SkClipOp clip_op) { - if (clip_op == SkClipOp::kIntersect) { - intersect(path.getBounds()); - } -} -void ClipBoundsDispatchHelper::intersect(const SkRect& rect) { - SkRect devClipBounds = matrix().mapRect(rect); - if (!bounds_.intersect(devClipBounds)) { - bounds_.setEmpty(); - } -} -void ClipBoundsDispatchHelper::save() { - saved_.push_back(bounds_); -} -void ClipBoundsDispatchHelper::restore() { - bounds_ = saved_.back(); - saved_.pop_back(); -} - -void DisplayListBoundsCalculator::saveLayer(const SkRect* bounds, - bool with_paint) { - SkMatrixDispatchHelper::save(); - ClipBoundsDispatchHelper::save(); - SaveInfo info = - with_paint ? SaveLayerWithPaintInfo(this, accumulator_, matrix(), paint()) - : SaveLayerInfo(accumulator_, matrix()); - saved_infos_.push_back(info); - accumulator_ = info.save(); - SkMatrixDispatchHelper::reset(); -} -void DisplayListBoundsCalculator::save() { - SkMatrixDispatchHelper::save(); - ClipBoundsDispatchHelper::save(); - SaveInfo info = SaveInfo(accumulator_); - saved_infos_.push_back(info); - accumulator_ = info.save(); -} -void DisplayListBoundsCalculator::restore() { - if (!saved_infos_.empty()) { - SkMatrixDispatchHelper::restore(); - ClipBoundsDispatchHelper::restore(); - SaveInfo info = saved_infos_.back(); - saved_infos_.pop_back(); - accumulator_ = info.restore(); - } -} - -void DisplayListBoundsCalculator::drawPaint() { - if (!bounds_cull_.isEmpty()) { - root_accumulator_.accumulate(bounds_cull_); - } -} -void DisplayListBoundsCalculator::drawColor(SkColor color, SkBlendMode mode) { - if (!bounds_cull_.isEmpty()) { - root_accumulator_.accumulate(bounds_cull_); - } -} -void DisplayListBoundsCalculator::drawLine(const SkPoint& p0, - const SkPoint& p1) { - SkRect bounds = SkRect::MakeLTRB(p0.fX, p0.fY, p1.fX, p1.fY).makeSorted(); - accumulateRect(bounds, true); -} -void DisplayListBoundsCalculator::drawRect(const SkRect& rect) { - accumulateRect(rect); -} -void DisplayListBoundsCalculator::drawOval(const SkRect& bounds) { - accumulateRect(bounds); -} -void DisplayListBoundsCalculator::drawCircle(const SkPoint& center, - SkScalar radius) { - accumulateRect(SkRect::MakeLTRB(center.fX - radius, center.fY - radius, - center.fX + radius, center.fY + radius)); -} -void DisplayListBoundsCalculator::drawRRect(const SkRRect& rrect) { - accumulateRect(rrect.getBounds()); -} -void DisplayListBoundsCalculator::drawDRRect(const SkRRect& outer, - const SkRRect& inner) { - accumulateRect(outer.getBounds()); -} -void DisplayListBoundsCalculator::drawPath(const SkPath& path) { - accumulateRect(path.getBounds()); -} -void DisplayListBoundsCalculator::drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) { - // This could be tighter if we compute where the start and end - // angles are and then also consider the quadrants swept and - // the center if specified. - accumulateRect(bounds); -} -void DisplayListBoundsCalculator::drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) { - if (count > 0) { - BoundsAccumulator ptBounds; - for (size_t i = 0; i < count; i++) { - ptBounds.accumulate(pts[i]); - } - accumulateRect(ptBounds.getBounds(), true); - } -} -void DisplayListBoundsCalculator::drawVertices(const sk_sp vertices, - SkBlendMode mode) { - accumulateRect(vertices->bounds()); -} -void DisplayListBoundsCalculator::drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) { - SkRect bounds = SkRect::Make(image->bounds()); - bounds.offset(point); - accumulateRect(bounds); -} -void DisplayListBoundsCalculator::drawImageRect( - const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint) { - accumulateRect(dst); -} -void DisplayListBoundsCalculator::drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) { - accumulateRect(dst); -} -void DisplayListBoundsCalculator::drawImageLattice( - const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) { - accumulateRect(dst); -} -void DisplayListBoundsCalculator::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) { - SkPoint quad[4]; - BoundsAccumulator atlasBounds; - for (int i = 0; i < count; i++) { - const SkRect& src = tex[i]; - xform[i].toQuad(src.width(), src.height(), quad); - for (int j = 0; j < 4; j++) { - atlasBounds.accumulate(quad[j]); - } - } - if (atlasBounds.isNotEmpty()) { - accumulateRect(atlasBounds.getBounds()); - } -} -void DisplayListBoundsCalculator::drawPicture(const sk_sp picture, - const SkMatrix* pic_matrix, - bool with_save_layer) { - // TODO(flar) cull rect really cannot be trusted in general, but it will - // work for SkPictures generated from our own PictureRecorder or any - // picture captured with an SkRTreeFactory or accurate bounds estimate. - SkRect bounds = picture->cullRect(); - if (pic_matrix) { - pic_matrix->mapRect(&bounds); - } - if (with_save_layer) { - accumulateRect(bounds); - } else { - matrix().mapRect(&bounds); - accumulator_->accumulate(bounds); - } -} -void DisplayListBoundsCalculator::drawDisplayList( - const sk_sp display_list) { - accumulateRect(display_list->bounds()); -} -void DisplayListBoundsCalculator::drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) { - accumulateRect(blob->bounds().makeOffset(x, y)); -} -void DisplayListBoundsCalculator::drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) { - // Constants from physical_shape_layer.cc - const SkScalar kLightHeight = 600; - const SkScalar kLightRadius = 800; - - SkShadowFlags flags = occludes - ? SkShadowFlags::kTransparentOccluder_ShadowFlag - : SkShadowFlags::kNone_ShadowFlag; - const SkRect& bounds = path.getBounds(); - SkScalar shadow_x = (bounds.left() + bounds.right()) / 2; - SkScalar shadow_y = bounds.top() - 600.0f; - SkRect shadow_bounds; - SkShadowUtils::GetLocalBounds( - matrix(), path, SkPoint3::Make(0, 0, elevation), - SkPoint3::Make(shadow_x, shadow_y, kLightHeight), kLightRadius, flags, - &shadow_bounds); - accumulateRect(shadow_bounds); -} - -void DisplayListBoundsCalculator::accumulateRect(const SkRect& rect, - bool forceStroke) { - SkRect dstRect = rect; - const SkPaint& p = paint(); - if (forceStroke) { - if (p.getStyle() == SkPaint::kFill_Style) { - setDrawStyle(SkPaint::kStroke_Style); - } else { - forceStroke = false; - } - } - if (p.canComputeFastBounds()) { - dstRect = p.computeFastBounds(rect, &dstRect); - matrix().mapRect(&dstRect); - accumulator_->accumulate(dstRect); - } else { - root_accumulator_.accumulate(bounds_cull_); - } - if (forceStroke) { - setDrawStyle(SkPaint::kFill_Style); - } -} - -DisplayListBoundsCalculator::SaveInfo::SaveInfo(BoundsAccumulator* accumulator) - : saved_accumulator_(accumulator) {} -BoundsAccumulator* DisplayListBoundsCalculator::SaveInfo::save() { - // No need to swap out the accumulator for a normal save - return saved_accumulator_; -} -BoundsAccumulator* DisplayListBoundsCalculator::SaveInfo::restore() { - return saved_accumulator_; -} - -DisplayListBoundsCalculator::SaveLayerInfo::SaveLayerInfo( - BoundsAccumulator* accumulator, - const SkMatrix& matrix) - : SaveInfo(accumulator), matrix_(matrix) {} -BoundsAccumulator* DisplayListBoundsCalculator::SaveLayerInfo::save() { - // Use the local layerAccumulator until restore is called and - // then transform (and adjust with paint if necessary) on restore() - return &layer_accumulator_; -} -BoundsAccumulator* DisplayListBoundsCalculator::SaveLayerInfo::restore() { - SkRect layer_bounds = layer_accumulator_.getBounds(); - matrix_.mapRect(&layer_bounds); - saved_accumulator_->accumulate(layer_bounds); - return saved_accumulator_; -} - -DisplayListBoundsCalculator::SaveLayerWithPaintInfo::SaveLayerWithPaintInfo( - DisplayListBoundsCalculator* calculator, - BoundsAccumulator* accumulator, - const SkMatrix& saveMatrix, - const SkPaint& savePaint) - : SaveLayerInfo(accumulator, saveMatrix), - calculator_(calculator), - paint_(savePaint) {} - -BoundsAccumulator* -DisplayListBoundsCalculator::SaveLayerWithPaintInfo::restore() { - SkRect layer_bounds = layer_accumulator_.getBounds(); - if (paint_.canComputeFastBounds()) { - layer_bounds = paint_.computeFastBounds(layer_bounds, &layer_bounds); - matrix_.mapRect(&layer_bounds); - saved_accumulator_->accumulate(layer_bounds); - } else { - calculator_->root_accumulator_.accumulate(calculator_->bounds_cull_); - } - return saved_accumulator_; -} - -} // namespace flutter diff --git a/flow/display_list_utils.h b/flow/display_list_utils.h deleted file mode 100644 index 68b9dc56b0120..0000000000000 --- a/flow/display_list_utils.h +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_FLOW_DISPLAY_LIST_UTILS_H_ -#define FLUTTER_FLOW_DISPLAY_LIST_UTILS_H_ - -#include "flutter/flow/display_list.h" - -#include "third_party/skia/include/core/SkMaskFilter.h" - -// This file contains various utility classes to ease implementing -// a Flutter DisplayList Dispatcher, including: -// -// IngoreAttributeDispatchHelper: -// IngoreClipDispatchHelper: -// IngoreTransformDispatchHelper -// Empty overrides of all of the associated methods of Dispatcher -// for dispatchers that only track some of the rendering operations -// -// SkPaintAttributeDispatchHelper: -// Tracks the attribute methods and maintains their state in an -// SkPaint object. -// SkMatrixTransformDispatchHelper: -// Tracks the transform methods and maintains their state in a -// (save/restore stack of) SkMatrix object. -// ClipBoundsDispatchHelper: -// Tracks the clip methods and maintains a culling box in a -// (save/restore stack of) SkRect culling rectangle. -// -// DisplayListBoundsCalculator: -// A class that can traverse an entire display list and compute -// a conservative estimate of the bounds of all of the rendering -// operations. - -namespace flutter { - -// A utility class that will ignore all Dispatcher methods relating -// to the setting of attributes. -class IngoreAttributeDispatchHelper : public virtual Dispatcher { - public: - void setAA(bool aa) override {} - void setDither(bool dither) override {} - void setInvertColors(bool invert) override {} - void setCaps(SkPaint::Cap cap) override {} - void setJoins(SkPaint::Join join) override {} - void setDrawStyle(SkPaint::Style style) override {} - void setStrokeWidth(SkScalar width) override {} - void setMiterLimit(SkScalar limit) override {} - void setColor(SkColor color) override {} - void setBlendMode(SkBlendMode mode) override {} - void setFilterQuality(SkFilterQuality quality) override {} - void setShader(sk_sp shader) override {} - void setImageFilter(sk_sp filter) override {} - void setColorFilter(sk_sp filter) override {} - void setMaskFilter(sk_sp filter) override {} - void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override {} -}; - -// A utility class that will ignore all Dispatcher methods relating -// to setting a clip. -class IngoreClipDispatchHelper : public virtual Dispatcher { - void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) override {} - void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) override {} - void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) override {} -}; - -// A utility class that will ignore all Dispatcher methods relating -// to modifying the transform. -class IngoreTransformDispatchHelper : public virtual Dispatcher { - public: - void translate(SkScalar tx, SkScalar ty) override {} - void scale(SkScalar sx, SkScalar sy) override {} - void rotate(SkScalar degrees) override {} - void skew(SkScalar sx, SkScalar sy) override {} - void transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) override {} - void transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) override {} -}; - -// A utility class that will monitor the Dispatcher methods relating -// to the rendering attributes and accumulate them into an SkPaint -// which can be accessed at any time via paint(). -class SkPaintDispatchHelper : public virtual Dispatcher { - public: - void setAA(bool aa) override; - void setDither(bool dither) override; - void setInvertColors(bool invert) override; - void setCaps(SkPaint::Cap cap) override; - void setJoins(SkPaint::Join join) override; - void setDrawStyle(SkPaint::Style style) override; - void setStrokeWidth(SkScalar width) override; - void setMiterLimit(SkScalar limit) override; - void setColor(SkColor color) override; - void setBlendMode(SkBlendMode mode) override; - void setFilterQuality(SkFilterQuality quality) override; - void setShader(sk_sp shader) override; - void setImageFilter(sk_sp filter) override; - void setColorFilter(sk_sp filter) override; - void setMaskFilter(sk_sp filter) override; - void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override; - - const SkPaint& paint() { return paint_; } - - private: - SkPaint paint_; - bool invert_colors_ = false; - sk_sp color_filter_; - - sk_sp makeColorFilter(); -}; - -class SkMatrixSource { - public: - virtual const SkMatrix& matrix() const = 0; -}; - -// A utility class that will monitor the Dispatcher methods relating -// to the transform and accumulate them into an SkMatrix which can -// be accessed at any time via getMatrix(). -// -// This class also implements an appropriate stack of transforms via -// its save() and restore() methods so those methods will need to be -// forwarded if overridden in more than one super class. -class SkMatrixDispatchHelper : public virtual Dispatcher, - public virtual SkMatrixSource { - public: - void translate(SkScalar tx, SkScalar ty) override; - void scale(SkScalar sx, SkScalar sy) override; - void rotate(SkScalar degrees) override; - void skew(SkScalar sx, SkScalar sy) override; - void transform2x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt) override; - void transform3x3(SkScalar mxx, - SkScalar mxy, - SkScalar mxt, - SkScalar myx, - SkScalar myy, - SkScalar myt, - SkScalar px, - SkScalar py, - SkScalar pt) override; - - void save() override; - void restore() override; - - const SkMatrix& matrix() const override { return matrix_; } - - protected: - void reset(); - - private: - SkMatrix matrix_; - std::vector saved_; -}; - -// A utility class that will monitor the Dispatcher methods relating -// to the clip and accumulate a conservative bounds into an SkRect -// which can be accessed at any time via getCullingBounds(). -// -// The subclass must implement a single virtual method matrix() -// which will happen automatically if the subclass also inherits -// from SkMatrixTransformDispatchHelper. -// -// This class also implements an appropriate stack of transforms via -// its save() and restore() methods so those methods will need to be -// forwarded if overridden in more than one super class. -class ClipBoundsDispatchHelper : public virtual Dispatcher, - private virtual SkMatrixSource { - public: - void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) override; - void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) override; - void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) override; - - void save() override; - void restore() override; - - const SkRect& getCullingBounds() const { return bounds_; } - - private: - SkRect bounds_; - std::vector saved_; - - void intersect(const SkRect& clipBounds); -}; - -class BoundsAccumulator { - public: - void accumulate(const SkPoint& p) { accumulate(p.fX, p.fY); } - void accumulate(SkScalar x, SkScalar y) { - if (min_x_ > x) - min_x_ = x; - if (min_y_ > y) - min_y_ = y; - if (max_x_ < x) - max_x_ = x; - if (max_y_ < y) - max_y_ = y; - } - void accumulate(const SkRect& r) { - if (r.fLeft <= r.fRight && r.fTop <= r.fBottom) { - accumulate(r.fLeft, r.fTop); - accumulate(r.fRight, r.fBottom); - } - } - - bool isEmpty() const { return min_x_ >= max_x_ || min_y_ >= max_y_; } - bool isNotEmpty() const { return min_x_ < max_x_ && min_y_ < max_y_; } - - SkRect getBounds() const { - return (max_x_ > min_x_ && max_y_ > min_y_) - ? SkRect::MakeLTRB(min_x_, min_y_, max_x_, max_y_) - : SkRect::MakeEmpty(); - } - - private: - SkScalar min_x_ = std::numeric_limits::infinity(); - SkScalar min_y_ = std::numeric_limits::infinity(); - SkScalar max_x_ = -std::numeric_limits::infinity(); - SkScalar max_y_ = -std::numeric_limits::infinity(); -}; - -// This class implements all rendering methods and computes a liberal -// bounds of the rendering operations. -class DisplayListBoundsCalculator final - : public virtual Dispatcher, - public virtual SkPaintDispatchHelper, - public virtual SkMatrixDispatchHelper, - public virtual ClipBoundsDispatchHelper { - public: - // Construct a Calculator to determine the bounds of a list of - // DisplayList dispatcher method calls. Since 2 of the method calls - // have no intrinsic size because they render to the entire available, - // the |cullRect| provides a bounds for them to include. - DisplayListBoundsCalculator(const SkRect& cull_rect = SkRect::MakeEmpty()) - : accumulator_(&root_accumulator_), bounds_cull_(cull_rect) {} - - void saveLayer(const SkRect* bounds, bool with_paint) override; - void save() override; - void restore() override; - - void drawPaint() override; - void drawColor(SkColor color, SkBlendMode mode) override; - void drawLine(const SkPoint& p0, const SkPoint& p1) override; - void drawRect(const SkRect& rect) override; - void drawOval(const SkRect& bounds) override; - void drawCircle(const SkPoint& center, SkScalar radius) override; - void drawRRect(const SkRRect& rrect) override; - void drawDRRect(const SkRRect& outer, const SkRRect& inner) override; - void drawPath(const SkPath& path) override; - void drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) override; - void drawPoints(SkCanvas::PointMode mode, - uint32_t count, - const SkPoint pts[]) override; - void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; - void drawImage(const sk_sp image, - const SkPoint point, - const SkSamplingOptions& sampling) override; - void drawImageRect(const sk_sp image, - const SkRect& src, - const SkRect& dst, - const SkSamplingOptions& sampling, - SkCanvas::SrcRectConstraint constraint) override; - void drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - SkFilterMode filter) override; - void drawImageLattice(const sk_sp image, - const SkCanvas::Lattice& lattice, - const SkRect& dst, - SkFilterMode filter, - bool with_paint) override; - void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const SkColor colors[], - int count, - SkBlendMode mode, - const SkSamplingOptions& sampling, - const SkRect* cullRect) override; - void drawPicture(const sk_sp picture, - const SkMatrix* matrix, - bool with_save_layer) override; - void drawDisplayList(const sk_sp display_list) override; - void drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) override; - void drawShadow(const SkPath& path, - const SkColor color, - const SkScalar elevation, - bool occludes) override; - - SkRect getBounds() { return accumulator_->getBounds(); } - - private: - // current accumulator based on saveLayer history - BoundsAccumulator* accumulator_; - - // Only used for drawColor and drawPaint and paint objects that - // cannot support fast bounds. - SkRect bounds_cull_; - BoundsAccumulator root_accumulator_; - - class SaveInfo { - public: - SaveInfo(BoundsAccumulator* accumulator); - virtual ~SaveInfo() = default; - - virtual BoundsAccumulator* save(); - virtual BoundsAccumulator* restore(); - - protected: - BoundsAccumulator* saved_accumulator_; - }; - - class SaveLayerInfo : public SaveInfo { - public: - SaveLayerInfo(BoundsAccumulator* accumulator, const SkMatrix& matrix); - virtual ~SaveLayerInfo() = default; - - BoundsAccumulator* save() override; - BoundsAccumulator* restore() override; - - protected: - BoundsAccumulator layer_accumulator_; - const SkMatrix matrix_; - }; - - class SaveLayerWithPaintInfo : public SaveLayerInfo { - public: - SaveLayerWithPaintInfo(DisplayListBoundsCalculator* calculator, - BoundsAccumulator* accumulator, - const SkMatrix& save_matrix, - const SkPaint& save_paint); - virtual ~SaveLayerWithPaintInfo() = default; - - BoundsAccumulator* restore() override; - - protected: - DisplayListBoundsCalculator* calculator_; - - SkPaint paint_; - }; - - std::vector saved_infos_; - - void accumulateRect(const SkRect& rect, bool force_stroke = false); -}; - -} // namespace flutter - -#endif // FLUTTER_FLOW_DISPLAY_LIST_UTILS_H_ diff --git a/flow/layers/display_list_layer.cc b/flow/layers/display_list_layer.cc deleted file mode 100644 index a40cc314c82ec..0000000000000 --- a/flow/layers/display_list_layer.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/flow/layers/display_list_layer.h" - -#include "flutter/flow/display_list_canvas.h" - -namespace flutter { - -DisplayListLayer::DisplayListLayer(const SkPoint& offset, - sk_sp display_list, - bool is_complex, - bool will_change) - : offset_(offset), - display_list_(display_list), - is_complex_(is_complex), - will_change_(will_change) {} - -#ifdef FLUTTER_ENABLE_DIFF_CONTEXT - -bool DisplayListLayer::IsReplacing(DiffContext* context, - const Layer* layer) const { - // Only return true for identical display lists; This way - // ContainerLayer::DiffChildren can detect when a display list layer - // got inserted between other display list layers - auto old_layer = layer->as_display_list_layer(); - return old_layer != nullptr && offset_ == old_layer->offset_ && - Compare(context->statistics(), this, old_layer); -} - -void DisplayListLayer::Diff(DiffContext* context, const Layer* old_layer) { - DiffContext::AutoSubtreeRestore subtree(context); - if (!context->IsSubtreeDirty()) { -#ifndef NDEBUG - FML_DCHECK(old_layer); - auto prev = old_layer->as_display_list_layer(); - DiffContext::Statistics dummy_statistics; - // IsReplacing has already determined that the display list is same - FML_DCHECK(prev->offset_ == offset_ && - Compare(dummy_statistics, this, prev)); -#endif - } - context->PushTransform(SkMatrix::Translate(offset_.x(), offset_.y())); - context->AddLayerBounds(display_list_->bounds()); - context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion()); -} - -bool DisplayListLayer::Compare(DiffContext::Statistics& statistics, - const DisplayListLayer* l1, - const DisplayListLayer* l2) { - const auto& dl1 = l1->display_list_; - const auto& dl2 = l2->display_list_; - if (dl1.get() == dl2.get()) { - statistics.AddSameInstancePicture(); - return true; - } - const auto op_cnt_1 = dl1->op_count(); - const auto op_cnt_2 = dl2->op_count(); - const auto op_bytes_1 = dl1->bytes(); - const auto op_bytes_2 = dl2->bytes(); - if (op_cnt_1 != op_cnt_2 || op_bytes_1 != op_bytes_2 || - dl1->bounds() != dl2->bounds()) { - statistics.AddNewPicture(); - return false; - } - - if (op_bytes_1 > kMaxBytesToCompare) { - statistics.AddPictureTooComplexToCompare(); - return false; - } - - statistics.AddDeepComparePicture(); - - auto res = dl1->Equals(*dl2); - if (res) { - statistics.AddDifferentInstanceButEqualPicture(); - } else { - statistics.AddNewPicture(); - } - return res; -} - -#endif // FLUTTER_ENABLE_DIFF_CONTEXT - -void DisplayListLayer::Preroll(PrerollContext* context, - const SkMatrix& matrix) { - TRACE_EVENT0("flutter", "DisplayListLayer::Preroll"); - - DisplayList* disp_list = display_list(); - - if (auto* cache = context->raster_cache) { - TRACE_EVENT0("flutter", "DisplayListLayer::RasterCache (Preroll)"); - - SkMatrix ctm = matrix; - ctm.preTranslate(offset_.x(), offset_.y()); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - ctm = RasterCache::GetIntegralTransCTM(ctm); -#endif - cache->Prepare(context->gr_context, disp_list, ctm, - context->dst_color_space, is_complex_, will_change_); - } - - SkRect bounds = disp_list->bounds().makeOffset(offset_.x(), offset_.y()); - set_paint_bounds(bounds); -} - -void DisplayListLayer::Paint(PaintContext& context) const { - TRACE_EVENT0("flutter", "DisplayListLayer::Paint"); - FML_DCHECK(display_list_.get()); - FML_DCHECK(needs_painting(context)); - - SkAutoCanvasRestore save(context.leaf_nodes_canvas, true); - context.leaf_nodes_canvas->translate(offset_.x(), offset_.y()); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM( - context.leaf_nodes_canvas->getTotalMatrix())); -#endif - - if (context.raster_cache && - context.raster_cache->Draw(*display_list(), *context.leaf_nodes_canvas)) { - TRACE_EVENT_INSTANT0("flutter", "raster cache hit"); - return; - } - - display_list()->RenderTo(context.leaf_nodes_canvas); -} - -} // namespace flutter diff --git a/flow/layers/display_list_layer.h b/flow/layers/display_list_layer.h deleted file mode 100644 index 4760d2d200654..0000000000000 --- a/flow/layers/display_list_layer.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_FLOW_LAYERS_DISPLAY_LIST_LAYER_H_ -#define FLUTTER_FLOW_LAYERS_DISPLAY_LIST_LAYER_H_ - -#include "flutter/flow/display_list.h" -#include "flutter/flow/layers/layer.h" - -namespace flutter { - -class DisplayListLayer : public Layer { - public: - static constexpr size_t kMaxBytesToCompare = 10000; - - DisplayListLayer(const SkPoint& offset, - sk_sp display_list, - bool is_complex, - bool will_change); - - DisplayList* display_list() const { return display_list_.get(); } - -#ifdef FLUTTER_ENABLE_DIFF_CONTEXT - - bool IsReplacing(DiffContext* context, const Layer* layer) const override; - - void Diff(DiffContext* context, const Layer* old_layer) override; - - const DisplayListLayer* as_display_list_layer() const override { - return this; - } - -#endif // FLUTTER_ENABLE_DIFF_CONTEXT - - void Preroll(PrerollContext* frame, const SkMatrix& matrix) override; - - void Paint(PaintContext& context) const override; - - private: - SkPoint offset_; - sk_sp display_list_; - bool is_complex_ = false; - bool will_change_ = false; - -#ifdef FLUTTER_ENABLE_DIFF_CONTEXT - - sk_sp SerializedPicture() const; - mutable sk_sp cached_serialized_picture_; - static bool Compare(DiffContext::Statistics& statistics, - const DisplayListLayer* l1, - const DisplayListLayer* l2); - -#endif // FLUTTER_ENABLE_DIFF_CONTEXT - - FML_DISALLOW_COPY_AND_ASSIGN(DisplayListLayer); -}; - -} // namespace flutter - -#endif // FLUTTER_FLOW_LAYERS_DISPLAY_LIST_LAYER_H_ diff --git a/flow/layers/display_list_layer_unittests.cc b/flow/layers/display_list_layer_unittests.cc deleted file mode 100644 index ad1842b8c5a73..0000000000000 --- a/flow/layers/display_list_layer_unittests.cc +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#define FML_USED_ON_EMBEDDER - -#include "flutter/flow/layers/display_list_layer.h" - -#include "flutter/flow/testing/diff_context_test.h" -#include "flutter/fml/macros.h" -#include "flutter/testing/mock_canvas.h" - -#ifndef SUPPORT_FRACTIONAL_TRANSLATION -#include "flutter/flow/raster_cache.h" -#endif - -namespace flutter { -namespace testing { - -using DisplayListLayerTest = LayerTest; - -#ifndef NDEBUG -TEST_F(DisplayListLayerTest, PaintBeforePrerollInvalidDisplayListDies) { - const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); - auto layer = std::make_shared( - layer_offset, sk_ref_sp(nullptr), false, false); - - EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "display_list_\\.get\\(\\)"); -} - -TEST_F(DisplayListLayerTest, PaintBeforePrerollDies) { - const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); - auto layer = std::make_shared( - layer_offset, sk_make_sp(), false, false); - - EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(context\\)"); -} - -TEST_F(DisplayListLayerTest, PaintingEmptyLayerDies) { - const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); - auto layer = std::make_shared( - layer_offset, sk_make_sp(), false, false); - - layer->Preroll(preroll_context(), SkMatrix()); - EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting(paint_context())); - - EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(context\\)"); -} - -TEST_F(DisplayListLayerTest, InvalidDisplayListDies) { - const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); - auto layer = std::make_shared( - layer_offset, sk_ref_sp(nullptr), false, false); - - // Crashes reading a nullptr. - EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()), ""); -} -#endif - -TEST_F(DisplayListLayerTest, SimpleDisplayList) { - const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f); - const SkMatrix layer_offset_matrix = - SkMatrix::Translate(layer_offset.fX, layer_offset.fY); - const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); - DisplayListBuilder builder; - builder.drawRect(picture_bounds); - auto display_list = builder.Build(); - auto layer = std::make_shared(layer_offset, display_list, - false, false); - - layer->Preroll(preroll_context(), SkMatrix()); - EXPECT_EQ(layer->paint_bounds(), - picture_bounds.makeOffset(layer_offset.fX, layer_offset.fY)); - EXPECT_EQ(layer->display_list(), display_list.get()); - EXPECT_TRUE(layer->needs_painting(paint_context())); - - layer->Paint(paint_context()); - auto expected_draw_calls = std::vector( - {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::ConcatMatrixData{SkM44(layer_offset_matrix)}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 1, MockCanvas::SetMatrixData{SkM44( - RasterCache::GetIntegralTransCTM(layer_offset_matrix))}}, -#endif - MockCanvas::DrawCall{ - 1, MockCanvas::DrawRectData{picture_bounds, SkPaint()}}, - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}); - EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls); -} - -#ifdef FLUTTER_ENABLE_DIFF_CONTEXT - -using DisplayListLayerDiffTest = DiffContextTest; - -TEST_F(DisplayListLayerDiffTest, SimpleDisplayList) { - auto display_list = CreateDisplayList(SkRect::MakeLTRB(10, 10, 60, 60), 1); - - MockLayerTree tree1; - tree1.root()->Add(CreateDisplayListLayer(display_list)); - - auto damage = DiffLayerTree(tree1, MockLayerTree()); - EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(10, 10, 60, 60)); - - MockLayerTree tree2; - tree2.root()->Add(CreateDisplayListLayer(display_list)); - - damage = DiffLayerTree(tree2, tree1); - EXPECT_TRUE(damage.frame_damage.isEmpty()); - - MockLayerTree tree3; - damage = DiffLayerTree(tree3, tree2); - EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(10, 10, 60, 60)); -} - -TEST_F(DisplayListLayerDiffTest, DisplayListCompare) { - MockLayerTree tree1; - auto display_list1 = CreateDisplayList(SkRect::MakeLTRB(10, 10, 60, 60), 1); - tree1.root()->Add(CreateDisplayListLayer(display_list1)); - - auto damage = DiffLayerTree(tree1, MockLayerTree()); - EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(10, 10, 60, 60)); - - MockLayerTree tree2; - auto display_list2 = CreateDisplayList(SkRect::MakeLTRB(10, 10, 60, 60), 1); - tree2.root()->Add(CreateDisplayListLayer(display_list2)); - - damage = DiffLayerTree(tree2, tree1); - EXPECT_EQ(damage.frame_damage, SkIRect::MakeEmpty()); - - MockLayerTree tree3; - auto display_list3 = CreateDisplayList(SkRect::MakeLTRB(10, 10, 60, 60), 1); - // add offset - tree3.root()->Add( - CreateDisplayListLayer(display_list3, SkPoint::Make(10, 10))); - - damage = DiffLayerTree(tree3, tree2); - EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(10, 10, 70, 70)); - - MockLayerTree tree4; - // different color - auto display_list4 = CreateDisplayList(SkRect::MakeLTRB(10, 10, 60, 60), 2); - tree4.root()->Add( - CreateDisplayListLayer(display_list4, SkPoint::Make(10, 10))); - - damage = DiffLayerTree(tree4, tree3); - EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(20, 20, 70, 70)); -} - -#endif - -} // namespace testing -} // namespace flutter diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 9ad88e6b7843e..ec7c00d6247fb 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -64,7 +64,6 @@ struct PrerollContext { }; class PictureLayer; -class DisplayListLayer; class PerformanceOverlayLayer; class TextureLayer; @@ -240,9 +239,6 @@ class Layer { #ifdef FLUTTER_ENABLE_DIFF_CONTEXT virtual const PictureLayer* as_picture_layer() const { return nullptr; } - virtual const DisplayListLayer* as_display_list_layer() const { - return nullptr; - } virtual const TextureLayer* as_texture_layer() const { return nullptr; } virtual const PerformanceOverlayLayer* as_performance_overlay_layer() const { return nullptr; diff --git a/flow/layers/picture_layer_unittests.cc b/flow/layers/picture_layer_unittests.cc index dba13d117ca2b..cdd6e6b75fc2b 100644 --- a/flow/layers/picture_layer_unittests.cc +++ b/flow/layers/picture_layer_unittests.cc @@ -57,6 +57,7 @@ TEST_F(PictureLayerTest, PaintingEmptyLayerDies) { EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), "needs_painting\\(context\\)"); } +#endif TEST_F(PictureLayerTest, InvalidPictureDies) { const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); @@ -66,7 +67,6 @@ TEST_F(PictureLayerTest, InvalidPictureDies) { // Crashes reading a nullptr. EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()), ""); } -#endif TEST_F(PictureLayerTest, SimplePicture) { const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f); diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index d1671a1c1ab13..e748520006724 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -56,28 +56,6 @@ static bool CanRasterizePicture(SkPicture* picture) { if (!cull_rect.isFinite()) { // Cannot attempt to rasterize into an infinitely large surface. - FML_LOG(INFO) << "Attempted to raster cache non-finite picture"; - return false; - } - - return true; -} - -static bool CanRasterizeDisplayList(DisplayList* display_list) { - if (display_list == nullptr) { - return false; - } - - const SkRect cull_rect = display_list->bounds(); - - if (cull_rect.isEmpty()) { - // No point in ever rasterizing an empty display list. - return false; - } - - if (!cull_rect.isFinite()) { - // Cannot attempt to rasterize into an infinitely large surface. - FML_LOG(INFO) << "Attempted to raster cache non-finite display list"; return false; } @@ -110,32 +88,6 @@ static bool IsPictureWorthRasterizing(SkPicture* picture, return picture->approximateOpCount() > 5; } -static bool IsDisplayListWorthRasterizing(DisplayList* display_list, - bool will_change, - bool is_complex) { - if (will_change) { - // If the display list is going to change in the future, there is no point - // in doing to extra work to rasterize. - return false; - } - - if (!CanRasterizeDisplayList(display_list)) { - // No point in deciding whether the display list is worth rasterizing if it - // cannot be rasterized at all. - return false; - } - - if (is_complex) { - // The caller seems to have extra information about the display list and - // thinks the display list is always worth rasterizing. - return true; - } - - // TODO(abarth): We should find a better heuristic here that lets us avoid - // wasting memory on trivial layers that are easy to re-rasterize every frame. - return display_list->op_count() > 5; -} - /// @note Procedure doesn't copy all closures. static std::unique_ptr Rasterize( GrDirectContext* context, @@ -184,17 +136,6 @@ std::unique_ptr RasterCache::RasterizePicture( [=](SkCanvas* canvas) { canvas->drawPicture(picture); }); } -std::unique_ptr RasterCache::RasterizeDisplayList( - DisplayList* display_list, - GrDirectContext* context, - const SkMatrix& ctm, - SkColorSpace* dst_color_space, - bool checkerboard) const { - return Rasterize(context, ctm, dst_color_space, checkerboard, - display_list->bounds(), - [=](SkCanvas* canvas) { display_list->RenderTo(canvas); }); -} - void RasterCache::Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm) { @@ -282,52 +223,6 @@ bool RasterCache::Prepare(GrDirectContext* context, return true; } -bool RasterCache::Prepare(GrDirectContext* context, - DisplayList* display_list, - const SkMatrix& transformation_matrix, - SkColorSpace* dst_color_space, - bool is_complex, - bool will_change) { - // Disabling caching when access_threshold is zero is historic behavior. - if (access_threshold_ == 0) { - return false; - } - if (picture_cached_this_frame_ >= picture_cache_limit_per_frame_) { - return false; - } - if (!IsDisplayListWorthRasterizing(display_list, will_change, is_complex)) { - // We only deal with display lists that are worthy of rasterization. - return false; - } - - // Decompose the matrix (once) for all subsequent operations. We want to make - // sure to avoid volumetric distortions while accounting for scaling. - const MatrixDecomposition matrix(transformation_matrix); - - if (!matrix.IsValid()) { - // The matrix was singular. No point in going further. - return false; - } - - DisplayListRasterCacheKey cache_key(display_list->unique_id(), - transformation_matrix); - - // Creates an entry, if not present prior. - Entry& entry = display_list_cache_[cache_key]; - if (entry.access_count < access_threshold_) { - // Frame threshold has not yet been reached. - return false; - } - - if (!entry.image) { - entry.image = - RasterizeDisplayList(display_list, context, transformation_matrix, - dst_color_space, checkerboard_images_); - picture_cached_this_frame_++; - } - return true; -} - bool RasterCache::Draw(const SkPicture& picture, SkCanvas& canvas) const { PictureRasterCacheKey cache_key(picture.uniqueID(), canvas.getTotalMatrix()); auto it = picture_cache_.find(cache_key); @@ -347,27 +242,6 @@ bool RasterCache::Draw(const SkPicture& picture, SkCanvas& canvas) const { return false; } -bool RasterCache::Draw(const DisplayList& display_list, - SkCanvas& canvas) const { - DisplayListRasterCacheKey cache_key(display_list.unique_id(), - canvas.getTotalMatrix()); - auto it = display_list_cache_.find(cache_key); - if (it == display_list_cache_.end()) { - return false; - } - - Entry& entry = it->second; - entry.access_count++; - entry.used_this_frame = true; - - if (entry.image) { - entry.image->draw(canvas, nullptr); - return true; - } - - return false; -} - bool RasterCache::Draw(const Layer* layer, SkCanvas& canvas, SkPaint* paint) const { @@ -391,7 +265,6 @@ bool RasterCache::Draw(const Layer* layer, void RasterCache::SweepAfterFrame() { SweepOneCacheAfterFrame(picture_cache_); - SweepOneCacheAfterFrame(display_list_cache_); SweepOneCacheAfterFrame(layer_cache_); picture_cached_this_frame_ = 0; TraceStatsToTimeline(); @@ -399,13 +272,11 @@ void RasterCache::SweepAfterFrame() { void RasterCache::Clear() { picture_cache_.clear(); - display_list_cache_.clear(); layer_cache_.clear(); } size_t RasterCache::GetCachedEntriesCount() const { - return layer_cache_.size() + picture_cache_.size() + - display_list_cache_.size(); + return layer_cache_.size() + picture_cache_.size(); } size_t RasterCache::GetLayerCachedEntriesCount() const { @@ -416,10 +287,6 @@ size_t RasterCache::GetPictureCachedEntriesCount() const { return picture_cache_.size(); } -size_t RasterCache::GetDisplayListCachedEntriesCount() const { - return display_list_cache_.size(); -} - void RasterCache::SetCheckboardCacheImages(bool checkerboard) { if (checkerboard_images_ == checkerboard) { return; @@ -438,10 +305,7 @@ void RasterCache::TraceStatsToTimeline() const { "LayerCount", layer_cache_.size(), "LayerMBytes", EstimateLayerCacheByteSize() / kMegaByteSizeInBytes, "PictureCount", picture_cache_.size(), "PictureMBytes", - EstimatePictureCacheByteSize() / kMegaByteSizeInBytes, - "DisplayListCount", display_list_cache_.size(), - "DisplayListMBytes", - EstimateDisplayListCacheByteSize() / kMegaByteSizeInBytes); + EstimatePictureCacheByteSize() / kMegaByteSizeInBytes); #endif // !FLUTTER_RELEASE } @@ -466,14 +330,4 @@ size_t RasterCache::EstimatePictureCacheByteSize() const { return picture_cache_bytes; } -size_t RasterCache::EstimateDisplayListCacheByteSize() const { - size_t display_list_cache_bytes = 0; - for (const auto& item : display_list_cache_) { - if (item.second.image) { - display_list_cache_bytes += item.second.image->image_bytes(); - } - } - return display_list_cache_bytes; -} - } // namespace flutter diff --git a/flow/raster_cache.h b/flow/raster_cache.h index a440ade7919d9..e2b317cb55d11 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -8,7 +8,6 @@ #include #include -#include "flutter/flow/display_list.h" #include "flutter/flow/raster_cache_key.h" #include "flutter/fml/macros.h" #include "flutter/fml/memory/weak_ptr.h" @@ -75,12 +74,6 @@ class RasterCache { const SkMatrix& ctm, SkColorSpace* dst_color_space, bool checkerboard) const; - virtual std::unique_ptr RasterizeDisplayList( - DisplayList* display_list, - GrDirectContext* context, - const SkMatrix& ctm, - SkColorSpace* dst_color_space, - bool checkerboard) const; /** * @brief Rasterize an engine Layer and produce a RasterCacheResult @@ -145,12 +138,6 @@ class RasterCache { SkColorSpace* dst_color_space, bool is_complex, bool will_change); - bool Prepare(GrDirectContext* context, - DisplayList* display_list, - const SkMatrix& transformation_matrix, - SkColorSpace* dst_color_space, - bool is_complex, - bool will_change); void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm); @@ -159,11 +146,6 @@ class RasterCache { // Return true if it's found and drawn. bool Draw(const SkPicture& picture, SkCanvas& canvas) const; - // Find the raster cache for the display list and draw it to the canvas. - // - // Return true if it's found and drawn. - bool Draw(const DisplayList& display_list, SkCanvas& canvas) const; - // Find the raster cache for the layer and draw it to the canvas. // // Additional paint can be given to change how the raster cache is drawn @@ -186,8 +168,6 @@ class RasterCache { size_t GetPictureCachedEntriesCount() const; - size_t GetDisplayListCachedEntriesCount() const; - /** * @brief Estimate how much memory is used by picture raster cache entries in * bytes. @@ -198,16 +178,6 @@ class RasterCache { */ size_t EstimatePictureCacheByteSize() const; - /** - * @brief Estimate how much memory is used by display list raster cache - * entries in bytes. - * - * Only SkImage's memory usage is counted as other objects are often much - * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to - * estimate the SkImage memory usage. - */ - size_t EstimateDisplayListCacheByteSize() const; - /** * @brief Estimate how much memory is used by layer raster cache entries in * bytes. @@ -246,7 +216,6 @@ class RasterCache { const size_t picture_cache_limit_per_frame_; size_t picture_cached_this_frame_ = 0; mutable PictureRasterCacheKey::Map picture_cache_; - mutable DisplayListRasterCacheKey::Map display_list_cache_; mutable LayerRasterCacheKey::Map layer_cache_; bool checkerboard_images_; diff --git a/flow/raster_cache_key.h b/flow/raster_cache_key.h index 21d6bfe3dfdcb..cc4c5fe2b0c7d 100644 --- a/flow/raster_cache_key.h +++ b/flow/raster_cache_key.h @@ -52,9 +52,6 @@ class RasterCacheKey { // The ID is the uint32_t picture uniqueID using PictureRasterCacheKey = RasterCacheKey; -// The ID is the uint32_t DisplayList uniqueID -using DisplayListRasterCacheKey = RasterCacheKey; - class Layer; // The ID is the uint64_t layer unique_id diff --git a/flow/testing/diff_context_test.cc b/flow/testing/diff_context_test.cc index 74f26f780c659..1321c617ef12a 100644 --- a/flow/testing/diff_context_test.cc +++ b/flow/testing/diff_context_test.cc @@ -42,20 +42,6 @@ std::shared_ptr DiffContextTest::CreatePictureLayer( offset, SkiaGPUObject(picture, unref_queue()), false, false); } -sk_sp DiffContextTest::CreateDisplayList(const SkRect& bounds, - SkColor color) { - DisplayListBuilder builder; - builder.setColor(color); - builder.drawRect(bounds); - return builder.Build(); -} - -std::shared_ptr DiffContextTest::CreateDisplayListLayer( - sk_sp display_list, - const SkPoint& offset) { - return std::make_shared(offset, display_list, false, false); -} - std::shared_ptr DiffContextTest::CreateContainerLayer( std::initializer_list> layers) { auto res = std::make_shared(); diff --git a/flow/testing/diff_context_test.h b/flow/testing/diff_context_test.h index 75341146d98e6..5c5b574b735ac 100644 --- a/flow/testing/diff_context_test.h +++ b/flow/testing/diff_context_test.h @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "flutter/flow/layers/container_layer.h" -#include "flutter/flow/layers/display_list_layer.h" #include "flutter/flow/layers/picture_layer.h" #include "flutter/flow/testing/skia_gpu_object_layer_test.h" #include "third_party/skia/include/core/SkPicture.h" @@ -49,14 +48,6 @@ class DiffContextTest : public ThreadTest { sk_sp picture, const SkPoint& offset = SkPoint::Make(0, 0)); - // Create display list consisting of filled rect with given color; Being able - // to specify different color is useful to test deep comparison of pictures - sk_sp CreateDisplayList(const SkRect& bounds, uint32_t color); - - std::shared_ptr CreateDisplayListLayer( - sk_sp display_list, - const SkPoint& offset = SkPoint::Make(0, 0)); - std::shared_ptr CreateContainerLayer( std::initializer_list> layers); diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index e7c2b3ea151cc..c3e5377287697 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -10,7 +10,6 @@ #include "flutter/flow/layers/clip_rrect_layer.h" #include "flutter/flow/layers/color_filter_layer.h" #include "flutter/flow/layers/container_layer.h" -#include "flutter/flow/layers/display_list_layer.h" #include "flutter/flow/layers/image_filter_layer.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/layers/layer_tree.h" @@ -266,17 +265,10 @@ void SceneBuilder::addPicture(double dx, double dy, Picture* picture, int hints) { - if (picture->picture()) { - auto layer = std::make_unique( - SkPoint::Make(dx, dy), UIDartState::CreateGPUObject(picture->picture()), - !!(hints & 1), !!(hints & 2)); - AddLayer(std::move(layer)); - } else { - auto layer = std::make_unique( - SkPoint::Make(dx, dy), picture->display_list(), !!(hints & 1), - !!(hints & 2)); - AddLayer(std::move(layer)); - } + auto layer = std::make_unique( + SkPoint::Make(dx, dy), UIDartState::CreateGPUObject(picture->picture()), + !!(hints & 1), !!(hints & 2)); + AddLayer(std::move(layer)); } void SceneBuilder::addTexture(double dx, diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index fee3127f06dbe..728540c2d4dd4 100644 --- a/lib/ui/painting/canvas.cc +++ b/lib/ui/painting/canvas.cc @@ -85,7 +85,6 @@ fml::RefPtr Canvas::Create(PictureRecorder* recorder, fml::RefPtr canvas = fml::MakeRefCounted( recorder->BeginRecording(SkRect::MakeLTRB(left, top, right, bottom))); recorder->set_canvas(canvas); - canvas->display_list_recorder_ = recorder->display_list_recorder(); return canvas; } @@ -384,19 +383,8 @@ void Canvas::drawImageNine(const CanvasImage* image, center.round(&icenter); SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom); auto filter = ImageFilter::FilterModeFromIndex(bitmapSamplingIndex); - if (display_list_recorder_) { - // SkCanvas turns a simple 2-rect DrawImageNine operation into a - // drawImageLattice operation which has arrays to allocate and - // pass along. For simplicity, we will bypass the canvas and ask - // the recorder to record our paint attributes and record a much - // simpler DrawImageNineOp record directly. - display_list_recorder_->RecordPaintAttributes( - paint.paint(), DisplayListCanvasRecorder::DrawType::kImageOpType); - builder()->drawImageNine(image->image(), icenter, dst, filter); - } else { - canvas_->drawImageNine(image->image().get(), icenter, dst, filter, - paint.paint()); - } + canvas_->drawImageNine(image->image().get(), icenter, dst, filter, + paint.paint()); } void Canvas::drawPicture(Picture* picture) { @@ -408,17 +396,7 @@ void Canvas::drawPicture(Picture* picture) { ToDart("Canvas.drawPicture called with non-genuine Picture.")); return; } - if (picture->picture()) { - canvas_->drawPicture(picture->picture().get()); - } else if (picture->display_list()) { - if (display_list_recorder_) { - builder()->drawDisplayList(picture->display_list()); - } else { - picture->display_list()->RenderTo(canvas_); - } - } else { - FML_DCHECK(false); - } + canvas_->drawPicture(picture->picture().get()); } void Canvas::drawPoints(const Paint& paint, @@ -499,24 +477,13 @@ void Canvas::drawShadow(const CanvasPath* path, ToDart("Canvas.drawShader called with non-genuine Path.")); return; } - if (display_list_recorder_) { - // The DrawShadow mechanism results in non-public operations to be - // performed on the canvas involving an SkDrawShadowRec. Since we - // cannot include the header that defines that structure, we cannot - // record an operation that it injects into an SkCanvas. To prevent - // that situation we bypass the canvas interface and inject the - // shadow parameters directly into the underlying DisplayList. - // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 - builder()->drawShadow(path->path(), color, elevation, transparentOccluder); - } else { - SkScalar dpr = UIDartState::Current() - ->platform_configuration() - ->get_window(0) - ->viewport_metrics() - .device_pixel_ratio; - flutter::PhysicalShapeLayer::DrawShadow( - canvas_, path->path(), color, elevation, transparentOccluder, dpr); - } + SkScalar dpr = UIDartState::Current() + ->platform_configuration() + ->get_window(0) + ->viewport_metrics() + .device_pixel_ratio; + flutter::PhysicalShapeLayer::DrawShadow(canvas_, path->path(), color, + elevation, transparentOccluder, dpr); } void Canvas::Invalidate() { diff --git a/lib/ui/painting/canvas.h b/lib/ui/painting/canvas.h index ca328d310dbb6..cf067d2b3f95a 100644 --- a/lib/ui/painting/canvas.h +++ b/lib/ui/painting/canvas.h @@ -180,17 +180,6 @@ class Canvas : public RefCountedDartWrappable { // which does not transfer ownership. For this reason, we hold a raw // pointer and manually set to null in Clear. SkCanvas* canvas_; - - // A copy of the recorder used by the SkCanvas->DisplayList adapter for cases - // where we cannot record the SkCanvas method call through the various OnOp() - // virtual methods or where we can be more efficient by talking directly in - // the DisplayList operation lexicon. The recorder has a method for recording - // paint attributes from an SkPaint and an operation type as well as access - // to the raw DisplayListBuilder for emitting custom rendering operations. - sk_sp display_list_recorder_; - sk_sp builder() { - return display_list_recorder_->builder(); - } }; } // namespace flutter diff --git a/lib/ui/painting/image_dispose_unittests.cc b/lib/ui/painting/image_dispose_unittests.cc index 3a673328932ea..245d0a58ee631 100644 --- a/lib/ui/painting/image_dispose_unittests.cc +++ b/lib/ui/painting/image_dispose_unittests.cc @@ -6,10 +6,8 @@ #include "flutter/common/task_runners.h" #include "flutter/fml/synchronization/waitable_event.h" -#include "flutter/lib/ui/painting/canvas.h" #include "flutter/lib/ui/painting/image.h" #include "flutter/lib/ui/painting/picture.h" -#include "flutter/lib/ui/painting/picture_recorder.h" #include "flutter/runtime/dart_vm.h" #include "flutter/shell/common/shell_test.h" #include "flutter/shell/common/thread_host.h" @@ -33,7 +31,6 @@ class ImageDisposeTest : public ShellTest { fml::AutoResetWaitableEvent message_latch_; sk_sp current_picture_; - sk_sp current_display_list_; sk_sp current_image_; }; @@ -48,14 +45,9 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) { CanvasImage* image = GetNativePeer(native_image_handle); Picture* picture = GetNativePeer(Dart_GetNativeArgument(args, 1)); ASSERT_FALSE(image->image()->unique()); - if (picture->display_list()) { - ASSERT_FALSE(picture->display_list()->unique()); - current_display_list_ = picture->display_list(); - } else { - ASSERT_FALSE(picture->picture()->unique()); - current_picture_ = picture->picture(); - } + ASSERT_FALSE(picture->picture()->unique()); current_image_ = image->image(); + current_picture_ = picture->picture(); }; auto native_finish = [&](Dart_NativeArguments args) { @@ -92,7 +84,7 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) { message_latch_.Wait(); - ASSERT_TRUE(current_display_list_ || current_picture_); + ASSERT_TRUE(current_picture_); ASSERT_TRUE(current_image_); // Force a drain the SkiaUnrefQueue. The engine does this normally as frames @@ -104,13 +96,8 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) { }); message_latch_.Wait(); - if (current_display_list_) { - EXPECT_TRUE(current_display_list_->unique()); - current_display_list_.reset(); - } else { - EXPECT_TRUE(current_picture_->unique()); - current_picture_.reset(); - } + EXPECT_TRUE(current_picture_->unique()); + current_picture_.reset(); EXPECT_TRUE(current_image_->unique()); current_image_.reset(); diff --git a/lib/ui/painting/picture.cc b/lib/ui/painting/picture.cc index 2789d2eec6720..5225d993ba4fb 100644 --- a/lib/ui/painting/picture.cc +++ b/lib/ui/painting/picture.cc @@ -37,50 +37,29 @@ fml::RefPtr Picture::Create( return canvas_picture; } -fml::RefPtr Picture::Create(Dart_Handle dart_handle, - sk_sp display_list) { - auto canvas_picture = fml::MakeRefCounted(std::move(display_list)); - - canvas_picture->AssociateWithDartWrapper(dart_handle); - return canvas_picture; -} - Picture::Picture(flutter::SkiaGPUObject picture) : picture_(std::move(picture)) {} -Picture::Picture(sk_sp display_list) - : display_list_(std::move(display_list)) {} - Picture::~Picture() = default; Dart_Handle Picture::toImage(uint32_t width, uint32_t height, Dart_Handle raw_image_callback) { - if (display_list_) { - return RasterizeToImage( - [display_list = display_list_.get()](SkCanvas* canvas) { - display_list->RenderTo(canvas); - }, - width, height, raw_image_callback); - } else { - if (!picture_.get()) { - return tonic::ToDart("Picture is null"); - } - return RasterizeToImage(picture_.get(), width, height, raw_image_callback); + if (!picture_.get()) { + return tonic::ToDart("Picture is null"); } + + return RasterizeToImage(picture_.get(), width, height, raw_image_callback); } void Picture::dispose() { picture_.reset(); - display_list_.reset(); ClearDartWrapper(); } size_t Picture::GetAllocationSize() const { if (auto picture = picture_.get()) { return picture->approximateBytesUsed() + sizeof(Picture); - } else if (auto display_list = display_list_.get()) { - return display_list_->bytes() + sizeof(Picture); } else { return sizeof(Picture); } @@ -90,18 +69,6 @@ Dart_Handle Picture::RasterizeToImage(sk_sp picture, uint32_t width, uint32_t height, Dart_Handle raw_image_callback) { - return RasterizeToImage( - [sk_picture = picture.get()](SkCanvas* canvas) { - canvas->drawPicture(sk_picture); - }, - width, height, raw_image_callback); -} - -Dart_Handle Picture::RasterizeToImage( - std::function draw_callback, - uint32_t width, - uint32_t height, - Dart_Handle raw_image_callback) { if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) { return tonic::ToDart("Image callback was invalid"); } @@ -154,10 +121,10 @@ Dart_Handle Picture::RasterizeToImage( // Kick things off on the raster rask runner. fml::TaskRunner::RunNowOrPostTask( - raster_task_runner, [ui_task_runner, snapshot_delegate, draw_callback, - picture_bounds, ui_task] { - sk_sp raster_image = snapshot_delegate->MakeRasterSnapshot( - draw_callback, picture_bounds); + raster_task_runner, + [ui_task_runner, snapshot_delegate, picture, picture_bounds, ui_task] { + sk_sp raster_image = + snapshot_delegate->MakeRasterSnapshot(picture, picture_bounds); fml::TaskRunner::RunNowOrPostTask( ui_task_runner, diff --git a/lib/ui/painting/picture.h b/lib/ui/painting/picture.h index 432d9d32fb1b4..e0158d400ff5e 100644 --- a/lib/ui/painting/picture.h +++ b/lib/ui/painting/picture.h @@ -5,7 +5,6 @@ #ifndef FLUTTER_LIB_UI_PAINTING_PICTURE_H_ #define FLUTTER_LIB_UI_PAINTING_PICTURE_H_ -#include "flutter/flow/display_list.h" #include "flutter/flow/skia_gpu_object.h" #include "flutter/lib/ui/dart_wrapper.h" #include "flutter/lib/ui/painting/image.h" @@ -27,11 +26,8 @@ class Picture : public RefCountedDartWrappable { ~Picture() override; static fml::RefPtr Create(Dart_Handle dart_handle, flutter::SkiaGPUObject picture); - static fml::RefPtr Create(Dart_Handle dart_handle, - sk_sp display_list); sk_sp picture() const { return picture_.get(); } - sk_sp display_list() const { return display_list_; } Dart_Handle toImage(uint32_t width, uint32_t height, @@ -48,18 +44,10 @@ class Picture : public RefCountedDartWrappable { uint32_t height, Dart_Handle raw_image_callback); - static Dart_Handle RasterizeToImage( - std::function draw_callback, - uint32_t width, - uint32_t height, - Dart_Handle raw_image_callback); - private: Picture(flutter::SkiaGPUObject picture); - Picture(sk_sp display_list); flutter::SkiaGPUObject picture_; - sk_sp display_list_; }; } // namespace flutter diff --git a/lib/ui/painting/picture_recorder.cc b/lib/ui/painting/picture_recorder.cc index ed6f88cfeda78..5084f30d7812f 100644 --- a/lib/ui/painting/picture_recorder.cc +++ b/lib/ui/painting/picture_recorder.cc @@ -39,13 +39,7 @@ PictureRecorder::PictureRecorder() {} PictureRecorder::~PictureRecorder() {} SkCanvas* PictureRecorder::BeginRecording(SkRect bounds) { - bool enable_display_list = UIDartState::Current()->enable_display_list(); - if (enable_display_list) { - display_list_recorder_ = sk_make_sp(bounds); - return display_list_recorder_.get(); - } else { - return picture_recorder_.beginRecording(bounds, &rtree_factory_); - } + return picture_recorder_.beginRecording(bounds, &rtree_factory_); } fml::RefPtr PictureRecorder::endRecording(Dart_Handle dart_picture) { @@ -53,16 +47,9 @@ fml::RefPtr PictureRecorder::endRecording(Dart_Handle dart_picture) { return nullptr; } - fml::RefPtr picture; - - if (display_list_recorder_) { - picture = Picture::Create(dart_picture, display_list_recorder_->Build()); - display_list_recorder_ = nullptr; - } else { - picture = Picture::Create( - dart_picture, UIDartState::CreateGPUObject( - picture_recorder_.finishRecordingAsPicture())); - } + fml::RefPtr picture = Picture::Create( + dart_picture, UIDartState::CreateGPUObject( + picture_recorder_.finishRecordingAsPicture())); canvas_->Invalidate(); canvas_ = nullptr; diff --git a/lib/ui/painting/picture_recorder.h b/lib/ui/painting/picture_recorder.h index 7d2303284d32b..59d0d782c57ae 100644 --- a/lib/ui/painting/picture_recorder.h +++ b/lib/ui/painting/picture_recorder.h @@ -5,7 +5,6 @@ #ifndef FLUTTER_LIB_UI_PAINTING_PICTURE_RECORDER_H_ #define FLUTTER_LIB_UI_PAINTING_PICTURE_RECORDER_H_ -#include "flutter/flow/display_list_canvas.h" #include "flutter/lib/ui/dart_wrapper.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -29,10 +28,6 @@ class PictureRecorder : public RefCountedDartWrappable { SkCanvas* BeginRecording(SkRect bounds); fml::RefPtr endRecording(Dart_Handle dart_picture); - sk_sp display_list_recorder() { - return display_list_recorder_; - } - void set_canvas(fml::RefPtr canvas) { canvas_ = std::move(canvas); } static void RegisterNatives(tonic::DartLibraryNatives* natives); @@ -42,9 +37,6 @@ class PictureRecorder : public RefCountedDartWrappable { SkRTreeFactory rtree_factory_; SkPictureRecorder picture_recorder_; - - sk_sp display_list_recorder_; - fml::RefPtr canvas_; }; diff --git a/lib/ui/snapshot_delegate.h b/lib/ui/snapshot_delegate.h index a1f7c618b0653..ad9b8ef1f3612 100644 --- a/lib/ui/snapshot_delegate.h +++ b/lib/ui/snapshot_delegate.h @@ -12,10 +12,6 @@ namespace flutter { class SnapshotDelegate { public: - virtual sk_sp MakeRasterSnapshot( - std::function draw_callback, - SkISize picture_size) = 0; - virtual sk_sp MakeRasterSnapshot(sk_sp picture, SkISize picture_size) = 0; diff --git a/lib/ui/ui_dart_state.cc b/lib/ui/ui_dart_state.cc index 06411c4d3ce98..71d02c7b73b9f 100644 --- a/lib/ui/ui_dart_state.cc +++ b/lib/ui/ui_dart_state.cc @@ -56,7 +56,6 @@ UIDartState::UIDartState( std::shared_ptr isolate_name_server, bool is_root_isolate, bool enable_skparagraph, - bool enable_display_list, const UIDartState::Context& context) : add_callback_(std::move(add_callback)), remove_callback_(std::move(remove_callback)), @@ -66,7 +65,6 @@ UIDartState::UIDartState( log_message_callback_(log_message_callback), isolate_name_server_(std::move(isolate_name_server)), enable_skparagraph_(enable_skparagraph), - enable_display_list_(enable_display_list), context_(std::move(context)) { AddOrRemoveTaskObserver(true /* add */); } @@ -240,8 +238,4 @@ bool UIDartState::enable_skparagraph() const { return enable_skparagraph_; } -bool UIDartState::enable_display_list() const { - return enable_display_list_; -} - } // namespace flutter diff --git a/lib/ui/ui_dart_state.h b/lib/ui/ui_dart_state.h index f79d584ad0090..fb2baadb1aa2f 100644 --- a/lib/ui/ui_dart_state.h +++ b/lib/ui/ui_dart_state.h @@ -143,8 +143,6 @@ class UIDartState : public tonic::DartState { bool enable_skparagraph() const; - bool enable_display_list() const; - template static flutter::SkiaGPUObject CreateGPUObject(sk_sp object) { if (!object) { @@ -165,7 +163,6 @@ class UIDartState : public tonic::DartState { std::shared_ptr isolate_name_server, bool is_root_isolate_, bool enable_skparagraph, - bool enable_display_list, const UIDartState::Context& context); ~UIDartState() override; @@ -192,7 +189,6 @@ class UIDartState : public tonic::DartState { LogMessageCallback log_message_callback_; const std::shared_ptr isolate_name_server_; const bool enable_skparagraph_; - const bool enable_display_list_; UIDartState::Context context_; void AddOrRemoveTaskObserver(bool add); diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 916ce6e72ad1c..52aa2ffb4d3ab 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -311,7 +311,6 @@ DartIsolate::DartIsolate(const Settings& settings, DartVMRef::GetIsolateNameServer(), is_root_isolate, settings.enable_skparagraph, - settings.enable_display_list, std::move(context)), may_insecurely_connect_to_all_domains_( settings.may_insecurely_connect_to_all_domains), diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 8a149bebd5b2f..05facc74fc0a7 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -313,12 +313,6 @@ sk_sp Rasterizer::DoMakeRasterSnapshot( return result; } -sk_sp Rasterizer::MakeRasterSnapshot( - std::function draw_callback, - SkISize picture_size) { - return DoMakeRasterSnapshot(picture_size, draw_callback); -} - sk_sp Rasterizer::MakeRasterSnapshot(sk_sp picture, SkISize picture_size) { return DoMakeRasterSnapshot(picture_size, diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index aa7334179e970..b34e10b0b0d74 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -449,11 +449,6 @@ class Rasterizer final : public SnapshotDelegate { std::shared_ptr external_view_embedder_; bool shared_engine_block_thread_merging_ = false; - // |SnapshotDelegate| - sk_sp MakeRasterSnapshot( - std::function draw_callback, - SkISize picture_size) override; - // |SnapshotDelegate| sk_sp MakeRasterSnapshot(sk_sp picture, SkISize picture_size) override; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index beea55e86736e..e423a1759689c 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1690,9 +1690,6 @@ bool Shell::OnServiceProtocolEstimateRasterCacheMemory( response->AddMember("pictureBytes", raster_cache.EstimatePictureCacheByteSize(), response->GetAllocator()); - response->AddMember("displayListBytes", - raster_cache.EstimateDisplayListCacheByteSize(), - response->GetAllocator()); return true; } diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 58e7e780a7fbc..5f8777bbe2a8e 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -2116,7 +2116,7 @@ TEST_F(ShellTest, OnServiceProtocolEstimateRasterCacheMemoryWorks) { document.Accept(writer); std::string expected_json = "{\"type\":\"EstimateRasterCacheMemory\",\"layerBytes\":40000,\"picture" - "Bytes\":400,\"displayListBytes\":0}"; + "Bytes\":400}"; std::string actual_json = buffer.GetString(); ASSERT_EQ(actual_json, expected_json); diff --git a/shell/common/switches.cc b/shell/common/switches.cc index d49f99bda13be..249e9c5d8dca1 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -66,8 +66,6 @@ static const std::string gAllowedDartFlags[] = { "--write-service-info", "--null_assertions", "--strict_null_safety_checks", - "--enable-display-list", - "--no-enable-display-list", }; // clang-format on @@ -406,16 +404,6 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { settings.dart_flags.push_back(flag); } } - if (std::find(settings.dart_flags.begin(), settings.dart_flags.end(), - "--enable-display-list") != settings.dart_flags.end()) { - FML_LOG(ERROR) << "Manually enabling display lists"; - settings.enable_display_list = true; - } else if (std::find(settings.dart_flags.begin(), settings.dart_flags.end(), - "--no-enable-display-list") != - settings.dart_flags.end()) { - FML_LOG(ERROR) << "Manually disabling display lists"; - settings.enable_display_list = false; - } #if !FLUTTER_RELEASE command_line.GetOptionValue(FlagForSwitch(Switch::LogTag), &settings.log_tag); diff --git a/testing/mock_canvas.cc b/testing/mock_canvas.cc index 9084563973dc6..518f52c89c035 100644 --- a/testing/mock_canvas.cc +++ b/testing/mock_canvas.cc @@ -105,7 +105,6 @@ void MockCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { void MockCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { - // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 (void)rec; // Can't use b/c Skia keeps this type anonymous. draw_calls_.emplace_back(DrawCall{current_layer_, DrawShadowData{path}}); }