[Impeller] Use BlackTransparent clear color when backdrop filters are present. (flutter/engine#46085)

Fix for https://github.com/flutter/flutter/issues/135053.

We already duck out of the Entity absorbing part of the optimization,
but we also need to duck here when computing clear colors, otherwise we
end up double-applying the effect of clearing entities at the beginning
of a pass in some cases.
This commit is contained in:
Brandon DeRosier 2023-09-20 01:13:37 -04:00 committed by GitHub
parent c7ea36f2c5
commit 2bc09e284c
2 changed files with 33 additions and 0 deletions

View File

@ -2368,6 +2368,35 @@ TEST_P(AiksTest, ClipRectElidesNoOpClips) {
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
}
TEST_P(AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters) {
Canvas canvas;
canvas.SaveLayer({}, std::nullopt,
ImageFilter::MakeBlur(Sigma(3), Sigma(3),
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp));
canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});
canvas.Restore();
Picture picture = canvas.EndRecordingAsPicture();
std::optional<Color> actual_color;
picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
actual_color = subpass->get()->GetClearColor();
}
// Fail if the first element isn't a subpass.
return true;
});
ASSERT_TRUE(actual_color.has_value());
if (!actual_color) {
return;
}
ASSERT_EQ(actual_color.value(), Color::BlackTransparent());
}
TEST_P(AiksTest, CollapsedDrawPaintInSubpass) {
Canvas canvas;
canvas.DrawPaint(

View File

@ -1091,6 +1091,10 @@ void EntityPass::SetBlendMode(BlendMode blend_mode) {
Color EntityPass::GetClearColor(ISize target_size) const {
Color result = Color::BlackTransparent();
if (backdrop_filter_proc_) {
return result;
}
for (const Element& element : elements_) {
auto [entity_color, blend_mode] =
ElementAsBackgroundColor(element, target_size);