From 032540880cf5b76589b4e40dfc76052860e2fc56 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 15 Nov 2022 17:23:43 -0800 Subject: [PATCH] Refactor color source resolution to use explicit factory types --- ci/licenses_golden/licenses_flutter | 6 + impeller/aiks/BUILD.gn | 2 + impeller/aiks/aiks_unittests.cc | 425 ++++++++++-------- impeller/aiks/canvas.cc | 11 +- impeller/aiks/canvas.h | 2 +- impeller/aiks/color_source_factory.cc | 11 + impeller/aiks/color_source_factory.h | 32 ++ impeller/aiks/paint.cc | 5 +- impeller/aiks/paint.h | 17 +- impeller/display_list/BUILD.gn | 4 + impeller/display_list/conversion_utilities.cc | 179 ++++++++ impeller/display_list/conversion_utilities.h | 69 +++ .../display_list_color_source_factory.cc | 286 ++++++++++++ .../display_list_color_source_factory.h | 146 ++++++ .../display_list/display_list_dispatcher.cc | 388 +--------------- 15 files changed, 1001 insertions(+), 582 deletions(-) create mode 100644 impeller/aiks/color_source_factory.cc create mode 100644 impeller/aiks/color_source_factory.h create mode 100644 impeller/display_list/conversion_utilities.cc create mode 100644 impeller/display_list/conversion_utilities.h create mode 100644 impeller/display_list/display_list_color_source_factory.cc create mode 100644 impeller/display_list/display_list_color_source_factory.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 83d3b324cae10..0158ea5cee400 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1030,6 +1030,8 @@ FILE: ../../../flutter/impeller/aiks/aiks_playground.h FILE: ../../../flutter/impeller/aiks/aiks_unittests.cc FILE: ../../../flutter/impeller/aiks/canvas.cc FILE: ../../../flutter/impeller/aiks/canvas.h +FILE: ../../../flutter/impeller/aiks/color_source_factory.cc +FILE: ../../../flutter/impeller/aiks/color_source_factory.h FILE: ../../../flutter/impeller/aiks/image.cc FILE: ../../../flutter/impeller/aiks/image.h FILE: ../../../flutter/impeller/aiks/paint.cc @@ -1129,6 +1131,10 @@ FILE: ../../../flutter/impeller/compiler/types.cc FILE: ../../../flutter/impeller/compiler/types.h FILE: ../../../flutter/impeller/compiler/utilities.cc FILE: ../../../flutter/impeller/compiler/utilities.h +FILE: ../../../flutter/impeller/display_list/conversion_utilities.cc +FILE: ../../../flutter/impeller/display_list/conversion_utilities.h +FILE: ../../../flutter/impeller/display_list/display_list_color_source_factory.cc +FILE: ../../../flutter/impeller/display_list/display_list_color_source_factory.h FILE: ../../../flutter/impeller/display_list/display_list_dispatcher.cc FILE: ../../../flutter/impeller/display_list/display_list_dispatcher.h FILE: ../../../flutter/impeller/display_list/display_list_image_impeller.cc diff --git a/impeller/aiks/BUILD.gn b/impeller/aiks/BUILD.gn index 744e1a9633c25..fa6e0139c356a 100644 --- a/impeller/aiks/BUILD.gn +++ b/impeller/aiks/BUILD.gn @@ -10,6 +10,8 @@ impeller_component("aiks") { "aiks_context.h", "canvas.cc", "canvas.h", + "color_source_factory.cc", + "color_source_factory.h", "image.cc", "image.h", "paint.cc", diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 9b06d08802be8..40dfc8ed1fcd3 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -4,7 +4,9 @@ #include #include +#include #include +#include #include #include @@ -31,6 +33,35 @@ namespace testing { using AiksTest = AiksPlayground; INSTANTIATE_PLAYGROUND_SUITE(AiksTest); +class ProcColorSourceFactory final : public ColorSourceFactory { + public: + using ColorSourceProc = std::function()>; + + static std::shared_ptr Make(ColorSourceType type, + ColorSourceProc proc) { + auto result = std::make_shared(); + result->type_ = type; + result->proc_ = std::move(proc); + return result; + } + + // |ColorSourceFactory| + ~ProcColorSourceFactory() override = default; + + // |ColorSourceFactory| + std::shared_ptr MakeContents() override { + assert(proc_ != nullptr); + return proc_(); + } + + // |ColorSourceFactory| + ColorSourceFactory::ColorSourceType GetType() override { return type_; } + + private: + ColorSourceType type_ = ColorSourceType::kColor; + ColorSourceProc proc_ = nullptr; +}; + TEST_P(AiksTest, CanvasCTMCanBeUpdated) { Canvas canvas; Matrix identity; @@ -153,14 +184,16 @@ TEST_P(AiksTest, CanRenderTiledTexture) { descriptor.mip_filter = mip_filters[selected_mip_filter]; descriptor.min_filter = min_mag_filters[selected_min_mag_filter]; descriptor.mag_filter = min_mag_filters[selected_min_mag_filter]; - paint.color_source = [texture, x_tile_mode, y_tile_mode, descriptor]() { - auto contents = std::make_shared(); - contents->SetTexture(texture); - contents->SetTileModes(x_tile_mode, y_tile_mode); - contents->SetSamplerDescriptor(descriptor); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kImage, + [texture, x_tile_mode, y_tile_mode, descriptor]() { + auto contents = std::make_shared(); + contents->SetTexture(texture); + contents->SetTileModes(x_tile_mode, y_tile_mode); + contents->SetSamplerDescriptor(descriptor); + contents->SetMatrix(matrix); + return contents; + }); paint.color = Color(1, 1, 1, alpha); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); @@ -332,19 +365,20 @@ TEST_P(AiksTest, CanRenderLinearGradient) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, - Color{0.1294, 0.5882, 0.9529, 0.0}}; - std::vector stops = {0.0, 1.0}; - - auto contents = std::make_shared(); - contents->SetEndPoints({0, 0}, {200, 200}); - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() { + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 0.0}}; + std::vector stops = {0.0, 1.0}; + + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {200, 200}); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); paint.color = Color(1.0, 1.0, 1.0, alpha); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); @@ -383,33 +417,34 @@ TEST_P(AiksTest, CanRenderLinearGradientManyColors) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - std::vector colors = { - Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, - Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, - Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, - Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, - Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; - std::vector stops = { - 0.0, - (1.0 / 6.0) * 1, - (1.0 / 6.0) * 2, - (1.0 / 6.0) * 3, - (1.0 / 6.0) * 4, - (1.0 / 6.0) * 5, - 1.0, - }; - - auto contents = std::make_shared(); - contents->SetEndPoints({0, 0}, {200, 200}); - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() { + std::vector colors = { + Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, + Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, + Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, + Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, + Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; + std::vector stops = { + 0.0, + (1.0 / 6.0) * 1, + (1.0 / 6.0) * 2, + (1.0 / 6.0) * 3, + (1.0 / 6.0) * 4, + (1.0 / 6.0) * 5, + 1.0, + }; + + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {200, 200}); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); paint.color = Color(1.0, 1.0, 1.0, alpha); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); @@ -456,16 +491,17 @@ TEST_P(AiksTest, CanRenderLinearGradientWayManyColors) { current_stop += 1 / 2000.0; } stops[2000 - 1] = 1.0; - paint.color_source = [tile_mode, stops = std::move(stops), - colors = std::move(colors)]() { - auto contents = std::make_shared(); - contents->SetEndPoints({0, 0}, {200, 200}); - contents->SetColors(colors); - contents->SetStops(stops); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kLinearGradient, + [tile_mode, stops = std::move(stops), colors = std::move(colors)]() { + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {200, 200}); + contents->SetColors(colors); + contents->SetStops(stops); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; @@ -501,28 +537,29 @@ TEST_P(AiksTest, CanRenderLinearGradientManyColorsUnevenStops) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - std::vector colors = { - Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, - Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, - Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, - Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, - Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; - std::vector stops = { - 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, - 16.0 / 62.0, 32.0 / 62.0, 1.0, - }; - - auto contents = std::make_shared(); - contents->SetEndPoints({0, 0}, {200, 200}); - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() { + std::vector colors = { + Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, + Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, + Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, + Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, + Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; + std::vector stops = { + 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, + 16.0 / 62.0, 32.0 / 62.0, 1.0, + }; + + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {200, 200}); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; @@ -558,19 +595,20 @@ TEST_P(AiksTest, CanRenderRadialGradient) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, - Color{0.1294, 0.5882, 0.9529, 1.0}}; - std::vector stops = {0.0, 1.0}; - - auto contents = std::make_shared(); - contents->SetCenterAndRadius({100, 100}, 100); - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kRadialGradient, [tile_mode]() { + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}}; + std::vector stops = {0.0, 1.0}; + + auto contents = std::make_shared(); + contents->SetCenterAndRadius({100, 100}, 100); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; @@ -606,33 +644,34 @@ TEST_P(AiksTest, CanRenderRadialGradientManyColors) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - std::vector colors = { - Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, - Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, - Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, - Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, - Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; - std::vector stops = { - 0.0, - (1.0 / 6.0) * 1, - (1.0 / 6.0) * 2, - (1.0 / 6.0) * 3, - (1.0 / 6.0) * 4, - (1.0 / 6.0) * 5, - 1.0, - }; - - auto contents = std::make_shared(); - contents->SetCenterAndRadius({100, 100}, 100); - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kRadialGradient, [tile_mode]() { + std::vector colors = { + Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, + Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, + Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, + Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, + Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; + std::vector stops = { + 0.0, + (1.0 / 6.0) * 1, + (1.0 / 6.0) * 2, + (1.0 / 6.0) * 3, + (1.0 / 6.0) * 4, + (1.0 / 6.0) * 5, + 1.0, + }; + + auto contents = std::make_shared(); + contents->SetCenterAndRadius({100, 100}, 100); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; @@ -668,18 +707,19 @@ TEST_P(AiksTest, CanRenderSweepGradient) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - auto contents = std::make_shared(); - contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135)); - std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, - Color{0.1294, 0.5882, 0.9529, 1.0}}; - std::vector stops = {0.0, 1.0}; - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kSweepGradient, [tile_mode]() { + auto contents = std::make_shared(); + contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135)); + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}}; + std::vector stops = {0.0, 1.0}; + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; @@ -715,33 +755,34 @@ TEST_P(AiksTest, CanRenderSweepGradientManyColors) { Paint paint; canvas.Translate({100.0, 100.0, 0}); auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - auto contents = std::make_shared(); - contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135)); - std::vector colors = { - Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, - Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, - Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, - Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, - Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, - Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; - std::vector stops = { - 0.0, - (1.0 / 6.0) * 1, - (1.0 / 6.0) * 2, - (1.0 / 6.0) * 3, - (1.0 / 6.0) * 4, - (1.0 / 6.0) * 5, - 1.0, - }; - - contents->SetStops(std::move(stops)); - contents->SetColors(std::move(colors)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kSweepGradient, [tile_mode]() { + auto contents = std::make_shared(); + contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135)); + std::vector colors = { + Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}, + Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}, + Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}, + Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}, + Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}, + Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}}; + std::vector stops = { + 0.0, + (1.0 / 6.0) * 1, + (1.0 / 6.0) * 2, + (1.0 / 6.0) * 3, + (1.0 / 6.0) * 4, + (1.0 / 6.0) * 5, + 1.0, + }; + + contents->SetStops(std::move(stops)); + contents->SetColors(std::move(colors)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; @@ -751,20 +792,21 @@ TEST_P(AiksTest, CanRenderSweepGradientManyColors) { TEST_P(AiksTest, CanRenderDifferentShapesWithSameColorSource) { Canvas canvas; Paint paint; - paint.color_source = []() { - auto contents = std::make_shared(); - contents->SetEndPoints({0, 0}, {100, 100}); - std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, - Color{0.1294, 0.5882, 0.9529, 1.0}}; - std::vector stops = { - 0.0, - 1.0, - }; - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(Entity::TileMode::kRepeat); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kLinearGradient, []() { + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {100, 100}); + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}}; + std::vector stops = { + 0.0, + 1.0, + }; + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(Entity::TileMode::kRepeat); + return contents; + }); canvas.Save(); canvas.Translate({100, 100, 0}); canvas.DrawRect({0, 0, 200, 200}, paint); @@ -1452,24 +1494,25 @@ TEST_P(AiksTest, GradientStrokesRenderCorrectly) { paint.color = Color(1.0, 1.0, 1.0, alpha); paint.stroke_width = 10; auto tile_mode = tile_modes[selected_tile_mode]; - paint.color_source = [tile_mode]() { - std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, - Color{0.1294, 0.5882, 0.9529, 1.0}}; - std::vector stops = {0.0, 1.0}; - Matrix matrix = { - 1, 0, 0, 0, // - 0, 1, 0, 0, // - 0, 0, 1, 0, // - 0, 0, 0, 1 // - }; - auto contents = std::make_shared(); - contents->SetEndPoints({0, 0}, {50, 50}); - contents->SetColors(std::move(colors)); - contents->SetStops(std::move(stops)); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; + paint.color_source = ProcColorSourceFactory::Make( + ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() { + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}}; + std::vector stops = {0.0, 1.0}; + Matrix matrix = { + 1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1 // + }; + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {50, 50}); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; + }); Path path = PathBuilder{} .MoveTo({20, 20}) diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 996ea68839355..97b9997a36989 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -160,9 +160,7 @@ void Canvas::DrawPaint(const Paint& paint) { bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, Scalar corner_radius, const Paint& paint) { - if (paint.color_source == nullptr || - paint.color_source_type != Paint::ColorSourceType::kColor || - paint.style != Paint::Style::kFill) { + if (!paint.color_source || paint.style != Paint::Style::kFill) { return false; } @@ -375,7 +373,7 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame, void Canvas::DrawVertices(const Vertices& vertices, BlendMode blend_mode, - Paint paint) { + const Paint& paint) { auto geometry = Geometry::MakeVertices(vertices); Entity entity; @@ -383,9 +381,8 @@ void Canvas::DrawVertices(const Vertices& vertices, entity.SetStencilDepth(GetStencilDepth()); entity.SetBlendMode(paint.blend_mode); - if (paint.color_source.has_value()) { - auto& source = paint.color_source.value(); - auto contents = source(); + if (paint.color_source) { + auto contents = paint.color_source->MakeContents(); contents->SetGeometry(std::move(geometry)); contents->SetAlpha(paint.color.alpha); entity.SetContents(paint.WithFilters(std::move(contents), true)); diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index 7638c888b4b34..da5dd6ca0502a 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -99,7 +99,7 @@ class Canvas { void DrawVertices(const Vertices& vertices, BlendMode blend_mode, - Paint paint); + const Paint& paint); void DrawAtlas(const std::shared_ptr& atlas, std::vector transforms, diff --git a/impeller/aiks/color_source_factory.cc b/impeller/aiks/color_source_factory.cc new file mode 100644 index 0000000000000..d2f77c9ef4797 --- /dev/null +++ b/impeller/aiks/color_source_factory.cc @@ -0,0 +1,11 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/aiks/color_source_factory.h" + +namespace impeller { + +ColorSourceFactory::~ColorSourceFactory() = default; + +} // namespace impeller diff --git a/impeller/aiks/color_source_factory.h b/impeller/aiks/color_source_factory.h new file mode 100644 index 0000000000000..d87a66195baa3 --- /dev/null +++ b/impeller/aiks/color_source_factory.h @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "impeller/entity/contents/color_source_contents.h" + +namespace impeller { + +class ColorSourceFactory { + public: + enum class ColorSourceType { + kColor, + kImage, + kLinearGradient, + kRadialGradient, + kConicalGradient, + kSweepGradient, + kRuntimeEffect, + }; + + virtual ~ColorSourceFactory(); + + virtual std::shared_ptr MakeContents() = 0; + + virtual ColorSourceType GetType() = 0; +}; + +} // namespace impeller diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index 04b93e248bea1..9fef59f7c37f1 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -27,9 +27,8 @@ std::shared_ptr Paint::CreateContentsForEntity(const Path& path, std::shared_ptr Paint::CreateContentsForGeometry( std::unique_ptr geometry) const { - if (color_source.has_value()) { - auto& source = color_source.value(); - auto contents = source(); + if (color_source) { + auto contents = color_source->MakeContents(); contents->SetGeometry(std::move(geometry)); contents->SetAlpha(color.alpha); return contents; diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index 6f3784112e94c..8ab4c09bfced6 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -7,6 +7,7 @@ #include #include "flutter/fml/macros.h" +#include "impeller/aiks/color_source_factory.h" #include "impeller/entity/contents/contents.h" #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" @@ -29,23 +30,12 @@ struct Paint { FilterInput::Ref, bool is_solid_color, const Matrix& effect_transform)>; - using ColorSourceProc = std::function()>; enum class Style { kFill, kStroke, }; - enum class ColorSourceType { - kColor, - kImage, - kLinearGradient, - kRadialGradient, - kConicalGradient, - kSweepGradient, - kRuntimeEffect, - }; - struct MaskBlurDescriptor { FilterContents::BlurStyle style; Sigma sigma; @@ -56,10 +46,9 @@ struct Paint { const Matrix& effect_matrix) const; }; - Color color = Color::Black(); - std::optional color_source; - ColorSourceType color_source_type = ColorSourceType::kColor; + std::shared_ptr color_source; + Color color = Color::Black(); Scalar stroke_width = 0.0; Cap stroke_cap = Cap::kButt; Join stroke_join = Join::kMiter; diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn index a6c4fcd60e13b..aa2302dc4d553 100644 --- a/impeller/display_list/BUILD.gn +++ b/impeller/display_list/BUILD.gn @@ -6,6 +6,10 @@ import("//flutter/impeller/tools/impeller.gni") impeller_component("display_list") { sources = [ + "conversion_utilities.cc", + "conversion_utilities.h", + "display_list_color_source_factory.cc", + "display_list_color_source_factory.h", "display_list_dispatcher.cc", "display_list_dispatcher.h", "display_list_image_impeller.cc", diff --git a/impeller/display_list/conversion_utilities.cc b/impeller/display_list/conversion_utilities.cc new file mode 100644 index 0000000000000..9cb8be4677e64 --- /dev/null +++ b/impeller/display_list/conversion_utilities.cc @@ -0,0 +1,179 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/display_list/conversion_utilities.h" + +namespace impeller { + +BlendMode ToBlendMode(flutter::DlBlendMode mode) { + switch (mode) { + case flutter::DlBlendMode::kClear: + return BlendMode::kClear; + case flutter::DlBlendMode::kSrc: + return BlendMode::kSource; + case flutter::DlBlendMode::kDst: + return BlendMode::kDestination; + case flutter::DlBlendMode::kSrcOver: + return BlendMode::kSourceOver; + case flutter::DlBlendMode::kDstOver: + return BlendMode::kDestinationOver; + case flutter::DlBlendMode::kSrcIn: + return BlendMode::kSourceIn; + case flutter::DlBlendMode::kDstIn: + return BlendMode::kDestinationIn; + case flutter::DlBlendMode::kSrcOut: + return BlendMode::kSourceOut; + case flutter::DlBlendMode::kDstOut: + return BlendMode::kDestinationOut; + case flutter::DlBlendMode::kSrcATop: + return BlendMode::kSourceATop; + case flutter::DlBlendMode::kDstATop: + return BlendMode::kDestinationATop; + case flutter::DlBlendMode::kXor: + return BlendMode::kXor; + case flutter::DlBlendMode::kPlus: + return BlendMode::kPlus; + case flutter::DlBlendMode::kModulate: + return BlendMode::kModulate; + case flutter::DlBlendMode::kScreen: + return BlendMode::kScreen; + case flutter::DlBlendMode::kOverlay: + return BlendMode::kOverlay; + case flutter::DlBlendMode::kDarken: + return BlendMode::kDarken; + case flutter::DlBlendMode::kLighten: + return BlendMode::kLighten; + case flutter::DlBlendMode::kColorDodge: + return BlendMode::kColorDodge; + case flutter::DlBlendMode::kColorBurn: + return BlendMode::kColorBurn; + case flutter::DlBlendMode::kHardLight: + return BlendMode::kHardLight; + case flutter::DlBlendMode::kSoftLight: + return BlendMode::kSoftLight; + case flutter::DlBlendMode::kDifference: + return BlendMode::kDifference; + case flutter::DlBlendMode::kExclusion: + return BlendMode::kExclusion; + case flutter::DlBlendMode::kMultiply: + return BlendMode::kMultiply; + case flutter::DlBlendMode::kHue: + return BlendMode::kHue; + case flutter::DlBlendMode::kSaturation: + return BlendMode::kSaturation; + case flutter::DlBlendMode::kColor: + return BlendMode::kColor; + case flutter::DlBlendMode::kLuminosity: + return BlendMode::kLuminosity; + } + FML_UNREACHABLE(); +} + +Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) { + switch (tile_mode) { + case flutter::DlTileMode::kClamp: + return Entity::TileMode::kClamp; + case flutter::DlTileMode::kRepeat: + return Entity::TileMode::kRepeat; + case flutter::DlTileMode::kMirror: + return Entity::TileMode::kMirror; + case flutter::DlTileMode::kDecal: + return Entity::TileMode::kDecal; + } +} + +impeller::SamplerDescriptor ToSamplerDescriptor( + const flutter::DlImageSampling options) { + impeller::SamplerDescriptor desc; + switch (options) { + case flutter::DlImageSampling::kNearestNeighbor: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; + desc.label = "Nearest Sampler"; + break; + case flutter::DlImageSampling::kLinear: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; + desc.label = "Linear Sampler"; + break; + case flutter::DlImageSampling::kMipmapLinear: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; + desc.mip_filter = impeller::MipFilter::kLinear; + desc.label = "Mipmap Linear Sampler"; + break; + default: + break; + } + return desc; +} + +impeller::SamplerDescriptor ToSamplerDescriptor( + const flutter::DlFilterMode options) { + impeller::SamplerDescriptor desc; + switch (options) { + case flutter::DlFilterMode::kNearest: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; + desc.label = "Nearest Sampler"; + break; + case flutter::DlFilterMode::kLinear: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; + desc.label = "Linear Sampler"; + break; + default: + break; + } + return desc; +} + +Matrix ToMatrix(const SkMatrix& m) { + return Matrix{ + // clang-format off + m[0], m[3], 0, m[6], + m[1], m[4], 0, m[7], + 0, 0, 1, 0, + m[2], m[5], 0, m[8], + // clang-format on + }; +} + +Point ToPoint(const SkPoint& point) { + return Point::MakeXY(point.fX, point.fY); +} + +Color ToColor(const SkColor& color) { + return { + static_cast(SkColorGetR(color) / 255.0), // + static_cast(SkColorGetG(color) / 255.0), // + static_cast(SkColorGetB(color) / 255.0), // + static_cast(SkColorGetA(color) / 255.0) // + }; +} + +std::vector ToColors(const flutter::DlColor colors[], int count) { + auto result = std::vector(); + if (colors == nullptr) { + return result; + } + for (int i = 0; i < count; i++) { + result.push_back(ToColor(colors[i])); + } + return result; +} + +std::vector ToRSXForms(const SkRSXform xform[], int count) { + auto result = std::vector(); + for (int i = 0; i < count; i++) { + auto form = xform[i]; + // clang-format off + auto matrix = Matrix{ + form.fSCos, form.fSSin, 0, 0, + -form.fSSin, form.fSCos, 0, 0, + 0, 0, 1, 0, + form.fTx, form.fTy, 0, 1 + }; + // clang-format on + result.push_back(matrix); + } + return result; +} + +} // namespace impeller diff --git a/impeller/display_list/conversion_utilities.h b/impeller/display_list/conversion_utilities.h new file mode 100644 index 0000000000000..8cf0cee988e0f --- /dev/null +++ b/impeller/display_list/conversion_utilities.h @@ -0,0 +1,69 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "flutter/display_list/display_list_blend_mode.h" +#include "flutter/display_list/display_list_color.h" +#include "flutter/display_list/display_list_sampling_options.h" +#include "flutter/display_list/display_list_tile_mode.h" +#include "impeller/entity/entity.h" +#include "impeller/geometry/color.h" +#include "impeller/geometry/matrix.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkMatrix.h" +#include "third_party/skia/include/core/SkPoint.h" + +namespace impeller { + +#define UNIMPLEMENTED \ + FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__; + +BlendMode ToBlendMode(flutter::DlBlendMode mode); + +Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode); + +impeller::SamplerDescriptor ToSamplerDescriptor( + const flutter::DlImageSampling options); + +impeller::SamplerDescriptor ToSamplerDescriptor( + const flutter::DlFilterMode options); + +Matrix ToMatrix(const SkMatrix& m); + +Point ToPoint(const SkPoint& point); + +Color ToColor(const SkColor& color); + +std::vector ToColors(const flutter::DlColor colors[], int count); + +std::vector ToRSXForms(const SkRSXform xform[], int count); + +// Convert display list colors + stops into impeller colors and stops, taking +// care to ensure that the stops always start with 0.0 and end with 1.0. +template +void ConvertStops(T* gradient, + std::vector* colors, + std::vector* stops) { + FML_DCHECK(gradient->stop_count() >= 2); + + auto* dl_colors = gradient->colors(); + auto* dl_stops = gradient->stops(); + if (dl_stops[0] != 0.0) { + colors->emplace_back(ToColor(dl_colors[0])); + stops->emplace_back(0); + } + for (auto i = 0; i < gradient->stop_count(); i++) { + colors->emplace_back(ToColor(dl_colors[i])); + stops->emplace_back(dl_stops[i]); + } + if (stops->back() != 1.0) { + colors->emplace_back(colors->back()); + stops->emplace_back(1.0); + } +} + +} // namespace impeller diff --git a/impeller/display_list/display_list_color_source_factory.cc b/impeller/display_list/display_list_color_source_factory.cc new file mode 100644 index 0000000000000..af3e938f4702c --- /dev/null +++ b/impeller/display_list/display_list_color_source_factory.cc @@ -0,0 +1,286 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/display_list/display_list_color_source_factory.h" + +#include + +#include "flutter/display_list/display_list_color_source.h" +#include "impeller/display_list/conversion_utilities.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" + +namespace impeller { + +//------------------------------------------------------------------------------ +/// DlColorSourceFactory +/// + +DlColorSourceFactory::DlColorSourceFactory( + const std::shared_ptr& dl_color_source) + : dl_color_source_(dl_color_source){}; + +DlColorSourceFactory::~DlColorSourceFactory() = default; + +//------------------------------------------------------------------------------ +/// DlImageColorSourceFactory +/// + +DlImageColorSourceFactory::DlImageColorSourceFactory( + const std::shared_ptr& dl_color_source) + : DlColorSourceFactory(dl_color_source){}; + +DlImageColorSourceFactory::~DlImageColorSourceFactory() = default; + +std::shared_ptr DlImageColorSourceFactory::Make( + const std::shared_ptr& dl_color_source) { + if (!dl_color_source->asImage()) { + return nullptr; + } + return std::shared_ptr( + new DlImageColorSourceFactory(dl_color_source)); +} + +// |ColorSourceFactory| +std::shared_ptr DlImageColorSourceFactory::MakeContents() { + const flutter::DlImageColorSource* image_color_source = + dl_color_source_->asImage(); + FML_DCHECK(image_color_source && + image_color_source->image()->impeller_texture()); + + auto texture = image_color_source->image()->impeller_texture(); + auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode()); + auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode()); + auto desc = ToSamplerDescriptor(image_color_source->sampling()); + auto matrix = ToMatrix(image_color_source->matrix()); + + auto contents = std::make_shared(); + contents->SetTexture(texture); + contents->SetTileModes(x_tile_mode, y_tile_mode); + contents->SetSamplerDescriptor(desc); + contents->SetMatrix(matrix); + return contents; +} + +// |ColorSourceFactory| +ColorSourceFactory::ColorSourceType DlImageColorSourceFactory::GetType() { + return ColorSourceFactory::ColorSourceType::kImage; +} + +//------------------------------------------------------------------------------ +/// DlLinearGradientColorSourceFactory +/// + +DlLinearGradientColorSourceFactory::DlLinearGradientColorSourceFactory( + const std::shared_ptr& dl_color_source) + : DlColorSourceFactory(dl_color_source){}; + +DlLinearGradientColorSourceFactory::~DlLinearGradientColorSourceFactory() = + default; + +std::shared_ptr DlLinearGradientColorSourceFactory::Make( + const std::shared_ptr& dl_color_source) { + if (!dl_color_source->asImage()) { + return nullptr; + } + return std::shared_ptr( + new DlLinearGradientColorSourceFactory(dl_color_source)); +} + +// |ColorSourceFactory| +std::shared_ptr +DlLinearGradientColorSourceFactory::MakeContents() { + const flutter::DlLinearGradientColorSource* linear = + dl_color_source_->asLinearGradient(); + FML_DCHECK(linear); + + auto start_point = ToPoint(linear->start_point()); + auto end_point = ToPoint(linear->end_point()); + std::vector colors; + std::vector stops; + ConvertStops(linear, &colors, &stops); + auto tile_mode = ToTileMode(linear->tile_mode()); + auto matrix = ToMatrix(linear->matrix()); + auto contents = std::make_shared(); + + contents->SetColors(colors); + contents->SetStops(stops); + contents->SetEndPoints(start_point, end_point); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; +} + +// |ColorSourceFactory| +ColorSourceFactory::ColorSourceType +DlLinearGradientColorSourceFactory::GetType() { + return ColorSourceFactory::ColorSourceType::kLinearGradient; +} + +//------------------------------------------------------------------------------ +/// DlRadialGradientColorSourceFactory +/// + +DlRadialGradientColorSourceFactory::DlRadialGradientColorSourceFactory( + const std::shared_ptr& dl_color_source) + : DlColorSourceFactory(dl_color_source){}; + +DlRadialGradientColorSourceFactory::~DlRadialGradientColorSourceFactory() = + default; + +std::shared_ptr DlRadialGradientColorSourceFactory::Make( + const std::shared_ptr& dl_color_source) { + if (!dl_color_source->asImage()) { + return nullptr; + } + return std::shared_ptr( + new DlRadialGradientColorSourceFactory(dl_color_source)); +} + +// |ColorSourceFactory| +std::shared_ptr +DlRadialGradientColorSourceFactory::MakeContents() { + const flutter::DlRadialGradientColorSource* radial_gradient = + dl_color_source_->asRadialGradient(); + FML_DCHECK(radial_gradient); + + auto center = ToPoint(radial_gradient->center()); + auto radius = radial_gradient->radius(); + std::vector colors; + std::vector stops; + ConvertStops(radial_gradient, &colors, &stops); + auto tile_mode = ToTileMode(radial_gradient->tile_mode()); + auto matrix = ToMatrix(radial_gradient->matrix()); + auto contents = std::make_shared(); + + contents->SetColors(colors); + contents->SetStops(stops); + contents->SetCenterAndRadius(center, radius); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; +} + +// |ColorSourceFactory| +ColorSourceFactory::ColorSourceType +DlRadialGradientColorSourceFactory::GetType() { + return ColorSourceFactory::ColorSourceType::kRadialGradient; +} + +//------------------------------------------------------------------------------ +/// DlSweepGradientColorSourceFactory +/// + +DlSweepGradientColorSourceFactory::DlSweepGradientColorSourceFactory( + const std::shared_ptr& dl_color_source) + : DlColorSourceFactory(dl_color_source){}; + +DlSweepGradientColorSourceFactory::~DlSweepGradientColorSourceFactory() = + default; + +std::shared_ptr DlSweepGradientColorSourceFactory::Make( + const std::shared_ptr& dl_color_source) { + if (!dl_color_source->asImage()) { + return nullptr; + } + return std::shared_ptr( + new DlSweepGradientColorSourceFactory(dl_color_source)); +} + +// |ColorSourceFactory| +std::shared_ptr +DlSweepGradientColorSourceFactory::MakeContents() { + const flutter::DlSweepGradientColorSource* sweep_gradient = + dl_color_source_->asSweepGradient(); + FML_DCHECK(sweep_gradient); + + auto center = ToPoint(sweep_gradient->center()); + auto start_angle = Degrees(sweep_gradient->start()); + auto end_angle = Degrees(sweep_gradient->end()); + std::vector colors; + std::vector stops; + ConvertStops(sweep_gradient, &colors, &stops); + auto tile_mode = ToTileMode(sweep_gradient->tile_mode()); + auto matrix = ToMatrix(sweep_gradient->matrix()); + + auto contents = std::make_shared(); + contents->SetCenterAndAngles(center, start_angle, end_angle); + contents->SetColors(colors); + contents->SetStops(stops); + contents->SetTileMode(tile_mode); + contents->SetMatrix(matrix); + return contents; +} + +// |ColorSourceFactory| +ColorSourceFactory::ColorSourceType +DlSweepGradientColorSourceFactory::GetType() { + return ColorSourceFactory::ColorSourceType::kSweepGradient; +} + +//------------------------------------------------------------------------------ +/// DlRuntimeEffectColorSourceFactory +/// + +DlRuntimeEffectColorSourceFactory::DlRuntimeEffectColorSourceFactory( + const std::shared_ptr& dl_color_source) + : DlColorSourceFactory(dl_color_source){}; + +DlRuntimeEffectColorSourceFactory::~DlRuntimeEffectColorSourceFactory() = + default; + +std::shared_ptr DlRuntimeEffectColorSourceFactory::Make( + const std::shared_ptr& dl_color_source) { + if (!dl_color_source->asImage()) { + return nullptr; + } + return std::shared_ptr( + new DlRuntimeEffectColorSourceFactory(dl_color_source)); +} + +// |ColorSourceFactory| +std::shared_ptr +DlRuntimeEffectColorSourceFactory::MakeContents() { + const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source = + dl_color_source_->asRuntimeEffect(); + auto runtime_stage = + runtime_effect_color_source->runtime_effect()->runtime_stage(); + auto uniform_data = runtime_effect_color_source->uniform_data(); + auto samplers = runtime_effect_color_source->samplers(); + + std::vector texture_inputs; + + for (auto& sampler : samplers) { + if (sampler == nullptr) { + return nullptr; + } + auto* image = sampler->asImage(); + if (!sampler->asImage()) { + UNIMPLEMENTED; + return nullptr; + } + FML_DCHECK(image->image()->impeller_texture()); + texture_inputs.push_back({ + .sampler_descriptor = ToSamplerDescriptor(image->sampling()), + .texture = image->image()->impeller_texture(), + }); + } + + auto contents = std::make_shared(); + contents->SetRuntimeStage(runtime_stage); + contents->SetUniformData(uniform_data); + contents->SetTextureInputs(texture_inputs); + return contents; +} + +// |ColorSourceFactory| +ColorSourceFactory::ColorSourceType +DlRuntimeEffectColorSourceFactory::GetType() { + return ColorSourceFactory::ColorSourceType::kRuntimeEffect; +} + +} // namespace impeller diff --git a/impeller/display_list/display_list_color_source_factory.h b/impeller/display_list/display_list_color_source_factory.h new file mode 100644 index 0000000000000..4346930e98e2d --- /dev/null +++ b/impeller/display_list/display_list_color_source_factory.h @@ -0,0 +1,146 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "flutter/display_list/display_list_color_source.h" +#include "impeller/aiks/color_source_factory.h" +#include "impeller/entity/contents/color_source_contents.h" + +namespace impeller { + +//------------------------------------------------------------------------------ +/// DlColorSourceFactory +/// + +class DlColorSourceFactory : public ColorSourceFactory { + public: + // |ColorSourceFactory| + ~DlColorSourceFactory() override; + + protected: + explicit DlColorSourceFactory( + const std::shared_ptr& dl_color_source); + + std::shared_ptr dl_color_source_; +}; + +//------------------------------------------------------------------------------ +/// DlImageColorSourceFactory +/// + +class DlImageColorSourceFactory final : public DlColorSourceFactory { + public: + static std::shared_ptr Make( + const std::shared_ptr& dl_color_source); + + // |ColorSourceFactory| + ~DlImageColorSourceFactory() override; + + // |ColorSourceFactory| + std::shared_ptr MakeContents() override; + + // |ColorSourceFactory| + ColorSourceFactory::ColorSourceType GetType() override; + + private: + explicit DlImageColorSourceFactory( + const std::shared_ptr& dl_color_source); +}; + +//------------------------------------------------------------------------------ +/// DlLinearGradientColorSourceFactory +/// + +class DlLinearGradientColorSourceFactory final : public DlColorSourceFactory { + public: + static std::shared_ptr Make( + const std::shared_ptr& dl_color_source); + + // |ColorSourceFactory| + ~DlLinearGradientColorSourceFactory() override; + + // |ColorSourceFactory| + std::shared_ptr MakeContents() override; + + // |ColorSourceFactory| + ColorSourceFactory::ColorSourceType GetType() override; + + private: + explicit DlLinearGradientColorSourceFactory( + const std::shared_ptr& dl_color_source); +}; + +//------------------------------------------------------------------------------ +/// DlRadialGradientColorSourceFactory +/// + +class DlRadialGradientColorSourceFactory final : public DlColorSourceFactory { + public: + static std::shared_ptr Make( + const std::shared_ptr& dl_color_source); + + // |ColorSourceFactory| + ~DlRadialGradientColorSourceFactory() override; + + // |ColorSourceFactory| + std::shared_ptr MakeContents() override; + + // |ColorSourceFactory| + ColorSourceFactory::ColorSourceType GetType() override; + + private: + explicit DlRadialGradientColorSourceFactory( + const std::shared_ptr& dl_color_source); +}; + +//------------------------------------------------------------------------------ +/// DlSweepGradientColorSourceFactory +/// + +class DlSweepGradientColorSourceFactory final : public DlColorSourceFactory { + public: + static std::shared_ptr Make( + const std::shared_ptr& dl_color_source); + + // |ColorSourceFactory| + ~DlSweepGradientColorSourceFactory() override; + + // |ColorSourceFactory| + std::shared_ptr MakeContents() override; + + // |ColorSourceFactory| + ColorSourceFactory::ColorSourceType GetType() override; + + private: + explicit DlSweepGradientColorSourceFactory( + const std::shared_ptr& dl_color_source); +}; + +//------------------------------------------------------------------------------ +/// DlRuntimeEffectColorSourceFactory +/// + +class DlRuntimeEffectColorSourceFactory final : public DlColorSourceFactory { + public: + static std::shared_ptr Make( + const std::shared_ptr& dl_color_source); + + // |ColorSourceFactory| + ~DlRuntimeEffectColorSourceFactory() override; + + // |ColorSourceFactory| + std::shared_ptr MakeContents() override; + + // |ColorSourceFactory| + ColorSourceFactory::ColorSourceType GetType() override; + + private: + explicit DlRuntimeEffectColorSourceFactory( + const std::shared_ptr& dl_color_source); +}; + +} // namespace impeller diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index a5fe27bb24aca..f771d35bbf49e 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -19,6 +19,8 @@ #include "display_list/display_list_tile_mode.h" #include "flutter/fml/logging.h" #include "flutter/fml/trace_event.h" +#include "impeller/display_list/conversion_utilities.h" +#include "impeller/display_list/display_list_color_source_factory.h" #include "impeller/display_list/display_list_image_impeller.h" #include "impeller/display_list/nine_patch_converter.h" #include "impeller/display_list/vertices_converter.h" @@ -43,142 +45,10 @@ namespace impeller { -#define UNIMPLEMENTED \ - FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__; - DisplayListDispatcher::DisplayListDispatcher() = default; DisplayListDispatcher::~DisplayListDispatcher() = default; -static BlendMode ToBlendMode(flutter::DlBlendMode mode) { - switch (mode) { - case flutter::DlBlendMode::kClear: - return BlendMode::kClear; - case flutter::DlBlendMode::kSrc: - return BlendMode::kSource; - case flutter::DlBlendMode::kDst: - return BlendMode::kDestination; - case flutter::DlBlendMode::kSrcOver: - return BlendMode::kSourceOver; - case flutter::DlBlendMode::kDstOver: - return BlendMode::kDestinationOver; - case flutter::DlBlendMode::kSrcIn: - return BlendMode::kSourceIn; - case flutter::DlBlendMode::kDstIn: - return BlendMode::kDestinationIn; - case flutter::DlBlendMode::kSrcOut: - return BlendMode::kSourceOut; - case flutter::DlBlendMode::kDstOut: - return BlendMode::kDestinationOut; - case flutter::DlBlendMode::kSrcATop: - return BlendMode::kSourceATop; - case flutter::DlBlendMode::kDstATop: - return BlendMode::kDestinationATop; - case flutter::DlBlendMode::kXor: - return BlendMode::kXor; - case flutter::DlBlendMode::kPlus: - return BlendMode::kPlus; - case flutter::DlBlendMode::kModulate: - return BlendMode::kModulate; - case flutter::DlBlendMode::kScreen: - return BlendMode::kScreen; - case flutter::DlBlendMode::kOverlay: - return BlendMode::kOverlay; - case flutter::DlBlendMode::kDarken: - return BlendMode::kDarken; - case flutter::DlBlendMode::kLighten: - return BlendMode::kLighten; - case flutter::DlBlendMode::kColorDodge: - return BlendMode::kColorDodge; - case flutter::DlBlendMode::kColorBurn: - return BlendMode::kColorBurn; - case flutter::DlBlendMode::kHardLight: - return BlendMode::kHardLight; - case flutter::DlBlendMode::kSoftLight: - return BlendMode::kSoftLight; - case flutter::DlBlendMode::kDifference: - return BlendMode::kDifference; - case flutter::DlBlendMode::kExclusion: - return BlendMode::kExclusion; - case flutter::DlBlendMode::kMultiply: - return BlendMode::kMultiply; - case flutter::DlBlendMode::kHue: - return BlendMode::kHue; - case flutter::DlBlendMode::kSaturation: - return BlendMode::kSaturation; - case flutter::DlBlendMode::kColor: - return BlendMode::kColor; - case flutter::DlBlendMode::kLuminosity: - return BlendMode::kLuminosity; - } - FML_UNREACHABLE(); -} - -static Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) { - switch (tile_mode) { - case flutter::DlTileMode::kClamp: - return Entity::TileMode::kClamp; - case flutter::DlTileMode::kRepeat: - return Entity::TileMode::kRepeat; - case flutter::DlTileMode::kMirror: - return Entity::TileMode::kMirror; - case flutter::DlTileMode::kDecal: - return Entity::TileMode::kDecal; - } -} - -static impeller::SamplerDescriptor ToSamplerDescriptor( - const flutter::DlImageSampling options) { - impeller::SamplerDescriptor desc; - switch (options) { - case flutter::DlImageSampling::kNearestNeighbor: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; - desc.label = "Nearest Sampler"; - break; - case flutter::DlImageSampling::kLinear: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; - desc.label = "Linear Sampler"; - break; - case flutter::DlImageSampling::kMipmapLinear: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; - desc.mip_filter = impeller::MipFilter::kLinear; - desc.label = "Mipmap Linear Sampler"; - break; - default: - break; - } - return desc; -} - -static impeller::SamplerDescriptor ToSamplerDescriptor( - const flutter::DlFilterMode options) { - impeller::SamplerDescriptor desc; - switch (options) { - case flutter::DlFilterMode::kNearest: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; - desc.label = "Nearest Sampler"; - break; - case flutter::DlFilterMode::kLinear: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; - desc.label = "Linear Sampler"; - break; - default: - break; - } - return desc; -} - -static Matrix ToMatrix(const SkMatrix& m) { - return Matrix{ - // clang-format off - m[0], m[3], 0, m[6], - m[1], m[4], 0, m[7], - 0, 0, 1, 0, - m[2], m[5], 0, m[8], - // clang-format on - }; -} - // |flutter::Dispatcher| void DisplayListDispatcher::setAntiAlias(bool aa) { // Nothing to do because AA is implicit. @@ -255,255 +125,41 @@ void DisplayListDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) { } } -static Point ToPoint(const SkPoint& point) { - return Point::MakeXY(point.fX, point.fY); -} - -static Color ToColor(const SkColor& color) { - return { - static_cast(SkColorGetR(color) / 255.0), // - static_cast(SkColorGetG(color) / 255.0), // - static_cast(SkColorGetB(color) / 255.0), // - static_cast(SkColorGetA(color) / 255.0) // - }; -} - -static std::vector ToColors(const flutter::DlColor colors[], int count) { - auto result = std::vector(); - if (colors == nullptr) { - return result; +static std::shared_ptr ToColorSourceFactory( + const std::shared_ptr& dl_color_source) { + if (!dl_color_source) { + return nullptr; } - for (int i = 0; i < count; i++) { - result.push_back(ToColor(colors[i])); - } - return result; -} - -static std::vector ToRSXForms(const SkRSXform xform[], int count) { - auto result = std::vector(); - for (int i = 0; i < count; i++) { - auto form = xform[i]; - // clang-format off - auto matrix = Matrix{ - form.fSCos, form.fSSin, 0, 0, - -form.fSSin, form.fSCos, 0, 0, - 0, 0, 1, 0, - form.fTx, form.fTy, 0, 1 - }; - // clang-format on - result.push_back(matrix); - } - return result; -} -// Convert display list colors + stops into impeller colors and stops, taking -// care to ensure that the stops always start with 0.0 and end with 1.0. -template -static void ConvertStops(T* gradient, - std::vector* colors, - std::vector* stops) { - FML_DCHECK(gradient->stop_count() >= 2); - - auto* dl_colors = gradient->colors(); - auto* dl_stops = gradient->stops(); - if (dl_stops[0] != 0.0) { - colors->emplace_back(ToColor(dl_colors[0])); - stops->emplace_back(0); - } - for (auto i = 0; i < gradient->stop_count(); i++) { - colors->emplace_back(ToColor(dl_colors[i])); - stops->emplace_back(dl_stops[i]); - } - if (stops->back() != 1.0) { - colors->emplace_back(colors->back()); - stops->emplace_back(1.0); - } -} - -static std::optional ToColorSourceType( - flutter::DlColorSourceType type) { - switch (type) { + switch (dl_color_source->type()) { case flutter::DlColorSourceType::kColor: - return Paint::ColorSourceType::kColor; + return nullptr; case flutter::DlColorSourceType::kImage: - return Paint::ColorSourceType::kImage; + return DlImageColorSourceFactory::Make(dl_color_source->shared()); case flutter::DlColorSourceType::kLinearGradient: - return Paint::ColorSourceType::kLinearGradient; + return DlLinearGradientColorSourceFactory::Make( + dl_color_source->shared()); case flutter::DlColorSourceType::kRadialGradient: - return Paint::ColorSourceType::kRadialGradient; - case flutter::DlColorSourceType::kConicalGradient: - return Paint::ColorSourceType::kConicalGradient; + return DlRadialGradientColorSourceFactory::Make( + dl_color_source->shared()); case flutter::DlColorSourceType::kSweepGradient: - return Paint::ColorSourceType::kSweepGradient; + return DlSweepGradientColorSourceFactory::Make(dl_color_source->shared()); case flutter::DlColorSourceType::kRuntimeEffect: - return Paint::ColorSourceType::kRuntimeEffect; + return DlRuntimeEffectColorSourceFactory::Make(dl_color_source->shared()); + case flutter::DlColorSourceType::kConicalGradient: case flutter::DlColorSourceType::kUnknown: - return std::nullopt; + UNIMPLEMENTED; + return nullptr; } } // |flutter::Dispatcher| void DisplayListDispatcher::setColorSource( - const flutter::DlColorSource* source) { - if (!source) { - paint_.color_source = std::nullopt; - paint_.color_source_type = Paint::ColorSourceType::kColor; - return; - } - - std::optional type = - ToColorSourceType(source->type()); - - if (!type.has_value()) { - FML_LOG(ERROR) << "Requested ColorSourceType::kUnknown"; - paint_.color_source = std::nullopt; - paint_.color_source_type = Paint::ColorSourceType::kColor; - return; - } - - paint_.color_source_type = type.value(); - - switch (type.value()) { - case Paint::ColorSourceType::kColor: { - const flutter::DlColorColorSource* color = source->asColor(); - paint_.color_source = std::nullopt; - setColor(color->color()); - FML_DCHECK(color); - return; - } - case Paint::ColorSourceType::kLinearGradient: { - const flutter::DlLinearGradientColorSource* linear = - source->asLinearGradient(); - FML_DCHECK(linear); - auto start_point = ToPoint(linear->start_point()); - auto end_point = ToPoint(linear->end_point()); - std::vector colors; - std::vector stops; - ConvertStops(linear, &colors, &stops); - - auto tile_mode = ToTileMode(linear->tile_mode()); - auto matrix = ToMatrix(linear->matrix()); - paint_.color_source = [start_point, end_point, colors = std::move(colors), - stops = std::move(stops), tile_mode, matrix]() { - auto contents = std::make_shared(); - contents->SetColors(colors); - contents->SetStops(stops); - contents->SetEndPoints(start_point, end_point); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; - return; - } - case Paint::ColorSourceType::kRadialGradient: { - const flutter::DlRadialGradientColorSource* radialGradient = - source->asRadialGradient(); - FML_DCHECK(radialGradient); - auto center = ToPoint(radialGradient->center()); - auto radius = radialGradient->radius(); - std::vector colors; - std::vector stops; - ConvertStops(radialGradient, &colors, &stops); - - auto tile_mode = ToTileMode(radialGradient->tile_mode()); - auto matrix = ToMatrix(radialGradient->matrix()); - paint_.color_source = [center, radius, colors = std::move(colors), - stops = std::move(stops), tile_mode, matrix]() { - auto contents = std::make_shared(); - contents->SetColors(colors); - contents->SetStops(stops); - contents->SetCenterAndRadius(center, radius); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; - return; - } - case Paint::ColorSourceType::kSweepGradient: { - const flutter::DlSweepGradientColorSource* sweepGradient = - source->asSweepGradient(); - FML_DCHECK(sweepGradient); - - auto center = ToPoint(sweepGradient->center()); - auto start_angle = Degrees(sweepGradient->start()); - auto end_angle = Degrees(sweepGradient->end()); - std::vector colors; - std::vector stops; - ConvertStops(sweepGradient, &colors, &stops); - - auto tile_mode = ToTileMode(sweepGradient->tile_mode()); - auto matrix = ToMatrix(sweepGradient->matrix()); - paint_.color_source = [center, start_angle, end_angle, - colors = std::move(colors), - stops = std::move(stops), tile_mode, matrix]() { - auto contents = std::make_shared(); - contents->SetCenterAndAngles(center, start_angle, end_angle); - contents->SetColors(colors); - contents->SetStops(stops); - contents->SetTileMode(tile_mode); - contents->SetMatrix(matrix); - return contents; - }; - return; - } - case Paint::ColorSourceType::kImage: { - const flutter::DlImageColorSource* image_color_source = source->asImage(); - FML_DCHECK(image_color_source && - image_color_source->image()->impeller_texture()); - auto texture = image_color_source->image()->impeller_texture(); - auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode()); - auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode()); - auto desc = ToSamplerDescriptor(image_color_source->sampling()); - auto matrix = ToMatrix(image_color_source->matrix()); - paint_.color_source = [texture, x_tile_mode, y_tile_mode, desc, - matrix]() { - auto contents = std::make_shared(); - contents->SetTexture(texture); - contents->SetTileModes(x_tile_mode, y_tile_mode); - contents->SetSamplerDescriptor(desc); - contents->SetMatrix(matrix); - return contents; - }; - return; - } - case Paint::ColorSourceType::kRuntimeEffect: { - const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source = - source->asRuntimeEffect(); - auto runtime_stage = - runtime_effect_color_source->runtime_effect()->runtime_stage(); - auto uniform_data = runtime_effect_color_source->uniform_data(); - auto samplers = runtime_effect_color_source->samplers(); - - std::vector texture_inputs; - - for (auto& sampler : samplers) { - if (sampler == nullptr) { - return; - } - auto* image = sampler->asImage(); - if (!sampler->asImage()) { - UNIMPLEMENTED; - return; - } - FML_DCHECK(image->image()->impeller_texture()); - texture_inputs.push_back({ - .sampler_descriptor = ToSamplerDescriptor(image->sampling()), - .texture = image->image()->impeller_texture(), - }); - } + const flutter::DlColorSource* dl_color_source) { + paint_.color_source = ToColorSourceFactory(dl_color_source->shared()); - paint_.color_source = [runtime_stage, uniform_data, texture_inputs]() { - auto contents = std::make_shared(); - contents->SetRuntimeStage(runtime_stage); - contents->SetUniformData(uniform_data); - contents->SetTextureInputs(texture_inputs); - return contents; - }; - return; - } - case Paint::ColorSourceType::kConicalGradient: - UNIMPLEMENTED; - break; + if (const flutter::DlColorColorSource* color = dl_color_source->asColor()) { + setColor(color->color()); } }