[impeller] dont apply opacity peephole on image/color filters (flutter/engine#40551)

[impeller] dont apply opacity peephole on image/color filters
This commit is contained in:
Jonah Williams 2023-03-22 19:46:05 -07:00 committed by GitHub
parent 7b228c8b4b
commit 10f47afe4b
2 changed files with 51 additions and 0 deletions

View File

@ -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<EntityPass>();
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<OpacityPeepholePassDelegate>(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<OpacityPeepholePassDelegate>(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<OpacityPeepholePassDelegate>(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<OpacityPeepholePassDelegate>(paint, rect);
ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
}
} // namespace testing
} // namespace impeller

View File

@ -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