Fix position of BackdropFilter above PlatformView (#39244)
* Fix position of BackdropFilter in PlatformView
* Add check of PushFilterToVisitedPlatformViews
diff --git a/flow/embedded_views.h b/flow/embedded_views.h
index 84ad68f..0ea0357 100644
--- a/flow/embedded_views.h
+++ b/flow/embedded_views.h
@@ -185,6 +185,7 @@
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<const DlImageFilter>& filter,
const SkRect& filter_rect);
@@ -284,6 +285,8 @@
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<const DlImageFilter> filter,
const SkRect& filter_rect) {
mutators_stack_.PushBackdropFilter(filter, filter_rect);
@@ -487,6 +490,8 @@
// 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 7091e4f..cc5664f 100644
--- a/flow/layers/backdrop_filter_layer.cc
+++ b/flow/layers/backdrop_filter_layer.cc
@@ -44,7 +44,7 @@
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/common/shell_unittests.cc b/shell/common/shell_unittests.cc
index d850eab..6f3418f 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 @@
auto platform_view_layer = std::make_shared<PlatformViewLayer>(
SkPoint::Make(10, 10), SkSize::Make(10, 10), 50);
root->Add(platform_view_layer);
+ auto transform_layer =
+ std::make_shared<TransformLayer>(SkMatrix::Translate(1, 1));
+ root->Add(transform_layer);
+ auto clip_rect_layer = std::make_shared<ClipRectLayer>(
+ SkRect::MakeLTRB(0, 0, 30, 30), Clip::hardEdge);
+ transform_layer->Add(clip_rect_layer);
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
auto backdrop_filter_layer =
std::make_shared<BackdropFilterLayer>(filter, DlBlendMode::kSrcOver);
- root->Add(backdrop_filter_layer);
+ clip_rect_layer->Add(backdrop_filter_layer);
auto platform_view_layer2 = std::make_shared<PlatformViewLayer>(
SkPoint::Make(10, 10), SkSize::Make(10, 10), 75);
backdrop_filter_layer->Add(platform_view_layer2);
@@ -846,6 +853,10 @@
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));
}
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
index 2612c13..211959f 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
@@ -485,6 +485,7 @@
}
[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()) {
@@ -531,6 +532,9 @@
}
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.
@@ -565,7 +569,6 @@
[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 945e5b4..d97acbb 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
@@ -278,12 +278,12 @@
// 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<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);
@@ -348,12 +348,12 @@
// 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<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(5, 10), stack);
@@ -418,17 +418,17 @@
// 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<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);
+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(20, 20), stack);
flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->CompositeEmbeddedView(2);
@@ -489,12 +489,12 @@
// 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<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);
@@ -530,7 +530,7 @@
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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -600,13 +600,13 @@
// 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<flutter::DlBlurImageFilter>(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 @@
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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -735,13 +735,13 @@
// 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<flutter::DlBlurImageFilter>(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 @@
auto filter2 =
std::make_shared<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -833,11 +834,12 @@
if (i == 0) {
auto filter2 =
std::make_shared<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -884,11 +886,12 @@
if (i == 4) {
auto filter2 =
std::make_shared<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -936,7 +939,7 @@
for (int i = 0; i < 5; i++) {
auto filter2 = std::make_shared<flutter::DlBlurImageFilter>(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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -1007,8 +1010,8 @@
// 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<flutter::DlDilateImageFilter>(5, 2);
@@ -1045,11 +1048,13 @@
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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -1082,11 +1087,13 @@
// 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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -1119,11 +1126,13 @@
// 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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -1155,7 +1164,8 @@
}
// 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<flutter::EmbeddedViewParams>(screenScaleMatrix,
@@ -1352,8 +1362,8 @@
// 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 @@
flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->PushVisitedPlatformView(2);
auto filter = std::make_shared<flutter::DlBlurImageFilter>(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;