diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 81fabeb2f7033..31f62072c3c60 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -4249,5 +4249,17 @@ TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, AdvancedBlendWithClearColorOptimization) { + Canvas canvas; + canvas.DrawPaint( + {.color = {1.0, 1.0, 0.0, 1.0}, .blend_mode = BlendMode::kSource}); + + canvas.DrawRect( + Rect::MakeXYWH(0, 0, 200, 300), + {.color = {1.0, 0.0, 1.0, 1.0}, .blend_mode = BlendMode::kMultiply}); + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 3e68449b4cc29..4ac61827c2865 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -19,6 +19,7 @@ #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/contents/framebuffer_blend_contents.h" +#include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" #include "impeller/entity/inline_pass_context.h" @@ -877,6 +878,7 @@ bool EntityPass::OnRender( !backdrop_filter_proc_; for (const auto& element : elements_) { // Skip elements that are incorporated into the clear color. + bool was_collapsing_clear_colors = is_collapsing_clear_colors; if (is_collapsing_clear_colors) { auto [entity_color, _] = ElementAsBackgroundColor(element, clear_color_size); @@ -950,9 +952,20 @@ bool EntityPass::OnRender( FilterInput::Vector inputs = { FilterInput::Make(texture, result.entity.GetTransform().Invert()), FilterInput::Make(result.entity.GetContents())}; + std::optional foreground_color; + std::optional coverage; + if (was_collapsing_clear_colors) { + // If all previous elements were skipped due to clear color + // optimization, then provide the clear color as the foreground of the + // advanced blend. + foreground_color = GetClearColor(clear_color_size); + coverage = Rect::MakeSize(clear_color_size); + } else { + coverage = result.entity.GetCoverage(); + } auto contents = ColorFilterContents::MakeBlend( - result.entity.GetBlendMode(), inputs); - contents->SetCoverageHint(result.entity.GetCoverage()); + result.entity.GetBlendMode(), inputs, foreground_color); + contents->SetCoverageHint(coverage); result.entity.SetContents(std::move(contents)); result.entity.SetBlendMode(BlendMode::kSource); } diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 520f7a1c203b2..aca937bc1ebee 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -2443,6 +2443,14 @@ TEST_P(EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass) { "for advanced blends."; } + auto background_contents = std::make_shared(); + background_contents->SetGeometry( + Geometry::MakeRect(Rect::MakeXYWH(200, 200, 200, 200))); + background_contents->SetColor(Color::Blue()); + Entity background_entity; + background_entity.SetTransform(Matrix::MakeScale(Vector3(2, 2, 1))); + background_entity.SetContents(background_contents); + auto contents = std::make_shared(); contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100))); contents->SetColor(Color::Red()); @@ -2468,6 +2476,7 @@ TEST_P(EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass) { RenderTarget::kDefaultColorAttachmentConfig, stencil_config); auto content_context = ContentContext( GetContext(), TypographerContextSkia::Make(), test_allocator); + pass->AddEntity(std::move(background_entity)); pass->AddEntity(std::move(entity)); EXPECT_TRUE(pass->Render(content_context, rt));