From 10f47afe4b68287ac2ddf5881863ce525242bc51 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 22 Mar 2023 19:46:05 -0700 Subject: [PATCH] [impeller] dont apply opacity peephole on image/color filters (flutter/engine#40551) [impeller] dont apply opacity peephole on image/color filters --- .../flutter/impeller/aiks/aiks_unittests.cc | 46 +++++++++++++++++++ .../impeller/aiks/paint_pass_delegate.cc | 5 ++ 2 files changed, 51 insertions(+) diff --git a/engine/src/flutter/impeller/aiks/aiks_unittests.cc b/engine/src/flutter/impeller/aiks/aiks_unittests.cc index 50d09c9464d..5f6ea3416e7 100644 --- a/engine/src/flutter/impeller/aiks/aiks_unittests.cc +++ b/engine/src/flutter/impeller/aiks/aiks_unittests.cc @@ -15,9 +15,11 @@ #include "impeller/aiks/aiks_playground.h" #include "impeller/aiks/canvas.h" #include "impeller/aiks/image.h" +#include "impeller/aiks/paint_pass_delegate.h" #include "impeller/entity/contents/color_source_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/contents/scene_contents.h" +#include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/contents/tiled_texture_contents.h" #include "impeller/geometry/color.h" #include "impeller/geometry/constants.h" @@ -1947,5 +1949,49 @@ TEST_P(AiksTest, PaintWithFilters) { ASSERT_FALSE(paint.HasColorFilter()); } +TEST_P(AiksTest, OpacityPeepHoleApplicationTest) { + auto entity_pass = std::make_shared(); + auto rect = Rect::MakeLTRB(0, 0, 100, 100); + Paint paint; + paint.color = Color::White().WithAlpha(0.5); + paint.color_filter = [](FilterInput::Ref input) { + return ColorFilterContents::MakeBlend(BlendMode::kSourceOver, + {std::move(input)}, Color::Blue()); + }; + + // Paint has color filter, can't elide. + auto delegate = std::make_shared(paint, rect); + ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get())); + + paint.color_filter = std::nullopt; + paint.image_filter = [](const FilterInput::Ref& input, + const Matrix& effect_transform, bool is_subpass) { + return FilterContents::MakeGaussianBlur( + input, Sigma(1.0), Sigma(1.0), FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp, effect_transform); + }; + + // Paint has image filter, can't elide. + delegate = std::make_shared(paint, rect); + ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get())); + + paint.image_filter = std::nullopt; + paint.color = Color::Red(); + + // Paint has no alpha, can't elide; + delegate = std::make_shared(paint, rect); + ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get())); + + // Positive test. + Entity entity; + entity.SetContents(SolidColorContents::Make( + PathBuilder{}.AddRect(rect).TakePath(), Color::Red())); + entity_pass->AddEntity(entity); + paint.color = Color::Red().WithAlpha(0.5); + + delegate = std::make_shared(paint, rect); + ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get())); +} + } // namespace testing } // namespace impeller diff --git a/engine/src/flutter/impeller/aiks/paint_pass_delegate.cc b/engine/src/flutter/impeller/aiks/paint_pass_delegate.cc index cbe66f7c625..c308a7fadbd 100644 --- a/engine/src/flutter/impeller/aiks/paint_pass_delegate.cc +++ b/engine/src/flutter/impeller/aiks/paint_pass_delegate.cc @@ -72,6 +72,11 @@ bool OpacityPeepholePassDelegate::CanElide() { // |EntityPassDelgate| bool OpacityPeepholePassDelegate::CanCollapseIntoParentPass( EntityPass* entity_pass) { + if (paint_.color.alpha <= 0.0 || paint_.color.alpha >= 1.0 || + paint_.image_filter.has_value() || paint_.color_filter.has_value()) { + return false; + } + // Note: determing whether any coverage intersects has quadradic complexity in // the number of rectangles, and depending on whether or not we cache at // different levels of the entity tree may end up cubic. In the interest of