From bf1cd8348707668e3b6b4dba5e8a6d0be60e932f Mon Sep 17 00:00:00 2001 From: Callum Moffat Date: Mon, 30 Jan 2023 02:06:25 -0500 Subject: [PATCH 1/2] Fix position of BackdropFilter in PlatformView --- flow/embedded_views.h | 5 + flow/layers/backdrop_filter_layer.cc | 2 +- .../framework/Source/FlutterPlatformViews.mm | 5 +- .../Source/FlutterPlatformViewsTest.mm | 92 ++++++++++--------- 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 84ad68f41faa6..0ea0357e00245 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -185,6 +185,7 @@ class MutatorsStack { void PushClipPath(const SkPath& path); void PushTransform(const SkMatrix& matrix); void PushOpacity(const int& alpha); + // `filter_rect` is in global coordinates. void PushBackdropFilter(const std::shared_ptr& filter, const SkRect& filter_rect); @@ -284,6 +285,8 @@ class EmbeddedViewParams { const SkRect& finalBoundingRect() const { return final_bounding_rect_; } // Pushes the stored DlImageFilter object to the mutators stack. + // + // `filter_rect` is in global coordinates. void PushImageFilter(std::shared_ptr filter, const SkRect& filter_rect) { mutators_stack_.PushBackdropFilter(filter, filter_rect); @@ -487,6 +490,8 @@ class ExternalViewEmbedder { // Pushes a DlImageFilter object to each platform view within a list of // visited platform views. // + // `filter_rect` is in global coordinates. + // // See also: |PushVisitedPlatformView| for pushing platform view ids to the // visited platform views list. virtual void PushFilterToVisitedPlatformViews( diff --git a/flow/layers/backdrop_filter_layer.cc b/flow/layers/backdrop_filter_layer.cc index 7091e4f5c69dd..cc5664f84e36e 100644 --- a/flow/layers/backdrop_filter_layer.cc +++ b/flow/layers/backdrop_filter_layer.cc @@ -44,7 +44,7 @@ void BackdropFilterLayer::Preroll(PrerollContext* context) { Layer::AutoPrerollSaveLayerState::Create(context, true, bool(filter_)); if (context->view_embedder != nullptr) { context->view_embedder->PushFilterToVisitedPlatformViews( - filter_, context->state_stack.local_cull_rect()); + filter_, context->state_stack.device_cull_rect()); } SkRect child_paint_bounds = SkRect::MakeEmpty(); PrerollChildren(context, &child_paint_bounds); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 8df862e4e3d0a..4a70d99f30052 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -484,6 +484,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, } [mask_view_pool_.get() recycleMaskViews]; clipView.maskView = nil; + CGFloat screenScale = [UIScreen mainScreen].scale; auto iter = mutators_stack.Begin(); while (iter != mutators_stack.End()) { switch ((*iter)->GetType()) { @@ -530,6 +531,9 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, } CGRect filterRect = flutter::GetCGRectFromSkRect((*iter)->GetFilterMutation().GetFilterRect()); + // `filterRect` is in global coordinates. We need to convert to local space. + filterRect = CGRectApplyAffineTransform( + filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale)); // `filterRect` reprents the rect that should be filtered inside the `flutter_view_`. // The `PlatformViewFilter` needs the frame inside the `clipView` that needs to be // filtered. @@ -564,7 +568,6 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, [clipView applyBlurBackdropFilters:blurFilters]; } - CGFloat screenScale = [UIScreen mainScreen].scale; // The UIKit frame is set based on the logical resolution (points) instead of physical. // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). // However, flow is based on the physical resolution. For example, 1000 pixels in flow equals diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 945e5b44536ff..d97acbbddf537 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -278,12 +278,12 @@ - (void)testApplyBackdropFilter { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push a backdrop filter auto filter = std::make_shared(5, 2, flutter::DlTileMode::kClamp); - stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); @@ -348,12 +348,12 @@ - (void)testApplyBackdropFilterWithCorrectFrame { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push a backdrop filter auto filter = std::make_shared(5, 2, flutter::DlTileMode::kClamp); - stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 8, 8)); + stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 8, screenScale * 8)); auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(5, 10), stack); @@ -418,17 +418,17 @@ - (void)testApplyMultipleBackdropFilters { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push backdrop filters for (int i = 0; i < 50; i++) { auto filter = std::make_shared(i, 2, flutter::DlTileMode::kClamp); - stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } auto embeddedViewParams = - std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); + std::make_unique(screenScaleMatrix, SkSize::Make(20, 20), stack); flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); flutterPlatformViewsController->CompositeEmbeddedView(2); @@ -489,12 +489,12 @@ - (void)testAddBackdropFilters { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push a backdrop filter auto filter = std::make_shared(5, 2, flutter::DlTileMode::kClamp); - stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); @@ -530,7 +530,7 @@ - (void)testAddBackdropFilters { stack2.PushTransform(screenScaleMatrix); // Push backdrop filters for (int i = 0; i < 2; i++) { - stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -600,13 +600,13 @@ - (void)testRemoveBackdropFilters { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push backdrop filters auto filter = std::make_shared(5, 2, flutter::DlTileMode::kClamp); for (int i = 0; i < 5; i++) { - stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } auto embeddedViewParams = @@ -641,7 +641,7 @@ - (void)testRemoveBackdropFilters { stack2.PushTransform(screenScaleMatrix); // Push backdrop filters for (int i = 0; i < 4; i++) { - stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -735,13 +735,13 @@ - (void)testEditBackdropFilters { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push backdrop filters auto filter = std::make_shared(5, 2, flutter::DlTileMode::kClamp); for (int i = 0; i < 5; i++) { - stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } auto embeddedViewParams = @@ -780,11 +780,12 @@ - (void)testEditBackdropFilters { auto filter2 = std::make_shared(2, 5, flutter::DlTileMode::kClamp); - stack2.PushBackdropFilter(filter2, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter2, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); continue; } - stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -833,11 +834,12 @@ - (void)testEditBackdropFilters { if (i == 0) { auto filter2 = std::make_shared(2, 5, flutter::DlTileMode::kClamp); - stack2.PushBackdropFilter(filter2, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter2, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); continue; } - stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -884,11 +886,12 @@ - (void)testEditBackdropFilters { if (i == 4) { auto filter2 = std::make_shared(2, 5, flutter::DlTileMode::kClamp); - stack2.PushBackdropFilter(filter2, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter2, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); continue; } - stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -936,7 +939,7 @@ - (void)testEditBackdropFilters { for (int i = 0; i < 5; i++) { auto filter2 = std::make_shared(i, 2, flutter::DlTileMode::kClamp); - stack2.PushBackdropFilter(filter2, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(filter2, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -1007,8 +1010,8 @@ - (void)testApplyBackdropFilterNotDlBlurImageFilter { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); // Push a dilate backdrop filter auto dilateFilter = std::make_shared(5, 2); @@ -1045,11 +1048,13 @@ - (void)testApplyBackdropFilterNotDlBlurImageFilter { for (int i = 0; i < 5; i++) { if (i == 2) { - stack2.PushBackdropFilter(dilateFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(dilateFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); continue; } - stack2.PushBackdropFilter(blurFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(blurFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -1082,11 +1087,13 @@ - (void)testApplyBackdropFilterNotDlBlurImageFilter { // Push backdrop filters and dilate filter for (int i = 0; i < 5; i++) { if (i == 0) { - stack2.PushBackdropFilter(dilateFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(dilateFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); continue; } - stack2.PushBackdropFilter(blurFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(blurFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -1119,11 +1126,13 @@ - (void)testApplyBackdropFilterNotDlBlurImageFilter { // Push backdrop filters and dilate filter for (int i = 0; i < 5; i++) { if (i == 4) { - stack2.PushBackdropFilter(dilateFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(dilateFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); continue; } - stack2.PushBackdropFilter(blurFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(blurFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -1155,7 +1164,8 @@ - (void)testApplyBackdropFilterNotDlBlurImageFilter { } // Push dilate filters for (int i = 0; i < 5; i++) { - stack2.PushBackdropFilter(dilateFilter, SkRect::MakeXYWH(0, 0, 10, 10)); + stack2.PushBackdropFilter(dilateFilter, + SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); } embeddedViewParams = std::make_unique(screenScaleMatrix, @@ -1352,8 +1362,8 @@ - (void)testBackdropFilterCorrectlyPushedAndReset { // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack - SkMatrix screenScaleMatrix = - SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + CGFloat screenScale = [UIScreen mainScreen].scale; + SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); stack.PushTransform(screenScaleMatrix); auto embeddedViewParams = @@ -1363,8 +1373,8 @@ - (void)testBackdropFilterCorrectlyPushedAndReset { flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); flutterPlatformViewsController->PushVisitedPlatformView(2); auto filter = std::make_shared(5, 2, flutter::DlTileMode::kClamp); - flutterPlatformViewsController->PushFilterToVisitedPlatformViews(filter, - SkRect::MakeXYWH(0, 0, 10, 10)); + flutterPlatformViewsController->PushFilterToVisitedPlatformViews( + filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); flutterPlatformViewsController->CompositeEmbeddedView(2); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; From 0967a1f50538b4febb4a53c0b8c1ccbbd46116e7 Mon Sep 17 00:00:00 2001 From: Callum Moffat Date: Mon, 30 Jan 2023 15:09:44 -0500 Subject: [PATCH 2/2] Add check of PushFilterToVisitedPlatformViews --- shell/common/shell_unittests.cc | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index d850eab688012..6f3418f9adf4b 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -14,6 +14,7 @@ #include "assets/directory_asset_bundle.h" #include "common/graphics/persistent_cache.h" #include "flutter/flow/layers/backdrop_filter_layer.h" +#include "flutter/flow/layers/clip_rect_layer.h" #include "flutter/flow/layers/display_list_layer.h" #include "flutter/flow/layers/layer_raster_cache_item.h" #include "flutter/flow/layers/platform_view_layer.h" @@ -827,10 +828,16 @@ TEST_F(ShellTest, PushBackdropFilterToVisitedPlatformViews) { auto platform_view_layer = std::make_shared( SkPoint::Make(10, 10), SkSize::Make(10, 10), 50); root->Add(platform_view_layer); + auto transform_layer = + std::make_shared(SkMatrix::Translate(1, 1)); + root->Add(transform_layer); + auto clip_rect_layer = std::make_shared( + SkRect::MakeLTRB(0, 0, 30, 30), Clip::hardEdge); + transform_layer->Add(clip_rect_layer); auto filter = std::make_shared(5, 5, DlTileMode::kClamp); auto backdrop_filter_layer = std::make_shared(filter, DlBlendMode::kSrcOver); - root->Add(backdrop_filter_layer); + clip_rect_layer->Add(backdrop_filter_layer); auto platform_view_layer2 = std::make_shared( SkPoint::Make(10, 10), SkSize::Make(10, 10), 75); backdrop_filter_layer->Add(platform_view_layer2); @@ -846,6 +853,10 @@ TEST_F(ShellTest, PushBackdropFilterToVisitedPlatformViews) { auto mutator = *external_view_embedder->GetStack(50).Begin(); ASSERT_EQ(mutator->GetType(), MutatorType::kBackdropFilter); ASSERT_EQ(mutator->GetFilterMutation().GetFilter(), filter); + // Make sure the filterRect is in global coordinates (contains the (1,1) + // translation). + ASSERT_EQ(mutator->GetFilterMutation().GetFilterRect(), + SkRect::MakeLTRB(1, 1, 31, 31)); DestroyShell(std::move(shell)); }