Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit accee82

Browse files
bderoharryterkelsen
authored andcommitted
[Impeller] Ensure that reused textures are cleared before getting sampled by backdrop textures (#46084)
Fix for flutter/flutter#135053. I'm going to try and optimize out this case later, since Wondrous is inadvertently paying for a backdrop filter that contributes nothing to the final image.
1 parent 1314541 commit accee82

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

impeller/aiks/aiks_unittests.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,30 @@ TEST_P(AiksTest, DrawPaintAbsorbsClears) {
22642264
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
22652265
}
22662266

2267+
// This is important to enforce with texture reuse, since cached textures need
2268+
// to be cleared before reuse.
2269+
TEST_P(AiksTest,
2270+
ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent) {
2271+
Canvas canvas;
2272+
canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
2273+
canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2274+
canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2275+
.blend_mode = BlendMode::kSourceOver});
2276+
canvas.Restore();
2277+
2278+
Picture picture = canvas.EndRecordingAsPicture();
2279+
2280+
std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2281+
std::shared_ptr<Context> real_context = GetContext();
2282+
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2283+
AiksContext renderer(mock_context, nullptr);
2284+
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2285+
2286+
ASSERT_EQ(spy->render_passes_.size(), 3llu);
2287+
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2288+
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2289+
}
2290+
22672291
TEST_P(AiksTest, DrawRectAbsorbsClears) {
22682292
Canvas canvas;
22692293
canvas.DrawRect({0, 0, 300, 300},

impeller/entity/entity_pass.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,14 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
534534
proc(FilterInput::Make(std::move(texture)),
535535
subpass->xformation_.Basis(), Entity::RenderingMode::kSubpass);
536536

537+
// If the very first thing we render in this EntityPass is a subpass that
538+
// happens to have a backdrop filter, than that backdrop filter will end
539+
// may wind up sampling from the raw, uncleared texture that came straight
540+
// out of the texture cache. By calling `pass_context.GetRenderPass` here,
541+
// we force the texture to pass through at least one RenderPass with the
542+
// correct clear configuration before any sampling occurs.
543+
pass_context.GetRenderPass(pass_depth);
544+
537545
// The subpass will need to read from the current pass texture when
538546
// rendering the backdrop, so if there's an active pass, end it prior to
539547
// rendering the subpass.

0 commit comments

Comments
 (0)