diff --git a/engine/src/flutter/impeller/aiks/aiks_unittests.cc b/engine/src/flutter/impeller/aiks/aiks_unittests.cc index 32e9bfc7f07..a34a9892387 100644 --- a/engine/src/flutter/impeller/aiks/aiks_unittests.cc +++ b/engine/src/flutter/impeller/aiks/aiks_unittests.cc @@ -2322,6 +2322,27 @@ TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, CanRenderClippedBlur) { + Canvas canvas; + canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400)); + canvas.DrawCircle( + {400, 400}, 200, + { + .color = Color::Green(), + .image_filter = + [](const FilterInput::Ref& input, const Matrix& effect_transform, + bool is_subpass) { + return FilterContents::MakeGaussianBlur( + input, Sigma(20), Sigma(20), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp, effect_transform); + }, + }); + canvas.Restore(); + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + // Regression test for https://github.com/flutter/flutter/issues/126701 . TEST_P(AiksTest, CanRenderClippedRuntimeEffects) { if (GetParam() != PlaygroundBackend::kMetal) { diff --git a/engine/src/flutter/impeller/entity/entity_pass.cc b/engine/src/flutter/impeller/entity/entity_pass.cc index 88622975f02..b929ab54d52 100644 --- a/engine/src/flutter/impeller/entity/entity_pass.cc +++ b/engine/src/flutter/impeller/entity/entity_pass.cc @@ -615,6 +615,12 @@ bool EntityPass::OnRender( stencil_coverage.coverage->origin += global_pass_position; } + // The coverage hint tells the rendered Contents which portion of the + // rendered output will actually be used, and so we set this to the current + // stencil coverage (which is the max clip bounds). The contents may + // optionally use this hint to avoid unnecessary rendering work. + element_entity.GetContents()->SetCoverageHint(current_stencil_coverage); + switch (stencil_coverage.type) { case Contents::StencilCoverage::Type::kNoChange: break; @@ -685,17 +691,6 @@ bool EntityPass::OnRender( return false; } - // Tell the backdrop contents which portion of the rendered output will - // actually be used. The contents may optionally use this hint to avoid - // unnecessary rendering work. - if (!stencil_coverage_stack.empty() && - stencil_coverage_stack.back().coverage.has_value()) { - auto coverage_hint = Rect( - stencil_coverage_stack.back().coverage->origin - global_pass_position, - stencil_coverage_stack.back().coverage->size); - backdrop_filter_contents->SetCoverageHint(coverage_hint); - } - Entity backdrop_entity; backdrop_entity.SetContents(std::move(backdrop_filter_contents)); backdrop_entity.SetTransformation(