From 1dad72a760c317c1511a24ec01a65d4a57b7eec8 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 7 Oct 2024 09:25:45 -0700 Subject: [PATCH 01/20] [Impeller] add mechanism for sharing bdf inputs. --- display_list/benchmarking/dl_complexity_gl.cc | 5 +- display_list/benchmarking/dl_complexity_gl.h | 3 +- .../benchmarking/dl_complexity_metal.cc | 5 +- .../benchmarking/dl_complexity_metal.h | 3 +- display_list/display_list_unittests.cc | 15 ++- display_list/dl_builder.cc | 11 +- display_list/dl_builder.h | 6 +- display_list/dl_canvas.h | 3 +- display_list/dl_op_receiver.h | 19 +-- display_list/dl_op_records.h | 13 +- display_list/effects/dl_image_filter.h | 3 +- display_list/skia/dl_sk_canvas.cc | 3 +- display_list/skia/dl_sk_canvas.h | 3 +- display_list/skia/dl_sk_dispatcher.cc | 4 +- display_list/skia/dl_sk_dispatcher.h | 3 +- display_list/utils/dl_receiver_utils.h | 3 +- flow/layers/backdrop_filter_layer.cc | 10 +- flow/layers/backdrop_filter_layer.h | 4 +- flow/layers/layer_state_stack.cc | 30 +++-- flow/layers/layer_state_stack.h | 9 +- impeller/display_list/canvas.cc | 119 ++++++++++++++---- impeller/display_list/canvas.h | 19 ++- impeller/display_list/dl_dispatcher.cc | 29 ++++- impeller/display_list/dl_dispatcher.h | 20 ++- impeller/entity/entity_pass_target.h | 3 + lib/ui/compositing.dart | 18 ++- lib/ui/compositing/scene_builder.cc | 3 +- lib/ui/compositing/scene_builder.h | 1 + shell/common/dl_op_spy.cc | 3 +- shell/common/dl_op_spy.h | 3 +- testing/display_list_testing.cc | 6 +- testing/display_list_testing.h | 6 +- testing/mock_canvas.cc | 3 +- testing/mock_canvas.h | 3 +- 34 files changed, 298 insertions(+), 93 deletions(-) diff --git a/display_list/benchmarking/dl_complexity_gl.cc b/display_list/benchmarking/dl_complexity_gl.cc index 44f658bb99146..072298b68f7c3 100644 --- a/display_list/benchmarking/dl_complexity_gl.cc +++ b/display_list/benchmarking/dl_complexity_gl.cc @@ -51,7 +51,8 @@ unsigned int DisplayListGLComplexityCalculator::GLHelper::BatchedComplexity() { void DisplayListGLComplexityCalculator::GLHelper::saveLayer( const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { if (IsComplex()) { return; } @@ -627,7 +628,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList( GLHelper helper(Ceiling() - CurrentComplexityScore()); if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { auto bounds = display_list->GetBounds(); - helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr); + helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); } display_list->Dispatch(helper); AccumulateComplexity(helper.ComplexityScore()); diff --git a/display_list/benchmarking/dl_complexity_gl.h b/display_list/benchmarking/dl_complexity_gl.h index d0fcbb98a3bf4..524fc76b28f5c 100644 --- a/display_list/benchmarking/dl_complexity_gl.h +++ b/display_list/benchmarking/dl_complexity_gl.h @@ -37,7 +37,8 @@ class DisplayListGLComplexityCalculator void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override; + const DlImageFilter* backdrop, + int64_t backdrop_id) override; void drawLine(const DlPoint& p0, const DlPoint& p1) override; void drawDashedLine(const DlPoint& p0, diff --git a/display_list/benchmarking/dl_complexity_metal.cc b/display_list/benchmarking/dl_complexity_metal.cc index 82f641e6cc123..a88e9b2ffeb48 100644 --- a/display_list/benchmarking/dl_complexity_metal.cc +++ b/display_list/benchmarking/dl_complexity_metal.cc @@ -65,7 +65,8 @@ DisplayListMetalComplexityCalculator::MetalHelper::BatchedComplexity() { void DisplayListMetalComplexityCalculator::MetalHelper::saveLayer( const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { if (IsComplex()) { return; } @@ -571,7 +572,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDisplayList( MetalHelper helper(Ceiling() - CurrentComplexityScore()); if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { auto bounds = display_list->GetBounds(); - helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr); + helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); } display_list->Dispatch(helper); AccumulateComplexity(helper.ComplexityScore()); diff --git a/display_list/benchmarking/dl_complexity_metal.h b/display_list/benchmarking/dl_complexity_metal.h index d11d0ff2a7b02..95d02c1bb541d 100644 --- a/display_list/benchmarking/dl_complexity_metal.h +++ b/display_list/benchmarking/dl_complexity_metal.h @@ -37,7 +37,8 @@ class DisplayListMetalComplexityCalculator void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override; + const DlImageFilter* backdrop, + int64_t backdrop_id) override; void drawLine(const DlPoint& p0, const DlPoint& p1) override; void drawDashedLine(const DlPoint& p0, diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 56c560540bce4..55e0b8416b3fb 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -1476,7 +1476,8 @@ class SaveLayerExpector : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int64_t backdrop_id) override { FML_UNREACHABLE(); } @@ -1484,7 +1485,8 @@ class SaveLayerExpector : public virtual DlOpReceiver, const SaveLayerOptions& options, uint32_t total_content_depth, DlBlendMode max_content_blend_mode, - const DlImageFilter* backdrop = nullptr) { + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) { ASSERT_LT(save_layer_count_, expected_.size()) << label(); auto expect = expected_[save_layer_count_]; if (expect.options.has_value()) { @@ -3657,7 +3659,8 @@ class SaveLayerBoundsExpector : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int64_t backdrop_id) override { ASSERT_LT(save_layer_count_, expected_.size()); auto expected = expected_[save_layer_count_]; EXPECT_EQ(options.bounds_from_caller(), @@ -4122,7 +4125,8 @@ class DepthExpector : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, SaveLayerOptions options, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int64_t backdrop_id) override { // This method should not be called since we override the variant with // the total_content_depth parameter. FAIL() << "saveLayer(no depth parameter) method should not be called"; @@ -4132,7 +4136,8 @@ class DepthExpector : public virtual DlOpReceiver, const SaveLayerOptions& options, uint32_t total_content_depth, DlBlendMode max_content_mode, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int64_t backdrop_id) override { ASSERT_LT(index_, depth_expectations_.size()); EXPECT_EQ(depth_expectations_[index_], total_content_depth) << "at index " << index_; diff --git a/display_list/dl_builder.cc b/display_list/dl_builder.cc index 86b6def705e12..c5fa0ecc43e83 100644 --- a/display_list/dl_builder.cc +++ b/display_list/dl_builder.cc @@ -409,7 +409,8 @@ void DisplayListBuilder::Save() { void DisplayListBuilder::saveLayer(const DlRect& bounds, const SaveLayerOptions in_options, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { SaveLayerOptions options = in_options.without_optimizations(); DisplayListAttributeFlags flags = options.renders_with_attributes() ? kSaveLayerWithPaintFlags @@ -524,7 +525,8 @@ void DisplayListBuilder::saveLayer(const DlRect& bounds, } if (backdrop) { - Push(0, options, record_bounds, backdrop); + Push(0, options, record_bounds, backdrop, + backdrop_id); } else { Push(0, options, record_bounds); } @@ -542,7 +544,8 @@ void DisplayListBuilder::saveLayer(const DlRect& bounds, } void DisplayListBuilder::SaveLayer(const SkRect* bounds, const DlPaint* paint, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { SaveLayerOptions options; DlRect temp_bounds; if (bounds) { @@ -556,7 +559,7 @@ void DisplayListBuilder::SaveLayer(const SkRect* bounds, SetAttributesFromPaint(*paint, DisplayListOpFlags::kSaveLayerWithPaintFlags); } - saveLayer(temp_bounds, options, backdrop); + saveLayer(temp_bounds, options, backdrop, backdrop_id); } void DisplayListBuilder::Restore() { diff --git a/display_list/dl_builder.h b/display_list/dl_builder.h index ed2a5a8759ad6..d412d4ba33a5b 100644 --- a/display_list/dl_builder.h +++ b/display_list/dl_builder.h @@ -51,7 +51,8 @@ class DisplayListBuilder final : public virtual DlCanvas, // |DlCanvas| void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr) override; + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) override; // |DlCanvas| void Restore() override; // |DlCanvas| @@ -381,7 +382,8 @@ class DisplayListBuilder final : public virtual DlCanvas, // |DlOpReceiver| void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override; + const DlImageFilter* backdrop, + int64_t backdrop_id) override; // |DlOpReceiver| void restore() override { Restore(); } diff --git a/display_list/dl_canvas.h b/display_list/dl_canvas.h index 43771e39661df..31249750e9202 100644 --- a/display_list/dl_canvas.h +++ b/display_list/dl_canvas.h @@ -62,7 +62,8 @@ class DlCanvas { virtual void Save() = 0; virtual void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr) = 0; + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) = 0; virtual void Restore() = 0; virtual int GetSaveCount() const = 0; virtual void RestoreToCount(int restore_count) = 0; diff --git a/display_list/dl_op_receiver.h b/display_list/dl_op_receiver.h index 091ed6f655ec6..080ea37fd901b 100644 --- a/display_list/dl_op_receiver.h +++ b/display_list/dl_op_receiver.h @@ -17,8 +17,6 @@ #include "flutter/display_list/effects/dl_mask_filter.h" #include "flutter/display_list/image/dl_image.h" -#include "flutter/impeller/geometry/path.h" - namespace flutter { class DisplayList; @@ -143,15 +141,17 @@ class DlOpReceiver { // layer before further rendering happens. virtual void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop = nullptr) = 0; + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) = 0; // Optional variant of saveLayer() that passes the total depth count of // all rendering operations that occur until the next restore() call. virtual void saveLayer(const DlRect& bounds, const SaveLayerOptions& options, uint32_t total_content_depth, DlBlendMode max_content_blend_mode, - const DlImageFilter* backdrop = nullptr) { - saveLayer(bounds, options, backdrop); + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) { + saveLayer(bounds, options, backdrop, backdrop_id); } virtual void restore() = 0; @@ -172,11 +172,14 @@ class DlOpReceiver { // https://github.com/flutter/flutter/issues/144070 virtual void saveLayer(const DlRect* bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop = nullptr) final { + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) final { if (bounds) { - saveLayer(*bounds, options.with_bounds_from_caller(), backdrop); + saveLayer(*bounds, options.with_bounds_from_caller(), backdrop, + backdrop_id); } else { - saveLayer(DlRect(), options.without_bounds_from_caller(), backdrop); + saveLayer(DlRect(), options.without_bounds_from_caller(), backdrop, + backdrop_id); } } // --------------------------------------------------------------------- diff --git a/display_list/dl_op_records.h b/display_list/dl_op_records.h index 592c31e914ca2..77fd0dd8cbbd4 100644 --- a/display_list/dl_op_records.h +++ b/display_list/dl_op_records.h @@ -310,19 +310,24 @@ struct SaveLayerBackdropOp final : SaveLayerOpBase { SaveLayerBackdropOp(const SaveLayerOptions& options, const DlRect& rect, - const DlImageFilter* backdrop) - : SaveLayerOpBase(options, rect), backdrop(backdrop->shared()) {} + const DlImageFilter* backdrop, + int64_t backdrop_id = -1) + : SaveLayerOpBase(options, rect), + backdrop(backdrop->shared()), + backdrop_id_(backdrop_id) {} const std::shared_ptr backdrop; + int64_t backdrop_id_; void dispatch(DlOpReceiver& receiver) const { receiver.saveLayer(rect, options, total_content_depth, max_blend_mode, - backdrop.get()); + backdrop.get(), backdrop_id_); } DisplayListCompare equals(const SaveLayerBackdropOp* other) const { return (options == other->options && rect == other->rect && - Equals(backdrop, other->backdrop)) + Equals(backdrop, other->backdrop) && + backdrop_id_ == other->backdrop_id_) ? DisplayListCompare::kEqual : DisplayListCompare::kNotEqual; } diff --git a/display_list/effects/dl_image_filter.h b/display_list/effects/dl_image_filter.h index f98010f56f0bc..1e6b01529429c 100644 --- a/display_list/effects/dl_image_filter.h +++ b/display_list/effects/dl_image_filter.h @@ -281,7 +281,8 @@ class DlBlurImageFilter final : public DlImageFilter { bool equals_(const DlImageFilter& other) const override { FML_DCHECK(other.type() == DlImageFilterType::kBlur); auto that = static_cast(&other); - return (sigma_x_ == that->sigma_x_ && sigma_y_ == that->sigma_y_ && + return (SkScalarNearlyEqual(sigma_x_, that->sigma_x_) && + SkScalarNearlyEqual(sigma_y_, that->sigma_y_) && tile_mode_ == that->tile_mode_); } diff --git a/display_list/skia/dl_sk_canvas.cc b/display_list/skia/dl_sk_canvas.cc index 2dfd11e6547d4..e35d271218b75 100644 --- a/display_list/skia/dl_sk_canvas.cc +++ b/display_list/skia/dl_sk_canvas.cc @@ -54,7 +54,8 @@ void DlSkCanvasAdapter::Save() { void DlSkCanvasAdapter::SaveLayer(const SkRect* bounds, const DlPaint* paint, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { sk_sp sk_backdrop = ToSk(backdrop); SkOptionalPaint sk_paint(paint); TRACE_EVENT0("flutter", "Canvas::saveLayer"); diff --git a/display_list/skia/dl_sk_canvas.h b/display_list/skia/dl_sk_canvas.h index 4c1c550c2cb7d..2f9bef904e8ee 100644 --- a/display_list/skia/dl_sk_canvas.h +++ b/display_list/skia/dl_sk_canvas.h @@ -32,7 +32,8 @@ class DlSkCanvasAdapter final : public virtual DlCanvas { void Save() override; void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr) override; + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) override; void Restore() override; int GetSaveCount() const override; void RestoreToCount(int restore_count) override; diff --git a/display_list/skia/dl_sk_dispatcher.cc b/display_list/skia/dl_sk_dispatcher.cc index 33b11166cd5ae..5104dc50a0059 100644 --- a/display_list/skia/dl_sk_dispatcher.cc +++ b/display_list/skia/dl_sk_dispatcher.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flutter/display_list/skia/dl_sk_dispatcher.h" +#include #include "flutter/display_list/dl_blend_mode.h" #include "flutter/display_list/skia/dl_sk_conversions.h" @@ -46,7 +47,8 @@ void DlSkCanvasDispatcher::restore() { } void DlSkCanvasDispatcher::saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { if (!options.content_is_clipped() && options.can_distribute_opacity() && backdrop == nullptr) { // We know that: diff --git a/display_list/skia/dl_sk_dispatcher.h b/display_list/skia/dl_sk_dispatcher.h index fa5fbdd21259b..ed38bf55ef94f 100644 --- a/display_list/skia/dl_sk_dispatcher.h +++ b/display_list/skia/dl_sk_dispatcher.h @@ -31,7 +31,8 @@ class DlSkCanvasDispatcher : public virtual DlOpReceiver, void restore() override; void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override; + const DlImageFilter* backdrop, + int64_t backdrop_id) override; void translate(DlScalar tx, DlScalar ty) override; void scale(DlScalar sx, DlScalar sy) override; diff --git a/display_list/utils/dl_receiver_utils.h b/display_list/utils/dl_receiver_utils.h index 257d276657b86..ea8f087d2eef0 100644 --- a/display_list/utils/dl_receiver_utils.h +++ b/display_list/utils/dl_receiver_utils.h @@ -82,7 +82,8 @@ class IgnoreDrawDispatchHelper : public virtual DlOpReceiver { void save() override {} void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override {} + const DlImageFilter* backdrop, + int64_t backdrop_id) override {} void restore() override {} void drawColor(DlColor color, DlBlendMode mode) override {} void drawPaint() override {} diff --git a/flow/layers/backdrop_filter_layer.cc b/flow/layers/backdrop_filter_layer.cc index 32707c4f77e6d..83e6a38fcab06 100644 --- a/flow/layers/backdrop_filter_layer.cc +++ b/flow/layers/backdrop_filter_layer.cc @@ -8,8 +8,11 @@ namespace flutter { BackdropFilterLayer::BackdropFilterLayer( std::shared_ptr filter, - DlBlendMode blend_mode) - : filter_(std::move(filter)), blend_mode_(blend_mode) {} + DlBlendMode blend_mode, + int64_t backdrop_id) + : filter_(std::move(filter)), + blend_mode_(blend_mode), + backdrop_id_(backdrop_id) {} void BackdropFilterLayer::Diff(DiffContext* context, const Layer* old_layer) { DiffContext::AutoSubtreeRestore subtree(context); @@ -57,7 +60,8 @@ void BackdropFilterLayer::Paint(PaintContext& context) const { FML_DCHECK(needs_painting(context)); auto mutator = context.state_stack.save(); - mutator.applyBackdropFilter(paint_bounds(), filter_, blend_mode_); + mutator.applyBackdropFilter(paint_bounds(), filter_, blend_mode_, + backdrop_id_); PaintChildren(context); } diff --git a/flow/layers/backdrop_filter_layer.h b/flow/layers/backdrop_filter_layer.h index d17fed110d5e9..2896c3dc126f1 100644 --- a/flow/layers/backdrop_filter_layer.h +++ b/flow/layers/backdrop_filter_layer.h @@ -13,7 +13,8 @@ namespace flutter { class BackdropFilterLayer : public ContainerLayer { public: BackdropFilterLayer(std::shared_ptr filter, - DlBlendMode blend_mode); + DlBlendMode blend_mode, + int64_t backdrop_id = -1); void Diff(DiffContext* context, const Layer* old_layer) override; @@ -24,6 +25,7 @@ class BackdropFilterLayer : public ContainerLayer { private: std::shared_ptr filter_; DlBlendMode blend_mode_; + int64_t backdrop_id_ = -1; FML_DISALLOW_COPY_AND_ASSIGN(BackdropFilterLayer); }; diff --git a/flow/layers/layer_state_stack.cc b/flow/layers/layer_state_stack.cc index a3908df25bcbf..86fb801313778 100644 --- a/flow/layers/layer_state_stack.cc +++ b/flow/layers/layer_state_stack.cc @@ -52,7 +52,8 @@ class DummyDelegate : public LayerStateStack::Delegate { void saveLayer(const SkRect& bounds, LayerStateStack::RenderingAttributes& attributes, DlBlendMode blend, - const DlImageFilter* backdrop) override {} + const DlImageFilter* backdrop, + int backdrop_id) override {} void restore() override {} void translate(SkScalar tx, SkScalar ty) override {} @@ -99,10 +100,12 @@ class DlCanvasDelegate : public LayerStateStack::Delegate { void saveLayer(const SkRect& bounds, LayerStateStack::RenderingAttributes& attributes, DlBlendMode blend_mode, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int backdrop_id) override { TRACE_EVENT0("flutter", "Canvas::saveLayer"); DlPaint paint; - canvas_->SaveLayer(&bounds, attributes.fill(paint, blend_mode), backdrop); + canvas_->SaveLayer(&bounds, attributes.fill(paint, blend_mode), backdrop, + backdrop_id); } void restore() override { canvas_->Restore(); } @@ -157,7 +160,8 @@ class PrerollDelegate : public LayerStateStack::Delegate { void saveLayer(const SkRect& bounds, LayerStateStack::RenderingAttributes& attributes, DlBlendMode blend, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int backdrop_id) override { save_stack_.emplace_back(state()); } void restore() override { save_stack_.pop_back(); } @@ -343,13 +347,16 @@ class BackdropFilterEntry : public SaveLayerEntry { BackdropFilterEntry(const SkRect& bounds, const std::shared_ptr& filter, DlBlendMode blend_mode, + int64_t backdrop_id, const LayerStateStack::RenderingAttributes& prev) - : SaveLayerEntry(bounds, blend_mode, prev), filter_(filter) {} + : SaveLayerEntry(bounds, blend_mode, prev), + filter_(filter), + backdrop_id_(backdrop_id) {} ~BackdropFilterEntry() override = default; void apply(LayerStateStack* stack) const override { stack->delegate_->saveLayer(bounds_, stack->outstanding_, blend_mode_, - filter_.get()); + filter_.get(), backdrop_id_); stack->outstanding_ = {}; } @@ -366,6 +373,7 @@ class BackdropFilterEntry : public SaveLayerEntry { private: const std::shared_ptr filter_; + int64_t backdrop_id_ = -1; FML_DISALLOW_COPY_ASSIGN_AND_MOVE(BackdropFilterEntry); }; @@ -558,8 +566,9 @@ void MutatorContext::applyColorFilter( void MutatorContext::applyBackdropFilter( const SkRect& bounds, const std::shared_ptr& filter, - DlBlendMode blend_mode) { - layer_state_stack_->push_backdrop(bounds, filter, blend_mode); + DlBlendMode blend_mode, + int64_t backdrop_id) { + layer_state_stack_->push_backdrop(bounds, filter, blend_mode, backdrop_id); } void MutatorContext::translate(SkScalar tx, SkScalar ty) { @@ -706,9 +715,10 @@ void LayerStateStack::push_image_filter( void LayerStateStack::push_backdrop( const SkRect& bounds, const std::shared_ptr& filter, - DlBlendMode blend_mode) { + DlBlendMode blend_mode, + int64_t backdrop_id) { state_stack_.emplace_back(std::make_unique( - bounds, filter, blend_mode, outstanding_)); + bounds, filter, blend_mode, backdrop_id, outstanding_)); apply_last_entry(); } diff --git a/flow/layers/layer_state_stack.h b/flow/layers/layer_state_stack.h index c9e606e86e245..ba15601f06859 100644 --- a/flow/layers/layer_state_stack.h +++ b/flow/layers/layer_state_stack.h @@ -197,7 +197,8 @@ class LayerStateStack { // will only see a saveLayer with the indicated blend_mode. void applyBackdropFilter(const SkRect& bounds, const std::shared_ptr& filter, - DlBlendMode blend_mode); + DlBlendMode blend_mode, + int64_t backdrop_id); void translate(SkScalar tx, SkScalar ty); void translate(SkPoint tp) { translate(tp.fX, tp.fY); } @@ -334,7 +335,8 @@ class LayerStateStack { const std::shared_ptr& filter); void push_backdrop(const SkRect& bounds, const std::shared_ptr& filter, - DlBlendMode blend_mode); + DlBlendMode blend_mode, + int64_t push_backdrop); void push_translate(SkScalar tx, SkScalar ty); void push_transform(const SkM44& matrix); @@ -447,7 +449,8 @@ class LayerStateStack { virtual void saveLayer(const SkRect& bounds, RenderingAttributes& attributes, DlBlendMode blend, - const DlImageFilter* backdrop) = 0; + const DlImageFilter* backdrop, + int backdrop_id = -1) = 0; virtual void restore() = 0; virtual void translate(SkScalar tx, SkScalar ty) = 0; diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 9c45f8d6dce84..b4fb4fb18010a 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -158,7 +158,8 @@ static std::shared_ptr FlipBackdrop( std::vector& render_passes, Point global_pass_position, EntityPassClipStack& clip_coverage_stack, - ContentContext& renderer) { + ContentContext& renderer, + bool should_remove_texture = false) { auto rendering_config = std::move(render_passes.back()); render_passes.pop_back(); @@ -205,6 +206,12 @@ static std::shared_ptr FlipBackdrop( render_passes.push_back(LazyRenderingConfig( renderer, std::move(rendering_config.entity_pass_target), std::move(rendering_config.inline_pass_context))); + // If the current texture is being cachced for a BDF we need to ensure we + // don't recycle it during recording. remove it from the entity pass target. + if (should_remove_texture) { + render_passes.back().entity_pass_target->RemoveSecondary(); + } + // Eagerly restore the BDF contents. // If the pass context returns a backdrop texture, we need to draw it to the @@ -1072,8 +1079,9 @@ void Canvas::SaveLayer(const Paint& paint, const flutter::DlImageFilter* backdrop_filter, ContentBoundsPromise bounds_promise, uint32_t total_content_depth, - bool can_distribute_opacity) { - TRACE_EVENT0("flutter", "Canvas::saveLayer"); + bool can_distribute_opacity, + int64_t backdrop_id) { + // TRACE_EVENT0("flutter", "Canvas::saveLayer"); if (IsSkipping()) { return SkipUntilMatchingRestore(total_content_depth); } @@ -1154,14 +1162,31 @@ void Canvas::SaveLayer(const Paint& paint, return filter; }; - auto input_texture = FlipBackdrop(render_passes_, // - GetGlobalPassPosition(), // - clip_coverage_stack_, // - renderer_ // - ); - if (!input_texture) { - // Validation failures are logged in FlipBackdrop. - return; + std::shared_ptr input_texture; + const auto& backdrop_data = backdrop_keys_.find(backdrop_id); + // If the backdrop ID is not the no-op id, and there is more than one usage + // of it in the current scene, cache the backdrop texture and remove it from + // the current entity pass flip. + bool will_cache_texture = + backdrop_id != -1 && backdrop_data->second.global_rects.size() > 1; + if (backdrop_data == backdrop_keys_.end() || + !backdrop_data->second.texture_slot) { + input_texture = FlipBackdrop(render_passes_, // + GetGlobalPassPosition(), // + clip_coverage_stack_, // + renderer_, // + will_cache_texture // + ); + if (!input_texture) { + // Validation failures are logged in FlipBackdrop. + return; + } + + if (will_cache_texture) { + backdrop_data->second.texture_slot = input_texture; + } + } else { + input_texture = backdrop_data->second.texture_slot; } backdrop_filter_contents = backdrop_filter_proc( @@ -1172,6 +1197,36 @@ void Canvas::SaveLayer(const Paint& paint, transform_stack_.back().transform.HasTranslation() ? Entity::RenderingMode::kSubpassPrependSnapshotTransform : Entity::RenderingMode::kSubpassAppendSnapshotTransform); + + // If all filters are equal, process the filter input once. + if (will_cache_texture && backdrop_data->second.all_filters_equal && + !backdrop_data->second.filtered_input_slot.has_value()) { + backdrop_data->second.filtered_input_slot = + backdrop_filter_contents->RenderToSnapshot(renderer_, {}); + } + + if (will_cache_texture && + backdrop_data->second.filtered_input_slot.has_value()) { + auto snapshot = backdrop_data->second.filtered_input_slot.value(); + auto contents = TextureContents::MakeRect(subpass_coverage); + auto scaled = + subpass_coverage.TransformBounds(snapshot.transform.Invert()); + contents->SetTexture(snapshot.texture); + contents->SetSourceRect(scaled); + + Entity backdrop_entity; + backdrop_entity.SetContents(std::move(contents)); + // backdrop_entity.SetTransform( + // Matrix::MakeTranslation(Vector3(-local_position))); + backdrop_entity.SetClipDepth(std::numeric_limits::max()); + backdrop_entity.SetBlendMode(paint.blend_mode); + + backdrop_entity.Render( + renderer_, + *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + Save(0); + return; + } } // When applying a save layer, absorb any pending distributed opacity. @@ -1206,16 +1261,37 @@ void Canvas::SaveLayer(const Paint& paint, clip_coverage_stack_.PushSubpass(subpass_coverage, GetClipHeight()); if (backdrop_filter_contents) { - // Render the backdrop entity. - Entity backdrop_entity; - backdrop_entity.SetContents(std::move(backdrop_filter_contents)); - backdrop_entity.SetTransform( - Matrix::MakeTranslation(Vector3(-local_position))); - backdrop_entity.SetClipDepth(std::numeric_limits::max()); - - backdrop_entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + const auto& backdrop_data = backdrop_keys_.find(backdrop_id); + if (backdrop_id != -1 && + backdrop_data->second.filtered_input_slot.has_value()) { + auto snapshot = backdrop_data->second.filtered_input_slot.value(); + auto contents = TextureContents::MakeRect(subpass_coverage); + auto scaled = + subpass_coverage.TransformBounds(snapshot.transform.Invert()); + contents->SetTexture(snapshot.texture); + contents->SetSourceRect(scaled); + + Entity backdrop_entity; + backdrop_entity.SetContents(std::move(contents)); + backdrop_entity.SetTransform( + Matrix::MakeTranslation(Vector3(-local_position))); + backdrop_entity.SetClipDepth(std::numeric_limits::max()); + + backdrop_entity.Render( + renderer_, + *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + } else { + // Render the backdrop entity. + Entity backdrop_entity; + backdrop_entity.SetContents(std::move(backdrop_filter_contents)); + backdrop_entity.SetTransform( + Matrix::MakeTranslation(Vector3(-local_position))); + backdrop_entity.SetClipDepth(std::numeric_limits::max()); + + backdrop_entity.Render( + renderer_, + *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + } } } @@ -1650,6 +1726,7 @@ void Canvas::EndReplay() { FML_DCHECK(render_passes_.size() == 1u); render_passes_.back().inline_pass_context->GetRenderPass(0); render_passes_.back().inline_pass_context->EndPass(); + backdrop_keys_.clear(); // If requires_readback_ was true, then we rendered to an offscreen texture // instead of to the onscreen provided in the render target. Now we need to diff --git a/impeller/display_list/canvas.h b/impeller/display_list/canvas.h index e1cc8e2afda4c..03270a45fb871 100644 --- a/impeller/display_list/canvas.h +++ b/impeller/display_list/canvas.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "display_list/effects/dl_image_filter.h" @@ -24,10 +25,19 @@ #include "impeller/geometry/path.h" #include "impeller/geometry/point.h" #include "impeller/geometry/vector.h" +#include "impeller/renderer/snapshot.h" #include "impeller/typographer/text_frame.h" namespace impeller { +struct BackdropData { + std::vector global_rects; + bool all_filters_equal = true; + std::shared_ptr texture_slot; + std::optional filtered_input_slot; + const flutter::DlImageFilter* last_backdrop = nullptr; +}; + struct CanvasStackEntry { Matrix transform; uint32_t clip_depth = 0u; @@ -123,6 +133,11 @@ class Canvas { ~Canvas() = default; + void SetBackdropKeys( + std::unordered_map backdrop_keys) { + backdrop_keys_ = std::move(backdrop_keys); + } + /// @brief Return the culling bounds of the current render target, or nullopt /// if there is no coverage. std::optional GetLocalCoverageLimit() const; @@ -135,7 +150,8 @@ class Canvas { const flutter::DlImageFilter* backdrop_filter = nullptr, ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown, uint32_t total_content_depth = kMaxDepth, - bool can_distribute_opacity = false); + bool can_distribute_opacity = false, + int64_t backdrop_id = -1); bool Restore(); @@ -246,6 +262,7 @@ class Canvas { std::optional initial_cull_rect_; std::vector render_passes_; std::vector save_layer_state_; + std::unordered_map backdrop_keys_; uint64_t current_depth_ = 0u; diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 6a06ce5ff5b34..f4880b930be12 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -15,6 +15,7 @@ #include "flutter/fml/logging.h" #include "impeller/core/formats.h" #include "impeller/display_list/aiks_context.h" +#include "impeller/display_list/canvas.h" #include "impeller/display_list/color_filter.h" #include "impeller/display_list/dl_atlas_geometry.h" #include "impeller/display_list/dl_vertices_geometry.h" @@ -301,7 +302,8 @@ void DlDispatcherBase::saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions& options, uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, - const flutter::DlImageFilter* backdrop) { + const flutter::DlImageFilter* backdrop, + int64_t backdrop_id) { AUTO_DEPTH_WATCHER(1u); auto paint = options.renders_with_attributes() ? paint_ : Paint{}; @@ -319,7 +321,9 @@ void DlDispatcherBase::saveLayer(const DlRect& bounds, paint, impeller_bounds, backdrop, promise, total_content_depth, // Unbounded content can still have user specified bounds that require a // saveLayer to be created to perform the clip. - options.can_distribute_opacity() && !options.content_is_unbounded()); + options.can_distribute_opacity() && !options.content_is_unbounded(), + backdrop_id // + ); } // |flutter::DlOpReceiver| @@ -985,9 +989,26 @@ void TextFrameDispatcher::save() { void TextFrameDispatcher::saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions options, - const flutter::DlImageFilter* backdrop) { + const flutter::DlImageFilter* backdrop, + int64_t backdrop_id) { save(); + if (backdrop != nullptr && backdrop_id != -1) { + const auto& existing = backdrop_keys_.find(backdrop_id); + if (existing == backdrop_keys_.end()) { + backdrop_keys_[backdrop_id] = + BackdropData{.global_rects = {bounds.TransformBounds(matrix_)}, + .last_backdrop = backdrop}; + } else { + BackdropData& data = backdrop_keys_[backdrop_id]; + if (data.all_filters_equal) { + data.all_filters_equal = true; // data.last_backdrop == backdrop; + data.last_backdrop = backdrop; + } + data.global_rects.push_back(bounds.TransformBounds(matrix_)); + } + } + // This dispatcher does not track enough state to accurately compute // cull rects with image filters. auto global_cull_rect = cull_rect_state_.back(); @@ -1230,6 +1251,7 @@ std::shared_ptr DisplayListToTexture( display_list->max_root_blend_mode(), // impeller::IRect::MakeSize(size) // ); + impeller_dispatcher.SetBackdropKeys(collector.TakeBackdropData()); display_list->Dispatch(impeller_dispatcher, sk_cull_rect); impeller_dispatcher.FinishRecording(); @@ -1258,6 +1280,7 @@ bool RenderToOnscreen(ContentContext& context, display_list->max_root_blend_mode(), // IRect::RoundOut(ip_cull_rect) // ); + impeller_dispatcher.SetBackdropKeys(collector.TakeBackdropData()); display_list->Dispatch(impeller_dispatcher, cull_rect); impeller_dispatcher.FinishRecording(); if (reset_host_buffer) { diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h index 1418229430bf0..b7b2d41ecc93c 100644 --- a/impeller/display_list/dl_dispatcher.h +++ b/impeller/display_list/dl_dispatcher.h @@ -5,6 +5,8 @@ #ifndef FLUTTER_IMPELLER_DISPLAY_LIST_DL_DISPATCHER_H_ #define FLUTTER_IMPELLER_DISPLAY_LIST_DL_DISPATCHER_H_ +#include + #include "flutter/display_list/dl_op_receiver.h" #include "flutter/display_list/geometry/dl_geometry_types.h" #include "flutter/display_list/geometry/dl_path.h" @@ -73,7 +75,8 @@ class DlDispatcherBase : public flutter::DlOpReceiver { const flutter::SaveLayerOptions& options, uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, - const flutter::DlImageFilter* backdrop) override; + const flutter::DlImageFilter* backdrop, + int64_t backdrop_id) override; // |flutter::DlOpReceiver| void restore() override; @@ -253,6 +256,10 @@ class CanvasDlDispatcher : public DlDispatcherBase { ~CanvasDlDispatcher() = default; + void SetBackdropKeys(std::unordered_map backdrop) { + GetCanvas().SetBackdropKeys(std::move(backdrop)); + } + // |flutter::DlOpReceiver| void save() override { // This dispatcher should never be used with the save() variant @@ -264,7 +271,8 @@ class CanvasDlDispatcher : public DlDispatcherBase { // |flutter::DlOpReceiver| void saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions options, - const flutter::DlImageFilter* backdrop) override { + const flutter::DlImageFilter* backdrop, + int64_t backdrop_id) override { // This dispatcher should never be used with the saveLayer() variant // that does not include the content_depth parameter. FML_UNREACHABLE(); @@ -299,7 +307,8 @@ class TextFrameDispatcher : public flutter::IgnoreAttributeDispatchHelper, void saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions options, - const flutter::DlImageFilter* backdrop) override; + const flutter::DlImageFilter* backdrop, + int64_t backdrop_id) override; void restore() override; @@ -353,12 +362,17 @@ class TextFrameDispatcher : public flutter::IgnoreAttributeDispatchHelper, // |flutter::DlOpReceiver| void setImageFilter(const flutter::DlImageFilter* filter) override; + std::unordered_map TakeBackdropData() { + return std::move(backdrop_keys_); + } + private: const Rect GetCurrentLocalCullingBounds() const; const ContentContext& renderer_; Matrix matrix_; std::vector stack_; + std::unordered_map backdrop_keys_; // note: cull rects are always in the global coordinate space. std::vector cull_rect_state_; bool has_image_filter_ = false; diff --git a/impeller/entity/entity_pass_target.h b/impeller/entity/entity_pass_target.h index e82bad573874a..42a3b2906a884 100644 --- a/impeller/entity/entity_pass_target.h +++ b/impeller/entity/entity_pass_target.h @@ -28,6 +28,9 @@ class EntityPassTarget { RenderTarget& GetRenderTarget(); + /// @brief Remove the cached secondary color texture. + void RemoveSecondary() { secondary_color_texture_ = nullptr; } + bool IsValid() const; private: diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index da23f53f06043..1c8663dd06049 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -401,6 +401,16 @@ abstract class SceneBuilder { /// the most recent save layer and rendered back to the scene using the indicated /// [blendMode] prior to rasterizing the child layers. /// + /// if [backdropId] is provided and not equal to -1, then this value is treated + /// as a unique identifier for the backdrop. When the first backdrop filter with + /// a given id is processed during rasterization, the state of the backdrop is + /// recorded and cached. All subsequent backdrop filters with the same identifier + /// will apply their filter to the cached backdrop. The correct usage of the + /// backdrop id has the benefit of dramatically improving performance for + /// applications with multiple backdrop filters. For example, an application + /// that uses a backdrop blur filter for each item in a list view should set + /// all filters to have the same backdrop id. + /// /// {@macro dart.ui.sceneBuilder.oldLayer} /// /// {@macro dart.ui.sceneBuilder.oldLayerVsRetained} @@ -409,6 +419,7 @@ abstract class SceneBuilder { BackdropFilterEngineLayer pushBackdropFilter( ImageFilter filter, { BlendMode blendMode = BlendMode.srcOver, + int backdropId = -1, BackdropFilterEngineLayer? oldLayer, }); @@ -772,18 +783,19 @@ base class _NativeSceneBuilder extends NativeFieldWrapperClass1 implements Scene BackdropFilterEngineLayer pushBackdropFilter( ImageFilter filter, { BlendMode blendMode = BlendMode.srcOver, + int backdropId = -1, BackdropFilterEngineLayer? oldLayer, }) { assert(_debugCheckCanBeUsedAsOldLayer(oldLayer, 'pushBackdropFilter')); final EngineLayer engineLayer = _NativeEngineLayer._(); - _pushBackdropFilter(engineLayer, filter._toNativeImageFilter(), blendMode.index, oldLayer?._nativeLayer); + _pushBackdropFilter(engineLayer, filter._toNativeImageFilter(), blendMode.index, backdropId, oldLayer?._nativeLayer); final BackdropFilterEngineLayer layer = BackdropFilterEngineLayer._(engineLayer); assert(_debugPushLayer(layer)); return layer; } - @Native, Handle, Pointer, Int32, Handle)>(symbol: 'SceneBuilder::pushBackdropFilter') - external void _pushBackdropFilter(EngineLayer outEngineLayer, _ImageFilter filter, int blendMode, EngineLayer? oldLayer); + @Native, Handle, Pointer, Int32, Int32, Handle)>(symbol: 'SceneBuilder::pushBackdropFilter') + external void _pushBackdropFilter(EngineLayer outEngineLayer, _ImageFilter filter, int blendMode, int backdropId, EngineLayer? oldLayer); @override ShaderMaskEngineLayer pushShaderMask( diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index b89a7f7cde99c..c48d05dcf7c64 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -168,9 +168,10 @@ void SceneBuilder::pushBackdropFilter( Dart_Handle layer_handle, ImageFilter* filter, int blendMode, + int backdropId, const fml::RefPtr& oldLayer) { auto layer = std::make_shared( - filter->filter(), static_cast(blendMode)); + filter->filter(), static_cast(blendMode), backdropId); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index d13f4d0117564..600ae5825c231 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -80,6 +80,7 @@ class SceneBuilder : public RefCountedDartWrappable { void pushBackdropFilter(Dart_Handle layer_handle, ImageFilter* filter, int blendMode, + int backdropId, const fml::RefPtr& oldLayer); void pushShaderMask(Dart_Handle layer_handle, Shader* shader, diff --git a/shell/common/dl_op_spy.cc b/shell/common/dl_op_spy.cc index 19f54d104768f..f0becd417ab82 100644 --- a/shell/common/dl_op_spy.cc +++ b/shell/common/dl_op_spy.cc @@ -31,7 +31,8 @@ void DlOpSpy::setColorSource(const DlColorSource* source) { void DlOpSpy::save() {} void DlOpSpy::saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) {} + const DlImageFilter* backdrop, + int64_t backdrop_id) {} void DlOpSpy::restore() {} void DlOpSpy::drawColor(DlColor color, DlBlendMode mode) { did_draw_ |= !color.isTransparent(); diff --git a/shell/common/dl_op_spy.h b/shell/common/dl_op_spy.h index 6d3d9c9587f24..1c93a23335d7f 100644 --- a/shell/common/dl_op_spy.h +++ b/shell/common/dl_op_spy.h @@ -41,7 +41,8 @@ class DlOpSpy final : public virtual DlOpReceiver, void save() override; void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override; + const DlImageFilter* backdrop, + int64_t backdrop_id) override; void restore() override; void drawColor(DlColor color, DlBlendMode mode) override; void drawPaint() override; diff --git a/testing/display_list_testing.cc b/testing/display_list_testing.cc index d21b58664451b..ab1b9a99efb91 100644 --- a/testing/display_list_testing.cc +++ b/testing/display_list_testing.cc @@ -4,6 +4,7 @@ #include "flutter/testing/display_list_testing.h" +#include #include #include "flutter/display_list/display_list.h" @@ -701,12 +702,13 @@ void DisplayListStreamDispatcher::save() { } void DisplayListStreamDispatcher::saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { startl() << "saveLayer(" << bounds << ", " << options; if (backdrop) { os_ << "," << std::endl; indent(10); - startl() << "backdrop: "; + startl() << "backdrop: " << backdrop_id; out(backdrop); outdent(10); } else { diff --git a/testing/display_list_testing.h b/testing/display_list_testing.h index 8dcaa7de5151d..e370826601acd 100644 --- a/testing/display_list_testing.h +++ b/testing/display_list_testing.h @@ -110,7 +110,8 @@ class DisplayListStreamDispatcher final : public DlOpReceiver { void save() override; void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override; + const DlImageFilter* backdrop, + int64_t backdrop_id) override; void restore() override; void translate(DlScalar tx, DlScalar ty) override; @@ -397,7 +398,8 @@ class DisplayListGeneralReceiver : public DlOpReceiver { void save() override { RecordByType(DisplayListOpType::kSave); } void saveLayer(const DlRect& bounds, const SaveLayerOptions options, - const DlImageFilter* backdrop) override { + const DlImageFilter* backdrop, + int64_t backdrop_id) override { if (backdrop) { RecordByType(DisplayListOpType::kSaveLayerBackdrop); } else { diff --git a/testing/mock_canvas.cc b/testing/mock_canvas.cc index 521bb1f311c1f..bab0d21851e2b 100644 --- a/testing/mock_canvas.cc +++ b/testing/mock_canvas.cc @@ -45,7 +45,8 @@ void MockCanvas::Save() { void MockCanvas::SaveLayer(const SkRect* bounds, const DlPaint* paint, - const DlImageFilter* backdrop) { + const DlImageFilter* backdrop, + int64_t backdrop_id) { // saveLayer calls this prior to running, so we use it to track saveLayer // calls draw_calls_.emplace_back(DrawCall{ diff --git a/testing/mock_canvas.h b/testing/mock_canvas.h index 16b89ebbc85fa..e32689b703185 100644 --- a/testing/mock_canvas.h +++ b/testing/mock_canvas.h @@ -175,7 +175,8 @@ class MockCanvas final : public DlCanvas { void Save() override; void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr) override; + const DlImageFilter* backdrop = nullptr, + int64_t backdrop_id = -1) override; void Restore() override; int GetSaveCount() const { return current_layer_; } void RestoreToCount(int restore_count) { From 14174b798c19b11655dfa5d48d24feb57930e0da Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 10:15:54 -0700 Subject: [PATCH 02/20] Cleanup. --- impeller/display_list/canvas.cc | 59 +++++++++++++------------- impeller/display_list/canvas.h | 2 +- impeller/display_list/dl_dispatcher.cc | 7 ++- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index af56fbaf65f74..b2b01da3256b9 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -993,7 +993,7 @@ void Canvas::SaveLayer(const Paint& paint, uint32_t total_content_depth, bool can_distribute_opacity, int64_t backdrop_id) { - // TRACE_EVENT0("flutter", "Canvas::saveLayer"); + TRACE_EVENT0("flutter", "Canvas::saveLayer"); if (IsSkipping()) { return SkipUntilMatchingRestore(total_content_depth); } @@ -1080,7 +1080,7 @@ void Canvas::SaveLayer(const Paint& paint, // of it in the current scene, cache the backdrop texture and remove it from // the current entity pass flip. bool will_cache_texture = - backdrop_id != -1 && backdrop_data->second.global_rects.size() > 1; + backdrop_id != -1 && backdrop_data->second.backdrop_count > 1; if (backdrop_data == backdrop_keys_.end() || !backdrop_data->second.texture_slot) { input_texture = FlipBackdrop(render_passes_, // @@ -1110,34 +1110,35 @@ void Canvas::SaveLayer(const Paint& paint, ? Entity::RenderingMode::kSubpassPrependSnapshotTransform : Entity::RenderingMode::kSubpassAppendSnapshotTransform); - // If all filters are equal, process the filter input once. - if (will_cache_texture && backdrop_data->second.all_filters_equal && - !backdrop_data->second.filtered_input_slot.has_value()) { - backdrop_data->second.filtered_input_slot = - backdrop_filter_contents->RenderToSnapshot(renderer_, {}); - } - - if (will_cache_texture && - backdrop_data->second.filtered_input_slot.has_value()) { - auto snapshot = backdrop_data->second.filtered_input_slot.value(); - auto contents = TextureContents::MakeRect(subpass_coverage); - auto scaled = - subpass_coverage.TransformBounds(snapshot.transform.Invert()); - contents->SetTexture(snapshot.texture); - contents->SetSourceRect(scaled); - - Entity backdrop_entity; - backdrop_entity.SetContents(std::move(contents)); - // backdrop_entity.SetTransform( - // Matrix::MakeTranslation(Vector3(-local_position))); - backdrop_entity.SetClipDepth(std::numeric_limits::max()); - backdrop_entity.SetBlendMode(paint.blend_mode); + if (will_cache_texture) { + auto& data = backdrop_data->second; + // If all filters on the shared backdrop layer are equal, process the + // layer once. + if (data.all_filters_equal && !data.filtered_input_slot.has_value()) { + // TODO(jonahwilliams): compute minimum input hint. + data.filtered_input_slot = + backdrop_filter_contents->RenderToSnapshot(renderer_, {}); + } - backdrop_entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); - Save(0); - return; + if (data.filtered_input_slot.has_value()) { + auto snapshot = data.filtered_input_slot.value(); + auto contents = TextureContents::MakeRect(subpass_coverage); + auto scaled = + subpass_coverage.TransformBounds(snapshot.transform.Invert()); + contents->SetTexture(snapshot.texture); + contents->SetSourceRect(scaled); + + Entity backdrop_entity; + backdrop_entity.SetContents(std::move(contents)); + backdrop_entity.SetClipDepth(std::numeric_limits::max()); + backdrop_entity.SetBlendMode(paint.blend_mode); + + backdrop_entity.Render( + renderer_, + *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + Save(0); + return; + } } } diff --git a/impeller/display_list/canvas.h b/impeller/display_list/canvas.h index 8c119702a67cb..96816478c0ceb 100644 --- a/impeller/display_list/canvas.h +++ b/impeller/display_list/canvas.h @@ -31,7 +31,7 @@ namespace impeller { struct BackdropData { - std::vector global_rects; + size_t backdrop_count = 0; bool all_filters_equal = true; std::shared_ptr texture_slot; std::optional filtered_input_slot; diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 3a09221d82934..40b7580dea1e7 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -1006,15 +1006,14 @@ void TextFrameDispatcher::saveLayer(const DlRect& bounds, const auto& existing = backdrop_keys_.find(backdrop_id); if (existing == backdrop_keys_.end()) { backdrop_keys_[backdrop_id] = - BackdropData{.global_rects = {bounds.TransformBounds(matrix_)}, - .last_backdrop = backdrop}; + BackdropData{.backdrop_count = 1, .last_backdrop = backdrop}; } else { BackdropData& data = backdrop_keys_[backdrop_id]; if (data.all_filters_equal) { - data.all_filters_equal = true; // data.last_backdrop == backdrop; + data.all_filters_equal = (*data.last_backdrop == *backdrop); data.last_backdrop = backdrop; } - data.global_rects.push_back(bounds.TransformBounds(matrix_)); + data.backdrop_count++; } } From cc08f603bdc34dbf91336ea6102a8dcbe2b9b7b1 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 11:09:13 -0700 Subject: [PATCH 03/20] testing. --- .../display_list/aiks_dl_blur_unittests.cc | 81 +++++++++++++++++++ impeller/display_list/canvas.cc | 17 ++-- 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/impeller/display_list/aiks_dl_blur_unittests.cc b/impeller/display_list/aiks_dl_blur_unittests.cc index 4185b173086bc..63d4ad4fd4a11 100644 --- a/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/impeller/display_list/aiks_dl_blur_unittests.cc @@ -268,6 +268,87 @@ TEST_P(AiksTest, CanRenderBackdropBlur) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(AiksTest, CanRenderBackdropBlurWithSingleBackdropId) { + auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg")); + + DisplayListBuilder builder; + + DlPaint paint; + builder.DrawImage(image, SkPoint::Make(50.0, 50.0), + DlImageSampling::kNearestNeighbor, &paint); + + SkRRect rrect = SkRRect::MakeRectXY( + SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20); + builder.Save(); + builder.ClipRRect(rrect); + + DlPaint save_paint; + save_paint.setBlendMode(DlBlendMode::kSrc); + auto backdrop_filter = DlBlurImageFilter::Make(30, 30, DlTileMode::kClamp); + builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(), + /*backdrop_id=*/1); + builder.Restore(); + builder.Restore(); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +TEST_P(AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropId) { + auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg")); + + DisplayListBuilder builder; + + DlPaint paint; + builder.DrawImage(image, SkPoint::Make(50.0, 50.0), + DlImageSampling::kNearestNeighbor, &paint); + + for (int i = 0; i < 6; i++) { + SkRRect rrect = SkRRect::MakeRectXY( + SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20); + builder.Save(); + builder.ClipRRect(rrect); + + DlPaint save_paint; + save_paint.setBlendMode(DlBlendMode::kSrc); + auto backdrop_filter = DlBlurImageFilter::Make(30, 30, DlTileMode::kClamp); + builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(), + /*backdrop_id=*/1); + builder.Restore(); + builder.Restore(); + } + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +TEST_P(AiksTest, + CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters) { + auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg")); + + DisplayListBuilder builder; + + DlPaint paint; + builder.DrawImage(image, SkPoint::Make(50.0, 50.0), + DlImageSampling::kNearestNeighbor, &paint); + + for (int i = 0; i < 6; i++) { + SkRRect rrect = SkRRect::MakeRectXY( + SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20); + builder.Save(); + builder.ClipRRect(rrect); + + DlPaint save_paint; + save_paint.setBlendMode(DlBlendMode::kSrc); + auto backdrop_filter = + DlBlurImageFilter::Make(30 + i, 30, DlTileMode::kClamp); + builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(), + /*backdrop_id=*/1); + builder.Restore(); + builder.Restore(); + } + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) { DisplayListBuilder builder; diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index b2b01da3256b9..56fc2255165b1 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1061,7 +1061,7 @@ void Canvas::SaveLayer(const Paint& paint, // Backdrop filter state, ignored if there is no BDF. std::shared_ptr backdrop_filter_contents; - Point local_position = {0, 0}; + Point local_position = Point(0, 0); if (backdrop_filter) { local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition(); Canvas::BackdropFilterProc backdrop_filter_proc = @@ -1079,10 +1079,11 @@ void Canvas::SaveLayer(const Paint& paint, // If the backdrop ID is not the no-op id, and there is more than one usage // of it in the current scene, cache the backdrop texture and remove it from // the current entity pass flip. - bool will_cache_texture = - backdrop_id != -1 && backdrop_data->second.backdrop_count > 1; - if (backdrop_data == backdrop_keys_.end() || - !backdrop_data->second.texture_slot) { + bool will_cache_texture = backdrop_id != -1 && + backdrop_data != backdrop_keys_.end() && + backdrop_data->second.backdrop_count > 1; + if (!will_cache_texture || + (will_cache_texture && !backdrop_data->second.texture_slot)) { input_texture = FlipBackdrop(render_passes_, // GetGlobalPassPosition(), // clip_coverage_stack_, // @@ -1121,7 +1122,7 @@ void Canvas::SaveLayer(const Paint& paint, } if (data.filtered_input_slot.has_value()) { - auto snapshot = data.filtered_input_slot.value(); + Snapshot snapshot = data.filtered_input_slot.value(); auto contents = TextureContents::MakeRect(subpass_coverage); auto scaled = subpass_coverage.TransformBounds(snapshot.transform.Invert()); @@ -1175,9 +1176,9 @@ void Canvas::SaveLayer(const Paint& paint, if (backdrop_filter_contents) { const auto& backdrop_data = backdrop_keys_.find(backdrop_id); - if (backdrop_id != -1 && + if (backdrop_id != -1 && backdrop_data != backdrop_keys_.end() && backdrop_data->second.filtered_input_slot.has_value()) { - auto snapshot = backdrop_data->second.filtered_input_slot.value(); + Snapshot snapshot = backdrop_data->second.filtered_input_slot.value(); auto contents = TextureContents::MakeRect(subpass_coverage); auto scaled = subpass_coverage.TransformBounds(snapshot.transform.Invert()); From fb94ae696d5712c2d9577cb8a3f68518322463ed Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 12:36:24 -0700 Subject: [PATCH 04/20] ++ --- impeller/display_list/aiks_dl_blur_unittests.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impeller/display_list/aiks_dl_blur_unittests.cc b/impeller/display_list/aiks_dl_blur_unittests.cc index 63d4ad4fd4a11..94a675532a1e3 100644 --- a/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/impeller/display_list/aiks_dl_blur_unittests.cc @@ -277,8 +277,8 @@ TEST_P(AiksTest, CanRenderBackdropBlurWithSingleBackdropId) { builder.DrawImage(image, SkPoint::Make(50.0, 50.0), DlImageSampling::kNearestNeighbor, &paint); - SkRRect rrect = SkRRect::MakeRectXY( - SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20); + SkRRect rrect = + SkRRect::MakeRectXY(SkRect::MakeXYWH(50, 250, 100, 100), 20, 20); builder.Save(); builder.ClipRRect(rrect); From 63344a3cb7339b89e7e9b2e4013c1592898f9d15 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 13:16:08 -0700 Subject: [PATCH 05/20] ++ --- impeller/display_list/canvas.cc | 39 +++++++++++++++----------- impeller/display_list/dl_dispatcher.cc | 5 ++-- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 56fc2255165b1..ae43961b797d6 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1079,8 +1079,7 @@ void Canvas::SaveLayer(const Paint& paint, // If the backdrop ID is not the no-op id, and there is more than one usage // of it in the current scene, cache the backdrop texture and remove it from // the current entity pass flip. - bool will_cache_texture = backdrop_id != -1 && - backdrop_data != backdrop_keys_.end() && + bool will_cache_texture = backdrop_data != backdrop_keys_.end() && backdrop_data->second.backdrop_count > 1; if (!will_cache_texture || (will_cache_texture && !backdrop_data->second.texture_slot)) { @@ -1174,10 +1173,15 @@ void Canvas::SaveLayer(const Paint& paint, // the subpass will affect in the parent pass. clip_coverage_stack_.PushSubpass(subpass_coverage, GetClipHeight()); - if (backdrop_filter_contents) { - const auto& backdrop_data = backdrop_keys_.find(backdrop_id); - if (backdrop_id != -1 && backdrop_data != backdrop_keys_.end() && - backdrop_data->second.filtered_input_slot.has_value()) { + if (!backdrop_filter_contents) { + return; + } + const auto& backdrop_data = backdrop_keys_.find(backdrop_id); + if (backdrop_data != backdrop_keys_.end()) { + auto& data = backdrop_data->second; + // If there is a cached input snapshot, render the subregion of the backdrop + // filter. + if (data.filtered_input_slot.has_value()) { Snapshot snapshot = backdrop_data->second.filtered_input_slot.value(); auto contents = TextureContents::MakeRect(subpass_coverage); auto scaled = @@ -1194,19 +1198,20 @@ void Canvas::SaveLayer(const Paint& paint, backdrop_entity.Render( renderer_, *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); - } else { - // Render the backdrop entity. - Entity backdrop_entity; - backdrop_entity.SetContents(std::move(backdrop_filter_contents)); - backdrop_entity.SetTransform( - Matrix::MakeTranslation(Vector3(-local_position))); - backdrop_entity.SetClipDepth(std::numeric_limits::max()); - - backdrop_entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + return; } } + + // Render the backdrop entity. + Entity backdrop_entity; + backdrop_entity.SetContents(std::move(backdrop_filter_contents)); + backdrop_entity.SetTransform( + Matrix::MakeTranslation(Vector3(-local_position))); + backdrop_entity.SetClipDepth(std::numeric_limits::max()); + + backdrop_entity.Render( + renderer_, + *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); } bool Canvas::Restore() { diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 40b7580dea1e7..1660fa91e10e3 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "display_list/effects/dl_color_source.h" @@ -16,7 +15,6 @@ #include "impeller/core/formats.h" #include "impeller/display_list/aiks_context.h" #include "impeller/display_list/canvas.h" -#include "impeller/display_list/color_filter.h" #include "impeller/display_list/dl_atlas_geometry.h" #include "impeller/display_list/dl_vertices_geometry.h" #include "impeller/display_list/nine_patch_converter.h" @@ -1009,11 +1007,12 @@ void TextFrameDispatcher::saveLayer(const DlRect& bounds, BackdropData{.backdrop_count = 1, .last_backdrop = backdrop}; } else { BackdropData& data = backdrop_keys_[backdrop_id]; + + data.backdrop_count++; if (data.all_filters_equal) { data.all_filters_equal = (*data.last_backdrop == *backdrop); data.last_backdrop = backdrop; } - data.backdrop_count++; } } From 1c050fd9d0d20c92916b4bfd56d60bba710f651b Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 14:08:52 -0700 Subject: [PATCH 06/20] ++ --- impeller/display_list/canvas.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index ae43961b797d6..a075ce8a127f0 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1182,7 +1182,7 @@ void Canvas::SaveLayer(const Paint& paint, // If there is a cached input snapshot, render the subregion of the backdrop // filter. if (data.filtered_input_slot.has_value()) { - Snapshot snapshot = backdrop_data->second.filtered_input_slot.value(); + Snapshot snapshot = data.filtered_input_slot.value(); auto contents = TextureContents::MakeRect(subpass_coverage); auto scaled = subpass_coverage.TransformBounds(snapshot.transform.Invert()); From 34b7d3f85f813394609c31d631242b88904cf485 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 15:20:01 -0700 Subject: [PATCH 07/20] update op sizes. --- display_list/testing/dl_test_snippets.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/display_list/testing/dl_test_snippets.cc b/display_list/testing/dl_test_snippets.cc index 05ca54dbd38ae..a55222164f7fc 100644 --- a/display_list/testing/dl_test_snippets.cc +++ b/display_list/testing/dl_test_snippets.cc @@ -327,7 +327,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 136, 3, + {5, 144, 3, [](DlOpReceiver& r) { r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); @@ -337,7 +337,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 136, 3, + {5, 144, 3, [](DlOpReceiver& r) { r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); @@ -347,7 +347,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 136, 3, + {5, 144, 3, [](DlOpReceiver& r) { r.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); @@ -357,7 +357,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 136, 3, + {5, 144, 3, [](DlOpReceiver& r) { r.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); From 8bfe0e8b2841cf170aa631374dfdd7081a7dcd40 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 19:34:41 -0700 Subject: [PATCH 08/20] remove copies, fix depth. --- .../display_list/aiks_dl_blur_unittests.cc | 36 +++++++++++++++++++ impeller/display_list/aiks_playground.cc | 23 +++++------- impeller/display_list/canvas.cc | 35 ++++-------------- impeller/display_list/dl_playground.cc | 23 +++++------- 4 files changed, 59 insertions(+), 58 deletions(-) diff --git a/impeller/display_list/aiks_dl_blur_unittests.cc b/impeller/display_list/aiks_dl_blur_unittests.cc index 94a675532a1e3..cb837dcf2515f 100644 --- a/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/impeller/display_list/aiks_dl_blur_unittests.cc @@ -1339,5 +1339,41 @@ TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) { } } +TEST_P(AiksTest, + CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers) { + auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg")); + + DisplayListBuilder builder; + + DlPaint paint; + builder.DrawImage(image, SkPoint::Make(50.0, 50.0), + DlImageSampling::kNearestNeighbor, &paint); + + for (int i = 0; i < 6; i++) { + if (i != 0) { + DlPaint paint; + paint.setColor(DlColor::kWhite().withAlphaF(0.95)); + builder.SaveLayer(nullptr, &paint); + } + SkRRect rrect = SkRRect::MakeRectXY( + SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20); + builder.Save(); + builder.ClipRRect(rrect); + + DlPaint save_paint; + save_paint.setBlendMode(DlBlendMode::kSrc); + auto backdrop_filter = DlBlurImageFilter::Make(30, 30, DlTileMode::kClamp); + builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(), + /*backdrop_id=*/-1); + builder.Restore(); + builder.Restore(); + if (i != 0) { + builder.Restore(); + } + } + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/display_list/aiks_playground.cc b/impeller/display_list/aiks_playground.cc index ae42bf9d69078..029703fea0904 100644 --- a/impeller/display_list/aiks_playground.cc +++ b/impeller/display_list/aiks_playground.cc @@ -10,6 +10,7 @@ #include "impeller/display_list/dl_dispatcher.h" #include "impeller/typographer/backends/skia/typographer_context_skia.h" #include "impeller/typographer/typographer_context.h" +#include "include/core/SkRect.h" namespace impeller { @@ -49,22 +50,14 @@ bool AiksPlayground::OpenPlaygroundHere( return Playground::OpenPlaygroundHere( [&renderer, &callback](RenderTarget& render_target) -> bool { - auto display_list = callback(); - TextFrameDispatcher collector(renderer.GetContentContext(), // - Matrix(), // - Rect::MakeMaximum() // + return RenderToOnscreen( + renderer.GetContentContext(), // + render_target, // + callback(), // + SkIRect::MakeWH(render_target.GetRenderTargetSize().width, + render_target.GetRenderTargetSize().height), // + true // ); - display_list->Dispatch(collector); - - CanvasDlDispatcher impeller_dispatcher( - renderer.GetContentContext(), render_target, - display_list->root_has_backdrop_filter(), - display_list->max_root_blend_mode(), IRect::MakeMaximum()); - display_list->Dispatch(impeller_dispatcher); - impeller_dispatcher.FinishRecording(); - renderer.GetContentContext().GetTransientsBuffer().Reset(); - renderer.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames(); - return true; }); } diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index a075ce8a127f0..2c1f8627aa060 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1116,8 +1116,10 @@ void Canvas::SaveLayer(const Paint& paint, // layer once. if (data.all_filters_equal && !data.filtered_input_slot.has_value()) { // TODO(jonahwilliams): compute minimum input hint. - data.filtered_input_slot = - backdrop_filter_contents->RenderToSnapshot(renderer_, {}); + Entity snapshot_entity; + snapshot_entity.SetTransform(GetCurrentTransform()); + data.filtered_input_slot = backdrop_filter_contents->RenderToSnapshot( + renderer_, snapshot_entity); } if (data.filtered_input_slot.has_value()) { @@ -1128,9 +1130,11 @@ void Canvas::SaveLayer(const Paint& paint, contents->SetTexture(snapshot.texture); contents->SetSourceRect(scaled); + // This backdrop entity sets a depth value as it is written to the newly + // flipped backdrop and not into a new saveLayer. Entity backdrop_entity; backdrop_entity.SetContents(std::move(contents)); - backdrop_entity.SetClipDepth(std::numeric_limits::max()); + backdrop_entity.SetClipDepth(++current_depth_); backdrop_entity.SetBlendMode(paint.blend_mode); backdrop_entity.Render( @@ -1176,31 +1180,6 @@ void Canvas::SaveLayer(const Paint& paint, if (!backdrop_filter_contents) { return; } - const auto& backdrop_data = backdrop_keys_.find(backdrop_id); - if (backdrop_data != backdrop_keys_.end()) { - auto& data = backdrop_data->second; - // If there is a cached input snapshot, render the subregion of the backdrop - // filter. - if (data.filtered_input_slot.has_value()) { - Snapshot snapshot = data.filtered_input_slot.value(); - auto contents = TextureContents::MakeRect(subpass_coverage); - auto scaled = - subpass_coverage.TransformBounds(snapshot.transform.Invert()); - contents->SetTexture(snapshot.texture); - contents->SetSourceRect(scaled); - - Entity backdrop_entity; - backdrop_entity.SetContents(std::move(contents)); - backdrop_entity.SetTransform( - Matrix::MakeTranslation(Vector3(-local_position))); - backdrop_entity.SetClipDepth(std::numeric_limits::max()); - - backdrop_entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); - return; - } - } // Render the backdrop entity. Entity backdrop_entity; diff --git a/impeller/display_list/dl_playground.cc b/impeller/display_list/dl_playground.cc index eab910d1f73e4..10eeb7a673804 100644 --- a/impeller/display_list/dl_playground.cc +++ b/impeller/display_list/dl_playground.cc @@ -45,21 +45,14 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) { wireframe = !wireframe; context.GetContentContext().SetWireframe(wireframe); } - - auto list = callback(); - TextFrameDispatcher collector(context.GetContentContext(), Matrix(), - Rect::MakeMaximum()); - list->Dispatch(collector); - - CanvasDlDispatcher impeller_dispatcher( - context.GetContentContext(), render_target, - list->root_has_backdrop_filter(), list->max_root_blend_mode(), - IRect::MakeMaximum()); - list->Dispatch(impeller_dispatcher); - impeller_dispatcher.FinishRecording(); - context.GetContentContext().GetTransientsBuffer().Reset(); - context.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames(); - return true; + return RenderToOnscreen( + context.GetContentContext(), // + render_target, // + callback(), // + SkIRect::MakeWH(render_target.GetRenderTargetSize().width, + render_target.GetRenderTargetSize().height), // + true // + ); }); } From 6bc5363c10337355ebb761dbcd07a5ddb4f8f1cf Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 10 Oct 2024 21:11:08 -0700 Subject: [PATCH 09/20] use sampler desc. --- impeller/display_list/canvas.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 2c1f8627aa060..7571794a71bef 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1116,10 +1116,8 @@ void Canvas::SaveLayer(const Paint& paint, // layer once. if (data.all_filters_equal && !data.filtered_input_slot.has_value()) { // TODO(jonahwilliams): compute minimum input hint. - Entity snapshot_entity; - snapshot_entity.SetTransform(GetCurrentTransform()); - data.filtered_input_slot = backdrop_filter_contents->RenderToSnapshot( - renderer_, snapshot_entity); + data.filtered_input_slot = + backdrop_filter_contents->RenderToSnapshot(renderer_, {}); } if (data.filtered_input_slot.has_value()) { @@ -1129,6 +1127,7 @@ void Canvas::SaveLayer(const Paint& paint, subpass_coverage.TransformBounds(snapshot.transform.Invert()); contents->SetTexture(snapshot.texture); contents->SetSourceRect(scaled); + contents->SetSamplerDescriptor(snapshot.sampler_descriptor); // This backdrop entity sets a depth value as it is written to the newly // flipped backdrop and not into a new saveLayer. From 5c71eebb468579c1b0766cfe3fa2753ae945da26 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 11 Oct 2024 15:13:06 -0700 Subject: [PATCH 10/20] use std::optional and make dart value nullable instead of using magic -1 --- display_list/benchmarking/dl_complexity_gl.cc | 2 +- display_list/benchmarking/dl_complexity_gl.h | 2 +- .../benchmarking/dl_complexity_metal.cc | 2 +- .../benchmarking/dl_complexity_metal.h | 2 +- display_list/display_list_unittests.cc | 10 +++--- display_list/dl_builder.cc | 4 +-- display_list/dl_builder.h | 4 +-- display_list/dl_canvas.h | 2 +- display_list/dl_op_receiver.h | 13 +++---- display_list/dl_op_records.h | 4 +-- display_list/skia/dl_sk_canvas.cc | 2 +- display_list/skia/dl_sk_canvas.h | 2 +- display_list/skia/dl_sk_dispatcher.cc | 2 +- display_list/skia/dl_sk_dispatcher.h | 2 +- display_list/utils/dl_receiver_utils.h | 2 +- flow/layers/backdrop_filter_layer.cc | 2 +- flow/layers/backdrop_filter_layer.h | 4 +-- flow/layers/layer_state_stack.cc | 14 ++++---- flow/layers/layer_state_stack.h | 15 ++++---- .../display_list/aiks_dl_blur_unittests.cc | 2 +- impeller/display_list/canvas.cc | 36 +++++++++++-------- impeller/display_list/canvas.h | 2 +- impeller/display_list/dl_dispatcher.cc | 12 +++---- impeller/display_list/dl_dispatcher.h | 6 ++-- lib/ui/compositing.dart | 10 +++--- lib/ui/compositing/scene_builder.cc | 13 +++++-- lib/ui/compositing/scene_builder.h | 2 +- shell/common/dl_op_spy.cc | 2 +- shell/common/dl_op_spy.h | 2 +- testing/display_list_testing.cc | 8 +++-- testing/display_list_testing.h | 4 +-- testing/mock_canvas.cc | 2 +- testing/mock_canvas.h | 6 ++-- 33 files changed, 110 insertions(+), 87 deletions(-) diff --git a/display_list/benchmarking/dl_complexity_gl.cc b/display_list/benchmarking/dl_complexity_gl.cc index 072298b68f7c3..34e43516ba621 100644 --- a/display_list/benchmarking/dl_complexity_gl.cc +++ b/display_list/benchmarking/dl_complexity_gl.cc @@ -52,7 +52,7 @@ void DisplayListGLComplexityCalculator::GLHelper::saveLayer( const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { if (IsComplex()) { return; } diff --git a/display_list/benchmarking/dl_complexity_gl.h b/display_list/benchmarking/dl_complexity_gl.h index 524fc76b28f5c..3041f9014102f 100644 --- a/display_list/benchmarking/dl_complexity_gl.h +++ b/display_list/benchmarking/dl_complexity_gl.h @@ -38,7 +38,7 @@ class DisplayListGLComplexityCalculator void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; void drawLine(const DlPoint& p0, const DlPoint& p1) override; void drawDashedLine(const DlPoint& p0, diff --git a/display_list/benchmarking/dl_complexity_metal.cc b/display_list/benchmarking/dl_complexity_metal.cc index a88e9b2ffeb48..2f86eb64394fe 100644 --- a/display_list/benchmarking/dl_complexity_metal.cc +++ b/display_list/benchmarking/dl_complexity_metal.cc @@ -66,7 +66,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::saveLayer( const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { if (IsComplex()) { return; } diff --git a/display_list/benchmarking/dl_complexity_metal.h b/display_list/benchmarking/dl_complexity_metal.h index 95d02c1bb541d..79dd5c3155be3 100644 --- a/display_list/benchmarking/dl_complexity_metal.h +++ b/display_list/benchmarking/dl_complexity_metal.h @@ -38,7 +38,7 @@ class DisplayListMetalComplexityCalculator void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; void drawLine(const DlPoint& p0, const DlPoint& p1) override; void drawDashedLine(const DlPoint& p0, diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 55e0b8416b3fb..90398c1063ac1 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -1477,7 +1477,7 @@ class SaveLayerExpector : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override { + std::optional backdrop_id) override { FML_UNREACHABLE(); } @@ -1486,7 +1486,7 @@ class SaveLayerExpector : public virtual DlOpReceiver, uint32_t total_content_depth, DlBlendMode max_content_blend_mode, const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) { + std::optional backdrop_id = std::nullopt) { ASSERT_LT(save_layer_count_, expected_.size()) << label(); auto expect = expected_[save_layer_count_]; if (expect.options.has_value()) { @@ -3660,7 +3660,7 @@ class SaveLayerBoundsExpector : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override { + std::optional backdrop_id) override { ASSERT_LT(save_layer_count_, expected_.size()); auto expected = expected_[save_layer_count_]; EXPECT_EQ(options.bounds_from_caller(), @@ -4126,7 +4126,7 @@ class DepthExpector : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override { + std::optional backdrop_id) override { // This method should not be called since we override the variant with // the total_content_depth parameter. FAIL() << "saveLayer(no depth parameter) method should not be called"; @@ -4137,7 +4137,7 @@ class DepthExpector : public virtual DlOpReceiver, uint32_t total_content_depth, DlBlendMode max_content_mode, const DlImageFilter* backdrop, - int64_t backdrop_id) override { + std::optional backdrop_id) override { ASSERT_LT(index_, depth_expectations_.size()); EXPECT_EQ(depth_expectations_[index_], total_content_depth) << "at index " << index_; diff --git a/display_list/dl_builder.cc b/display_list/dl_builder.cc index c5fa0ecc43e83..dfb667e9acb0b 100644 --- a/display_list/dl_builder.cc +++ b/display_list/dl_builder.cc @@ -410,7 +410,7 @@ void DisplayListBuilder::Save() { void DisplayListBuilder::saveLayer(const DlRect& bounds, const SaveLayerOptions in_options, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { SaveLayerOptions options = in_options.without_optimizations(); DisplayListAttributeFlags flags = options.renders_with_attributes() ? kSaveLayerWithPaintFlags @@ -545,7 +545,7 @@ void DisplayListBuilder::saveLayer(const DlRect& bounds, void DisplayListBuilder::SaveLayer(const SkRect* bounds, const DlPaint* paint, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { SaveLayerOptions options; DlRect temp_bounds; if (bounds) { diff --git a/display_list/dl_builder.h b/display_list/dl_builder.h index d412d4ba33a5b..42a6353bcd0b4 100644 --- a/display_list/dl_builder.h +++ b/display_list/dl_builder.h @@ -52,7 +52,7 @@ class DisplayListBuilder final : public virtual DlCanvas, void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) override; + std::optional backdrop_id = std::nullopt) override; // |DlCanvas| void Restore() override; // |DlCanvas| @@ -383,7 +383,7 @@ class DisplayListBuilder final : public virtual DlCanvas, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; // |DlOpReceiver| void restore() override { Restore(); } diff --git a/display_list/dl_canvas.h b/display_list/dl_canvas.h index 31249750e9202..f3e7dbb78810a 100644 --- a/display_list/dl_canvas.h +++ b/display_list/dl_canvas.h @@ -63,7 +63,7 @@ class DlCanvas { virtual void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) = 0; + std::optional backdrop_id = std::nullopt) = 0; virtual void Restore() = 0; virtual int GetSaveCount() const = 0; virtual void RestoreToCount(int restore_count) = 0; diff --git a/display_list/dl_op_receiver.h b/display_list/dl_op_receiver.h index 080ea37fd901b..79d5d28dcd5a4 100644 --- a/display_list/dl_op_receiver.h +++ b/display_list/dl_op_receiver.h @@ -142,7 +142,7 @@ class DlOpReceiver { virtual void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) = 0; + std::optional backdrop_id = std::nullopt) = 0; // Optional variant of saveLayer() that passes the total depth count of // all rendering operations that occur until the next restore() call. virtual void saveLayer(const DlRect& bounds, @@ -150,7 +150,7 @@ class DlOpReceiver { uint32_t total_content_depth, DlBlendMode max_content_blend_mode, const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) { + std::optional backdrop_id = std::nullopt) { saveLayer(bounds, options, backdrop, backdrop_id); } virtual void restore() = 0; @@ -170,10 +170,11 @@ class DlOpReceiver { // public DisplayListBuilder/DlCanvas public interfaces where possible, // as tracked in: // https://github.com/flutter/flutter/issues/144070 - virtual void saveLayer(const DlRect* bounds, - const SaveLayerOptions options, - const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) final { + virtual void saveLayer( + const DlRect* bounds, + const SaveLayerOptions options, + const DlImageFilter* backdrop = nullptr, + std::optional backdrop_id = std::nullopt) final { if (bounds) { saveLayer(*bounds, options.with_bounds_from_caller(), backdrop, backdrop_id); diff --git a/display_list/dl_op_records.h b/display_list/dl_op_records.h index 77fd0dd8cbbd4..189038b37a5fb 100644 --- a/display_list/dl_op_records.h +++ b/display_list/dl_op_records.h @@ -311,13 +311,13 @@ struct SaveLayerBackdropOp final : SaveLayerOpBase { SaveLayerBackdropOp(const SaveLayerOptions& options, const DlRect& rect, const DlImageFilter* backdrop, - int64_t backdrop_id = -1) + std::optional backdrop_id) : SaveLayerOpBase(options, rect), backdrop(backdrop->shared()), backdrop_id_(backdrop_id) {} const std::shared_ptr backdrop; - int64_t backdrop_id_; + std::optional backdrop_id_; void dispatch(DlOpReceiver& receiver) const { receiver.saveLayer(rect, options, total_content_depth, max_blend_mode, diff --git a/display_list/skia/dl_sk_canvas.cc b/display_list/skia/dl_sk_canvas.cc index e35d271218b75..bc9bc76b52eca 100644 --- a/display_list/skia/dl_sk_canvas.cc +++ b/display_list/skia/dl_sk_canvas.cc @@ -55,7 +55,7 @@ void DlSkCanvasAdapter::Save() { void DlSkCanvasAdapter::SaveLayer(const SkRect* bounds, const DlPaint* paint, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { sk_sp sk_backdrop = ToSk(backdrop); SkOptionalPaint sk_paint(paint); TRACE_EVENT0("flutter", "Canvas::saveLayer"); diff --git a/display_list/skia/dl_sk_canvas.h b/display_list/skia/dl_sk_canvas.h index 2f9bef904e8ee..47837350a4995 100644 --- a/display_list/skia/dl_sk_canvas.h +++ b/display_list/skia/dl_sk_canvas.h @@ -33,7 +33,7 @@ class DlSkCanvasAdapter final : public virtual DlCanvas { void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) override; + std::optional backdrop_id = std::nullopt) override; void Restore() override; int GetSaveCount() const override; void RestoreToCount(int restore_count) override; diff --git a/display_list/skia/dl_sk_dispatcher.cc b/display_list/skia/dl_sk_dispatcher.cc index 5104dc50a0059..45066eb22305f 100644 --- a/display_list/skia/dl_sk_dispatcher.cc +++ b/display_list/skia/dl_sk_dispatcher.cc @@ -48,7 +48,7 @@ void DlSkCanvasDispatcher::restore() { void DlSkCanvasDispatcher::saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { if (!options.content_is_clipped() && options.can_distribute_opacity() && backdrop == nullptr) { // We know that: diff --git a/display_list/skia/dl_sk_dispatcher.h b/display_list/skia/dl_sk_dispatcher.h index ed38bf55ef94f..1455479a8b22c 100644 --- a/display_list/skia/dl_sk_dispatcher.h +++ b/display_list/skia/dl_sk_dispatcher.h @@ -32,7 +32,7 @@ class DlSkCanvasDispatcher : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; void translate(DlScalar tx, DlScalar ty) override; void scale(DlScalar sx, DlScalar sy) override; diff --git a/display_list/utils/dl_receiver_utils.h b/display_list/utils/dl_receiver_utils.h index ea8f087d2eef0..fccc04c6ffcee 100644 --- a/display_list/utils/dl_receiver_utils.h +++ b/display_list/utils/dl_receiver_utils.h @@ -83,7 +83,7 @@ class IgnoreDrawDispatchHelper : public virtual DlOpReceiver { void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override {} + std::optional backdrop_id) override {} void restore() override {} void drawColor(DlColor color, DlBlendMode mode) override {} void drawPaint() override {} diff --git a/flow/layers/backdrop_filter_layer.cc b/flow/layers/backdrop_filter_layer.cc index 83e6a38fcab06..aec04bafae872 100644 --- a/flow/layers/backdrop_filter_layer.cc +++ b/flow/layers/backdrop_filter_layer.cc @@ -9,7 +9,7 @@ namespace flutter { BackdropFilterLayer::BackdropFilterLayer( std::shared_ptr filter, DlBlendMode blend_mode, - int64_t backdrop_id) + std::optional backdrop_id) : filter_(std::move(filter)), blend_mode_(blend_mode), backdrop_id_(backdrop_id) {} diff --git a/flow/layers/backdrop_filter_layer.h b/flow/layers/backdrop_filter_layer.h index 2896c3dc126f1..180c5a641341a 100644 --- a/flow/layers/backdrop_filter_layer.h +++ b/flow/layers/backdrop_filter_layer.h @@ -14,7 +14,7 @@ class BackdropFilterLayer : public ContainerLayer { public: BackdropFilterLayer(std::shared_ptr filter, DlBlendMode blend_mode, - int64_t backdrop_id = -1); + std::optional backdrop_id = std::nullopt); void Diff(DiffContext* context, const Layer* old_layer) override; @@ -25,7 +25,7 @@ class BackdropFilterLayer : public ContainerLayer { private: std::shared_ptr filter_; DlBlendMode blend_mode_; - int64_t backdrop_id_ = -1; + std::optional backdrop_id_; FML_DISALLOW_COPY_AND_ASSIGN(BackdropFilterLayer); }; diff --git a/flow/layers/layer_state_stack.cc b/flow/layers/layer_state_stack.cc index 86fb801313778..cb3f6a92ce799 100644 --- a/flow/layers/layer_state_stack.cc +++ b/flow/layers/layer_state_stack.cc @@ -53,7 +53,7 @@ class DummyDelegate : public LayerStateStack::Delegate { LayerStateStack::RenderingAttributes& attributes, DlBlendMode blend, const DlImageFilter* backdrop, - int backdrop_id) override {} + std::optional backdrop_id) override {} void restore() override {} void translate(SkScalar tx, SkScalar ty) override {} @@ -101,7 +101,7 @@ class DlCanvasDelegate : public LayerStateStack::Delegate { LayerStateStack::RenderingAttributes& attributes, DlBlendMode blend_mode, const DlImageFilter* backdrop, - int backdrop_id) override { + std::optional backdrop_id) override { TRACE_EVENT0("flutter", "Canvas::saveLayer"); DlPaint paint; canvas_->SaveLayer(&bounds, attributes.fill(paint, blend_mode), backdrop, @@ -161,7 +161,7 @@ class PrerollDelegate : public LayerStateStack::Delegate { LayerStateStack::RenderingAttributes& attributes, DlBlendMode blend, const DlImageFilter* backdrop, - int backdrop_id) override { + std::optional backdrop_id) override { save_stack_.emplace_back(state()); } void restore() override { save_stack_.pop_back(); } @@ -347,7 +347,7 @@ class BackdropFilterEntry : public SaveLayerEntry { BackdropFilterEntry(const SkRect& bounds, const std::shared_ptr& filter, DlBlendMode blend_mode, - int64_t backdrop_id, + std::optional backdrop_id, const LayerStateStack::RenderingAttributes& prev) : SaveLayerEntry(bounds, blend_mode, prev), filter_(filter), @@ -373,7 +373,7 @@ class BackdropFilterEntry : public SaveLayerEntry { private: const std::shared_ptr filter_; - int64_t backdrop_id_ = -1; + std::optional backdrop_id_; FML_DISALLOW_COPY_ASSIGN_AND_MOVE(BackdropFilterEntry); }; @@ -567,7 +567,7 @@ void MutatorContext::applyBackdropFilter( const SkRect& bounds, const std::shared_ptr& filter, DlBlendMode blend_mode, - int64_t backdrop_id) { + std::optional backdrop_id) { layer_state_stack_->push_backdrop(bounds, filter, blend_mode, backdrop_id); } @@ -716,7 +716,7 @@ void LayerStateStack::push_backdrop( const SkRect& bounds, const std::shared_ptr& filter, DlBlendMode blend_mode, - int64_t backdrop_id) { + std::optional backdrop_id) { state_stack_.emplace_back(std::make_unique( bounds, filter, blend_mode, backdrop_id, outstanding_)); apply_last_entry(); diff --git a/flow/layers/layer_state_stack.h b/flow/layers/layer_state_stack.h index ba15601f06859..a5cec34ed1cc4 100644 --- a/flow/layers/layer_state_stack.h +++ b/flow/layers/layer_state_stack.h @@ -198,7 +198,7 @@ class LayerStateStack { void applyBackdropFilter(const SkRect& bounds, const std::shared_ptr& filter, DlBlendMode blend_mode, - int64_t backdrop_id); + std::optional backdrop_id); void translate(SkScalar tx, SkScalar ty); void translate(SkPoint tp) { translate(tp.fX, tp.fY); } @@ -336,7 +336,7 @@ class LayerStateStack { void push_backdrop(const SkRect& bounds, const std::shared_ptr& filter, DlBlendMode blend_mode, - int64_t push_backdrop); + std::optional backdrop_id); void push_translate(SkScalar tx, SkScalar ty); void push_transform(const SkM44& matrix); @@ -446,11 +446,12 @@ class LayerStateStack { virtual bool content_culled(const SkRect& content_bounds) const = 0; virtual void save() = 0; - virtual void saveLayer(const SkRect& bounds, - RenderingAttributes& attributes, - DlBlendMode blend, - const DlImageFilter* backdrop, - int backdrop_id = -1) = 0; + virtual void saveLayer( + const SkRect& bounds, + RenderingAttributes& attributes, + DlBlendMode blend, + const DlImageFilter* backdrop, + std::optional backdrop_id = std::nullopt) = 0; virtual void restore() = 0; virtual void translate(SkScalar tx, SkScalar ty) = 0; diff --git a/impeller/display_list/aiks_dl_blur_unittests.cc b/impeller/display_list/aiks_dl_blur_unittests.cc index cb837dcf2515f..76a1ce6b31d97 100644 --- a/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/impeller/display_list/aiks_dl_blur_unittests.cc @@ -1364,7 +1364,7 @@ TEST_P(AiksTest, save_paint.setBlendMode(DlBlendMode::kSrc); auto backdrop_filter = DlBlurImageFilter::Make(30, 30, DlTileMode::kClamp); builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(), - /*backdrop_id=*/-1); + /*backdrop_id=*/1); builder.Restore(); builder.Restore(); if (i != 0) { diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 7571794a71bef..e0429b8b0d827 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -992,7 +992,7 @@ void Canvas::SaveLayer(const Paint& paint, ContentBoundsPromise bounds_promise, uint32_t total_content_depth, bool can_distribute_opacity, - int64_t backdrop_id) { + std::optional backdrop_id) { TRACE_EVENT0("flutter", "Canvas::saveLayer"); if (IsSkipping()) { return SkipUntilMatchingRestore(total_content_depth); @@ -1075,14 +1075,21 @@ void Canvas::SaveLayer(const Paint& paint, }; std::shared_ptr input_texture; - const auto& backdrop_data = backdrop_keys_.find(backdrop_id); + // If the backdrop ID is not the no-op id, and there is more than one usage // of it in the current scene, cache the backdrop texture and remove it from // the current entity pass flip. - bool will_cache_texture = backdrop_data != backdrop_keys_.end() && - backdrop_data->second.backdrop_count > 1; - if (!will_cache_texture || - (will_cache_texture && !backdrop_data->second.texture_slot)) { + bool will_cache_texture = false; + BackdropData* data = nullptr; + if (backdrop_id.has_value()) { + const auto& backdrop_data = backdrop_keys_.find(backdrop_id.value()); + if (backdrop_data != backdrop_keys_.end()) { + data = &backdrop_data->second; + will_cache_texture = backdrop_data->second.backdrop_count > 1; + } + } + + if (!will_cache_texture || (will_cache_texture && !data->texture_slot)) { input_texture = FlipBackdrop(render_passes_, // GetGlobalPassPosition(), // clip_coverage_stack_, // @@ -1095,10 +1102,10 @@ void Canvas::SaveLayer(const Paint& paint, } if (will_cache_texture) { - backdrop_data->second.texture_slot = input_texture; + data->texture_slot = input_texture; } } else { - input_texture = backdrop_data->second.texture_slot; + input_texture = data->texture_slot; } backdrop_filter_contents = backdrop_filter_proc( @@ -1111,18 +1118,19 @@ void Canvas::SaveLayer(const Paint& paint, : Entity::RenderingMode::kSubpassAppendSnapshotTransform); if (will_cache_texture) { - auto& data = backdrop_data->second; + FML_DCHECK(data); // If all filters on the shared backdrop layer are equal, process the // layer once. - if (data.all_filters_equal && !data.filtered_input_slot.has_value()) { + if (data->all_filters_equal && !data->filtered_input_slot.has_value()) { // TODO(jonahwilliams): compute minimum input hint. - data.filtered_input_slot = + data->filtered_input_slot = backdrop_filter_contents->RenderToSnapshot(renderer_, {}); } - if (data.filtered_input_slot.has_value()) { - Snapshot snapshot = data.filtered_input_slot.value(); - auto contents = TextureContents::MakeRect(subpass_coverage); + if (data->filtered_input_slot.has_value()) { + Snapshot snapshot = data->filtered_input_slot.value(); + std::shared_ptr contents = TextureContents::MakeRect( + subpass_coverage.Shift(-GetGlobalPassPosition())); auto scaled = subpass_coverage.TransformBounds(snapshot.transform.Invert()); contents->SetTexture(snapshot.texture); diff --git a/impeller/display_list/canvas.h b/impeller/display_list/canvas.h index 96816478c0ceb..536684307a4f2 100644 --- a/impeller/display_list/canvas.h +++ b/impeller/display_list/canvas.h @@ -151,7 +151,7 @@ class Canvas { ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown, uint32_t total_content_depth = kMaxDepth, bool can_distribute_opacity = false, - int64_t backdrop_id = -1); + std::optional backdrop_id = std::nullopt); bool Restore(); diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 1660fa91e10e3..eb8a30907d3f2 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -302,7 +302,7 @@ void DlDispatcherBase::saveLayer(const DlRect& bounds, uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, const flutter::DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { AUTO_DEPTH_WATCHER(1u); auto paint = options.renders_with_attributes() ? paint_ : Paint{}; @@ -997,16 +997,16 @@ void TextFrameDispatcher::save() { void TextFrameDispatcher::saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { save(); - if (backdrop != nullptr && backdrop_id != -1) { - const auto& existing = backdrop_keys_.find(backdrop_id); + if (backdrop != nullptr && backdrop_id.has_value()) { + const auto& existing = backdrop_keys_.find(backdrop_id.value()); if (existing == backdrop_keys_.end()) { - backdrop_keys_[backdrop_id] = + backdrop_keys_[backdrop_id.value()] = BackdropData{.backdrop_count = 1, .last_backdrop = backdrop}; } else { - BackdropData& data = backdrop_keys_[backdrop_id]; + BackdropData& data = backdrop_keys_[backdrop_id.value()]; data.backdrop_count++; if (data.all_filters_equal) { diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h index b7b2d41ecc93c..48a7beb046d66 100644 --- a/impeller/display_list/dl_dispatcher.h +++ b/impeller/display_list/dl_dispatcher.h @@ -76,7 +76,7 @@ class DlDispatcherBase : public flutter::DlOpReceiver { uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, const flutter::DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; // |flutter::DlOpReceiver| void restore() override; @@ -272,7 +272,7 @@ class CanvasDlDispatcher : public DlDispatcherBase { void saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter* backdrop, - int64_t backdrop_id) override { + std::optional backdrop_id) override { // This dispatcher should never be used with the saveLayer() variant // that does not include the content_depth parameter. FML_UNREACHABLE(); @@ -308,7 +308,7 @@ class TextFrameDispatcher : public flutter::IgnoreAttributeDispatchHelper, void saveLayer(const DlRect& bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; void restore() override; diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 1c8663dd06049..3646e03ac7e3a 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -401,7 +401,7 @@ abstract class SceneBuilder { /// the most recent save layer and rendered back to the scene using the indicated /// [blendMode] prior to rasterizing the child layers. /// - /// if [backdropId] is provided and not equal to -1, then this value is treated + /// if [backdropId] is provided and not null, then this value is treated /// as a unique identifier for the backdrop. When the first backdrop filter with /// a given id is processed during rasterization, the state of the backdrop is /// recorded and cached. All subsequent backdrop filters with the same identifier @@ -419,7 +419,7 @@ abstract class SceneBuilder { BackdropFilterEngineLayer pushBackdropFilter( ImageFilter filter, { BlendMode blendMode = BlendMode.srcOver, - int backdropId = -1, + int? backdropId, BackdropFilterEngineLayer? oldLayer, }); @@ -783,7 +783,7 @@ base class _NativeSceneBuilder extends NativeFieldWrapperClass1 implements Scene BackdropFilterEngineLayer pushBackdropFilter( ImageFilter filter, { BlendMode blendMode = BlendMode.srcOver, - int backdropId = -1, + int? backdropId, BackdropFilterEngineLayer? oldLayer, }) { assert(_debugCheckCanBeUsedAsOldLayer(oldLayer, 'pushBackdropFilter')); @@ -794,8 +794,8 @@ base class _NativeSceneBuilder extends NativeFieldWrapperClass1 implements Scene return layer; } - @Native, Handle, Pointer, Int32, Int32, Handle)>(symbol: 'SceneBuilder::pushBackdropFilter') - external void _pushBackdropFilter(EngineLayer outEngineLayer, _ImageFilter filter, int blendMode, int backdropId, EngineLayer? oldLayer); + @Native, Handle, Pointer, Int32, Handle, Handle)>(symbol: 'SceneBuilder::pushBackdropFilter') + external void _pushBackdropFilter(EngineLayer outEngineLayer, _ImageFilter filter, int blendMode, int? backdropId, EngineLayer? oldLayer); @override ShaderMaskEngineLayer pushShaderMask( diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index c48d05dcf7c64..fdb82bcdd55bc 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -3,7 +3,9 @@ // found in the LICENSE file. #include "flutter/lib/ui/compositing/scene_builder.h" +#include +#include "dart_api.h" #include "flutter/flow/layers/backdrop_filter_layer.h" #include "flutter/flow/layers/clip_path_layer.h" #include "flutter/flow/layers/clip_rect_layer.h" @@ -168,10 +170,17 @@ void SceneBuilder::pushBackdropFilter( Dart_Handle layer_handle, ImageFilter* filter, int blendMode, - int backdropId, + Dart_Handle backdropId, const fml::RefPtr& oldLayer) { + std::optional backdrop_id; + if (Dart_IsInteger(backdropId)) { + int64_t out; + Dart_IntegerToInt64(backdropId, &out); + backdrop_id = out; + } + auto layer = std::make_shared( - filter->filter(), static_cast(blendMode), backdropId); + filter->filter(), static_cast(blendMode), backdrop_id); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index 600ae5825c231..e9b3a41f1c833 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -80,7 +80,7 @@ class SceneBuilder : public RefCountedDartWrappable { void pushBackdropFilter(Dart_Handle layer_handle, ImageFilter* filter, int blendMode, - int backdropId, + Dart_Handle backdropId, const fml::RefPtr& oldLayer); void pushShaderMask(Dart_Handle layer_handle, Shader* shader, diff --git a/shell/common/dl_op_spy.cc b/shell/common/dl_op_spy.cc index f0becd417ab82..77fb2092a549a 100644 --- a/shell/common/dl_op_spy.cc +++ b/shell/common/dl_op_spy.cc @@ -32,7 +32,7 @@ void DlOpSpy::save() {} void DlOpSpy::saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) {} + std::optional backdrop_id) {} void DlOpSpy::restore() {} void DlOpSpy::drawColor(DlColor color, DlBlendMode mode) { did_draw_ |= !color.isTransparent(); diff --git a/shell/common/dl_op_spy.h b/shell/common/dl_op_spy.h index 1c93a23335d7f..82c2dfc55684b 100644 --- a/shell/common/dl_op_spy.h +++ b/shell/common/dl_op_spy.h @@ -42,7 +42,7 @@ class DlOpSpy final : public virtual DlOpReceiver, void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; void restore() override; void drawColor(DlColor color, DlBlendMode mode) override; void drawPaint() override; diff --git a/testing/display_list_testing.cc b/testing/display_list_testing.cc index ab1b9a99efb91..4f9065178cbf3 100644 --- a/testing/display_list_testing.cc +++ b/testing/display_list_testing.cc @@ -703,12 +703,16 @@ void DisplayListStreamDispatcher::save() { void DisplayListStreamDispatcher::saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { startl() << "saveLayer(" << bounds << ", " << options; if (backdrop) { os_ << "," << std::endl; indent(10); - startl() << "backdrop: " << backdrop_id; + if (backdrop_id.has_value()) { + startl() << "backdrop: " << backdrop_id.value(); + } else { + startl() << "backdrop: (no id)"; + } out(backdrop); outdent(10); } else { diff --git a/testing/display_list_testing.h b/testing/display_list_testing.h index e370826601acd..33fcd6b039dc3 100644 --- a/testing/display_list_testing.h +++ b/testing/display_list_testing.h @@ -111,7 +111,7 @@ class DisplayListStreamDispatcher final : public DlOpReceiver { void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override; + std::optional backdrop_id) override; void restore() override; void translate(DlScalar tx, DlScalar ty) override; @@ -399,7 +399,7 @@ class DisplayListGeneralReceiver : public DlOpReceiver { void saveLayer(const DlRect& bounds, const SaveLayerOptions options, const DlImageFilter* backdrop, - int64_t backdrop_id) override { + std::optional backdrop_id) override { if (backdrop) { RecordByType(DisplayListOpType::kSaveLayerBackdrop); } else { diff --git a/testing/mock_canvas.cc b/testing/mock_canvas.cc index bab0d21851e2b..0d4f2c8975dae 100644 --- a/testing/mock_canvas.cc +++ b/testing/mock_canvas.cc @@ -46,7 +46,7 @@ void MockCanvas::Save() { void MockCanvas::SaveLayer(const SkRect* bounds, const DlPaint* paint, const DlImageFilter* backdrop, - int64_t backdrop_id) { + std::optional backdrop_id) { // saveLayer calls this prior to running, so we use it to track saveLayer // calls draw_calls_.emplace_back(DrawCall{ diff --git a/testing/mock_canvas.h b/testing/mock_canvas.h index e32689b703185..12c715de8fb82 100644 --- a/testing/mock_canvas.h +++ b/testing/mock_canvas.h @@ -174,9 +174,9 @@ class MockCanvas final : public DlCanvas { void Save() override; void SaveLayer(const SkRect* bounds, - const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr, - int64_t backdrop_id = -1) override; + const DlPaint* paint, + const DlImageFilter* backdrop, + std::optional backdrop_id) override; void Restore() override; int GetSaveCount() const { return current_layer_; } void RestoreToCount(int restore_count) { From 90bbfbe90c61101a99cf90e547bac45805ce16ed Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 08:59:46 -0700 Subject: [PATCH 11/20] ++ --- impeller/display_list/canvas.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index e0429b8b0d827..9cd2c28e5d769 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1127,8 +1127,9 @@ void Canvas::SaveLayer(const Paint& paint, backdrop_filter_contents->RenderToSnapshot(renderer_, {}); } - if (data->filtered_input_slot.has_value()) { - Snapshot snapshot = data->filtered_input_slot.value(); + auto maybe_snapshot = data->filtered_input_slot; + if (maybe_snapshot.has_value()) { + Snapshot snapshot = maybe_snapshot.value(); std::shared_ptr contents = TextureContents::MakeRect( subpass_coverage.Shift(-GetGlobalPassPosition())); auto scaled = From 68b5f6bc3b56a4aab165503d83832c615fe7a8ff Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 09:17:57 -0700 Subject: [PATCH 12/20] do dl rect convrsion. --- flow/layers/layer_state_stack.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flow/layers/layer_state_stack.cc b/flow/layers/layer_state_stack.cc index cb3f6a92ce799..15cf79548edde 100644 --- a/flow/layers/layer_state_stack.cc +++ b/flow/layers/layer_state_stack.cc @@ -104,7 +104,8 @@ class DlCanvasDelegate : public LayerStateStack::Delegate { std::optional backdrop_id) override { TRACE_EVENT0("flutter", "Canvas::saveLayer"); DlPaint paint; - canvas_->SaveLayer(&bounds, attributes.fill(paint, blend_mode), backdrop, + std::optional rect = ToDlRect(bounds); + canvas_->SaveLayer(rect, attributes.fill(paint, blend_mode), backdrop, backdrop_id); } void restore() override { canvas_->Restore(); } From fdb55a0ddb9d97277a414c99aa49b149f8c84dc9 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 10:05:53 -0700 Subject: [PATCH 13/20] ++ --- display_list/dl_canvas.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/display_list/dl_canvas.h b/display_list/dl_canvas.h index 415131a804768..80076fc0012b3 100644 --- a/display_list/dl_canvas.h +++ b/display_list/dl_canvas.h @@ -234,9 +234,10 @@ class DlCanvas { void SaveLayer(const SkRect* bounds, const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr) { + const DlImageFilter* backdrop = nullptr, + std::optional backdrop_id = std::nullopt) { auto optional_bounds = ToOptDlRect(bounds); - SaveLayer(optional_bounds, paint, backdrop); + SaveLayer(optional_bounds, paint, backdrop, backdrop_id); } void Transform(const SkMatrix* matrix) { From 74803098b213a3931bca79992f7418066b677c67 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 13:10:45 -0700 Subject: [PATCH 14/20] aaron review. --- display_list/benchmarking/dl_complexity_gl.cc | 3 +- .../benchmarking/dl_complexity_metal.cc | 3 +- display_list/testing/dl_test_snippets.cc | 8 +- impeller/display_list/aiks_playground.cc | 2 +- impeller/display_list/canvas.cc | 102 +++++++++--------- impeller/display_list/canvas.h | 11 +- impeller/display_list/dl_dispatcher.cc | 22 ++-- impeller/display_list/dl_dispatcher.h | 8 +- impeller/display_list/dl_playground.cc | 2 +- impeller/entity/entity_pass_target.cc | 4 + impeller/entity/entity_pass_target.h | 2 +- lib/ui/compositing.dart | 6 +- 12 files changed, 96 insertions(+), 77 deletions(-) diff --git a/display_list/benchmarking/dl_complexity_gl.cc b/display_list/benchmarking/dl_complexity_gl.cc index 34e43516ba621..5da3703b7fbb2 100644 --- a/display_list/benchmarking/dl_complexity_gl.cc +++ b/display_list/benchmarking/dl_complexity_gl.cc @@ -628,7 +628,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList( GLHelper helper(Ceiling() - CurrentComplexityScore()); if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { auto bounds = display_list->GetBounds(); - helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); + helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, + /*backdrop_id=*/-1); } display_list->Dispatch(helper); AccumulateComplexity(helper.ComplexityScore()); diff --git a/display_list/benchmarking/dl_complexity_metal.cc b/display_list/benchmarking/dl_complexity_metal.cc index 2f86eb64394fe..25fa25a4912a2 100644 --- a/display_list/benchmarking/dl_complexity_metal.cc +++ b/display_list/benchmarking/dl_complexity_metal.cc @@ -572,7 +572,8 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDisplayList( MetalHelper helper(Ceiling() - CurrentComplexityScore()); if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { auto bounds = display_list->GetBounds(); - helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); + helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, + /*backdrop_id=*/-1); } display_list->Dispatch(helper); AccumulateComplexity(helper.ComplexityScore()); diff --git a/display_list/testing/dl_test_snippets.cc b/display_list/testing/dl_test_snippets.cc index a55222164f7fc..64ce2a0fef0a0 100644 --- a/display_list/testing/dl_test_snippets.cc +++ b/display_list/testing/dl_test_snippets.cc @@ -327,7 +327,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 144, 3, + {5, 152, 3, [](DlOpReceiver& r) { r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); @@ -337,7 +337,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 144, 3, + {5, 152, 3, [](DlOpReceiver& r) { r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); @@ -347,7 +347,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 144, 3, + {5, 152, 3, [](DlOpReceiver& r) { r.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); @@ -357,7 +357,7 @@ std::vector CreateAllSaveRestoreOps() { r.drawRect(DlRect::MakeLTRB(10, 10, 20, 20)); r.restore(); }}, - {5, 144, 3, + {5, 152, 3, [](DlOpReceiver& r) { r.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); diff --git a/impeller/display_list/aiks_playground.cc b/impeller/display_list/aiks_playground.cc index 029703fea0904..6b2ac34a9f315 100644 --- a/impeller/display_list/aiks_playground.cc +++ b/impeller/display_list/aiks_playground.cc @@ -56,7 +56,7 @@ bool AiksPlayground::OpenPlaygroundHere( callback(), // SkIRect::MakeWH(render_target.GetRenderTargetSize().width, render_target.GetRenderTargetSize().height), // - true // + /*reset_host_buffer=*/true // ); }); } diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 9cd2c28e5d769..8d52b500c6bd1 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -93,6 +93,11 @@ static void ApplyFramebufferBlend(Entity& entity) { /// /// Returns the previous render pass stored as a texture, or nullptr if there /// was a validation failure. +/// +/// [should_remove_texture] defaults to false. If true, the render target +/// texture is removed from the entity pass target. This allows the texture to +/// be cached by the canvas dispatcher for usage in the backdrop filter reuse +/// mechanism. static std::shared_ptr FlipBackdrop( std::vector& render_passes, Point global_pass_position, @@ -145,11 +150,13 @@ static std::shared_ptr FlipBackdrop( render_passes.push_back(LazyRenderingConfig( renderer, std::move(rendering_config.entity_pass_target), std::move(rendering_config.inline_pass_context))); - // If the current texture is being cachced for a BDF we need to ensure we - // don't recycle it during recording. remove it from the entity pass target. + // If the current texture is being cached for a BDF we need to ensure we + // don't recycle it during recording; remove it from the entity pass target. if (should_remove_texture) { render_passes.back().entity_pass_target->RemoveSecondary(); } + RenderPass& current_render_pass = + *render_passes.back().inline_pass_context->GetRenderPass(0).pass; // Eagerly restore the BDF contents. @@ -169,9 +176,7 @@ static std::shared_ptr FlipBackdrop( msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents)); msaa_backdrop_entity.SetBlendMode(BlendMode::kSource); msaa_backdrop_entity.SetClipDepth(std::numeric_limits::max()); - if (!msaa_backdrop_entity.Render( - renderer, - *render_passes.back().inline_pass_context->GetRenderPass(0).pass)) { + if (!msaa_backdrop_entity.Render(renderer, current_render_pass)) { VALIDATION_LOG << "Failed to render MSAA backdrop entity."; return nullptr; } @@ -180,13 +185,9 @@ static std::shared_ptr FlipBackdrop( // applied. auto& replay_entities = clip_coverage_stack.GetReplayEntities(); for (const auto& replay : replay_entities) { - SetClipScissor( - replay.clip_coverage, - *render_passes.back().inline_pass_context->GetRenderPass(0).pass, - global_pass_position); - if (!replay.entity.Render( - renderer, - *render_passes.back().inline_pass_context->GetRenderPass(0).pass)) { + SetClipScissor(replay.clip_coverage, current_render_pass, + global_pass_position); + if (!replay.entity.Render(renderer, current_render_pass)) { VALIDATION_LOG << "Failed to render entity for clip restore."; } } @@ -1079,33 +1080,35 @@ void Canvas::SaveLayer(const Paint& paint, // If the backdrop ID is not the no-op id, and there is more than one usage // of it in the current scene, cache the backdrop texture and remove it from // the current entity pass flip. - bool will_cache_texture = false; - BackdropData* data = nullptr; + bool will_cache_backdrop_texture = false; + BackdropData* backdrop_data = nullptr; if (backdrop_id.has_value()) { - const auto& backdrop_data = backdrop_keys_.find(backdrop_id.value()); - if (backdrop_data != backdrop_keys_.end()) { - data = &backdrop_data->second; - will_cache_texture = backdrop_data->second.backdrop_count > 1; + const auto& backdrop_data_it = backdrop_data_.find(backdrop_id.value()); + if (backdrop_data_it != backdrop_data_.end()) { + backdrop_data = &backdrop_data_it->second; + will_cache_backdrop_texture = + backdrop_data_it->second.backdrop_count > 1; } } - if (!will_cache_texture || (will_cache_texture && !data->texture_slot)) { - input_texture = FlipBackdrop(render_passes_, // - GetGlobalPassPosition(), // - clip_coverage_stack_, // - renderer_, // - will_cache_texture // + if (!will_cache_backdrop_texture || + (will_cache_backdrop_texture && !backdrop_data->texture_slot)) { + input_texture = FlipBackdrop(render_passes_, // + GetGlobalPassPosition(), // + clip_coverage_stack_, // + renderer_, // + will_cache_backdrop_texture // ); if (!input_texture) { // Validation failures are logged in FlipBackdrop. return; } - if (will_cache_texture) { - data->texture_slot = input_texture; + if (will_cache_backdrop_texture) { + backdrop_data->texture_slot = input_texture; } } else { - input_texture = data->texture_slot; + input_texture = backdrop_data->texture_slot; } backdrop_filter_contents = backdrop_filter_proc( @@ -1117,17 +1120,19 @@ void Canvas::SaveLayer(const Paint& paint, ? Entity::RenderingMode::kSubpassPrependSnapshotTransform : Entity::RenderingMode::kSubpassAppendSnapshotTransform); - if (will_cache_texture) { - FML_DCHECK(data); + if (will_cache_backdrop_texture) { + FML_DCHECK(backdrop_data); // If all filters on the shared backdrop layer are equal, process the // layer once. - if (data->all_filters_equal && !data->filtered_input_slot.has_value()) { + if (backdrop_data->all_filters_equal && + !backdrop_data->filtered_input_slot.has_value()) { // TODO(jonahwilliams): compute minimum input hint. - data->filtered_input_slot = + backdrop_data->filtered_input_slot = backdrop_filter_contents->RenderToSnapshot(renderer_, {}); } - auto maybe_snapshot = data->filtered_input_slot; + std::optional maybe_snapshot = + backdrop_data->filtered_input_slot; if (maybe_snapshot.has_value()) { Snapshot snapshot = maybe_snapshot.value(); std::shared_ptr contents = TextureContents::MakeRect( @@ -1145,9 +1150,7 @@ void Canvas::SaveLayer(const Paint& paint, backdrop_entity.SetClipDepth(++current_depth_); backdrop_entity.SetBlendMode(paint.blend_mode); - backdrop_entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + backdrop_entity.Render(renderer_, GetCurrentRenderPass()); Save(0); return; } @@ -1196,9 +1199,7 @@ void Canvas::SaveLayer(const Paint& paint, Matrix::MakeTranslation(Vector3(-local_position))); backdrop_entity.SetClipDepth(std::numeric_limits::max()); - backdrop_entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + backdrop_entity.Render(renderer_, GetCurrentRenderPass()); } bool Canvas::Restore() { @@ -1368,9 +1369,7 @@ bool Canvas::Restore() { return true; } - entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + entity.Render(renderer_, GetCurrentRenderPass()); } return true; @@ -1632,19 +1631,24 @@ void Canvas::AddClipEntityToCurrentPass(Entity& entity) { if (clip_state_result.clip_did_change) { // We only need to update the pass scissor if the clip state has changed. - SetClipScissor( - clip_coverage_stack_.CurrentClipCoverage(), - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass, - GetGlobalPassPosition()); + SetClipScissor(clip_coverage_stack_.CurrentClipCoverage(), + GetCurrentRenderPass(), GetGlobalPassPosition()); } if (!clip_state_result.should_render) { return; } - entity.Render( - renderer_, - *render_passes_.back().inline_pass_context->GetRenderPass(0).pass); + entity.Render(renderer_, GetCurrentRenderPass()); +} + +RenderPass& Canvas::GetCurrentRenderPass() const { + return *render_passes_.back().inline_pass_context->GetRenderPass(0).pass; +} + +void Canvas::SetBackdropData( + std::unordered_map backdrop_data) { + backdrop_data_ = std::move(backdrop_data); } bool Canvas::BlitToOnscreen() { @@ -1710,7 +1714,7 @@ void Canvas::EndReplay() { FML_DCHECK(render_passes_.size() == 1u); render_passes_.back().inline_pass_context->GetRenderPass(0); render_passes_.back().inline_pass_context->EndPass(); - backdrop_keys_.clear(); + backdrop_data_.clear(); // If requires_readback_ was true, then we rendered to an offscreen texture // instead of to the onscreen provided in the render target. Now we need to diff --git a/impeller/display_list/canvas.h b/impeller/display_list/canvas.h index 536684307a4f2..e753b6146b713 100644 --- a/impeller/display_list/canvas.h +++ b/impeller/display_list/canvas.h @@ -133,10 +133,9 @@ class Canvas { ~Canvas() = default; - void SetBackdropKeys( - std::unordered_map backdrop_keys) { - backdrop_keys_ = std::move(backdrop_keys); - } + /// @brief Update the backdrop data used to group together backdrop filters + /// within the same layer. + void SetBackdropData(std::unordered_map backdrop_data); /// @brief Return the culling bounds of the current render target, or nullopt /// if there is no coverage. @@ -248,7 +247,7 @@ class Canvas { std::optional initial_cull_rect_; std::vector render_passes_; std::vector save_layer_state_; - std::unordered_map backdrop_keys_; + std::unordered_map backdrop_data_; // All geometry objects created for regular draws can be stack allocated, // but clip geometries must be cached for record/replay for backdrop filters @@ -294,6 +293,8 @@ class Canvas { Size corner_radii, const Paint& paint); + RenderPass& GetCurrentRenderPass() const; + Canvas(const Canvas&) = delete; Canvas& operator=(const Canvas&) = delete; diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index eb8a30907d3f2..e10c8351b08b2 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -976,6 +976,11 @@ void CanvasDlDispatcher::drawVertices( skia_conversions::ToBlendMode(dl_mode), paint_); } +void CanvasDlDispatcher::SetBackdropData( + std::unordered_map backdrop) { + GetCanvas().SetBackdropData(std::move(backdrop)); +} + //// Text Frame Dispatcher TextFrameDispatcher::TextFrameDispatcher(const ContentContext& renderer, @@ -1001,16 +1006,17 @@ void TextFrameDispatcher::saveLayer(const DlRect& bounds, save(); if (backdrop != nullptr && backdrop_id.has_value()) { - const auto& existing = backdrop_keys_.find(backdrop_id.value()); - if (existing == backdrop_keys_.end()) { - backdrop_keys_[backdrop_id.value()] = + const std::unordered_map::iterator& existing = + backdrop_data_.find(backdrop_id.value()); + if (existing == backdrop_data_.end()) { + backdrop_data_[backdrop_id.value()] = BackdropData{.backdrop_count = 1, .last_backdrop = backdrop}; } else { - BackdropData& data = backdrop_keys_[backdrop_id.value()]; - + BackdropData& data = existing->second; data.backdrop_count++; if (data.all_filters_equal) { - data.all_filters_equal = (*data.last_backdrop == *backdrop); + data.all_filters_equal = + data.last_backdrop && (*data.last_backdrop == *backdrop); data.last_backdrop = backdrop; } } @@ -1258,7 +1264,7 @@ std::shared_ptr DisplayListToTexture( display_list->max_root_blend_mode(), // impeller::IRect::MakeSize(size) // ); - impeller_dispatcher.SetBackdropKeys(collector.TakeBackdropData()); + impeller_dispatcher.SetBackdropData(collector.TakeBackdropData()); display_list->Dispatch(impeller_dispatcher, sk_cull_rect); impeller_dispatcher.FinishRecording(); @@ -1287,7 +1293,7 @@ bool RenderToOnscreen(ContentContext& context, display_list->max_root_blend_mode(), // IRect::RoundOut(ip_cull_rect) // ); - impeller_dispatcher.SetBackdropKeys(collector.TakeBackdropData()); + impeller_dispatcher.SetBackdropData(collector.TakeBackdropData()); display_list->Dispatch(impeller_dispatcher, cull_rect); impeller_dispatcher.FinishRecording(); if (reset_host_buffer) { diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h index 48a7beb046d66..cc34ccbeb43c8 100644 --- a/impeller/display_list/dl_dispatcher.h +++ b/impeller/display_list/dl_dispatcher.h @@ -256,9 +256,7 @@ class CanvasDlDispatcher : public DlDispatcherBase { ~CanvasDlDispatcher() = default; - void SetBackdropKeys(std::unordered_map backdrop) { - GetCanvas().SetBackdropKeys(std::move(backdrop)); - } + void SetBackdropData(std::unordered_map backdrop); // |flutter::DlOpReceiver| void save() override { @@ -363,7 +361,7 @@ class TextFrameDispatcher : public flutter::IgnoreAttributeDispatchHelper, void setImageFilter(const flutter::DlImageFilter* filter) override; std::unordered_map TakeBackdropData() { - return std::move(backdrop_keys_); + return std::move(backdrop_data_); } private: @@ -372,7 +370,7 @@ class TextFrameDispatcher : public flutter::IgnoreAttributeDispatchHelper, const ContentContext& renderer_; Matrix matrix_; std::vector stack_; - std::unordered_map backdrop_keys_; + std::unordered_map backdrop_data_; // note: cull rects are always in the global coordinate space. std::vector cull_rect_state_; bool has_image_filter_ = false; diff --git a/impeller/display_list/dl_playground.cc b/impeller/display_list/dl_playground.cc index 10eeb7a673804..9a0561230d554 100644 --- a/impeller/display_list/dl_playground.cc +++ b/impeller/display_list/dl_playground.cc @@ -51,7 +51,7 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) { callback(), // SkIRect::MakeWH(render_target.GetRenderTargetSize().width, render_target.GetRenderTargetSize().height), // - true // + /*reset_host_buffer=*/true // ); }); } diff --git a/impeller/entity/entity_pass_target.cc b/impeller/entity/entity_pass_target.cc index c92a84a76a718..712645a61339f 100644 --- a/impeller/entity/entity_pass_target.cc +++ b/impeller/entity/entity_pass_target.cc @@ -73,4 +73,8 @@ bool EntityPassTarget::IsValid() const { return target_.IsValid(); } +void EntityPassTarget::RemoveSecondary() { + secondary_color_texture_ = nullptr; +} + } // namespace impeller diff --git a/impeller/entity/entity_pass_target.h b/impeller/entity/entity_pass_target.h index 42a3b2906a884..2adf4ecaeb50a 100644 --- a/impeller/entity/entity_pass_target.h +++ b/impeller/entity/entity_pass_target.h @@ -29,7 +29,7 @@ class EntityPassTarget { RenderTarget& GetRenderTarget(); /// @brief Remove the cached secondary color texture. - void RemoveSecondary() { secondary_color_texture_ = nullptr; } + void RemoveSecondary(); bool IsValid() const; diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 3646e03ac7e3a..32a25885f6cf6 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -401,7 +401,7 @@ abstract class SceneBuilder { /// the most recent save layer and rendered back to the scene using the indicated /// [blendMode] prior to rasterizing the child layers. /// - /// if [backdropId] is provided and not null, then this value is treated + /// If [backdropId] is provided and not null, then this value is treated /// as a unique identifier for the backdrop. When the first backdrop filter with /// a given id is processed during rasterization, the state of the backdrop is /// recorded and cached. All subsequent backdrop filters with the same identifier @@ -411,6 +411,10 @@ abstract class SceneBuilder { /// that uses a backdrop blur filter for each item in a list view should set /// all filters to have the same backdrop id. /// + /// If overlapping backdrop filters use the same backdropId, then each filter + /// will apply to the backdrop before the overlapping filter components were + /// rendered. + /// /// {@macro dart.ui.sceneBuilder.oldLayer} /// /// {@macro dart.ui.sceneBuilder.oldLayerVsRetained} From a4239069fcc907c90e861f81f1ca160f7fc3d251 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 16:03:23 -0700 Subject: [PATCH 15/20] more aaron review. --- impeller/display_list/canvas.cc | 10 ++++++---- impeller/display_list/canvas.h | 4 +++- impeller/display_list/dl_dispatcher.cc | 12 +++++++++--- impeller/display_list/dl_dispatcher.h | 4 +--- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 8d52b500c6bd1..62a194973dc1f 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include "display_list/effects/dl_color_source.h" @@ -1083,7 +1084,8 @@ void Canvas::SaveLayer(const Paint& paint, bool will_cache_backdrop_texture = false; BackdropData* backdrop_data = nullptr; if (backdrop_id.has_value()) { - const auto& backdrop_data_it = backdrop_data_.find(backdrop_id.value()); + std::unordered_map::iterator backdrop_data_it = + backdrop_data_.find(backdrop_id.value()); if (backdrop_data_it != backdrop_data_.end()) { backdrop_data = &backdrop_data_it->second; will_cache_backdrop_texture = @@ -1125,14 +1127,14 @@ void Canvas::SaveLayer(const Paint& paint, // If all filters on the shared backdrop layer are equal, process the // layer once. if (backdrop_data->all_filters_equal && - !backdrop_data->filtered_input_slot.has_value()) { + !backdrop_data->shared_filter_snapshot.has_value()) { // TODO(jonahwilliams): compute minimum input hint. - backdrop_data->filtered_input_slot = + backdrop_data->shared_filter_snapshot = backdrop_filter_contents->RenderToSnapshot(renderer_, {}); } std::optional maybe_snapshot = - backdrop_data->filtered_input_slot; + backdrop_data->shared_filter_snapshot; if (maybe_snapshot.has_value()) { Snapshot snapshot = maybe_snapshot.value(); std::shared_ptr contents = TextureContents::MakeRect( diff --git a/impeller/display_list/canvas.h b/impeller/display_list/canvas.h index e753b6146b713..745cd3dc9eda7 100644 --- a/impeller/display_list/canvas.h +++ b/impeller/display_list/canvas.h @@ -34,7 +34,9 @@ struct BackdropData { size_t backdrop_count = 0; bool all_filters_equal = true; std::shared_ptr texture_slot; - std::optional filtered_input_slot; + // A single snapshot of the backdrop filter that is used when there are + // multiple backdrops that share an identical filter. + std::optional shared_filter_snapshot; const flutter::DlImageFilter* last_backdrop = nullptr; }; diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index e10c8351b08b2..aa7b84c637e73 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -1006,7 +1006,7 @@ void TextFrameDispatcher::saveLayer(const DlRect& bounds, save(); if (backdrop != nullptr && backdrop_id.has_value()) { - const std::unordered_map::iterator& existing = + std::unordered_map::iterator existing = backdrop_data_.find(backdrop_id.value()); if (existing == backdrop_data_.end()) { backdrop_data_[backdrop_id.value()] = @@ -1015,8 +1015,7 @@ void TextFrameDispatcher::saveLayer(const DlRect& bounds, BackdropData& data = existing->second; data.backdrop_count++; if (data.all_filters_equal) { - data.all_filters_equal = - data.last_backdrop && (*data.last_backdrop == *backdrop); + data.all_filters_equal = (*data.last_backdrop == *backdrop); data.last_backdrop = backdrop; } } @@ -1217,6 +1216,13 @@ void TextFrameDispatcher::setImageFilter(const flutter::DlImageFilter* filter) { } } +std::unordered_map +TextFrameDispatcher::TakeBackdropData() { + std::unordered_map temp; + std::swap(temp, backdrop_data_); + return temp; +} + std::shared_ptr DisplayListToTexture( const sk_sp& display_list, ISize size, diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h index cc34ccbeb43c8..8302a1f6b436b 100644 --- a/impeller/display_list/dl_dispatcher.h +++ b/impeller/display_list/dl_dispatcher.h @@ -360,9 +360,7 @@ class TextFrameDispatcher : public flutter::IgnoreAttributeDispatchHelper, // |flutter::DlOpReceiver| void setImageFilter(const flutter::DlImageFilter* filter) override; - std::unordered_map TakeBackdropData() { - return std::move(backdrop_data_); - } + std::unordered_map TakeBackdropData(); private: const Rect GetCurrentLocalCullingBounds() const; From f9b16aff8457de8e1bddf31ef7247148ede30c8f Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 16:44:04 -0700 Subject: [PATCH 16/20] fixes camel case naming and some iterator issues. --- lib/ui/compositing/scene_builder.cc | 150 +++++++++--------- lib/ui/compositing/scene_builder.h | 57 ++++--- lib/ui/compositing/scene_builder_unittests.cc | 1 + 3 files changed, 102 insertions(+), 106 deletions(-) diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index fdb82bcdd55bc..a8e3a29f85435 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -15,7 +15,6 @@ #include "flutter/flow/layers/display_list_layer.h" #include "flutter/flow/layers/image_filter_layer.h" #include "flutter/flow/layers/layer.h" -#include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/layers/opacity_layer.h" #include "flutter/flow/layers/performance_overlay_layer.h" #include "flutter/flow/layers/platform_view_layer.h" @@ -23,13 +22,10 @@ #include "flutter/flow/layers/texture_layer.h" #include "flutter/flow/layers/transform_layer.h" #include "flutter/fml/build_config.h" +#include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/floating_point.h" #include "flutter/lib/ui/painting/matrix.h" #include "flutter/lib/ui/painting/shader.h" -#include "third_party/tonic/converter/dart_converter.h" -#include "third_party/tonic/dart_args.h" -#include "third_party/tonic/dart_binding_macros.h" -#include "third_party/tonic/dart_library_natives.h" namespace flutter { @@ -45,7 +41,7 @@ SceneBuilder::~SceneBuilder() = default; void SceneBuilder::pushTransform(Dart_Handle layer_handle, tonic::Float64List& matrix4, - const fml::RefPtr& oldLayer) { + const fml::RefPtr& old_layer) { SkM44 sk_matrix = ToSkM44(matrix4); auto layer = std::make_shared(sk_matrix); PushLayer(layer); @@ -53,22 +49,22 @@ void SceneBuilder::pushTransform(Dart_Handle layer_handle, matrix4.Release(); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } void SceneBuilder::pushOffset(Dart_Handle layer_handle, double dx, double dy, - const fml::RefPtr& oldLayer) { + const fml::RefPtr& old_layer) { SkMatrix sk_matrix = SkMatrix::Translate(SafeNarrow(dx), SafeNarrow(dy)); auto layer = std::make_shared(sk_matrix); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } @@ -77,49 +73,48 @@ void SceneBuilder::pushClipRect(Dart_Handle layer_handle, double right, double top, double bottom, - int clipBehavior, - const fml::RefPtr& oldLayer) { - SkRect clipRect = SkRect::MakeLTRB(SafeNarrow(left), SafeNarrow(top), - SafeNarrow(right), SafeNarrow(bottom)); - flutter::Clip clip_behavior = static_cast(clipBehavior); - auto layer = - std::make_shared(clipRect, clip_behavior); + int clip_behavior, + const fml::RefPtr& old_layer) { + SkRect clip_rect = SkRect::MakeLTRB(SafeNarrow(left), SafeNarrow(top), + SafeNarrow(right), SafeNarrow(bottom)); + auto layer = std::make_shared( + clip_rect, static_cast(clip_behavior)); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } void SceneBuilder::pushClipRRect(Dart_Handle layer_handle, const RRect& rrect, - int clipBehavior, - const fml::RefPtr& oldLayer) { - flutter::Clip clip_behavior = static_cast(clipBehavior); - auto layer = - std::make_shared(rrect.sk_rrect, clip_behavior); + int clip_behavior, + const fml::RefPtr& old_layer) { + auto layer = std::make_shared( + rrect.sk_rrect, static_cast(clip_behavior)); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } void SceneBuilder::pushClipPath(Dart_Handle layer_handle, const CanvasPath* path, - int clipBehavior, - const fml::RefPtr& oldLayer) { - flutter::Clip clip_behavior = static_cast(clipBehavior); - FML_DCHECK(clip_behavior != flutter::Clip::kNone); - auto layer = - std::make_shared(path->path(), clip_behavior); + int clip_behavior, + const fml::RefPtr& old_layer) { + flutter::Clip flutter_clip_behavior = + static_cast(clip_behavior); + FML_DCHECK(flutter_clip_behavior != flutter::Clip::kNone); + auto layer = std::make_shared( + path->path(), static_cast(flutter_clip_behavior)); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } @@ -127,27 +122,27 @@ void SceneBuilder::pushOpacity(Dart_Handle layer_handle, int alpha, double dx, double dy, - const fml::RefPtr& oldLayer) { + const fml::RefPtr& old_layer) { auto layer = std::make_shared( alpha, SkPoint::Make(SafeNarrow(dx), SafeNarrow(dy))); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } void SceneBuilder::pushColorFilter(Dart_Handle layer_handle, const ColorFilter* color_filter, - const fml::RefPtr& oldLayer) { + const fml::RefPtr& old_layer) { auto layer = std::make_shared(color_filter->filter()); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } @@ -155,65 +150,66 @@ void SceneBuilder::pushImageFilter(Dart_Handle layer_handle, const ImageFilter* image_filter, double dx, double dy, - const fml::RefPtr& oldLayer) { + const fml::RefPtr& old_layer) { auto layer = std::make_shared( image_filter->filter(), SkPoint::Make(SafeNarrow(dx), SafeNarrow(dy))); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } void SceneBuilder::pushBackdropFilter( Dart_Handle layer_handle, ImageFilter* filter, - int blendMode, - Dart_Handle backdropId, - const fml::RefPtr& oldLayer) { - std::optional backdrop_id; - if (Dart_IsInteger(backdropId)) { + int blend_mode, + Dart_Handle backdrop_id, + const fml::RefPtr& old_layer) { + std::optional converted_backdrop_id; + if (Dart_IsInteger(backdrop_id)) { int64_t out; - Dart_IntegerToInt64(backdropId, &out); - backdrop_id = out; + Dart_IntegerToInt64(backdrop_id, &out); + converted_backdrop_id = out; } auto layer = std::make_shared( - filter->filter(), static_cast(blendMode), backdrop_id); + filter->filter(), static_cast(blend_mode), + converted_backdrop_id); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } void SceneBuilder::pushShaderMask(Dart_Handle layer_handle, Shader* shader, - double maskRectLeft, - double maskRectRight, - double maskRectTop, - double maskRectBottom, - int blendMode, - int filterQualityIndex, - const fml::RefPtr& oldLayer) { + double mask_rect_left, + double mask_rect_right, + double mask_rect_top, + double mask_Rect_bottom, + int blend_mode, + int filter_quality_index, + const fml::RefPtr& old_layer) { SkRect rect = - SkRect::MakeLTRB(SafeNarrow(maskRectLeft), SafeNarrow(maskRectTop), - SafeNarrow(maskRectRight), SafeNarrow(maskRectBottom)); - auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); + SkRect::MakeLTRB(SafeNarrow(mask_rect_right), SafeNarrow(mask_rect_right), + SafeNarrow(mask_rect_top), SafeNarrow(mask_Rect_bottom)); + auto sampling = ImageFilter::SamplingFromIndex(filter_quality_index); auto layer = std::make_shared( - shader->shader(sampling), rect, static_cast(blendMode)); + shader->shader(sampling), rect, static_cast(blend_mode)); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer); - if (oldLayer && oldLayer->Layer()) { - layer->AssignOldLayer(oldLayer->Layer().get()); + if (old_layer && old_layer->Layer()) { + layer->AssignOldLayer(old_layer->Layer().get()); } } -void SceneBuilder::addRetained(const fml::RefPtr& retainedLayer) { - AddLayer(retainedLayer->Layer()); +void SceneBuilder::addRetained(const fml::RefPtr& retained_layer) { + AddLayer(retained_layer->Layer()); } void SceneBuilder::pop() { @@ -243,13 +239,13 @@ void SceneBuilder::addTexture(double dx, double dy, double width, double height, - int64_t textureId, + int64_t texture_id, bool freeze, - int filterQualityIndex) { - auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); + int filter_quality_index) { + auto sampling = ImageFilter::SamplingFromIndex(filter_quality_index); auto layer = std::make_unique( SkPoint::Make(SafeNarrow(dx), SafeNarrow(dy)), - SkSize::Make(SafeNarrow(width), SafeNarrow(height)), textureId, freeze, + SkSize::Make(SafeNarrow(width), SafeNarrow(height)), texture_id, freeze, sampling); AddLayer(std::move(layer)); } @@ -258,14 +254,14 @@ void SceneBuilder::addPlatformView(double dx, double dy, double width, double height, - int64_t viewId) { + int64_t view_id) { auto layer = std::make_unique( SkPoint::Make(SafeNarrow(dx), SafeNarrow(dy)), - SkSize::Make(SafeNarrow(width), SafeNarrow(height)), viewId); + SkSize::Make(SafeNarrow(width), SafeNarrow(height)), view_id); AddLayer(std::move(layer)); } -void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, +void SceneBuilder::addPerformanceOverlay(uint64_t enabled_options, double left, double right, double top, @@ -273,7 +269,7 @@ void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, SkRect rect = SkRect::MakeLTRB(SafeNarrow(left), SafeNarrow(top), SafeNarrow(right), SafeNarrow(bottom)); auto layer = - std::make_unique(enabledOptions); + std::make_unique(enabled_options); layer->set_paint_bounds(rect); AddLayer(std::move(layer)); } diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index e9b3a41f1c833..717129a6fd27f 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -10,7 +10,6 @@ #include #include "flutter/flow/layers/container_layer.h" -#include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/dart_wrapper.h" #include "flutter/lib/ui/painting/color_filter.h" #include "flutter/lib/ui/painting/engine_layer.h" @@ -38,65 +37,65 @@ class SceneBuilder : public RefCountedDartWrappable { void pushTransformHandle(Dart_Handle layer_handle, Dart_Handle matrix4_handle, - const fml::RefPtr& oldLayer) { + const fml::RefPtr& old_layer) { tonic::Float64List matrix4(matrix4_handle); - pushTransform(layer_handle, matrix4, oldLayer); + pushTransform(layer_handle, matrix4, old_layer); } void pushTransform(Dart_Handle layer_handle, tonic::Float64List& matrix4, - const fml::RefPtr& oldLayer); + const fml::RefPtr& old_layer); void pushOffset(Dart_Handle layer_handle, double dx, double dy, - const fml::RefPtr& oldLayer); + const fml::RefPtr& old_layer); void pushClipRect(Dart_Handle layer_handle, double left, double right, double top, double bottom, - int clipBehavior, - const fml::RefPtr& oldLayer); + int clip_behavior, + const fml::RefPtr& old_layer); void pushClipRRect(Dart_Handle layer_handle, const RRect& rrect, - int clipBehavior, - const fml::RefPtr& oldLayer); + int clip_behavior, + const fml::RefPtr& old_layer); void pushClipPath(Dart_Handle layer_handle, const CanvasPath* path, - int clipBehavior, - const fml::RefPtr& oldLayer); + int clip_behavior, + const fml::RefPtr& old_layer); void pushOpacity(Dart_Handle layer_handle, int alpha, double dx, double dy, - const fml::RefPtr& oldLayer); + const fml::RefPtr& old_layer); void pushColorFilter(Dart_Handle layer_handle, const ColorFilter* color_filter, - const fml::RefPtr& oldLayer); + const fml::RefPtr& old_layer); void pushImageFilter(Dart_Handle layer_handle, const ImageFilter* image_filter, double dx, double dy, - const fml::RefPtr& oldLayer); + const fml::RefPtr& old_layer); void pushBackdropFilter(Dart_Handle layer_handle, ImageFilter* filter, - int blendMode, - Dart_Handle backdropId, - const fml::RefPtr& oldLayer); + int blend_mode, + Dart_Handle backdrop_id, + const fml::RefPtr& old_layer); void pushShaderMask(Dart_Handle layer_handle, Shader* shader, - double maskRectLeft, - double maskRectRight, - double maskRectTop, - double maskRectBottom, - int blendMode, - int filterQualityIndex, - const fml::RefPtr& oldLayer); + double mask_rect_left, + double mask_rect_right, + double mask_rect_top, + double mask_rect_bottom, + int blend_mode, + int filter_quality_index, + const fml::RefPtr& old_layer); - void addRetained(const fml::RefPtr& retainedLayer); + void addRetained(const fml::RefPtr& retained_layer); void pop(); - void addPerformanceOverlay(uint64_t enabledOptions, + void addPerformanceOverlay(uint64_t enabled_options, double left, double right, double top, @@ -108,15 +107,15 @@ class SceneBuilder : public RefCountedDartWrappable { double dy, double width, double height, - int64_t textureId, + int64_t texture_id, bool freeze, - int filterQuality); + int filter_quality); void addPlatformView(double dx, double dy, double width, double height, - int64_t viewId); + int64_t view_id); void build(Dart_Handle scene_handle); diff --git a/lib/ui/compositing/scene_builder_unittests.cc b/lib/ui/compositing/scene_builder_unittests.cc index 702d83bf61417..cbd2a3bfbb946 100644 --- a/lib/ui/compositing/scene_builder_unittests.cc +++ b/lib/ui/compositing/scene_builder_unittests.cc @@ -12,6 +12,7 @@ #include "flutter/shell/common/shell_test.h" #include "flutter/shell/common/thread_host.h" #include "flutter/testing/testing.h" +#include "lib/ui/compositing/scene.h" // CREATE_NATIVE_ENTRY is leaky by design // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape) From 959efc8a94daceeebcf0edfe86cda84df65ebd90 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 17:13:22 -0700 Subject: [PATCH 17/20] web ui changes. --- impeller/display_list/canvas.h | 2 +- impeller/display_list/dl_dispatcher.cc | 9 ++++++--- lib/web_ui/lib/compositing.dart | 1 + .../lib/src/engine/canvaskit/layer_scene_builder.dart | 1 + lib/web_ui/lib/src/engine/html/scene_builder.dart | 1 + lib/web_ui/lib/src/engine/scene_builder.dart | 3 ++- 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/impeller/display_list/canvas.h b/impeller/display_list/canvas.h index 745cd3dc9eda7..f856c8caa47cb 100644 --- a/impeller/display_list/canvas.h +++ b/impeller/display_list/canvas.h @@ -37,7 +37,7 @@ struct BackdropData { // A single snapshot of the backdrop filter that is used when there are // multiple backdrops that share an identical filter. std::optional shared_filter_snapshot; - const flutter::DlImageFilter* last_backdrop = nullptr; + std::shared_ptr last_backdrop; }; struct CanvasStackEntry { diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index aa7b84c637e73..895a4eb103cad 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -11,6 +11,7 @@ #include #include "display_list/effects/dl_color_source.h" +#include "display_list/effects/dl_image_filter.h" #include "flutter/fml/logging.h" #include "impeller/core/formats.h" #include "impeller/display_list/aiks_context.h" @@ -1006,17 +1007,19 @@ void TextFrameDispatcher::saveLayer(const DlRect& bounds, save(); if (backdrop != nullptr && backdrop_id.has_value()) { + std::shared_ptr shared_backdrop = + backdrop->shared(); std::unordered_map::iterator existing = backdrop_data_.find(backdrop_id.value()); if (existing == backdrop_data_.end()) { backdrop_data_[backdrop_id.value()] = - BackdropData{.backdrop_count = 1, .last_backdrop = backdrop}; + BackdropData{.backdrop_count = 1, .last_backdrop = shared_backdrop}; } else { BackdropData& data = existing->second; data.backdrop_count++; if (data.all_filters_equal) { - data.all_filters_equal = (*data.last_backdrop == *backdrop); - data.last_backdrop = backdrop; + data.all_filters_equal = (*data.last_backdrop == *shared_backdrop); + data.last_backdrop = shared_backdrop; } } } diff --git a/lib/web_ui/lib/compositing.dart b/lib/web_ui/lib/compositing.dart index 09a4d25300be2..2f0d558f5bb34 100644 --- a/lib/web_ui/lib/compositing.dart +++ b/lib/web_ui/lib/compositing.dart @@ -76,6 +76,7 @@ abstract class SceneBuilder { ImageFilter filter, { BlendMode blendMode = BlendMode.srcOver, BackdropFilterEngineLayer? oldLayer, + int? backdropId, }); ShaderMaskEngineLayer pushShaderMask( Shader shader, diff --git a/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart b/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart index 183180e8a21d2..d2f34bc6a01c8 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart @@ -110,6 +110,7 @@ class LayerSceneBuilder implements ui.SceneBuilder { ui.ImageFilter filter, { ui.BlendMode blendMode = ui.BlendMode.srcOver, ui.EngineLayer? oldLayer, + int? backdropId, }) { return pushLayer(BackdropFilterEngineLayer( filter, diff --git a/lib/web_ui/lib/src/engine/html/scene_builder.dart b/lib/web_ui/lib/src/engine/html/scene_builder.dart index ff63108231e6e..88644adc0529a 100644 --- a/lib/web_ui/lib/src/engine/html/scene_builder.dart +++ b/lib/web_ui/lib/src/engine/html/scene_builder.dart @@ -240,6 +240,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.ImageFilter filter, { ui.BlendMode blendMode = ui.BlendMode.srcOver, ui.BackdropFilterEngineLayer? oldLayer, + int? backdropId, }) { return _pushSurface(PersistedBackdropFilter( oldLayer as PersistedBackdropFilter?, filter)); diff --git a/lib/web_ui/lib/src/engine/scene_builder.dart b/lib/web_ui/lib/src/engine/scene_builder.dart index af84cb00990c6..37d29e66f7fdd 100644 --- a/lib/web_ui/lib/src/engine/scene_builder.dart +++ b/lib/web_ui/lib/src/engine/scene_builder.dart @@ -131,7 +131,8 @@ class EngineSceneBuilder implements ui.SceneBuilder { ui.BackdropFilterEngineLayer pushBackdropFilter( ui.ImageFilter filter, { ui.BlendMode blendMode = ui.BlendMode.srcOver, - ui.BackdropFilterEngineLayer? oldLayer + ui.BackdropFilterEngineLayer? oldLayer, + int? backdropId, }) => pushLayer( BackdropFilterLayer(), BackdropFilterOperation(filter, blendMode), From 05b24dba9ea3afdac41ee56eb9dea7da6a1e02f4 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 19:48:25 -0700 Subject: [PATCH 18/20] fix param order. --- lib/ui/compositing.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 32a25885f6cf6..d8684270486e6 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -423,8 +423,8 @@ abstract class SceneBuilder { BackdropFilterEngineLayer pushBackdropFilter( ImageFilter filter, { BlendMode blendMode = BlendMode.srcOver, - int? backdropId, BackdropFilterEngineLayer? oldLayer, + int? backdropId, }); /// Pushes a shader mask operation onto the operation stack. From 11ab30b02a37271743f165abd076deb071284a63 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 14 Oct 2024 21:54:02 -0700 Subject: [PATCH 19/20] ++ --- testing/impeller_golden_tests_output.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index 0979bbc406399..d7686267f6c29 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -254,6 +254,9 @@ impeller_Play_AiksTest_CanRenderBackdropBlurHugeSigma_Vulkan.png impeller_Play_AiksTest_CanRenderBackdropBlurInteractive_Metal.png impeller_Play_AiksTest_CanRenderBackdropBlurInteractive_OpenGLES.png impeller_Play_AiksTest_CanRenderBackdropBlurInteractive_Vulkan.png +impeller_Play_AiksTest_CanRenderBackdropBlurWithSingleBackdropId_Metal.png +impeller_Play_AiksTest_CanRenderBackdropBlurWithSingleBackdropId_OpenGLES.png +impeller_Play_AiksTest_CanRenderBackdropBlurWithSingleBackdropId_Vulkan.png impeller_Play_AiksTest_CanRenderBackdropBlur_Metal.png impeller_Play_AiksTest_CanRenderBackdropBlur_OpenGLES.png impeller_Play_AiksTest_CanRenderBackdropBlur_Vulkan.png @@ -382,6 +385,15 @@ impeller_Play_AiksTest_CanRenderLinearGradientWithOverlappingStopsClamp_Vulkan.p impeller_Play_AiksTest_CanRenderMaskBlurHugeSigma_Metal.png impeller_Play_AiksTest_CanRenderMaskBlurHugeSigma_OpenGLES.png impeller_Play_AiksTest_CanRenderMaskBlurHugeSigma_Vulkan.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters_Metal.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters_OpenGLES.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters_Vulkan.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers_Metal.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers_OpenGLES.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers_Vulkan.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropId_Metal.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropId_OpenGLES.png +impeller_Play_AiksTest_CanRenderMultipleBackdropBlurWithSingleBackdropId_Vulkan.png impeller_Play_AiksTest_CanRenderNestedClips_Metal.png impeller_Play_AiksTest_CanRenderNestedClips_OpenGLES.png impeller_Play_AiksTest_CanRenderNestedClips_Vulkan.png From 9d16bb5f5b41d55b2ba4aab31865ad0fbd09cfd2 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 17 Oct 2024 15:42:59 -0700 Subject: [PATCH 20/20] Update canvas.cc --- impeller/display_list/canvas.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/display_list/canvas.cc b/impeller/display_list/canvas.cc index 41d5faf4bfac0..f052634de5b58 100644 --- a/impeller/display_list/canvas.cc +++ b/impeller/display_list/canvas.cc @@ -1130,7 +1130,7 @@ void Canvas::SaveLayer(const Paint& paint, // layer once. if (backdrop_data->all_filters_equal && !backdrop_data->shared_filter_snapshot.has_value()) { - // TODO(jonahwilliams): compute minimum input hint. + // TODO(157110): compute minimum input hint. backdrop_data->shared_filter_snapshot = backdrop_filter_contents->RenderToSnapshot(renderer_, {}); }