From 81a4a5e34bd57f042faee5b0f9622f3e41bb0449 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 8 Jun 2023 14:58:59 -0700 Subject: [PATCH] [Impeller] Specify blend mode on blend filter commands (flutter/engine#42676) Side quest of https://github.com/flutter/flutter/issues/127232. This is particularly useful for debugging pipeline blend variations of the blend filter, since we otherwise have to look at the raw pipeline blend ops and figure out and piece together what the blend mode must've been. --- .../contents/filters/blend_filter_contents.cc | 48 +++++++++++-------- .../contents/filters/blend_filter_contents.h | 1 + engine/src/flutter/impeller/geometry/color.cc | 11 +++++ engine/src/flutter/impeller/geometry/color.h | 4 +- .../impeller/geometry/geometry_unittests.cc | 16 +++++++ 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc index 287ec60ee3..4fb81ce6fa 100644 --- a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc @@ -8,6 +8,7 @@ #include #include +#include "impeller/base/strings.h" #include "impeller/core/formats.h" #include "impeller/entity/contents/anonymous_contents.h" #include "impeller/entity/contents/content_context.h" @@ -15,6 +16,7 @@ #include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/entity.h" +#include "impeller/geometry/color.h" #include "impeller/geometry/path_builder.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/sampler_library.h" @@ -37,6 +39,7 @@ static std::optional AdvancedBlend( const ContentContext& renderer, const Entity& entity, const Rect& coverage, + BlendMode blend_mode, std::optional foreground_color, bool absorb_opacity, PipelineProc pipeline_proc, @@ -114,7 +117,8 @@ static std::optional AdvancedBlend( std::invoke(pipeline_proc, renderer, options); Command cmd; - cmd.label = "Advanced Blend Filter"; + cmd.label = + SPrintF("Advanced Blend Filter (%s)", BlendModeToString(blend_mode)); cmd.BindVertices(vtx_buffer); cmd.pipeline = std::move(pipeline); @@ -228,7 +232,8 @@ std::optional BlendFilterContents::CreateForegroundAdvancedBlend( auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer); Command cmd; - cmd.label = "Foreground Advanced Blend Filter"; + cmd.label = SPrintF("Foreground Advanced Blend Filter (%s)", + BlendModeToString(blend_mode)); cmd.BindVertices(vtx_buffer); cmd.stencil_reference = entity.GetStencilDepth(); auto options = OptionsFromPass(pass); @@ -413,7 +418,8 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer); Command cmd; - cmd.label = "Foreground PorterDuff Blend Filter"; + cmd.label = SPrintF("Foreground PorterDuff Blend Filter (%s)", + BlendModeToString(blend_mode)); cmd.BindVertices(vtx_buffer); cmd.stencil_reference = entity.GetStencilDepth(); auto options = OptionsFromPass(pass); @@ -475,7 +481,7 @@ static std::optional PipelineBlend( const ContentContext& renderer, const Entity& entity, const Rect& coverage, - BlendMode pipeline_blend, + BlendMode blend_mode, std::optional foreground_color, bool absorb_opacity, std::optional alpha) { @@ -493,7 +499,8 @@ static std::optional PipelineBlend( auto& host_buffer = pass.GetTransientsBuffer(); Command cmd; - cmd.label = "Pipeline Blend Filter"; + cmd.label = + SPrintF("Pipeline Blend Filter (%s)", BlendModeToString(blend_mode)); auto options = OptionsFromPass(pass); auto add_blend_command = [&](std::optional input) { @@ -548,7 +555,7 @@ static std::optional PipelineBlend( // Write subsequent textures using the selected blend mode. if (inputs.size() >= 2) { - options.blend_mode = pipeline_blend; + options.blend_mode = blend_mode; cmd.pipeline = renderer.GetBlendPipeline(options); for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end(); @@ -570,7 +577,7 @@ static std::optional PipelineBlend( contents->SetColor(foreground_color.value()); Entity foreground_entity; - foreground_entity.SetBlendMode(pipeline_blend); + foreground_entity.SetBlendMode(blend_mode); foreground_entity.SetContents(contents); if (!foreground_entity.Render(renderer, pass)) { return false; @@ -598,19 +605,18 @@ static std::optional PipelineBlend( entity.GetBlendMode(), entity.GetStencilDepth()); } -#define BLEND_CASE(mode) \ - case BlendMode::k##mode: \ - advanced_blend_proc_ = [](const FilterInput::Vector& inputs, \ - const ContentContext& renderer, \ - const Entity& entity, const Rect& coverage, \ - std::optional fg_color, \ - bool absorb_opacity, \ - std::optional alpha) { \ - PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ - return AdvancedBlend(inputs, renderer, entity, \ - coverage, fg_color, \ - absorb_opacity, p, alpha); \ - }; \ +#define BLEND_CASE(mode) \ + case BlendMode::k##mode: \ + advanced_blend_proc_ = \ + [](const FilterInput::Vector& inputs, const ContentContext& renderer, \ + const Entity& entity, const Rect& coverage, BlendMode blend_mode, \ + std::optional fg_color, bool absorb_opacity, \ + std::optional alpha) { \ + PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ + return AdvancedBlend( \ + inputs, renderer, entity, coverage, blend_mode, fg_color, \ + absorb_opacity, p, alpha); \ + }; \ break; void BlendFilterContents::SetBlendMode(BlendMode blend_mode) { @@ -683,7 +689,7 @@ std::optional BlendFilterContents::RenderFilter( inputs[0], renderer, entity, coverage, foreground_color_.value(), blend_mode_, GetAlpha(), GetAbsorbOpacity()); } - return advanced_blend_proc_(inputs, renderer, entity, coverage, + return advanced_blend_proc_(inputs, renderer, entity, coverage, blend_mode_, foreground_color_, GetAbsorbOpacity(), GetAlpha()); } diff --git a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h index 01078e9aba..fc602fb85d 100644 --- a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h +++ b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h @@ -16,6 +16,7 @@ class BlendFilterContents : public ColorFilterContents { const ContentContext& renderer, const Entity& entity, const Rect& coverage, + BlendMode blend_mode, std::optional foreground_color, bool absorb_opacity, std::optional alpha)>; diff --git a/engine/src/flutter/impeller/geometry/color.cc b/engine/src/flutter/impeller/geometry/color.cc index 17dd4f34ae..d51ee111f5 100644 --- a/engine/src/flutter/impeller/geometry/color.cc +++ b/engine/src/flutter/impeller/geometry/color.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include "impeller/base/strings.h" #include "impeller/geometry/constants.h" @@ -37,6 +38,16 @@ static constexpr inline bool ValidateBlendModes() { static_assert(ValidateBlendModes(), "IMPELLER_FOR_EACH_BLEND_MODE must match impeller::BlendMode."); +#define _IMPELLER_BLEND_MODE_NAME_LIST(blend_mode) #blend_mode, + +static constexpr const char* kBlendModeNames[] = { + IMPELLER_FOR_EACH_BLEND_MODE(_IMPELLER_BLEND_MODE_NAME_LIST)}; + +const char* BlendModeToString(BlendMode blend_mode) { + return kBlendModeNames[static_cast>( + blend_mode)]; +} + ColorHSB ColorHSB::FromRGB(Color rgb) { Scalar R = rgb.red; Scalar G = rgb.green; diff --git a/engine/src/flutter/impeller/geometry/color.h b/engine/src/flutter/impeller/geometry/color.h index 99d491e8f4..89fe96ef80 100644 --- a/engine/src/flutter/impeller/geometry/color.h +++ b/engine/src/flutter/impeller/geometry/color.h @@ -54,7 +54,7 @@ enum class YUVColorSpace { kBT601LimitedRange, kBT601FullRange }; enum class BlendMode { // The following blend modes are able to be used as pipeline blend modes or // via `BlendFilterContents`. - kClear, + kClear = 0, kSource, kDestination, kSourceOver, @@ -91,6 +91,8 @@ enum class BlendMode { kLast = kLuminosity, }; +const char* BlendModeToString(BlendMode blend_mode); + /** * Represents a RGBA color */ diff --git a/engine/src/flutter/impeller/geometry/geometry_unittests.cc b/engine/src/flutter/impeller/geometry/geometry_unittests.cc index 654cf8e660..951a405002 100644 --- a/engine/src/flutter/impeller/geometry/geometry_unittests.cc +++ b/engine/src/flutter/impeller/geometry/geometry_unittests.cc @@ -6,9 +6,11 @@ #include #include +#include #include "flutter/fml/build_config.h" #include "flutter/testing/testing.h" +#include "impeller/geometry/color.h" #include "impeller/geometry/constants.h" #include "impeller/geometry/gradient.h" #include "impeller/geometry/half.h" @@ -1446,6 +1448,20 @@ TEST(GeometryTest, ColorMakeRGBA8) { } } +#define _BLEND_MODE_NAME_CHECK(blend_mode) \ + case BlendMode::k##blend_mode: \ + ASSERT_STREQ(result, #blend_mode); \ + break; + +TEST(GeometryTest, BlendModeToString) { + using BlendT = std::underlying_type_t; + for (BlendT i = 0; i <= static_cast(BlendMode::kLast); i++) { + auto mode = static_cast(i); + auto result = BlendModeToString(mode); + switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) } + } +} + TEST(GeometryTest, CanConvertBetweenDegressAndRadians) { { auto deg = Degrees{90.0};