diff --git a/impeller/display_list/canvas_unittests.cc b/impeller/display_list/canvas_unittests.cc index fc04272715977..2185c955d1ae6 100644 --- a/impeller/display_list/canvas_unittests.cc +++ b/impeller/display_list/canvas_unittests.cc @@ -4,7 +4,10 @@ #include +#include "display_list/dl_color.h" #include "display_list/dl_tile_mode.h" +#include "display_list/effects/dl_color_filter.h" +#include "display_list/effects/dl_color_source.h" #include "display_list/effects/dl_image_filter.h" #include "display_list/geometry/dl_geometry_types.h" #include "flutter/testing/testing.h" @@ -13,6 +16,8 @@ #include "impeller/core/texture_descriptor.h" #include "impeller/display_list/aiks_unittests.h" #include "impeller/display_list/canvas.h" +#include "impeller/display_list/dl_dispatcher.h" +#include "impeller/geometry/color.h" #include "impeller/geometry/geometry_asserts.h" #include "impeller/renderer/render_target.h" @@ -276,5 +281,80 @@ TEST_P(AiksTest, BackdropCountDownWithNestedSaveLayers) { EXPECT_TRUE(canvas->RequiresReadback()); } +TEST_P(AiksTest, PaintOpacityPeephole) { + { + Paint paint; + + EXPECT_TRUE(Paint::CanApplyOpacityPeephole(paint)); + } + + { + Paint paint; + paint.blend_mode = BlendMode::kColorBurn; + + EXPECT_FALSE(Paint::CanApplyOpacityPeephole(paint)); + } + + { + Paint paint; + paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{ + .sigma = Sigma(4), + .respect_ctm = true, + }; + + EXPECT_FALSE(Paint::CanApplyOpacityPeephole(paint)); + } + + { + auto image_filter = + flutter::DlBlurImageFilter::Make(1, 1, flutter::DlTileMode::kClamp); + Paint paint; + paint.image_filter = image_filter.get(); + + EXPECT_FALSE(Paint::CanApplyOpacityPeephole(paint)); + } + + { + auto color_filter = flutter::DlBlendColorFilter::Make( + flutter::DlColor::kRed(), flutter::DlBlendMode::kDarken); + Paint paint; + paint.color_filter = color_filter.get(); + + EXPECT_FALSE(Paint::CanApplyOpacityPeephole(paint)); + } + + { + std::vector colors = {flutter::DlColor::kRed(), + flutter::DlColor::kBlack()}; + std::vector stops = {0, 1}; + auto color_source = flutter::DlColorSource::MakeLinear( + SkPoint{0, 0}, SkPoint{100, 100}, 2, colors.data(), stops.data(), + flutter::DlTileMode::kClamp); + Paint paint; + paint.color_source = color_source.get(); + + EXPECT_TRUE(Paint::CanApplyOpacityPeephole(paint)); + } + + { + auto runtime_stages = + OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr"); + + auto runtime_stage = + runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]; + ASSERT_TRUE(runtime_stage); + + auto runtime_effect = flutter::DlRuntimeEffect::MakeImpeller(runtime_stage); + auto uniform_data = std::make_shared>(); + auto color_source = flutter::DlColorSource::MakeRuntimeEffect( + runtime_effect, {}, uniform_data); + + Paint paint; + paint.color_source = color_source.get(); + + EXPECT_FALSE(Paint::CanApplyOpacityPeephole(paint)); + } +} + } // namespace testing } // namespace impeller diff --git a/impeller/display_list/paint.cc b/impeller/display_list/paint.cc index 13bd681fe30fb..5e5a51e6ddb9e 100644 --- a/impeller/display_list/paint.cc +++ b/impeller/display_list/paint.cc @@ -11,6 +11,7 @@ #include "display_list/geometry/dl_path.h" #include "fml/logging.h" #include "impeller/display_list/color_filter.h" +#include "impeller/display_list/image_filter.h" #include "impeller/display_list/skia_conversions.h" #include "impeller/entity/contents/color_source_contents.h" #include "impeller/entity/contents/conical_gradient_contents.h" @@ -34,6 +35,22 @@ using DlRect = flutter::DlRect; using DlIRect = flutter::DlIRect; using DlPath = flutter::DlPath; +// static +bool Paint::CanApplyOpacityPeephole(const Paint& paint) { + if (paint.blend_mode != BlendMode::kSourceOver) { + return false; + } + if (paint.invert_colors || paint.mask_blur_descriptor.has_value() || + paint.image_filter || paint.color_filter) { + return false; + } + if (paint.color_source && paint.color_source->type() == + flutter::DlColorSourceType::kRuntimeEffect) { + return false; + } + return true; +} + std::shared_ptr Paint::CreateContents() const { if (color_source == nullptr) { auto contents = std::make_shared(); diff --git a/impeller/display_list/paint.h b/impeller/display_list/paint.h index 830b72673bac7..3beb387633649 100644 --- a/impeller/display_list/paint.h +++ b/impeller/display_list/paint.h @@ -10,15 +10,12 @@ #include "display_list/effects/dl_color_filter.h" #include "display_list/effects/dl_color_source.h" #include "display_list/effects/dl_image_filter.h" -#include "impeller/display_list/color_filter.h" -#include "impeller/display_list/image_filter.h" #include "impeller/entity/contents/color_source_contents.h" #include "impeller/entity/contents/contents.h" #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" -#include "impeller/entity/geometry/geometry.h" #include "impeller/geometry/color.h" namespace impeller { @@ -36,12 +33,7 @@ struct Paint { /// @brief Whether or not a save layer with the provided paint can perform the /// opacity peephole optimization. - static bool CanApplyOpacityPeephole(const Paint& paint) { - return paint.blend_mode == BlendMode::kSourceOver && - paint.invert_colors == false && - !paint.mask_blur_descriptor.has_value() && - paint.image_filter == nullptr && paint.color_filter == nullptr; - } + static bool CanApplyOpacityPeephole(const Paint& paint); enum class Style { kFill,