diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_basic_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_basic_unittests.cc index b396895a95..26e8b07029 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_basic_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_basic_unittests.cc @@ -1592,5 +1592,33 @@ TEST_P(AiksTest, NoDimplesInRRectPath) { ASSERT_TRUE(OpenPlaygroundHere(callback)); } +TEST_P(AiksTest, BackdropFilterOverUnclosedClip) { + DisplayListBuilder builder; + + builder.DrawPaint(DlPaint().setColor(DlColor::kWhite())); + builder.Save(); + { + builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800)); + + builder.Save(); + { + builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800)); + builder.DrawPaint(DlPaint().setColor(DlColor::kRed())); + builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5))); + builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800)); + builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5))); + } + builder.Restore(); + + auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal); + builder.SaveLayer(std::nullopt, nullptr, image_filter.get()); + } + builder.Restore(); + builder.DrawCircle(SkPoint{100, 100}, 100, + DlPaint().setColor(DlColor::kAqua())); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + } // namespace testing } // namespace impeller diff --git a/engine/src/flutter/impeller/display_list/canvas.cc b/engine/src/flutter/impeller/display_list/canvas.cc index 133e8c5f03..026cf41044 100644 --- a/engine/src/flutter/impeller/display_list/canvas.cc +++ b/engine/src/flutter/impeller/display_list/canvas.cc @@ -1662,6 +1662,10 @@ std::shared_ptr Canvas::FlipBackdrop(Point global_pass_position, // applied. auto& replay_entities = clip_coverage_stack_.GetReplayEntities(); for (const auto& replay : replay_entities) { + if (replay.clip_depth <= current_depth_) { + continue; + } + SetClipScissor(replay.clip_coverage, current_render_pass, global_pass_position); if (!replay.clip_contents.Render(renderer_, current_render_pass, diff --git a/engine/src/flutter/impeller/entity/entity_pass_clip_stack.cc b/engine/src/flutter/impeller/entity/entity_pass_clip_stack.cc index 3a00fd8595..aacb65fb54 100644 --- a/engine/src/flutter/impeller/entity/entity_pass_clip_stack.cc +++ b/engine/src/flutter/impeller/entity/entity_pass_clip_stack.cc @@ -83,6 +83,9 @@ EntityPassClipStack::ClipStateResult EntityPassClipStack::RecordRestore( if (subpass_state.clip_coverage.back().coverage.has_value()) { FML_DCHECK(next_replay_index_ <= subpass_state.rendered_clip_entities.size()); + // https://github.com/flutter/flutter/issues/162172 + // This code is slightly wrong and should be popping more than one clip + // entry. if (!subpass_state.rendered_clip_entities.empty()) { subpass_state.rendered_clip_entities.pop_back(); diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index 875ea2e436..25d50268e0 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -3,6 +3,9 @@ impeller_GoldenTests_ConicalGradient.png impeller_Play_AiksTest_AdvancedBlendColorFilterWithDestinationOpacity_Metal.png impeller_Play_AiksTest_AdvancedBlendColorFilterWithDestinationOpacity_OpenGLES.png impeller_Play_AiksTest_AdvancedBlendColorFilterWithDestinationOpacity_Vulkan.png +impeller_Play_AiksTest_BackdropFilterOverUnclosedClip_Metal.png +impeller_Play_AiksTest_BackdropFilterOverUnclosedClip_OpenGLES.png +impeller_Play_AiksTest_BackdropFilterOverUnclosedClip_Vulkan.png impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_Metal.png impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_OpenGLES.png impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_Vulkan.png