Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
021480d
Resolving merge conflicts.
emilyabest Jun 10, 2022
5027753
Removed trailing whitespace
emilyabest Jul 15, 2022
24731fa
Removed conflict code. Initial attempt with backdrop filter case.
emilyabest Jul 15, 2022
83b6607
Removed duplicate test
emilyabest Jul 18, 2022
fb0684c
Reverted code to pass the unit tests. Prepared method calls for mergi…
emilyabest Jul 19, 2022
31567f4
Ran whitespace check
emilyabest Jul 19, 2022
2bca987
Bringing back old checks.
emilyabest Jul 19, 2022
e830e4a
Updated code to plug into Javon's PR. Started unit tests for integrat…
emilyabest Jul 19, 2022
c881e11
Saving applyBackdropFilterWithRadius method for reference.
emilyabest Jul 20, 2022
81d2d71
Removed applyBackdropFilterWithRadius method. This is the new startin…
emilyabest Jul 20, 2022
bc2e1b1
Updated unit tests to use applyBackdropFilter method
emilyabest Jul 21, 2022
ff81803
Ran clang checks
emilyabest Jul 21, 2022
359a10d
First implementation to allow multiple backdrop filters. Also reorgan…
emilyabest Jul 21, 2022
cfd473d
Fixed BAD ACCESS error with private instance variable. Prepped for gi…
emilyabest Jul 22, 2022
ac3d4cf
Ran formatting checks
emilyabest Jul 22, 2022
c501a80
Condensed applyBackdropFilter method
emilyabest Jul 25, 2022
b4c64b6
Updated spacing.
emilyabest Jul 25, 2022
0f147e9
Formatted code
emilyabest Jul 25, 2022
604113e
Quick fix for failing applyBackdropFilters unit test. Started PR comm…
emilyabest Jul 27, 2022
ade2908
Added unit tests for non-DlImageBlurFilters. Made activeGaussianFilte…
emilyabest Jul 27, 2022
6a1e014
Formatting checks
emilyabest Jul 27, 2022
e07cb72
Minor formatting changes
emilyabest Jul 28, 2022
d9bcea9
Minor changes for visual testing.
emilyabest Jul 28, 2022
4ae563b
Ran formatting checks
emilyabest Jul 28, 2022
8e48100
Merge branch 'main' into BackdropView
emilyabest Jul 28, 2022
b18c2ad
Updated code to work with Chris' PR
emilyabest Aug 1, 2022
732c94d
Formatted code
emilyabest Aug 1, 2022
d6066ec
Resolved memory leak failure. Commented pass by reference alternative.
emilyabest Aug 2, 2022
2450016
Reorganized extraction method to use a for loop
emilyabest Aug 2, 2022
995fd57
Formatted code. Previous commit also updates API checks
emilyabest Aug 2, 2022
20a7d8f
Added unit test for invalid UIVEV API
emilyabest Aug 3, 2022
d81676f
Formatting check
emilyabest Aug 3, 2022
4e9da14
Implemented Chris' last comments, reverted back to original check to …
emilyabest Aug 4, 2022
2bdaec3
Formatting checks
emilyabest Aug 4, 2022
dc064ed
Removed typo
emilyabest Aug 4, 2022
beb4090
Formatting checks
emilyabest Aug 4, 2022
5599649
Moved blurEffectView release. Working on GitHub error.
emilyabest Aug 9, 2022
def8905
Formatting checks
emilyabest Aug 9, 2022
d010037
Adding gaussianFilter copies
emilyabest Aug 9, 2022
029d7cc
Formatting checks
emilyabest Aug 9, 2022
673b641
Simplified applyBackdropBlurFilter method
emilyabest Aug 10, 2022
aeef63e
Formatting checks
emilyabest Aug 10, 2022
b434756
Moved blurEffectView release to dealloc. Simplified while loops to cl…
emilyabest Aug 10, 2022
9429015
Simplified applyBackdropBlurFilters method
emilyabest Aug 10, 2022
cfea8e9
Trying a different init method for newGaussianFilters.
emilyabest Aug 10, 2022
3ed695d
Added autorelease after copying _gaussianFilter
emilyabest Aug 11, 2022
c4ab9cb
Merge branch 'main' into BackdropViewPreRebase
emilyabest Aug 12, 2022
a1ca917
review feedbacks
Aug 13, 2022
ee25e17
remove TODOs
Aug 18, 2022
92cc72b
fixes
Aug 18, 2022
1dca0dd
update golden
Aug 18, 2022
0702129
Merge branch 'main' into BackdropView
Aug 22, 2022
c810c40
Revert "Revert "Pushing BackdropFilter Mutator (#34355)" (#35543)"
Aug 22, 2022
a043cca
merge main
Aug 29, 2022
fd24904
update golden
Aug 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ class EmbeddedViewParams {
// Clippings are ignored.
const SkRect& finalBoundingRect() const { return final_bounding_rect_; }

// Pushes the stored DlImageFilter object to the mutators stack.
void PushImageFilter(std::shared_ptr<const DlImageFilter> filter) {
mutators_stack_.PushBackdropFilter(filter);
}

// Whether the embedder should construct DisplayList objects to hold the
// rendering commands for each between-view slice of the layer tree.
bool display_list_enabled() const { return display_list_enabled_; }
Expand Down Expand Up @@ -439,6 +444,18 @@ class ExternalViewEmbedder {
// 'EndFrame', otherwise returns false.
bool GetUsedThisFrame() const { return used_this_frame_; }

// Pushes the platform view id of a visited platform view to a list of
// visited platform views.
virtual void PushVisitedPlatformView(int64_t view_id) {}

// Pushes a DlImageFilter object to each platform view within a list of
// visited platform views.
//
// See also: |PushVisitedPlatformView| for pushing platform view ids to the
// visited platform views list.
virtual void PushFilterToVisitedPlatformViews(
std::shared_ptr<const DlImageFilter> filter) {}

private:
bool used_this_frame_ = false;

Expand Down
3 changes: 3 additions & 0 deletions flow/layers/backdrop_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ void BackdropFilterLayer::Preroll(PrerollContext* context,
const SkMatrix& matrix) {
Layer::AutoPrerollSaveLayerState save =
Layer::AutoPrerollSaveLayerState::Create(context, true, bool(filter_));
if (context->view_embedder != nullptr) {
context->view_embedder->PushFilterToVisitedPlatformViews(filter_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this push the outstanding clips as well? The filter will only be applied to the region inside those clips. More specifically, the output of the filter on the PlatformView will be clipped by the clips.

Copy link
Contributor

@cyanglaz cyanglaz Sep 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should when we figure out how to filter a specific region inside the PlatformView.
We should have a follow up PR to support filter only a part of the PlatformView (at least a rect), which will fix flutter/flutter#50183
And the clip path should be added to the method in that PR.

}
SkRect child_paint_bounds = SkRect::MakeEmpty();
PrerollChildren(context, matrix, &child_paint_bounds);
child_paint_bounds.join(context->cull_rect);
Expand Down
1 change: 1 addition & 0 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
context->display_list_enabled);
context->view_embedder->PrerollCompositeEmbeddedView(view_id_,
std::move(params));
context->view_embedder->PushVisitedPlatformView(view_id_);
}

void PlatformViewLayer::Paint(PaintContext& context) const {
Expand Down
27 changes: 27 additions & 0 deletions flow/mutators_stack_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ TEST(MutatorsStack, Equality) {
stack.PushClipPath(path);
int alpha = 240;
stack.PushOpacity(alpha);
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
stack.PushBackdropFilter(filter);

MutatorsStack stackOther;
SkMatrix matrixOther = SkMatrix::Scale(1, 1);
Expand All @@ -175,6 +177,9 @@ TEST(MutatorsStack, Equality) {
stackOther.PushClipPath(otherPath);
int otherAlpha = 240;
stackOther.PushOpacity(otherAlpha);
auto otherFilter =
std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
stackOther.PushBackdropFilter(otherFilter);

ASSERT_TRUE(stack == stackOther);
}
Expand Down Expand Up @@ -204,6 +209,11 @@ TEST(Mutator, Initialization) {
int alpha = 240;
Mutator mutator5 = Mutator(alpha);
ASSERT_TRUE(mutator5.GetType() == MutatorType::kOpacity);

auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter);
ASSERT_TRUE(mutator6.GetType() == MutatorType::kBackdropFilter);
ASSERT_TRUE(mutator6.GetFilter() == *filter);
}

TEST(Mutator, CopyConstructor) {
Expand Down Expand Up @@ -232,6 +242,11 @@ TEST(Mutator, CopyConstructor) {
Mutator mutator5 = Mutator(alpha);
Mutator copy5 = Mutator(mutator5);
ASSERT_TRUE(mutator5 == copy5);

auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter);
Mutator copy6 = Mutator(mutator6);
ASSERT_TRUE(mutator6 == copy6);
}

TEST(Mutator, Equality) {
Expand Down Expand Up @@ -260,6 +275,11 @@ TEST(Mutator, Equality) {
Mutator mutator5 = Mutator(alpha);
Mutator otherMutator5 = Mutator(alpha);
ASSERT_TRUE(mutator5 == otherMutator5);

auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter);
Mutator otherMutator6 = Mutator(filter);
ASSERT_TRUE(mutator6 == otherMutator6);
}

TEST(Mutator, UnEquality) {
Expand All @@ -275,6 +295,13 @@ TEST(Mutator, UnEquality) {
Mutator mutator2 = Mutator(alpha);
Mutator otherMutator2 = Mutator(alpha2);
ASSERT_TRUE(mutator2 != otherMutator2);

auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
auto filter2 =
std::make_shared<DlBlurImageFilter>(10, 10, DlTileMode::kClamp);
Mutator mutator3 = Mutator(filter);
Mutator otherMutator3 = Mutator(filter2);
ASSERT_TRUE(mutator3 != otherMutator3);
}

} // namespace testing
Expand Down
36 changes: 34 additions & 2 deletions shell/common/shell_test_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ SkISize ShellTestExternalViewEmbedder::GetLastSubmittedFrameSize() {
return last_submitted_frame_size_;
}

std::vector<int64_t> ShellTestExternalViewEmbedder::GetVisitedPlatformViews() {
return visited_platform_views_;
}

MutatorsStack ShellTestExternalViewEmbedder::GetStack(int64_t view_id) {
return mutators_stacks_[view_id];
}

// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::CancelFrame() {}

Expand All @@ -41,7 +49,16 @@ void ShellTestExternalViewEmbedder::BeginFrame(
// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<EmbeddedViewParams> params) {}
std::unique_ptr<EmbeddedViewParams> params) {
SkRect view_bounds = SkRect::Make(frame_size_);
std::unique_ptr<EmbedderViewSlice> view;
if (params->display_list_enabled()) {
view = std::make_unique<DisplayListEmbedderViewSlice>(view_bounds);
} else {
view = std::make_unique<SkPictureEmbedderViewSlice>(view_bounds);
}
slices_.insert_or_assign(view_id, std::move(view));
}

// |ExternalViewEmbedder|
PostPrerollResult ShellTestExternalViewEmbedder::PostPrerollAction(
Expand All @@ -62,9 +79,24 @@ ShellTestExternalViewEmbedder::GetCurrentBuilders() {
}

// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::PushVisitedPlatformView(int64_t view_id) {
visited_platform_views_.push_back(view_id);
}

// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::PushFilterToVisitedPlatformViews(
std::shared_ptr<const DlImageFilter> filter) {
for (int64_t id : visited_platform_views_) {
EmbeddedViewParams params = current_composition_params_[id];
params.PushImageFilter(filter);
current_composition_params_[id] = params;
mutators_stacks_[id] = params.mutatorsStack();
}
}

EmbedderPaintContext ShellTestExternalViewEmbedder::CompositeEmbeddedView(
int view_id) {
return {nullptr, nullptr};
return {slices_[view_id]->canvas(), slices_[view_id]->builder()};
}

// |ExternalViewEmbedder|
Expand Down
22 changes: 20 additions & 2 deletions shell/common/shell_test_external_view_embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "flutter/flow/embedded_views.h"
#include "flutter/fml/raster_thread_merger.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"

namespace flutter {

Expand All @@ -32,9 +33,15 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
// the external view embedder.
int GetSubmittedFrameCount();

// Returns the size of last submitted frame surface
// Returns the size of last submitted frame surface.
SkISize GetLastSubmittedFrameSize();

// Returns the mutators stack for the given platform view.
MutatorsStack GetStack(int64_t);

// Returns the list of visited platform views.
std::vector<int64_t> GetVisitedPlatformViews();

private:
// |ExternalViewEmbedder|
void CancelFrame() override;
Expand Down Expand Up @@ -64,6 +71,13 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
// |ExternalViewEmbedder|
EmbedderPaintContext CompositeEmbeddedView(int view_id) override;

// |ExternalViewEmbedder|
void PushVisitedPlatformView(int64_t view_id) override;

// |ExternalViewEmbedder|
void PushFilterToVisitedPlatformViews(
std::shared_ptr<const DlImageFilter> filter) override;

// |ExternalViewEmbedder|
void SubmitFrame(GrDirectContext* context,
std::unique_ptr<SurfaceFrame> frame) override;
Expand All @@ -84,7 +98,11 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
PostPrerollResult post_preroll_result_;

bool support_thread_merging_;

SkISize frame_size_;
std::map<int64_t, std::unique_ptr<EmbedderViewSlice>> slices_;
std::map<int64_t, MutatorsStack> mutators_stacks_;
std::map<int64_t, EmbeddedViewParams> current_composition_params_;
std::vector<int64_t> visited_platform_views_;
std::atomic<int> submitted_frame_count_;
std::atomic<SkISize> last_submitted_frame_size_;

Expand Down
58 changes: 57 additions & 1 deletion shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

#include "assets/directory_asset_bundle.h"
#include "common/graphics/persistent_cache.h"
#include "flutter/flow/layers/backdrop_filter_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"
#include "flutter/flow/layers/transform_layer.h"
#include "flutter/fml/command_line.h"
#include "flutter/fml/dart/dart_converter.h"
Expand Down Expand Up @@ -765,12 +767,66 @@ TEST_F(ShellTest, ExternalEmbedderNoThreadMerger) {

PumpOneFrame(shell.get(), 100, 100, builder);
end_frame_latch.Wait();

ASSERT_TRUE(end_frame_called);

DestroyShell(std::move(shell));
}

TEST_F(ShellTest, PushBackdropFilterToVisitedPlatformViews) {
auto settings = CreateSettingsForFixture();
fml::AutoResetWaitableEvent end_frame_latch;
bool end_frame_called = false;
auto end_frame_callback =
[&](bool should_resubmit_frame,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
ASSERT_TRUE(raster_thread_merger.get() == nullptr);
ASSERT_FALSE(should_resubmit_frame);
end_frame_called = true;
end_frame_latch.Signal();
};
auto external_view_embedder = std::make_shared<ShellTestExternalViewEmbedder>(
end_frame_callback, PostPrerollResult::kResubmitFrame, false);
auto shell = CreateShell(std::move(settings), GetTaskRunnersForFixture(),
false, external_view_embedder);

// Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get());

auto configuration = RunConfiguration::InferFromSettings(settings);
configuration.SetEntrypoint("emptyMain");

RunEngine(shell.get(), std::move(configuration));

LayerTreeBuilder builder = [&](std::shared_ptr<ContainerLayer> root) {
auto platform_view_layer = std::make_shared<PlatformViewLayer>(
SkPoint::Make(10, 10), SkSize::Make(10, 10), 50);
root->Add(platform_view_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);
auto platform_view_layer2 = std::make_shared<PlatformViewLayer>(
SkPoint::Make(10, 10), SkSize::Make(10, 10), 75);
backdrop_filter_layer->Add(platform_view_layer2);
};

PumpOneFrame(shell.get(), 100, 100, builder);
end_frame_latch.Wait();
ASSERT_EQ(external_view_embedder->GetVisitedPlatformViews().size(),
(const unsigned long)2);
ASSERT_EQ(external_view_embedder->GetVisitedPlatformViews()[0], 50);
ASSERT_EQ(external_view_embedder->GetVisitedPlatformViews()[1], 75);
ASSERT_TRUE(external_view_embedder->GetStack(75).is_empty());
ASSERT_FALSE(external_view_embedder->GetStack(50).is_empty());

auto filter = DlBlurImageFilter(5, 5, DlTileMode::kClamp);
auto mutator = *external_view_embedder->GetStack(50).Begin();
ASSERT_EQ(mutator->GetType(), MutatorType::kBackdropFilter);
ASSERT_EQ(mutator->GetFilter(), filter);

DestroyShell(std::move(shell));
}

// TODO(https://github.com/flutter/flutter/issues/59816): Enable on fuchsia.
TEST_F(ShellTest,
#if defined(OS_FUCHSIA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
@end

namespace flutter {
// Becomes NO if Apple's API changes and blurred backdrop filters cannot be applied.
BOOL canApplyBlurBackdrop = YES;

std::shared_ptr<FlutterPlatformViewLayer> FlutterPlatformViewLayerPool::GetLayer(
GrDirectContext* gr_context,
Expand Down Expand Up @@ -318,6 +320,15 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
}
}

void FlutterPlatformViewsController::PushFilterToVisitedPlatformViews(
std::shared_ptr<const DlImageFilter> filter) {
for (int64_t id : visited_platform_views_) {
EmbeddedViewParams params = current_composition_params_[id];
params.PushImageFilter(filter);
current_composition_params_[id] = params;
}
}

void FlutterPlatformViewsController::PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<EmbeddedViewParams> params) {
Expand Down Expand Up @@ -414,6 +425,8 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
CGRectGetWidth(flutter_view.bounds),
CGRectGetHeight(flutter_view.bounds))] autorelease];

NSMutableArray* blurRadii = [[[NSMutableArray alloc] init] autorelease];

auto iter = mutators_stack.Begin();
while (iter != mutators_stack.End()) {
switch ((*iter)->GetType()) {
Expand All @@ -434,11 +447,25 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
case kOpacity:
embedded_view.alpha = (*iter)->GetAlphaFloat() * embedded_view.alpha;
break;
case kBackdropFilter:
case kBackdropFilter: {
// We only support DlBlurImageFilter for BackdropFilter.
if ((*iter)->GetFilter().asBlur() && canApplyBlurBackdrop) {
// sigma_x is arbitrarily chosen as the radius value because Quartz sets
// sigma_x and sigma_y equal to each other. DlBlurImageFilter's Tile Mode
// is not supported in Quartz's gaussianBlur CAFilter, so it is not used
// to blur the PlatformView.
[blurRadii addObject:@((*iter)->GetFilter().asBlur()->sigma_x())];
}
break;
}
}
++iter;
}

if (canApplyBlurBackdrop) {
canApplyBlurBackdrop = [clipView applyBlurBackdropFilters:blurRadii];
}

// Reverse the offset of the clipView.
// The clipView's frame includes the final translate of the final transform matrix.
// So we need to revese this translate so the platform view can layout at the correct offset.
Expand Down Expand Up @@ -517,6 +544,7 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
clip_count_.clear();
views_to_recomposite_.clear();
layer_pool_->RecycleLayers();
visited_platform_views_.clear();
}

SkRect FlutterPlatformViewsController::GetPlatformViewRect(int view_id) {
Expand Down Expand Up @@ -777,6 +805,7 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
void FlutterPlatformViewsController::ResetFrameState() {
slices_.clear();
composition_order_.clear();
visited_platform_views_.clear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the fix for flutter/flutter#109783

}

} // namespace flutter
Expand Down
Loading