Skip to content

Commit

Permalink
Fix position of BackdropFilter above PlatformView (flutter#39244)
Browse files Browse the repository at this point in the history
* Fix position of BackdropFilter in PlatformView

* Add check of PushFilterToVisitedPlatformViews
  • Loading branch information
moffatman authored Feb 9, 2023
1 parent e1d0032 commit add9e11
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 44 deletions.
5 changes: 5 additions & 0 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const DlImageFilter>& filter,
const SkRect& filter_rect);

Expand Down Expand Up @@ -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<const DlImageFilter> filter,
const SkRect& filter_rect) {
mutators_stack_.PushBackdropFilter(filter, filter_rect);
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion flow/layers/backdrop_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 12 additions & 1 deletion shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -827,10 +828,16 @@ TEST_F(ShellTest, PushBackdropFilterToVisitedPlatformViews) {
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);
Expand All @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,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()) {
Expand Down Expand Up @@ -531,6 +532,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.
Expand Down Expand Up @@ -565,7 +569,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<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);
Expand Down Expand Up @@ -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<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);
Expand Down Expand Up @@ -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<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);
Expand Down Expand Up @@ -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<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);
Expand Down Expand Up @@ -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<flutter::EmbeddedViewParams>(screenScaleMatrix,
Expand Down Expand Up @@ -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<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 =
Expand Down Expand Up @@ -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<flutter::EmbeddedViewParams>(screenScaleMatrix,
Expand Down Expand Up @@ -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<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 =
Expand Down Expand Up @@ -780,11 +780,12 @@ - (void)testEditBackdropFilters {
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,
Expand Down Expand Up @@ -833,11 +834,12 @@ - (void)testEditBackdropFilters {
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,
Expand Down Expand Up @@ -884,11 +886,12 @@ - (void)testEditBackdropFilters {
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,
Expand Down Expand Up @@ -936,7 +939,7 @@ - (void)testEditBackdropFilters {
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,
Expand Down Expand Up @@ -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<flutter::DlDilateImageFilter>(5, 2);
Expand Down Expand Up @@ -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<flutter::EmbeddedViewParams>(screenScaleMatrix,
Expand Down Expand Up @@ -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<flutter::EmbeddedViewParams>(screenScaleMatrix,
Expand Down Expand Up @@ -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<flutter::EmbeddedViewParams>(screenScaleMatrix,
Expand Down Expand Up @@ -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<flutter::EmbeddedViewParams>(screenScaleMatrix,
Expand Down Expand Up @@ -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 =
Expand All @@ -1363,8 +1373,8 @@ - (void)testBackdropFilterCorrectlyPushedAndReset {
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;
Expand Down

0 comments on commit add9e11

Please sign in to comment.