From a10e25e727f88ae5120018f79fb6fb10e4fc9332 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Wed, 15 Jan 2025 11:08:38 -0800 Subject: [PATCH] [DisplayList] Migrate from SkRSXform to Impeller RSTransform (#161652) Fixes SkRSXform task in https://github.com/flutter/flutter/issues/161456 Removes (nearly) all uses of Skia SkRSXform object from DisplayList and replaces it with a new Impeller RSTransform geometry object. There are remaining uses in: - Skia adapter code which needs to convert them back to SkRSXform when using the Skia backend - dl_rendering_tests which is waiting for a major conversion effort - ?Fuchsia? code has an SkCanvas spy adapter used in its embedder code (not DisplayList related) - web_ui/skwasm --- .../flutter/ci/licenses_golden/excluded_files | 1 + .../ci/licenses_golden/licenses_flutter | 4 + .../benchmarking/dl_complexity_helper.h | 2 +- .../benchmarking/dl_complexity_unittests.cc | 8 +- .../display_list/display_list_unittests.cc | 10 ++- engine/src/flutter/display_list/dl_builder.cc | 13 +-- engine/src/flutter/display_list/dl_builder.h | 4 +- engine/src/flutter/display_list/dl_canvas.h | 15 +--- .../src/flutter/display_list/dl_op_receiver.h | 2 +- .../src/flutter/display_list/dl_op_records.h | 11 +-- .../display_list/geometry/dl_geometry_types.h | 2 + .../flutter/display_list/skia/dl_sk_canvas.cc | 8 +- .../flutter/display_list/skia/dl_sk_canvas.h | 2 +- .../display_list/skia/dl_sk_conversions.h | 4 + .../skia/dl_sk_conversions_unittests.cc | 51 +++++++++++ .../display_list/skia/dl_sk_dispatcher.cc | 4 +- .../display_list/skia/dl_sk_dispatcher.h | 2 +- .../testing/dl_rendering_unittests.cc | 54 +++++++---- .../display_list/testing/dl_test_snippets.cc | 50 ++++++++--- .../display_list/utils/dl_receiver_utils.h | 2 +- .../display_list/aiks_dl_atlas_unittests.cc | 47 +++------- .../display_list/aiks_dl_unittests.cc | 1 - .../display_list/dl_atlas_geometry.cc | 18 ++-- .../impeller/display_list/dl_atlas_geometry.h | 5 +- .../impeller/display_list/dl_dispatcher.cc | 2 +- .../impeller/display_list/dl_dispatcher.h | 2 +- .../impeller/display_list/skia_conversions.cc | 11 --- .../impeller/display_list/skia_conversions.h | 3 - engine/src/flutter/impeller/geometry/BUILD.gn | 3 + engine/src/flutter/impeller/geometry/matrix.h | 1 - engine/src/flutter/impeller/geometry/rect.h | 10 +-- .../impeller/geometry/rect_unittests.cc | 24 ++--- .../flutter/impeller/geometry/rstransform.cc | 57 ++++++++++++ .../flutter/impeller/geometry/rstransform.h | 89 +++++++++++++++++++ .../geometry/rstransform_unittests.cc | 61 +++++++++++++ engine/src/flutter/lib/ui/geometry.dart | 2 +- engine/src/flutter/lib/ui/painting/canvas.cc | 6 +- engine/src/flutter/shell/common/dl_op_spy.cc | 2 +- engine/src/flutter/shell/common/dl_op_spy.h | 2 +- .../shell/common/dl_op_spy_unittests.cc | 5 +- .../flutter/testing/display_list_testing.cc | 10 +-- .../flutter/testing/display_list_testing.h | 4 +- 42 files changed, 437 insertions(+), 177 deletions(-) create mode 100644 engine/src/flutter/impeller/geometry/rstransform.cc create mode 100644 engine/src/flutter/impeller/geometry/rstransform.h create mode 100644 engine/src/flutter/impeller/geometry/rstransform_unittests.cc diff --git a/engine/src/flutter/ci/licenses_golden/excluded_files b/engine/src/flutter/ci/licenses_golden/excluded_files index e4fdc56bed..c8ce16b128 100644 --- a/engine/src/flutter/ci/licenses_golden/excluded_files +++ b/engine/src/flutter/ci/licenses_golden/excluded_files @@ -174,6 +174,7 @@ ../../../flutter/impeller/geometry/path_unittests.cc ../../../flutter/impeller/geometry/rect_unittests.cc ../../../flutter/impeller/geometry/round_rect_unittests.cc +../../../flutter/impeller/geometry/rstransform_unittests.cc ../../../flutter/impeller/geometry/saturated_math_unittests.cc ../../../flutter/impeller/geometry/size_unittests.cc ../../../flutter/impeller/geometry/trig_unittests.cc diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index d638e2fdc5..2cc6b89bbb 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -42513,6 +42513,8 @@ ORIGIN: ../../../flutter/impeller/geometry/round_rect.cc + ../../../flutter/LICE ORIGIN: ../../../flutter/impeller/geometry/round_rect.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/rounding_radii.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/rounding_radii.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/geometry/rstransform.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/geometry/rstransform.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/saturated_math.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/scalar.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/separated_vector.cc + ../../../flutter/LICENSE @@ -45456,6 +45458,8 @@ FILE: ../../../flutter/impeller/geometry/round_rect.cc FILE: ../../../flutter/impeller/geometry/round_rect.h FILE: ../../../flutter/impeller/geometry/rounding_radii.cc FILE: ../../../flutter/impeller/geometry/rounding_radii.h +FILE: ../../../flutter/impeller/geometry/rstransform.cc +FILE: ../../../flutter/impeller/geometry/rstransform.h FILE: ../../../flutter/impeller/geometry/saturated_math.h FILE: ../../../flutter/impeller/geometry/scalar.h FILE: ../../../flutter/impeller/geometry/separated_vector.cc diff --git a/engine/src/flutter/display_list/benchmarking/dl_complexity_helper.h b/engine/src/flutter/display_list/benchmarking/dl_complexity_helper.h index 1303ff3a25..ed098920de 100644 --- a/engine/src/flutter/display_list/benchmarking/dl_complexity_helper.h +++ b/engine/src/flutter/display_list/benchmarking/dl_complexity_helper.h @@ -158,7 +158,7 @@ class ComplexityCalculatorHelper } void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/display_list/benchmarking/dl_complexity_unittests.cc b/engine/src/flutter/display_list/benchmarking/dl_complexity_unittests.cc index 2175266833..4f580f15d3 100644 --- a/engine/src/flutter/display_list/benchmarking/dl_complexity_unittests.cc +++ b/engine/src/flutter/display_list/benchmarking/dl_complexity_unittests.cc @@ -421,11 +421,11 @@ TEST(DisplayListComplexity, DrawAtlas) { bitmap.allocPixels(info, 0); auto image = SkImages::RasterFromBitmap(bitmap); - std::vector rects; - std::vector xforms; + std::vector rects; + std::vector xforms; for (int i = 0; i < 10; i++) { - rects.push_back(SkRect::MakeXYWH(0, 0, 10, 10)); - xforms.push_back(SkRSXform::Make(1, 0, 0, 0)); + rects.push_back(DlRect::MakeXYWH(0, 0, 10, 10)); + xforms.push_back(DlRSTransform(1, 0, 0, 0)); } DisplayListBuilder builder; diff --git a/engine/src/flutter/display_list/display_list_unittests.cc b/engine/src/flutter/display_list/display_list_unittests.cc index 10db130897..98bd233831 100644 --- a/engine/src/flutter/display_list/display_list_unittests.cc +++ b/engine/src/flutter/display_list/display_list_unittests.cc @@ -1201,7 +1201,10 @@ TEST_F(DisplayListTest, SingleOpsMightSupportGroupOpacityBlendMode) { kTestImage2, DlIRect::MakeLTRB(20, 20, 30, 30), DlRect::MakeLTRB(0, 0, 20, 20), DlFilterMode::kLinear, nullptr); , true); - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = { DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30), @@ -3502,7 +3505,10 @@ TEST_F(DisplayListTest, NopOperationsOmittedFromRecords) { builder.DrawImageNine(kTestImage1, DlIRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(10, 10, 100, 100), DlFilterMode::kLinear, &paint); - SkRSXform xforms[] = {{1, 0, 10, 10}, {0, 1, 10, 10}}; + DlRSTransform xforms[] = { + DlRSTransform::Make({10.0f, 10.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({10.0f, 10.0f}, 1.0f, DlDegrees(90)), + }; DlRect rects[] = { DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(10, 20, 30, 20), diff --git a/engine/src/flutter/display_list/dl_builder.cc b/engine/src/flutter/display_list/dl_builder.cc index 846ad3eac9..f301b6a8bf 100644 --- a/engine/src/flutter/display_list/dl_builder.cc +++ b/engine/src/flutter/display_list/dl_builder.cc @@ -1467,7 +1467,7 @@ void DisplayListBuilder::DrawImageNine(const sk_sp& image, } } void DisplayListBuilder::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, @@ -1482,19 +1482,20 @@ void DisplayListBuilder::drawAtlas(const sk_sp atlas, if (result == OpResult::kNoEffect) { return; } - SkPoint quad[4]; + DlQuad quad; AccumulationRect accumulator; for (int i = 0; i < count; i++) { const DlRect& src = tex[i]; - xform[i].toQuad(src.GetWidth(), src.GetHeight(), quad); + xform[i].GetQuad(src.GetWidth(), src.GetHeight(), quad); for (int j = 0; j < 4; j++) { - accumulator.accumulate(ToDlPoint(quad[j])); + accumulator.accumulate(quad[j]); } } if (accumulator.is_empty() || !AccumulateOpBounds(accumulator.GetBounds(), flags)) { return; } + // Accumulating the bounds might not trip the overlap condition if the // whole atlas operation is separated from other rendering calls, but // since each atlas op is treated as an independent operation, we have @@ -1509,7 +1510,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp atlas, current_layer().layer_local_accumulator.record_overlapping_bounds(); } - int bytes = count * (sizeof(SkRSXform) + sizeof(SkRect)); + int bytes = count * (sizeof(DlRSTransform) + sizeof(DlRect)); void* data_ptr; if (colors != nullptr) { bytes += count * sizeof(DlColor); @@ -1541,7 +1542,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp atlas, is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe(); } void DisplayListBuilder::DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/display_list/dl_builder.h b/engine/src/flutter/display_list/dl_builder.h index 992e4eb6ae..2a27a64f27 100644 --- a/engine/src/flutter/display_list/dl_builder.h +++ b/engine/src/flutter/display_list/dl_builder.h @@ -209,7 +209,7 @@ class DisplayListBuilder final : public virtual DlCanvas, const DlPaint* paint = nullptr) override; // |DlCanvas| void DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, @@ -471,7 +471,7 @@ class DisplayListBuilder final : public virtual DlCanvas, bool render_with_attributes) override; // |DlOpReceiver| void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/display_list/dl_canvas.h b/engine/src/flutter/display_list/dl_canvas.h index 13bd616574..246be2306e 100644 --- a/engine/src/flutter/display_list/dl_canvas.h +++ b/engine/src/flutter/display_list/dl_canvas.h @@ -17,7 +17,6 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRRect.h" -#include "third_party/skia/include/core/SkRSXform.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkTextBlob.h" @@ -189,7 +188,7 @@ class DlCanvas { DlFilterMode filter, const DlPaint* paint = nullptr) = 0; virtual void DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, @@ -373,18 +372,6 @@ class DlCanvas { const DlPaint* paint = nullptr) { DrawImageNine(image, ToDlIRect(center), ToDlRect(dst), filter, paint); } - void DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], - const SkRect tex[], - const DlColor colors[], - int count, - DlBlendMode mode, - DlImageSampling sampling, - const SkRect* cullRect, - const DlPaint* paint = nullptr) { - DrawAtlas(atlas, xform, ToDlRects(tex), colors, count, mode, sampling, - ToDlRect(cullRect), paint); - } void DrawShadow(const SkPath& path, const DlColor color, const DlScalar elevation, diff --git a/engine/src/flutter/display_list/dl_op_receiver.h b/engine/src/flutter/display_list/dl_op_receiver.h index 081c44b544..19bcb7988a 100644 --- a/engine/src/flutter/display_list/dl_op_receiver.h +++ b/engine/src/flutter/display_list/dl_op_receiver.h @@ -345,7 +345,7 @@ class DlOpReceiver { DlFilterMode filter, bool render_with_attributes) = 0; virtual void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/display_list/dl_op_records.h b/engine/src/flutter/display_list/dl_op_records.h index 1df10f933f..bd1c2ecc2f 100644 --- a/engine/src/flutter/display_list/dl_op_records.h +++ b/engine/src/flutter/display_list/dl_op_records.h @@ -15,7 +15,6 @@ #include "flutter/impeller/geometry/path.h" #include "flutter/impeller/typographer/text_frame.h" -#include "third_party/skia/include/core/SkRSXform.h" namespace flutter { @@ -841,7 +840,7 @@ DEFINE_DRAW_IMAGE_NINE_OP(DrawImageNineWithAttr, true) // 4 byte header + 40 byte payload uses 44 bytes but is rounded up to 48 bytes // (4 bytes unused) // 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 +// DlRSTransform list is a multiple of 16 bytes so it is always packed well // DlRect list is also a multiple of 16 bytes so it also packs well // DlColor list only packs well if the count is even, otherwise there // can be 4 unusued bytes at the end. @@ -876,7 +875,7 @@ struct DrawAtlasBaseOp : DrawOpBase { render_with_attributes == other->render_with_attributes && sampling == other->sampling && atlas->Equals(other->atlas)); if (ret) { - size_t bytes = count * (sizeof(SkRSXform) + sizeof(DlRect)); + size_t bytes = count * (sizeof(DlRSTransform) + sizeof(DlRect)); if (has_colors) { bytes += count * sizeof(DlColor); } @@ -906,7 +905,8 @@ struct DrawAtlasOp final : DrawAtlasBaseOp { render_with_attributes) {} void dispatch(DlOpReceiver& receiver) const { - const SkRSXform* xform = reinterpret_cast(this + 1); + const DlRSTransform* xform = + reinterpret_cast(this + 1); const DlRect* tex = reinterpret_cast(xform + count); const DlColor* colors = has_colors ? reinterpret_cast(tex + count) : nullptr; @@ -950,7 +950,8 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp { const DlRect cull_rect; void dispatch(DlOpReceiver& receiver) const { - const SkRSXform* xform = reinterpret_cast(this + 1); + const DlRSTransform* xform = + reinterpret_cast(this + 1); const DlRect* tex = reinterpret_cast(xform + count); const DlColor* colors = has_colors ? reinterpret_cast(tex + count) : nullptr; diff --git a/engine/src/flutter/display_list/geometry/dl_geometry_types.h b/engine/src/flutter/display_list/geometry/dl_geometry_types.h index 0f3039e6d1..30637de5a6 100644 --- a/engine/src/flutter/display_list/geometry/dl_geometry_types.h +++ b/engine/src/flutter/display_list/geometry/dl_geometry_types.h @@ -9,6 +9,7 @@ #include "flutter/impeller/geometry/path.h" #include "flutter/impeller/geometry/rect.h" #include "flutter/impeller/geometry/round_rect.h" +#include "flutter/impeller/geometry/rstransform.h" #include "flutter/impeller/geometry/scalar.h" #include "flutter/third_party/skia/include/core/SkM44.h" @@ -34,6 +35,7 @@ using DlRoundRect = impeller::RoundRect; using DlRoundingRadii = impeller::RoundingRadii; using DlMatrix = impeller::Matrix; using DlQuad = impeller::Quad; +using DlRSTransform = impeller::RSTransform; static_assert(sizeof(SkPoint) == sizeof(DlPoint)); static_assert(sizeof(SkIPoint) == sizeof(DlIPoint)); diff --git a/engine/src/flutter/display_list/skia/dl_sk_canvas.cc b/engine/src/flutter/display_list/skia/dl_sk_canvas.cc index 6d66c46674..6dcac5d5d6 100644 --- a/engine/src/flutter/display_list/skia/dl_sk_canvas.cc +++ b/engine/src/flutter/display_list/skia/dl_sk_canvas.cc @@ -296,7 +296,7 @@ void DlSkCanvasAdapter::DrawImageNine(const sk_sp& image, } void DlSkCanvasAdapter::DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, @@ -311,9 +311,9 @@ void DlSkCanvasAdapter::DrawAtlas(const sk_sp& atlas, for (int i = 0; i < count; ++i) { sk_colors.push_back(colors[i].argb()); } - delegate_->drawAtlas(sk_image.get(), xform, ToSkRects(tex), sk_colors.data(), - count, ToSk(mode), ToSk(sampling), ToSkRect(cullRect), - sk_paint()); + delegate_->drawAtlas(sk_image.get(), ToSk(xform), ToSkRects(tex), + sk_colors.data(), count, ToSk(mode), ToSk(sampling), + ToSkRect(cullRect), sk_paint()); } void DlSkCanvasAdapter::DrawDisplayList(const sk_sp display_list, diff --git a/engine/src/flutter/display_list/skia/dl_sk_canvas.h b/engine/src/flutter/display_list/skia/dl_sk_canvas.h index 3a42c3a61f..8c6e4f6cb8 100644 --- a/engine/src/flutter/display_list/skia/dl_sk_canvas.h +++ b/engine/src/flutter/display_list/skia/dl_sk_canvas.h @@ -134,7 +134,7 @@ class DlSkCanvasAdapter final : public virtual DlCanvas { DlFilterMode filter, const DlPaint* paint = nullptr) override; void DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/display_list/skia/dl_sk_conversions.h b/engine/src/flutter/display_list/skia/dl_sk_conversions.h index f3d5d7320b..f7103f9e7c 100644 --- a/engine/src/flutter/display_list/skia/dl_sk_conversions.h +++ b/engine/src/flutter/display_list/skia/dl_sk_conversions.h @@ -120,6 +120,10 @@ inline SkMatrix* ToSk(const DlMatrix* matrix, SkMatrix& scratch) { extern sk_sp ToSk(const std::shared_ptr& vertices); +inline const SkRSXform* ToSk(const DlRSTransform* transforms) { + return reinterpret_cast(transforms); +} + } // namespace flutter #endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_ diff --git a/engine/src/flutter/display_list/skia/dl_sk_conversions_unittests.cc b/engine/src/flutter/display_list/skia/dl_sk_conversions_unittests.cc index 574dfe209f..bc61aeb7a5 100644 --- a/engine/src/flutter/display_list/skia/dl_sk_conversions_unittests.cc +++ b/engine/src/flutter/display_list/skia/dl_sk_conversions_unittests.cc @@ -321,5 +321,56 @@ TEST(DisplayListSkConversions, ToSkDitheringEnabledForGradients) { } } +TEST(DisplayListSkConversions, ToSkRSTransform) { + constexpr size_t kTransformCount = 4; + DlRSTransform transforms[kTransformCount] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({12.25f, 14.75f}, 10.0f, DlDegrees(30)), + DlRSTransform::Make({-10.4f, 8.25f}, 11.0f, DlDegrees(400)), + DlRSTransform::Make({1.0f, 3.0f}, 0.5f, DlDegrees(45)), + }; + SkRSXform expected_transforms[kTransformCount] = { + SkRSXform::MakeFromRadians(1.0f, SkDegreesToRadians(0), // + 0.0f, 0.0f, 0.0f, 0.0f), + SkRSXform::MakeFromRadians(10.0f, SkDegreesToRadians(30), // + 12.25f, 14.75f, 0.0f, 0.0f), + SkRSXform::MakeFromRadians(11.0f, SkDegreesToRadians(400), // + -10.4f, 8.25f, 0.0f, 0.0f), + SkRSXform::MakeFromRadians(0.5f, SkDegreesToRadians(45), // + 1.0f, 3.0f, 0.0f, 0.0f), + }; + auto sk_transforms = ToSk(transforms); + for (size_t i = 0; i < kTransformCount; i++) { + // Comparing dl values to transformed copy values + // should match exactly because arrays were simply aliased + EXPECT_EQ(sk_transforms[i].fSCos, transforms[i].scaled_cos) << i; + EXPECT_EQ(sk_transforms[i].fSSin, transforms[i].scaled_sin) << i; + EXPECT_EQ(sk_transforms[i].fTx, transforms[i].translate_x) << i; + EXPECT_EQ(sk_transforms[i].fTy, transforms[i].translate_y) << i; + + // Comparing dl values to computed Skia values + // should match closely, but not exactly due to differences in trig + EXPECT_FLOAT_EQ(sk_transforms[i].fSCos, expected_transforms[i].fSCos) << i; + EXPECT_FLOAT_EQ(sk_transforms[i].fSSin, expected_transforms[i].fSSin) << i; + EXPECT_EQ(sk_transforms[i].fTx, expected_transforms[i].fTx) << i; + EXPECT_EQ(sk_transforms[i].fTy, expected_transforms[i].fTy) << i; + + // Comparing the results of transforming a sprite with Skia vs Impeller + SkPoint sk_quad[4]; + expected_transforms[i].toQuad(20, 30, sk_quad); + DlQuad dl_quad; + transforms[i].GetQuad(20, 30, dl_quad); + // Skia order is UL,UR,LR,LL, Impeller order is UL,UR,LL,LR + EXPECT_FLOAT_EQ(sk_quad[0].fX, dl_quad[0].x) << i; + EXPECT_FLOAT_EQ(sk_quad[0].fY, dl_quad[0].y) << i; + EXPECT_FLOAT_EQ(sk_quad[1].fX, dl_quad[1].x) << i; + EXPECT_FLOAT_EQ(sk_quad[1].fY, dl_quad[1].y) << i; + EXPECT_FLOAT_EQ(sk_quad[2].fX, dl_quad[3].x) << i; + EXPECT_FLOAT_EQ(sk_quad[2].fY, dl_quad[3].y) << i; + EXPECT_FLOAT_EQ(sk_quad[3].fX, dl_quad[2].x) << i; + EXPECT_FLOAT_EQ(sk_quad[3].fY, dl_quad[2].y) << i; + } +} + } // namespace testing } // namespace flutter diff --git a/engine/src/flutter/display_list/skia/dl_sk_dispatcher.cc b/engine/src/flutter/display_list/skia/dl_sk_dispatcher.cc index 0f9ffda988..101fb8553e 100644 --- a/engine/src/flutter/display_list/skia/dl_sk_dispatcher.cc +++ b/engine/src/flutter/display_list/skia/dl_sk_dispatcher.cc @@ -245,7 +245,7 @@ void DlSkCanvasDispatcher::drawImageNine(const sk_sp image, ToSk(filter), safe_paint(render_with_attributes)); } void DlSkCanvasDispatcher::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, @@ -267,7 +267,7 @@ void DlSkCanvasDispatcher::drawAtlas(const sk_sp atlas, sk_colors.push_back(colors[i].argb()); } } - canvas_->drawAtlas(skia_atlas.get(), xform, ToSkRects(tex), + canvas_->drawAtlas(skia_atlas.get(), ToSk(xform), ToSkRects(tex), sk_colors.empty() ? nullptr : sk_colors.data(), count, ToSk(mode), ToSk(sampling), ToSkRect(cullRect), safe_paint(render_with_attributes)); diff --git a/engine/src/flutter/display_list/skia/dl_sk_dispatcher.h b/engine/src/flutter/display_list/skia/dl_sk_dispatcher.h index 659506b6bf..bb57a8ee03 100644 --- a/engine/src/flutter/display_list/skia/dl_sk_dispatcher.h +++ b/engine/src/flutter/display_list/skia/dl_sk_dispatcher.h @@ -95,7 +95,7 @@ class DlSkCanvasDispatcher : public virtual DlOpReceiver, DlFilterMode filter, bool render_with_attributes) override; void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/display_list/testing/dl_rendering_unittests.cc b/engine/src/flutter/display_list/testing/dl_rendering_unittests.cc index dcb547f28a..33425cd3b0 100644 --- a/engine/src/flutter/display_list/testing/dl_rendering_unittests.cc +++ b/engine/src/flutter/display_list/testing/dl_rendering_unittests.cc @@ -3584,7 +3584,15 @@ TEST_F(DisplayListRendering, DrawImageNineLinear) { } TEST_F(DisplayListRendering, DrawAtlasNearest) { - const SkRSXform xform[] = { + const SkRSXform sk_xform[] = { + // clang-format off + { 1.2f, 0.0f, kRenderLeft, kRenderTop}, + { 0.0f, 1.2f, kRenderRight, kRenderTop}, + {-1.2f, 0.0f, kRenderRight, kRenderBottom}, + { 0.0f, -1.2f, kRenderLeft, kRenderBottom}, + // clang-format on + }; + const DlRSTransform dl_xform[] = { // clang-format off { 1.2f, 0.0f, kRenderLeft, kRenderTop}, { 0.0f, 1.2f, kRenderRight, kRenderTop}, @@ -3617,20 +3625,28 @@ TEST_F(DisplayListRendering, DrawAtlasNearest) { CanvasCompareTester::RenderAll( // TestParameters( [=](const SkRenderContext& ctx) { - ctx.canvas->drawAtlas(ctx.image.get(), xform, tex, sk_colors, 4, + ctx.canvas->drawAtlas(ctx.image.get(), sk_xform, tex, sk_colors, 4, SkBlendMode::kSrcOver, sk_sampling, nullptr, &ctx.paint); }, [=](const DlRenderContext& ctx) { - ctx.canvas->DrawAtlas(ctx.image, xform, tex, dl_colors, 4, - DlBlendMode::kSrcOver, dl_sampling, nullptr, - &ctx.paint); + ctx.canvas->DrawAtlas(ctx.image, dl_xform, ToDlRects(tex), + dl_colors, 4, DlBlendMode::kSrcOver, + dl_sampling, nullptr, &ctx.paint); }, kDrawAtlasWithPaintFlags)); } TEST_F(DisplayListRendering, DrawAtlasNearestNoPaint) { - const SkRSXform xform[] = { + const SkRSXform sk_xform[] = { + // clang-format off + { 1.2f, 0.0f, kRenderLeft, kRenderTop}, + { 0.0f, 1.2f, kRenderRight, kRenderTop}, + {-1.2f, 0.0f, kRenderRight, kRenderBottom}, + { 0.0f, -1.2f, kRenderLeft, kRenderBottom}, + // clang-format on + }; + const DlRSTransform dl_xform[] = { // clang-format off { 1.2f, 0.0f, kRenderLeft, kRenderTop}, { 0.0f, 1.2f, kRenderRight, kRenderTop}, @@ -3663,20 +3679,28 @@ TEST_F(DisplayListRendering, DrawAtlasNearestNoPaint) { CanvasCompareTester::RenderAll( // TestParameters( [=](const SkRenderContext& ctx) { - ctx.canvas->drawAtlas(ctx.image.get(), xform, tex, sk_colors, 4, + ctx.canvas->drawAtlas(ctx.image.get(), sk_xform, tex, sk_colors, 4, SkBlendMode::kSrcOver, sk_sampling, // nullptr, nullptr); }, [=](const DlRenderContext& ctx) { - ctx.canvas->DrawAtlas(ctx.image, xform, tex, dl_colors, 4, - DlBlendMode::kSrcOver, dl_sampling, // - nullptr, nullptr); + ctx.canvas->DrawAtlas(ctx.image, dl_xform, ToDlRects(tex), + dl_colors, 4, DlBlendMode::kSrcOver, + dl_sampling, nullptr, nullptr); }, kDrawAtlasFlags)); } TEST_F(DisplayListRendering, DrawAtlasLinear) { - const SkRSXform xform[] = { + const SkRSXform sk_xform[] = { + // clang-format off + { 1.2f, 0.0f, kRenderLeft, kRenderTop}, + { 0.0f, 1.2f, kRenderRight, kRenderTop}, + {-1.2f, 0.0f, kRenderRight, kRenderBottom}, + { 0.0f, -1.2f, kRenderLeft, kRenderBottom}, + // clang-format on + }; + const DlRSTransform dl_xform[] = { // clang-format off { 1.2f, 0.0f, kRenderLeft, kRenderTop}, { 0.0f, 1.2f, kRenderRight, kRenderTop}, @@ -3709,14 +3733,14 @@ TEST_F(DisplayListRendering, DrawAtlasLinear) { CanvasCompareTester::RenderAll( // TestParameters( [=](const SkRenderContext& ctx) { - ctx.canvas->drawAtlas(ctx.image.get(), xform, tex, sk_colors, 2, + ctx.canvas->drawAtlas(ctx.image.get(), sk_xform, tex, sk_colors, 2, SkBlendMode::kSrcOver, sk_sampling, // nullptr, &ctx.paint); }, [=](const DlRenderContext& ctx) { - ctx.canvas->DrawAtlas(ctx.image, xform, tex, dl_colors, 2, - DlBlendMode::kSrcOver, dl_sampling, // - nullptr, &ctx.paint); + ctx.canvas->DrawAtlas(ctx.image, dl_xform, ToDlRects(tex), + dl_colors, 2, DlBlendMode::kSrcOver, + dl_sampling, nullptr, &ctx.paint); }, kDrawAtlasWithPaintFlags)); } diff --git a/engine/src/flutter/display_list/testing/dl_test_snippets.cc b/engine/src/flutter/display_list/testing/dl_test_snippets.cc index 9964bbd818..c9b99cc220 100644 --- a/engine/src/flutter/display_list/testing/dl_test_snippets.cc +++ b/engine/src/flutter/display_list/testing/dl_test_snippets.cc @@ -943,7 +943,10 @@ std::vector CreateAllRenderingOps() { { {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2, @@ -952,7 +955,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2, @@ -960,7 +966,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{0, 1, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(45)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2, @@ -969,7 +978,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 25, 30, 30)}; r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2, @@ -978,7 +990,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2, @@ -986,7 +1001,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2, @@ -995,7 +1013,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 64 + 32 + 8, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; static DlRect cull_rect = DlRect::MakeLTRB(0, 0, 200, 200); @@ -1005,7 +1026,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 128, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()}; @@ -1015,7 +1039,10 @@ std::vector CreateAllRenderingOps() { }}, {1, 144, 1, [](DlOpReceiver& r) { - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()}; @@ -1027,7 +1054,10 @@ std::vector CreateAllRenderingOps() { {1, 48 + 32 + 8, 1, [](DlOpReceiver& r) { auto dl_image = DlImage::Make(kTestSkImage); - static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static DlRSTransform xforms[] = { + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)), + DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)), + }; static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20), DlRect::MakeLTRB(20, 20, 30, 30)}; r.drawAtlas(dl_image, xforms, texs, nullptr, 2, diff --git a/engine/src/flutter/display_list/utils/dl_receiver_utils.h b/engine/src/flutter/display_list/utils/dl_receiver_utils.h index 40a7df5de4..b32a561833 100644 --- a/engine/src/flutter/display_list/utils/dl_receiver_utils.h +++ b/engine/src/flutter/display_list/utils/dl_receiver_utils.h @@ -124,7 +124,7 @@ class IgnoreDrawDispatchHelper : public virtual DlOpReceiver { DlFilterMode filter, bool render_with_attributes) override {} void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_atlas_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_atlas_unittests.cc index 885e23780c..3995d9b099 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_atlas_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_atlas_unittests.cc @@ -16,7 +16,6 @@ #include "impeller/entity/contents/content_context.h" #include "impeller/geometry/color.h" #include "impeller/geometry/scalar.h" -#include "include/core/SkRSXform.h" #include "include/core/SkRefCnt.h" namespace impeller { @@ -25,34 +24,14 @@ namespace testing { using namespace flutter; namespace { -SkRSXform MakeTranslation(Scalar tx, Scalar ty) { - return SkRSXform::Make(1, 0, tx, ty); +RSTransform MakeTranslation(Scalar tx, Scalar ty) { + return RSTransform::Make({tx, ty}, 1, DlDegrees(0)); } -std::tuple, std::vector, sk_sp> +std::tuple, // + std::vector, // + sk_sp> CreateTestData(const AiksTest* test) { - // Draws the image as four squares stiched together. - auto atlas = - DlImageImpeller::Make(test->CreateTextureForFixture("bay_bridge.jpg")); - auto size = atlas->impeller_texture()->GetSize(); - // Divide image into four quadrants. - Scalar half_width = size.width / 2; - Scalar half_height = size.height / 2; - std::vector texture_coordinates = { - SkRect::MakeLTRB(0, 0, half_width, half_height), - SkRect::MakeLTRB(half_width, 0, size.width, half_height), - SkRect::MakeLTRB(0, half_height, half_width, size.height), - SkRect::MakeLTRB(half_width, half_height, size.width, size.height)}; - // Position quadrants adjacent to eachother. - std::vector transforms = { - MakeTranslation(0, 0), MakeTranslation(half_width, 0), - MakeTranslation(0, half_height), - MakeTranslation(half_width, half_height)}; - return std::make_tuple(texture_coordinates, transforms, atlas); -} - -std::tuple, std::vector, sk_sp> -CreateDlTestData(const AiksTest* test) { // Draws the image as four squares stiched together. auto atlas = DlImageImpeller::Make(test->CreateTextureForFixture("bay_bridge.jpg")); @@ -66,7 +45,7 @@ CreateDlTestData(const AiksTest* test) { DlRect::MakeLTRB(0, half_height, half_width, size.height), DlRect::MakeLTRB(half_width, half_height, size.width, size.height)}; // Position quadrants adjacent to eachother. - std::vector transforms = { + std::vector transforms = { MakeTranslation(0, 0), MakeTranslation(half_width, 0), MakeTranslation(0, half_height), MakeTranslation(half_width, half_height)}; @@ -138,9 +117,9 @@ TEST_P(AiksTest, DrawAtlasWithOpacity) { TEST_P(AiksTest, DrawAtlasNoColorFullSize) { auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg")); auto size = atlas->impeller_texture()->GetSize(); - std::vector texture_coordinates = { - SkRect::MakeLTRB(0, 0, size.width, size.height)}; - std::vector transforms = {MakeTranslation(0, 0)}; + std::vector texture_coordinates = { + DlRect::MakeLTRB(0, 0, size.width, size.height)}; + std::vector transforms = {MakeTranslation(0, 0)}; DisplayListBuilder builder; builder.Scale(GetContentScale().x, GetContentScale().y); @@ -199,7 +178,7 @@ TEST_P(AiksTest, DrawAtlasPlusWideGamut) { } TEST_P(AiksTest, DlAtlasGeometryNoBlend) { - auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this); + auto [texture_coordinates, transforms, atlas] = CreateTestData(this); DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(), texture_coordinates.data(), nullptr, transforms.size(), @@ -217,7 +196,7 @@ TEST_P(AiksTest, DlAtlasGeometryNoBlend) { } TEST_P(AiksTest, DlAtlasGeometryBlend) { - auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this); + auto [texture_coordinates, transforms, atlas] = CreateTestData(this); std::vector colors; colors.reserve(texture_coordinates.size()); @@ -241,7 +220,7 @@ TEST_P(AiksTest, DlAtlasGeometryBlend) { } TEST_P(AiksTest, DlAtlasGeometryColorButNoBlend) { - auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this); + auto [texture_coordinates, transforms, atlas] = CreateTestData(this); std::vector colors; colors.reserve(texture_coordinates.size()); @@ -258,7 +237,7 @@ TEST_P(AiksTest, DlAtlasGeometryColorButNoBlend) { } TEST_P(AiksTest, DlAtlasGeometrySkip) { - auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this); + auto [texture_coordinates, transforms, atlas] = CreateTestData(this); std::vector colors; colors.reserve(texture_coordinates.size()); diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_unittests.cc index 1a5bb912c4..fadb99cb12 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_unittests.cc @@ -26,7 +26,6 @@ #include "include/core/SkCanvas.h" #include "include/core/SkMatrix.h" #include "include/core/SkPath.h" -#include "include/core/SkRSXform.h" #include "include/core/SkRefCnt.h" namespace impeller { diff --git a/engine/src/flutter/impeller/display_list/dl_atlas_geometry.cc b/engine/src/flutter/impeller/display_list/dl_atlas_geometry.cc index 3d5e160833..0ff864126c 100644 --- a/engine/src/flutter/impeller/display_list/dl_atlas_geometry.cc +++ b/engine/src/flutter/impeller/display_list/dl_atlas_geometry.cc @@ -16,7 +16,7 @@ namespace impeller { DlAtlasGeometry::DlAtlasGeometry(const std::shared_ptr& atlas, - const SkRSXform* xform, + const RSTransform* xform, const flutter::DlRect* tex, const flutter::DlColor* colors, size_t count, @@ -46,12 +46,10 @@ Rect DlAtlasGeometry::ComputeBoundingBox() const { if (cull_rect_.has_value()) { return cull_rect_.value(); } - Rect bounding_box = {}; + Rect bounding_box; for (size_t i = 0; i < count_; i++) { - auto matrix = skia_conversions::ToRSXForm(xform_[i]); - auto sample_rect = tex_[i]; - auto bounds = Rect::MakeSize(sample_rect.GetSize()).TransformBounds(matrix); - bounding_box = bounds.Union(bounding_box); + auto bounds = xform_[i].GetBounds(tex_[i].GetSize()); + bounding_box = Rect::Union(bounding_box, bounds); } cull_rect_ = bounding_box; return bounding_box; @@ -84,10 +82,8 @@ VertexBuffer DlAtlasGeometry::CreateSimpleVertexBuffer( auto texture_size = atlas_->GetSize(); for (auto i = 0u; i < count_; i++) { flutter::DlRect sample_rect = tex_[i]; - Matrix matrix = skia_conversions::ToRSXForm(xform_[i]); auto points = sample_rect.GetPoints(); - auto transformed_points = Rect::MakeSize(sample_rect.GetSize()) - .GetTransformedPoints(matrix); + auto transformed_points = xform_[i].GetQuad(sample_rect.GetSize()); for (size_t j = 0; j < 6; j++) { data[offset].position = transformed_points[indices[j]]; data[offset].texture_coords = points[indices[j]] / texture_size; @@ -119,10 +115,8 @@ VertexBuffer DlAtlasGeometry::CreateBlendVertexBuffer( auto texture_size = atlas_->GetSize(); for (auto i = 0u; i < count_; i++) { flutter::DlRect sample_rect = tex_[i]; - Matrix matrix = skia_conversions::ToRSXForm(xform_[i]); auto points = sample_rect.GetPoints(); - auto transformed_points = Rect::MakeSize(sample_rect.GetSize()) - .GetTransformedPoints(matrix); + auto transformed_points = xform_[i].GetQuad(sample_rect.GetSize()); for (size_t j = 0; j < 6; j++) { data[offset].vertices = transformed_points[indices[j]]; data[offset].texture_coords = points[indices[j]] / texture_size; diff --git a/engine/src/flutter/impeller/display_list/dl_atlas_geometry.h b/engine/src/flutter/impeller/display_list/dl_atlas_geometry.h index 839df2b628..3c29451908 100644 --- a/engine/src/flutter/impeller/display_list/dl_atlas_geometry.h +++ b/engine/src/flutter/impeller/display_list/dl_atlas_geometry.h @@ -10,7 +10,6 @@ #include "impeller/core/sampler_descriptor.h" #include "impeller/entity/contents/atlas_contents.h" #include "impeller/geometry/color.h" -#include "include/core/SkRSXform.h" namespace impeller { @@ -18,7 +17,7 @@ namespace impeller { class DlAtlasGeometry : public AtlasGeometry { public: DlAtlasGeometry(const std::shared_ptr& atlas, - const SkRSXform* xform, + const RSTransform* xform, const flutter::DlRect* tex, const flutter::DlColor* colors, size_t count, @@ -47,7 +46,7 @@ class DlAtlasGeometry : public AtlasGeometry { private: const std::shared_ptr atlas_; - const SkRSXform* xform_; + const RSTransform* xform_; const flutter::DlRect* tex_; const flutter::DlColor* colors_; size_t count_; diff --git a/engine/src/flutter/impeller/display_list/dl_dispatcher.cc b/engine/src/flutter/impeller/display_list/dl_dispatcher.cc index 6d39f5719c..ce59d1f000 100644 --- a/engine/src/flutter/impeller/display_list/dl_dispatcher.cc +++ b/engine/src/flutter/impeller/display_list/dl_dispatcher.cc @@ -774,7 +774,7 @@ void DlDispatcherBase::drawImageNine(const sk_sp image, // |flutter::DlOpReceiver| void DlDispatcherBase::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const RSTransform xform[], const DlRect tex[], const flutter::DlColor colors[], int count, diff --git a/engine/src/flutter/impeller/display_list/dl_dispatcher.h b/engine/src/flutter/impeller/display_list/dl_dispatcher.h index 8d69eab149..35a6fbfa35 100644 --- a/engine/src/flutter/impeller/display_list/dl_dispatcher.h +++ b/engine/src/flutter/impeller/display_list/dl_dispatcher.h @@ -209,7 +209,7 @@ class DlDispatcherBase : public flutter::DlOpReceiver { // |flutter::DlOpReceiver| void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const RSTransform xform[], const DlRect tex[], const flutter::DlColor colors[], int count, diff --git a/engine/src/flutter/impeller/display_list/skia_conversions.cc b/engine/src/flutter/impeller/display_list/skia_conversions.cc index 14047ab964..2e7e28f84a 100644 --- a/engine/src/flutter/impeller/display_list/skia_conversions.cc +++ b/engine/src/flutter/impeller/display_list/skia_conversions.cc @@ -97,17 +97,6 @@ Color ToColor(const flutter::DlColor& color) { }; } -Matrix ToRSXForm(const SkRSXform& form) { - // clang-format off - return Matrix{ - form.fSCos, form.fSSin, 0, 0, - -form.fSSin, form.fSCos, 0, 0, - 0, 0, 1, 0, - form.fTx, form.fTy, 0, 1 - }; - // clang-format on -} - std::optional ToPixelFormat(SkColorType type) { switch (type) { case kRGBA_8888_SkColorType: diff --git a/engine/src/flutter/impeller/display_list/skia_conversions.h b/engine/src/flutter/impeller/display_list/skia_conversions.h index 7180da35ad..31530cbbe1 100644 --- a/engine/src/flutter/impeller/display_list/skia_conversions.h +++ b/engine/src/flutter/impeller/display_list/skia_conversions.h @@ -19,7 +19,6 @@ #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkRRect.h" -#include "third_party/skia/include/core/SkRSXform.h" #include "third_party/skia/include/core/SkTextBlob.h" namespace impeller { @@ -49,8 +48,6 @@ Size ToSize(const SkPoint& point); Color ToColor(const flutter::DlColor& color); -Matrix ToRSXForm(const SkRSXform& form); - std::optional ToPixelFormat(SkColorType type); impeller::SamplerDescriptor ToSamplerDescriptor( diff --git a/engine/src/flutter/impeller/geometry/BUILD.gn b/engine/src/flutter/impeller/geometry/BUILD.gn index fba613c3aa..9f2d831846 100644 --- a/engine/src/flutter/impeller/geometry/BUILD.gn +++ b/engine/src/flutter/impeller/geometry/BUILD.gn @@ -33,6 +33,8 @@ impeller_component("geometry") { "round_rect.h", "rounding_radii.cc", "rounding_radii.h", + "rstransform.cc", + "rstransform.h", "saturated_math.h", "scalar.h", "separated_vector.cc", @@ -76,6 +78,7 @@ impeller_component("geometry_unittests") { "path_unittests.cc", "rect_unittests.cc", "round_rect_unittests.cc", + "rstransform_unittests.cc", "saturated_math_unittests.cc", "size_unittests.cc", "trig_unittests.cc", diff --git a/engine/src/flutter/impeller/geometry/matrix.h b/engine/src/flutter/impeller/geometry/matrix.h index 484bf40ddc..fb4dc95e86 100644 --- a/engine/src/flutter/impeller/geometry/matrix.h +++ b/engine/src/flutter/impeller/geometry/matrix.h @@ -602,7 +602,6 @@ struct Matrix { // clang-format on } - private: static constexpr Vector2 CosSin(Radians radians) { // The precision of a float around 1.0 is much lower than it is // around 0.0, so we end up with cases on quadrant rotations where diff --git a/engine/src/flutter/impeller/geometry/rect.h b/engine/src/flutter/impeller/geometry/rect.h index 111ca30c99..703cd833b8 100644 --- a/engine/src/flutter/impeller/geometry/rect.h +++ b/engine/src/flutter/impeller/geometry/rect.h @@ -703,15 +703,13 @@ struct TRect { saturated::Cast(round(r.GetBottom()))); } - [[nodiscard]] constexpr static std::optional Union( - const TRect& a, - const std::optional b) { + [[nodiscard]] constexpr static TRect Union(const TRect& a, + const std::optional b) { return b.has_value() ? a.Union(b.value()) : a; } - [[nodiscard]] constexpr static std::optional Union( - const std::optional a, - const TRect& b) { + [[nodiscard]] constexpr static TRect Union(const std::optional a, + const TRect& b) { return a.has_value() ? a->Union(b) : b; } diff --git a/engine/src/flutter/impeller/geometry/rect_unittests.cc b/engine/src/flutter/impeller/geometry/rect_unittests.cc index 17d6ff6489..cb33c7debd 100644 --- a/engine/src/flutter/impeller/geometry/rect_unittests.cc +++ b/engine/src/flutter/impeller/geometry/rect_unittests.cc @@ -1457,16 +1457,14 @@ TEST(RectTest, OptRectUnion) { auto test1 = [](const Rect& r) { // Rect, NullOpt - EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value()); - EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r); + EXPECT_EQ(Rect::Union(r, std::nullopt), r); // OptRect, NullOpt EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value()); EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r); // NullOpt, Rect - EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value()); - EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r); + EXPECT_EQ(Rect::Union(std::nullopt, r), r); // NullOpt, OptRect EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value()); @@ -1481,12 +1479,10 @@ TEST(RectTest, OptRectUnion) { ASSERT_EQ(a.Union(b), u); // Rect, OptRect - EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value()); - EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u); + EXPECT_EQ(Rect::Union(a, std::optional(b)), u); // OptRect, Rect - EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value()); - EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u); + EXPECT_EQ(Rect::Union(std::optional(a), b), u); // OptRect, OptRect EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value()); @@ -1581,16 +1577,14 @@ TEST(RectTest, OptIRectUnion) { auto test1 = [](const IRect& r) { // Rect, NullOpt - EXPECT_TRUE(IRect::Union(r, std::nullopt).has_value()); - EXPECT_EQ(IRect::Union(r, std::nullopt).value(), r); + EXPECT_EQ(IRect::Union(r, std::nullopt), r); // OptRect, NullOpt EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value()); EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r); // NullOpt, Rect - EXPECT_TRUE(IRect::Union(std::nullopt, r).has_value()); - EXPECT_EQ(IRect::Union(std::nullopt, r).value(), r); + EXPECT_EQ(IRect::Union(std::nullopt, r), r); // NullOpt, OptRect EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value()); @@ -1605,12 +1599,10 @@ TEST(RectTest, OptIRectUnion) { ASSERT_EQ(a.Union(b), u); // Rect, OptRect - EXPECT_TRUE(IRect::Union(a, std::optional(b)).has_value()); - EXPECT_EQ(IRect::Union(a, std::optional(b)).value(), u); + EXPECT_EQ(IRect::Union(a, std::optional(b)), u); // OptRect, Rect - EXPECT_TRUE(IRect::Union(std::optional(a), b).has_value()); - EXPECT_EQ(IRect::Union(std::optional(a), b).value(), u); + EXPECT_EQ(IRect::Union(std::optional(a), b), u); // OptRect, OptRect EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value()); diff --git a/engine/src/flutter/impeller/geometry/rstransform.cc b/engine/src/flutter/impeller/geometry/rstransform.cc new file mode 100644 index 0000000000..05a509e992 --- /dev/null +++ b/engine/src/flutter/impeller/geometry/rstransform.cc @@ -0,0 +1,57 @@ +// 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/impeller/geometry/rstransform.h" + +#include "flutter/impeller/geometry/matrix.h" + +namespace impeller { + +bool RSTransform::IsAxisAligned() const { + return scaled_cos == 0.0f || scaled_sin == 0.0f; +} + +Matrix RSTransform::GetMatrix() const { + // clang-format off + return Matrix::MakeRow(scaled_cos, -scaled_sin, 0.0f, translate_x, + scaled_sin, scaled_cos, 0.0f, translate_y, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + // clang-format on +} + +void RSTransform::GetQuad(Scalar width, Scalar height, Quad& quad) const { + Point origin = {translate_x, translate_y}; + Point dx = width * Point{scaled_cos, scaled_sin}; + Point dy = height * Point{-scaled_sin, scaled_cos}; + quad = { + // Ordered in the same Z pattern as Rect::GetPoints() + origin, + origin + dx, + origin + dy, + origin + dx + dy, + }; +} + +Quad RSTransform::GetQuad(Scalar width, Scalar height) const { + Quad quad; + GetQuad(width, height, quad); + return quad; +} + +Quad RSTransform::GetQuad(Size size) const { + Quad quad; + GetQuad(size.width, size.height, quad); + return quad; +} + +std::optional RSTransform::GetBounds(Scalar width, Scalar height) const { + return Rect::MakePointBounds(GetQuad(width, height)); +} + +std::optional RSTransform::GetBounds(Size size) const { + return Rect::MakePointBounds(GetQuad(size)); +} + +} // namespace impeller diff --git a/engine/src/flutter/impeller/geometry/rstransform.h b/engine/src/flutter/impeller/geometry/rstransform.h new file mode 100644 index 0000000000..28b4cd09b4 --- /dev/null +++ b/engine/src/flutter/impeller/geometry/rstransform.h @@ -0,0 +1,89 @@ +// 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_IMPELLER_GEOMETRY_RSTRANSFORM_H_ +#define FLUTTER_IMPELLER_GEOMETRY_RSTRANSFORM_H_ + +#include "flutter/impeller/geometry/point.h" +#include "flutter/impeller/geometry/rect.h" +#include "flutter/impeller/geometry/scalar.h" +#include "flutter/impeller/geometry/size.h" + +namespace impeller { + +/// A utility struct that stores a simple transform composed of a translation, +/// a rotation, and a uniform scale. +/// +/// This transform is used by drawAtlas to transform the sprites. +/// This structure mirrors the Flutter RSTransform class. +struct RSTransform { + constexpr RSTransform() + : scaled_cos(1.0f), + scaled_sin(0.0f), + translate_x(0.0f), + translate_y(0.0f) {} + + constexpr RSTransform(Scalar scaled_cos, + Scalar scaled_sin, + Scalar translate_x, + Scalar translate_y) + : scaled_cos(scaled_cos), + scaled_sin(scaled_sin), + translate_x(translate_x), + translate_y(translate_y) {} + + /// Constructs an RSTransform from the indicated origin, uniform scale, + /// and radians rotation. + static constexpr RSTransform Make(Point origin, + Scalar scale, + Radians radians) { + auto scaled_cos_sin = Matrix::CosSin(radians) * scale; + return {scaled_cos_sin.x, scaled_cos_sin.y, origin.x, origin.y}; + } + + Scalar scaled_cos; + Scalar scaled_sin; + Scalar translate_x; + Scalar translate_y; + + /// Returns true iff the resulting transformed quad will be aligned with + /// the axes, even if rotated by a quadrant rotation. + bool IsAxisAligned() const; + + Matrix GetMatrix() const; + + /// Returns the 4 corner points of the transformed quad for a sub-image + /// of the indicated size in the same order as Rect::GetPoints. + /// + /// The order is UpperLeft, UpperRight, LowerLeft, LowerRight + void GetQuad(Scalar width, Scalar height, Quad& quad) const; + Quad GetQuad(Scalar width, Scalar height) const; + Quad GetQuad(Size size) const; + + /// Returns the bounds of the 4 corner points of the transformed quad + /// for a sub-image of the indicated size. + std::optional GetBounds(Scalar width, Scalar height) const; + std::optional GetBounds(Size size) const; +}; + +} // namespace impeller + +namespace std { + +inline std::ostream& operator<<(std::ostream& out, + const impeller::RSTransform& rst) { + // clang-format off + out << "(" + << "scos: " << rst.scaled_cos << ", " + << "ssin: " << rst.scaled_sin << ", " + << "origin: (" << rst.translate_x << ", " + << rst.translate_y << ")" + << ")"; + // clang-format on + return out; +} + +} // namespace std + +#endif // FLUTTER_IMPELLER_GEOMETRY_RSTRANSFORM_H_ diff --git a/engine/src/flutter/impeller/geometry/rstransform_unittests.cc b/engine/src/flutter/impeller/geometry/rstransform_unittests.cc new file mode 100644 index 0000000000..e9e046409d --- /dev/null +++ b/engine/src/flutter/impeller/geometry/rstransform_unittests.cc @@ -0,0 +1,61 @@ +// 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 "gtest/gtest.h" + +#include "flutter/impeller/geometry/rstransform.h" + +#include "flutter/impeller/geometry/geometry_asserts.h" + +namespace impeller { +namespace testing { + +TEST(RSTransformTest, Construction) { + RSTransform transform = RSTransform::Make({10.0f, 12.0f}, 2.0f, Degrees(90)); + + EXPECT_EQ(transform.scaled_cos, 0.0f); + EXPECT_EQ(transform.scaled_sin, 2.0f); + EXPECT_EQ(transform.translate_x, 10.0f); + EXPECT_EQ(transform.translate_y, 12.0f); + + EXPECT_EQ(transform.GetBounds(20.0f, 30.0f), + // relative corners are at + // 0, 0 + // 0, 40 + // -60, 0 + // -60, 40 + // then add 10, 12 to all values + Rect::MakeLTRB(10 + -2 * 30, 12 + 0, 10 + 0, 12 + 40)); +} + +TEST(RSTransformTest, CompareToMatrix) { + for (int tx = 0; tx <= 100; tx += 10) { + for (int ty = 0; ty <= 100; ty += 10) { + Point origin(tx, ty); + for (int scale = 1; scale <= 20; scale += 5) { + // Overshoot a full circle by 30 degrees + for (int degrees = 0; degrees <= 390; degrees += 45) { + auto matrix = Matrix::MakeTranslation(origin) * + Matrix::MakeRotationZ(Degrees(degrees)) * + Matrix::MakeScale(Vector2(scale, scale)); + auto rst = RSTransform::Make(origin, scale, Degrees(degrees)); + EXPECT_MATRIX_NEAR(rst.GetMatrix(), matrix); + for (int w = 10; w <= 100; w += 10) { + for (int h = 10; h <= 100; h += 10) { + Quad q = rst.GetQuad(w, h); + auto points = Rect::MakeWH(w, h).GetTransformedPoints(matrix); + for (int i = 0; i < 4; i++) { + EXPECT_NEAR(q[i].x, points[i].x, kEhCloseEnough); + EXPECT_NEAR(q[i].y, points[i].y, kEhCloseEnough); + } + } + } + } + } + } + } +} + +} // namespace testing +} // namespace impeller diff --git a/engine/src/flutter/lib/ui/geometry.dart b/engine/src/flutter/lib/ui/geometry.dart index f2756bf943..76fce9abf3 100644 --- a/engine/src/flutter/lib/ui/geometry.dart +++ b/engine/src/flutter/lib/ui/geometry.dart @@ -1747,7 +1747,7 @@ class RRect { /// /// Used by [Canvas.drawAtlas]. This is a more efficient way to represent these /// simple transformations than a full matrix. -// Modeled after Skia's SkRSXform. +// Modeled after Impeller's RSTransform. class RSTransform { /// Creates an RSTransform. /// diff --git a/engine/src/flutter/lib/ui/painting/canvas.cc b/engine/src/flutter/lib/ui/painting/canvas.cc index 121cb0270f..056b332e8c 100644 --- a/engine/src/flutter/lib/ui/painting/canvas.cc +++ b/engine/src/flutter/lib/ui/painting/canvas.cc @@ -581,8 +581,8 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects, return ToDart(error.value()); } - static_assert(sizeof(SkRSXform) == sizeof(float) * 4, - "SkRSXform doesn't use floats."); + static_assert(sizeof(DlRSTransform) == sizeof(float) * 4, + "DlRSTransform doesn't use floats."); static_assert(sizeof(DlRect) == sizeof(float) * 4, "DlRect doesn't use floats."); @@ -605,7 +605,7 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects, const DlPaint* opt_paint = paint.paint(dl_paint, kDrawAtlasWithPaintFlags, DlTileMode::kClamp); builder()->DrawAtlas( - dl_image, reinterpret_cast(transforms.data()), + dl_image, reinterpret_cast(transforms.data()), reinterpret_cast(rects.data()), dl_color.data(), rects.num_elements() / 4, // DlRect have four floats. blend_mode, sampling, reinterpret_cast(cull_rect.data()), diff --git a/engine/src/flutter/shell/common/dl_op_spy.cc b/engine/src/flutter/shell/common/dl_op_spy.cc index f9671ccab4..2ed156594b 100644 --- a/engine/src/flutter/shell/common/dl_op_spy.cc +++ b/engine/src/flutter/shell/common/dl_op_spy.cc @@ -110,7 +110,7 @@ void DlOpSpy::drawImageNine(const sk_sp image, did_draw_ = true; } void DlOpSpy::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/shell/common/dl_op_spy.h b/engine/src/flutter/shell/common/dl_op_spy.h index 27fe39554f..fd2741fdba 100644 --- a/engine/src/flutter/shell/common/dl_op_spy.h +++ b/engine/src/flutter/shell/common/dl_op_spy.h @@ -84,7 +84,7 @@ class DlOpSpy final : public virtual DlOpReceiver, DlFilterMode filter, bool render_with_attributes) override; void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/shell/common/dl_op_spy_unittests.cc b/engine/src/flutter/shell/common/dl_op_spy_unittests.cc index ba54d557dd..663324f4eb 100644 --- a/engine/src/flutter/shell/common/dl_op_spy_unittests.cc +++ b/engine/src/flutter/shell/common/dl_op_spy_unittests.cc @@ -7,7 +7,6 @@ #include "flutter/display_list/testing/dl_test_snippets.h" #include "flutter/shell/common/dl_op_spy.h" #include "flutter/testing/testing.h" -#include "third_party/skia/include/core/SkRSXform.h" namespace flutter { namespace testing { @@ -456,7 +455,9 @@ TEST(DlOpSpy, Images) { { // DrawAtlas DisplayListBuilder builder; DlPaint paint(DlColor::kBlack()); - const SkRSXform xform[] = {SkRSXform::Make(1, 0, 0, 0)}; + const DlRSTransform xform[] = { + DlRSTransform::Make({0, 0}, 1.0f, DlDegrees(0)), + }; const DlRect tex[] = {DlRect::MakeXYWH(10, 10, 10, 10)}; DlRect cull_rect = DlRect::MakeWH(5, 5); builder.DrawAtlas(kTestImage1, xform, tex, nullptr, 1, DlBlendMode::kSrc, diff --git a/engine/src/flutter/testing/display_list_testing.cc b/engine/src/flutter/testing/display_list_testing.cc index d57f93a2cc..ce8c953ca2 100644 --- a/engine/src/flutter/testing/display_list_testing.cc +++ b/engine/src/flutter/testing/display_list_testing.cc @@ -205,14 +205,6 @@ extern std::ostream& operator<<(std::ostream& os, const DlPath& path) { << ")"; } -static std::ostream& operator<<(std::ostream& os, const SkRSXform& xform) { - return os << "SkRSXform(" - << "scos: " << xform.fSCos << ", " - << "ssin: " << xform.fSSin << ", " - << "tx: " << xform.fTx << ", " - << "ty: " << xform.fTy << ")"; -} - std::ostream& operator<<(std::ostream& os, const DlCanvas::ClipOp& op) { switch (op) { case DlCanvas::ClipOp::kDifference: return os << "ClipOp::kDifference"; @@ -912,7 +904,7 @@ void DisplayListStreamDispatcher::drawImageNine(const sk_sp image, << ");" << std::endl; } void DisplayListStreamDispatcher::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, diff --git a/engine/src/flutter/testing/display_list_testing.h b/engine/src/flutter/testing/display_list_testing.h index 17cf01d023..a8a8d76127 100644 --- a/engine/src/flutter/testing/display_list_testing.h +++ b/engine/src/flutter/testing/display_list_testing.h @@ -177,7 +177,7 @@ class DisplayListStreamDispatcher final : public DlOpReceiver { DlFilterMode filter, bool render_with_attributes) override; void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, @@ -500,7 +500,7 @@ class DisplayListGeneralReceiver : public DlOpReceiver { } } void drawAtlas(const sk_sp atlas, - const SkRSXform xform[], + const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count,