From ca24ee6bed14a6020311a28913c50277a0fb57a4 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 28 Sep 2023 16:40:25 -0700 Subject: [PATCH 01/10] [Impeller] Simplify invert colors. --- impeller/aiks/aiks_unittests.cc | 36 ++++++++++++++++++++++++-- impeller/aiks/canvas.cc | 1 + impeller/aiks/color_filter.cc | 36 ++++++++++++++++++++++++++ impeller/aiks/color_filter.h | 24 +++++++++++++++++ impeller/aiks/paint.cc | 24 ----------------- impeller/aiks/paint.h | 4 --- impeller/display_list/dl_dispatcher.cc | 36 +++++++++++++++++++------- 7 files changed, 121 insertions(+), 40 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 4950aae8496fc..fc845c4169ac4 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -13,6 +13,7 @@ #include "flutter/testing/testing.h" #include "impeller/aiks/aiks_playground.h" #include "impeller/aiks/canvas.h" +#include "impeller/aiks/color_filter.h" #include "impeller/aiks/image.h" #include "impeller/aiks/image_filter.h" #include "impeller/aiks/paint_pass_delegate.h" @@ -123,16 +124,47 @@ TEST_P(AiksTest, CanRenderImage) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -TEST_P(AiksTest, CanRenderInvertedImage) { +constexpr ColorMatrix kColorInversion = {.array = { + -1.0, 0, 0, 1.0, 0, // + 0, -1.0, 0, 1.0, 0, // + 0, 0, -1.0, 1.0, 0, // + 1.0, 1.0, 1.0, 1.0, 0 // + }}; + +TEST_P(AiksTest, CanRenderMergedColorFilterImage) { Canvas canvas; Paint paint; auto image = std::make_shared(CreateTextureForFixture("kalimba.jpg")); paint.color = Color::Red(); - paint.invert_colors = true; + paint.color_filter = std::make_shared( + ColorFilter::MakeMatrix(kColorInversion), + ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, CanRenderMergedColorFilter) { + Canvas canvas; + Paint paint; + paint.color = Color::Red(); + paint.color_filter = std::make_shared( + ColorFilter::MakeMatrix(kColorInversion), + ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); + canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + +TEST_P(AiksTest, CanRenderMergedColorFilterDrawPaint) { + Canvas canvas; + Paint paint; + paint.color = Color::Red(); + paint.color_filter = std::make_shared( + ColorFilter::MakeMatrix(kColorInversion), + ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); + canvas.DrawPaint(paint); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + namespace { bool GenerateMipmap(const std::shared_ptr& context, std::shared_ptr texture, diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index ae4c9d512037f..a3c7dd28a63c6 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -181,6 +181,7 @@ void Canvas::DrawPath(const Path& path, const Paint& paint) { } void Canvas::DrawPaint(const Paint& paint) { + FML_LOG(ERROR) << "Draw Paint"; Entity entity; entity.SetTransformation(GetCurrentTransformation()); entity.SetStencilDepth(GetStencilDepth()); diff --git a/impeller/aiks/color_filter.cc b/impeller/aiks/color_filter.cc index 87f7022e1cd1f..f4888779989d3 100644 --- a/impeller/aiks/color_filter.cc +++ b/impeller/aiks/color_filter.cc @@ -3,7 +3,10 @@ // found in the LICENSE file. #include "impeller/aiks/color_filter.h" + +#include #include "impeller/entity/contents/filters/color_filter_contents.h" +#include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/geometry/color.h" @@ -142,4 +145,37 @@ std::shared_ptr LinearToSrgbColorFilter::Clone() const { return std::make_shared(*this); } +/******************************************************************************* + ******* MergedColorFilter + ******************************************************************************/ + +MergedColorFilter::MergedColorFilter(std::shared_ptr outer, + std::shared_ptr inner) + : outer_(std::move(outer)), inner_(std::move(inner)) {} + +MergedColorFilter::~MergedColorFilter() = default; + +std::shared_ptr MergedColorFilter::WrapWithGPUColorFilter( + std::shared_ptr input, + ColorFilterContents::AbsorbOpacity absorb_opacity) const { + std::shared_ptr inner = inner_->WrapWithGPUColorFilter( + input, ColorFilterContents::AbsorbOpacity::kNo); + return outer_->WrapWithGPUColorFilter(FilterInput::Make(inner), + absorb_opacity); +} + +// |ColorFilter| +ColorFilter::ColorFilterProc MergedColorFilter::GetCPUColorFilterProc() const { + auto inner_proc = inner_->GetCPUColorFilterProc(); + auto outer_proc = outer_->GetCPUColorFilterProc(); + return [inner_proc, outer_proc](Color color) { + return outer_proc(inner_proc(color)); + }; +} + +// |ColorFilter| +std::shared_ptr MergedColorFilter::Clone() const { + return std::make_shared(outer_, inner_); +} + } // namespace impeller diff --git a/impeller/aiks/color_filter.h b/impeller/aiks/color_filter.h index 1c5bf32dd9f8a..2a6065ed97f66 100644 --- a/impeller/aiks/color_filter.h +++ b/impeller/aiks/color_filter.h @@ -147,4 +147,28 @@ class LinearToSrgbColorFilter final : public ColorFilter { std::shared_ptr Clone() const override; }; +/// @brief Applies color filters as f(g(x)), where x is the input color. +class MergedColorFilter final : public ColorFilter { + public: + explicit MergedColorFilter(std::shared_ptr outer_, + std::shared_ptr inner_); + + ~MergedColorFilter() override; + + // |ColorFilter| + std::shared_ptr WrapWithGPUColorFilter( + std::shared_ptr input, + ColorFilterContents::AbsorbOpacity absorb_opacity) const override; + + // |ColorFilter| + ColorFilterProc GetCPUColorFilterProc() const override; + + // |ColorFilter| + std::shared_ptr Clone() const override; + + private: + std::shared_ptr outer_; + std::shared_ptr inner_; +}; + } // namespace impeller diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index 66a3f7280f70a..f9651f31c0ee0 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -59,7 +59,6 @@ std::shared_ptr Paint::CreateContentsForGeometry( std::shared_ptr Paint::WithFilters( std::shared_ptr input) const { input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes); - input = WithInvertFilter(input); auto image_filter = WithImageFilter(input, Matrix(), Entity::RenderingMode::kDirect); if (image_filter) { @@ -121,33 +120,10 @@ std::shared_ptr Paint::WithColorFilter( if (input->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) { return input; } - return color_filter->WrapWithGPUColorFilter(FilterInput::Make(input), absorb_opacity); } -/// A color matrix which inverts colors. -// clang-format off -constexpr ColorMatrix kColorInversion = { - .array = { - -1.0, 0, 0, 1.0, 0, // - 0, -1.0, 0, 1.0, 0, // - 0, 0, -1.0, 1.0, 0, // - 1.0, 1.0, 1.0, 1.0, 0 // - } -}; -// clang-format on - -std::shared_ptr Paint::WithInvertFilter( - std::shared_ptr input) const { - if (!invert_colors) { - return input; - } - - return ColorFilterContents::MakeColorMatrix( - {FilterInput::Make(std::move(input))}, kColorInversion); -} - std::shared_ptr Paint::MaskBlurDescriptor::CreateMaskBlur( std::shared_ptr color_source_contents, const std::shared_ptr& color_filter) const { diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index c2e907a1cc5b0..0fba8a628d12b 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -61,7 +61,6 @@ struct Paint { Scalar stroke_miter = 4.0; Style style = Style::kFill; BlendMode blend_mode = BlendMode::kSourceOver; - bool invert_colors = false; std::shared_ptr image_filter; std::shared_ptr color_filter; @@ -108,9 +107,6 @@ struct Paint { std::shared_ptr input, ColorFilterContents::AbsorbOpacity absorb_opacity = ColorFilterContents::AbsorbOpacity::kNo) const; - - std::shared_ptr WithInvertFilter( - std::shared_ptr input) const; }; } // namespace impeller diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 0b19cefb5b79b..356d3acd7211f 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -16,20 +15,13 @@ #include "flutter/fml/trace_event.h" #include "impeller/aiks/color_filter.h" #include "impeller/core/formats.h" -#include "impeller/display_list/dl_image_impeller.h" #include "impeller/display_list/dl_vertices_geometry.h" #include "impeller/display_list/nine_patch_converter.h" #include "impeller/display_list/skia_conversions.h" -#include "impeller/entity/contents/conical_gradient_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" -#include "impeller/entity/contents/linear_gradient_contents.h" -#include "impeller/entity/contents/radial_gradient_contents.h" #include "impeller/entity/contents/runtime_effect_contents.h" -#include "impeller/entity/contents/sweep_gradient_contents.h" -#include "impeller/entity/contents/tiled_texture_contents.h" #include "impeller/entity/entity.h" -#include "impeller/entity/geometry/geometry.h" #include "impeller/geometry/path.h" #include "impeller/geometry/path_builder.h" #include "impeller/geometry/scalar.h" @@ -41,6 +33,18 @@ namespace impeller { +/// A color matrix which inverts colors. +// clang-format off +constexpr ColorMatrix kColorInversion = { + .array = { + -1.0, 0, 0, 1.0, 0, // + 0, -1.0, 0, 1.0, 0, // + 0, 0, -1.0, 1.0, 0, // + 1.0, 1.0, 1.0, 1.0, 0 // + } +}; +// clang-format on + #define UNIMPLEMENTED \ FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__; @@ -484,12 +488,24 @@ static std::shared_ptr ToColorFilter( // |flutter::DlOpReceiver| void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { // Needs https://github.com/flutter/flutter/issues/95434 - paint_.color_filter = ToColorFilter(filter); + if (paint_.color_filter) { + auto color_filter = ToColorFilter(filter); + paint_.color_filter = std::make_shared( + std::move(paint_.color_filter), color_filter); + } else { + paint_.color_filter = ToColorFilter(filter); + } } // |flutter::DlOpReceiver| void DlDispatcher::setInvertColors(bool invert) { - paint_.invert_colors = invert; + if (paint_.color_filter) { + auto invert_filter = ColorFilter::MakeMatrix(kColorInversion); + paint_.color_filter = std::make_shared( + invert_filter, std::move(paint_.color_filter)); + } else { + paint_.color_filter = ColorFilter::MakeMatrix(kColorInversion); + } } // |flutter::DlOpReceiver| From bc1dcabc12a0db41c4f1c8d931122f0d9404a2db Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 28 Sep 2023 16:41:04 -0700 Subject: [PATCH 02/10] ++ --- impeller/aiks/color_filter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impeller/aiks/color_filter.h b/impeller/aiks/color_filter.h index 2a6065ed97f66..5e6f3a292db05 100644 --- a/impeller/aiks/color_filter.h +++ b/impeller/aiks/color_filter.h @@ -166,9 +166,9 @@ class MergedColorFilter final : public ColorFilter { // |ColorFilter| std::shared_ptr Clone() const override; - private: - std::shared_ptr outer_; - std::shared_ptr inner_; + private: + std::shared_ptr outer_; + std::shared_ptr inner_; }; } // namespace impeller From baa08b7aeefc63e30b67a062fcafca8036b1a1eb Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 28 Sep 2023 17:17:17 -0700 Subject: [PATCH 03/10] rename to composed --- impeller/aiks/aiks_unittests.cc | 6 +++--- impeller/aiks/canvas.cc | 1 - impeller/aiks/color_filter.cc | 24 ++++++++++++++++-------- impeller/aiks/color_filter.h | 12 ++++++++---- impeller/display_list/dl_dispatcher.cc | 6 +++--- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index fc845c4169ac4..72b1be1d1d80b 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -136,7 +136,7 @@ TEST_P(AiksTest, CanRenderMergedColorFilterImage) { Paint paint; auto image = std::make_shared(CreateTextureForFixture("kalimba.jpg")); paint.color = Color::Red(); - paint.color_filter = std::make_shared( + paint.color_filter = ColorFilter::MakeComposed( ColorFilter::MakeMatrix(kColorInversion), ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint); @@ -147,7 +147,7 @@ TEST_P(AiksTest, CanRenderMergedColorFilter) { Canvas canvas; Paint paint; paint.color = Color::Red(); - paint.color_filter = std::make_shared( + paint.color_filter = ColorFilter::MakeComposed( ColorFilter::MakeMatrix(kColorInversion), ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint); @@ -158,7 +158,7 @@ TEST_P(AiksTest, CanRenderMergedColorFilterDrawPaint) { Canvas canvas; Paint paint; paint.color = Color::Red(); - paint.color_filter = std::make_shared( + paint.color_filter = ColorFilter::MakeComposed( ColorFilter::MakeMatrix(kColorInversion), ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); canvas.DrawPaint(paint); diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index a3c7dd28a63c6..12c9523281481 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -4,7 +4,6 @@ #include "impeller/aiks/canvas.h" -#include #include #include diff --git a/impeller/aiks/color_filter.cc b/impeller/aiks/color_filter.cc index f4888779989d3..d1c2d640636a0 100644 --- a/impeller/aiks/color_filter.cc +++ b/impeller/aiks/color_filter.cc @@ -37,6 +37,12 @@ std::shared_ptr ColorFilter::MakeLinearToSrgb() { return std::make_shared(); } +std::shared_ptr ColorFilter::MakeComposed( + std::shared_ptr outer, + std::shared_ptr inner) { + return std::make_shared(outer, inner); +} + /******************************************************************************* ******* BlendColorFilter ******************************************************************************/ @@ -146,16 +152,17 @@ std::shared_ptr LinearToSrgbColorFilter::Clone() const { } /******************************************************************************* - ******* MergedColorFilter + ******* ComposedColorFilter ******************************************************************************/ -MergedColorFilter::MergedColorFilter(std::shared_ptr outer, - std::shared_ptr inner) +ComposedColorFilter::ComposedColorFilter(std::shared_ptr outer, + std::shared_ptr inner) : outer_(std::move(outer)), inner_(std::move(inner)) {} -MergedColorFilter::~MergedColorFilter() = default; +ComposedColorFilter::~ComposedColorFilter() = default; -std::shared_ptr MergedColorFilter::WrapWithGPUColorFilter( +std::shared_ptr +ComposedColorFilter::WrapWithGPUColorFilter( std::shared_ptr input, ColorFilterContents::AbsorbOpacity absorb_opacity) const { std::shared_ptr inner = inner_->WrapWithGPUColorFilter( @@ -165,7 +172,8 @@ std::shared_ptr MergedColorFilter::WrapWithGPUColorFilter( } // |ColorFilter| -ColorFilter::ColorFilterProc MergedColorFilter::GetCPUColorFilterProc() const { +ColorFilter::ColorFilterProc ComposedColorFilter::GetCPUColorFilterProc() + const { auto inner_proc = inner_->GetCPUColorFilterProc(); auto outer_proc = outer_->GetCPUColorFilterProc(); return [inner_proc, outer_proc](Color color) { @@ -174,8 +182,8 @@ ColorFilter::ColorFilterProc MergedColorFilter::GetCPUColorFilterProc() const { } // |ColorFilter| -std::shared_ptr MergedColorFilter::Clone() const { - return std::make_shared(outer_, inner_); +std::shared_ptr ComposedColorFilter::Clone() const { + return std::make_shared(outer_, inner_); } } // namespace impeller diff --git a/impeller/aiks/color_filter.h b/impeller/aiks/color_filter.h index 5e6f3a292db05..604937dfd4b97 100644 --- a/impeller/aiks/color_filter.h +++ b/impeller/aiks/color_filter.h @@ -34,6 +34,10 @@ class ColorFilter { static std::shared_ptr MakeLinearToSrgb(); + static std::shared_ptr MakeComposed( + std::shared_ptr outer, + std::shared_ptr inner); + /// @brief Wraps the given filter input with a GPU-based filter that will /// perform the color operation. The given input will first be /// rendered to a texture and then filtered. @@ -148,12 +152,12 @@ class LinearToSrgbColorFilter final : public ColorFilter { }; /// @brief Applies color filters as f(g(x)), where x is the input color. -class MergedColorFilter final : public ColorFilter { +class ComposedColorFilter final : public ColorFilter { public: - explicit MergedColorFilter(std::shared_ptr outer_, - std::shared_ptr inner_); + explicit ComposedColorFilter(std::shared_ptr outer_, + std::shared_ptr inner_); - ~MergedColorFilter() override; + ~ComposedColorFilter() override; // |ColorFilter| std::shared_ptr WrapWithGPUColorFilter( diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 356d3acd7211f..a3c6ad6e33097 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -490,8 +490,8 @@ void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { // Needs https://github.com/flutter/flutter/issues/95434 if (paint_.color_filter) { auto color_filter = ToColorFilter(filter); - paint_.color_filter = std::make_shared( - std::move(paint_.color_filter), color_filter); + paint_.color_filter = + ColorFilter::MakeComposed(std::move(paint_.color_filter), color_filter); } else { paint_.color_filter = ToColorFilter(filter); } @@ -501,7 +501,7 @@ void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { void DlDispatcher::setInvertColors(bool invert) { if (paint_.color_filter) { auto invert_filter = ColorFilter::MakeMatrix(kColorInversion); - paint_.color_filter = std::make_shared( + paint_.color_filter = ColorFilter::MakeComposed( invert_filter, std::move(paint_.color_filter)); } else { paint_.color_filter = ColorFilter::MakeMatrix(kColorInversion); From ccf0ec5b3214c695677b074cb79d52245bc34dce Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 28 Sep 2023 17:38:04 -0700 Subject: [PATCH 04/10] ++ --- impeller/aiks/aiks_unittests.cc | 6 +++--- impeller/aiks/canvas.cc | 1 - impeller/aiks/color_filter.cc | 6 +++--- impeller/aiks/color_filter.h | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 72b1be1d1d80b..f1557d2c6ad8e 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -138,7 +138,7 @@ TEST_P(AiksTest, CanRenderMergedColorFilterImage) { paint.color = Color::Red(); paint.color_filter = ColorFilter::MakeComposed( ColorFilter::MakeMatrix(kColorInversion), - ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); + ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow())); canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } @@ -149,7 +149,7 @@ TEST_P(AiksTest, CanRenderMergedColorFilter) { paint.color = Color::Red(); paint.color_filter = ColorFilter::MakeComposed( ColorFilter::MakeMatrix(kColorInversion), - ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); + ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow())); canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } @@ -160,7 +160,7 @@ TEST_P(AiksTest, CanRenderMergedColorFilterDrawPaint) { paint.color = Color::Red(); paint.color_filter = ColorFilter::MakeComposed( ColorFilter::MakeMatrix(kColorInversion), - ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Aqua())); + ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow())); canvas.DrawPaint(paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 12c9523281481..80f0cc734809e 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -180,7 +180,6 @@ void Canvas::DrawPath(const Path& path, const Paint& paint) { } void Canvas::DrawPaint(const Paint& paint) { - FML_LOG(ERROR) << "Draw Paint"; Entity entity; entity.SetTransformation(GetCurrentTransformation()); entity.SetStencilDepth(GetStencilDepth()); diff --git a/impeller/aiks/color_filter.cc b/impeller/aiks/color_filter.cc index d1c2d640636a0..1372a43b4b8ae 100644 --- a/impeller/aiks/color_filter.cc +++ b/impeller/aiks/color_filter.cc @@ -174,9 +174,9 @@ ComposedColorFilter::WrapWithGPUColorFilter( // |ColorFilter| ColorFilter::ColorFilterProc ComposedColorFilter::GetCPUColorFilterProc() const { - auto inner_proc = inner_->GetCPUColorFilterProc(); - auto outer_proc = outer_->GetCPUColorFilterProc(); - return [inner_proc, outer_proc](Color color) { + return [inner = inner_, outer = outer_](Color color) { + auto inner_proc = inner->GetCPUColorFilterProc(); + auto outer_proc = outer->GetCPUColorFilterProc(); return outer_proc(inner_proc(color)); }; } diff --git a/impeller/aiks/color_filter.h b/impeller/aiks/color_filter.h index 604937dfd4b97..9af784a6d0d79 100644 --- a/impeller/aiks/color_filter.h +++ b/impeller/aiks/color_filter.h @@ -154,8 +154,8 @@ class LinearToSrgbColorFilter final : public ColorFilter { /// @brief Applies color filters as f(g(x)), where x is the input color. class ComposedColorFilter final : public ColorFilter { public: - explicit ComposedColorFilter(std::shared_ptr outer_, - std::shared_ptr inner_); + ComposedColorFilter(std::shared_ptr outer, + std::shared_ptr inner); ~ComposedColorFilter() override; From 4c15cf3e13d9a8ce86594c00bc24b5cd218e7eac Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 28 Sep 2023 17:39:46 -0700 Subject: [PATCH 05/10] ++ --- impeller/aiks/color_filter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/aiks/color_filter.h b/impeller/aiks/color_filter.h index 9af784a6d0d79..77f96f02a9308 100644 --- a/impeller/aiks/color_filter.h +++ b/impeller/aiks/color_filter.h @@ -155,7 +155,7 @@ class LinearToSrgbColorFilter final : public ColorFilter { class ComposedColorFilter final : public ColorFilter { public: ComposedColorFilter(std::shared_ptr outer, - std::shared_ptr inner); + std::shared_ptr inner); ~ComposedColorFilter() override; From 1b33b1f1fd388026b35ae5072673f925a777b963 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 28 Sep 2023 17:56:52 -0700 Subject: [PATCH 06/10] ++ --- impeller/aiks/color_filter.cc | 11 ++++++----- impeller/aiks/color_filter.h | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/impeller/aiks/color_filter.cc b/impeller/aiks/color_filter.cc index 1372a43b4b8ae..b5498a195408b 100644 --- a/impeller/aiks/color_filter.cc +++ b/impeller/aiks/color_filter.cc @@ -38,8 +38,8 @@ std::shared_ptr ColorFilter::MakeLinearToSrgb() { } std::shared_ptr ColorFilter::MakeComposed( - std::shared_ptr outer, - std::shared_ptr inner) { + const std::shared_ptr& outer, + const std::shared_ptr& inner) { return std::make_shared(outer, inner); } @@ -155,9 +155,10 @@ std::shared_ptr LinearToSrgbColorFilter::Clone() const { ******* ComposedColorFilter ******************************************************************************/ -ComposedColorFilter::ComposedColorFilter(std::shared_ptr outer, - std::shared_ptr inner) - : outer_(std::move(outer)), inner_(std::move(inner)) {} +ComposedColorFilter::ComposedColorFilter( + const std::shared_ptr& outer, + const std::shared_ptr& inner) + : outer_(outer), inner_(inner) {} ComposedColorFilter::~ComposedColorFilter() = default; diff --git a/impeller/aiks/color_filter.h b/impeller/aiks/color_filter.h index 77f96f02a9308..84dfbbd19b40d 100644 --- a/impeller/aiks/color_filter.h +++ b/impeller/aiks/color_filter.h @@ -35,8 +35,8 @@ class ColorFilter { static std::shared_ptr MakeLinearToSrgb(); static std::shared_ptr MakeComposed( - std::shared_ptr outer, - std::shared_ptr inner); + const std::shared_ptr& outer, + const std::shared_ptr& inner); /// @brief Wraps the given filter input with a GPU-based filter that will /// perform the color operation. The given input will first be @@ -154,8 +154,8 @@ class LinearToSrgbColorFilter final : public ColorFilter { /// @brief Applies color filters as f(g(x)), where x is the input color. class ComposedColorFilter final : public ColorFilter { public: - ComposedColorFilter(std::shared_ptr outer, - std::shared_ptr inner); + ComposedColorFilter(const std::shared_ptr& outer, + const std::shared_ptr& inner); ~ComposedColorFilter() override; From dad6ac8df54675754304343fd46c93197608ceae Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 28 Sep 2023 18:42:41 -0700 Subject: [PATCH 07/10] Update dl_dispatcher.cc --- impeller/display_list/dl_dispatcher.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index a3c6ad6e33097..87cdc01a558b8 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -491,7 +491,7 @@ void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { if (paint_.color_filter) { auto color_filter = ToColorFilter(filter); paint_.color_filter = - ColorFilter::MakeComposed(std::move(paint_.color_filter), color_filter); + ColorFilter::MakeComposed(paint_.color_filter, color_filter); } else { paint_.color_filter = ToColorFilter(filter); } @@ -502,7 +502,7 @@ void DlDispatcher::setInvertColors(bool invert) { if (paint_.color_filter) { auto invert_filter = ColorFilter::MakeMatrix(kColorInversion); paint_.color_filter = ColorFilter::MakeComposed( - invert_filter, std::move(paint_.color_filter)); + invert_filter, paint_.color_filter); } else { paint_.color_filter = ColorFilter::MakeMatrix(kColorInversion); } From 5ff81584df57b3b556e5faa8b297fe563b3cffa2 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 28 Sep 2023 19:16:58 -0700 Subject: [PATCH 08/10] Update dl_dispatcher.cc --- impeller/display_list/dl_dispatcher.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 87cdc01a558b8..b2adf7d24e13c 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -501,8 +501,7 @@ void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { void DlDispatcher::setInvertColors(bool invert) { if (paint_.color_filter) { auto invert_filter = ColorFilter::MakeMatrix(kColorInversion); - paint_.color_filter = ColorFilter::MakeComposed( - invert_filter, paint_.color_filter); + paint_.color_filter = ColorFilter::MakeComposed(invert_filter, paint_.color_filter); } else { paint_.color_filter = ColorFilter::MakeMatrix(kColorInversion); } From 2ca5a1108f7ecf9d7768402f208ed06f519e62ed Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 28 Sep 2023 19:50:13 -0700 Subject: [PATCH 09/10] Update dl_dispatcher.cc --- impeller/display_list/dl_dispatcher.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index b2adf7d24e13c..c0b610157e1c6 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -501,7 +501,8 @@ void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { void DlDispatcher::setInvertColors(bool invert) { if (paint_.color_filter) { auto invert_filter = ColorFilter::MakeMatrix(kColorInversion); - paint_.color_filter = ColorFilter::MakeComposed(invert_filter, paint_.color_filter); + paint_.color_filter = + ColorFilter::MakeComposed(invert_filter, paint_.color_filter); } else { paint_.color_filter = ColorFilter::MakeMatrix(kColorInversion); } From 5ecb75fabf211f341057fb7bfde08d5f7e4fe188 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 29 Sep 2023 11:22:31 -0700 Subject: [PATCH 10/10] put logic in paint. --- impeller/aiks/aiks_unittests.cc | 34 ++++++++++++-------------- impeller/aiks/paint.cc | 30 ++++++++++++++++++++++- impeller/aiks/paint.h | 3 +++ impeller/display_list/dl_dispatcher.cc | 29 ++-------------------- 4 files changed, 49 insertions(+), 47 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index f1557d2c6ad8e..849cf648b1f8e 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -124,43 +124,39 @@ TEST_P(AiksTest, CanRenderImage) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -constexpr ColorMatrix kColorInversion = {.array = { - -1.0, 0, 0, 1.0, 0, // - 0, -1.0, 0, 1.0, 0, // - 0, 0, -1.0, 1.0, 0, // - 1.0, 1.0, 1.0, 1.0, 0 // - }}; - -TEST_P(AiksTest, CanRenderMergedColorFilterImage) { +TEST_P(AiksTest, CanRenderInvertedImageWithColorFilter) { Canvas canvas; Paint paint; auto image = std::make_shared(CreateTextureForFixture("kalimba.jpg")); paint.color = Color::Red(); - paint.color_filter = ColorFilter::MakeComposed( - ColorFilter::MakeMatrix(kColorInversion), - ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow())); + paint.color_filter = + ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow()); + paint.invert_colors = true; + canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -TEST_P(AiksTest, CanRenderMergedColorFilter) { +TEST_P(AiksTest, CanRenderColorFilterWithInvertColors) { Canvas canvas; Paint paint; paint.color = Color::Red(); - paint.color_filter = ColorFilter::MakeComposed( - ColorFilter::MakeMatrix(kColorInversion), - ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow())); + paint.color_filter = + ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow()); + paint.invert_colors = true; + canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -TEST_P(AiksTest, CanRenderMergedColorFilterDrawPaint) { +TEST_P(AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint) { Canvas canvas; Paint paint; paint.color = Color::Red(); - paint.color_filter = ColorFilter::MakeComposed( - ColorFilter::MakeMatrix(kColorInversion), - ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow())); + paint.color_filter = + ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow()); + paint.invert_colors = true; + canvas.DrawPaint(paint); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index f9651f31c0ee0..332973e3c2a99 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -14,6 +14,18 @@ namespace impeller { +/// A color matrix which inverts colors. +// clang-format off +constexpr ColorMatrix kColorInversion = { + .array = { + -1.0, 0, 0, 1.0, 0, // + 0, -1.0, 0, 1.0, 0, // + 0, 0, -1.0, 1.0, 0, // + 1.0, 1.0, 1.0, 1.0, 0 // + } +}; +// clang-format on + std::shared_ptr Paint::CreateContentsForEntity(const Path& path, bool cover) const { std::unique_ptr geometry; @@ -38,6 +50,7 @@ std::shared_ptr Paint::CreateContentsForGeometry( // Attempt to apply the color filter on the CPU first. // Note: This is not just an optimization; some color sources rely on // CPU-applied color filters to behave properly. + auto color_filter = GetColorFilter(); bool needs_color_filter = !!color_filter; if (color_filter && contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) { @@ -110,6 +123,7 @@ std::shared_ptr Paint::WithColorFilter( return input; } + auto color_filter = GetColorFilter(); if (!color_filter) { return input; } @@ -184,8 +198,22 @@ std::shared_ptr Paint::MaskBlurDescriptor::CreateMaskBlur( return FilterContents::MakeBorderMaskBlur(input, sigma, sigma, style); } +std::shared_ptr Paint::GetColorFilter() const { + if (invert_colors && color_filter) { + auto filter = ColorFilter::MakeMatrix(kColorInversion); + return ColorFilter::MakeComposed(filter, color_filter); + } + if (invert_colors) { + return ColorFilter::MakeMatrix(kColorInversion); + } + if (color_filter) { + return color_filter; + } + return nullptr; +} + bool Paint::HasColorFilter() const { - return !!color_filter; + return !!color_filter || invert_colors; } } // namespace impeller diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index 0fba8a628d12b..bf96842b783c9 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -61,11 +61,14 @@ struct Paint { Scalar stroke_miter = 4.0; Style style = Style::kFill; BlendMode blend_mode = BlendMode::kSourceOver; + bool invert_colors = false; std::shared_ptr image_filter; std::shared_ptr color_filter; std::optional mask_blur_descriptor; + std::shared_ptr GetColorFilter() const; + /// @brief Wrap this paint's configured filters to the given contents. /// @param[in] input The contents to wrap with paint's filters. /// @return The filter-wrapped contents. If there are no filters that need diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index c0b610157e1c6..7796efc26b8b6 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -33,18 +33,6 @@ namespace impeller { -/// A color matrix which inverts colors. -// clang-format off -constexpr ColorMatrix kColorInversion = { - .array = { - -1.0, 0, 0, 1.0, 0, // - 0, -1.0, 0, 1.0, 0, // - 0, 0, -1.0, 1.0, 0, // - 1.0, 1.0, 1.0, 1.0, 0 // - } -}; -// clang-format on - #define UNIMPLEMENTED \ FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__; @@ -487,25 +475,12 @@ static std::shared_ptr ToColorFilter( // |flutter::DlOpReceiver| void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) { - // Needs https://github.com/flutter/flutter/issues/95434 - if (paint_.color_filter) { - auto color_filter = ToColorFilter(filter); - paint_.color_filter = - ColorFilter::MakeComposed(paint_.color_filter, color_filter); - } else { - paint_.color_filter = ToColorFilter(filter); - } + paint_.color_filter = ToColorFilter(filter); } // |flutter::DlOpReceiver| void DlDispatcher::setInvertColors(bool invert) { - if (paint_.color_filter) { - auto invert_filter = ColorFilter::MakeMatrix(kColorInversion); - paint_.color_filter = - ColorFilter::MakeComposed(invert_filter, paint_.color_filter); - } else { - paint_.color_filter = ColorFilter::MakeMatrix(kColorInversion); - } + paint_.invert_colors = invert; } // |flutter::DlOpReceiver|