From 939a6a4eb0e24f50247aa4bed4ea9211ab07b968 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 30 Nov 2023 21:20:59 -0800 Subject: [PATCH] [Impeller] Provide the clear color to an advanced blend if it was optimized out If all previous elements were skipped due to clear color optimization, then the clear color must be provided as the foreground to the advanced blend if framebuffer fetch is not available. --- impeller/aiks/aiks_unittests.cc | 12 ++++++++++++ impeller/entity/entity_pass.cc | 17 +++++++++++++++-- impeller/entity/entity_unittests.cc | 9 +++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) 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));