From 8ef540fc0d82bc16dd9fcd08940583672386ab4d Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Mon, 26 Sep 2022 20:38:55 +0800 Subject: [PATCH 1/8] [Impeller] Support 'texture_sampler_y_coord_scale' in more filters --- .../entity/contents/filters/blend_filter_contents.cc | 8 +++++--- .../contents/filters/border_mask_blur_filter_contents.cc | 7 +++++-- .../contents/filters/linear_to_srgb_filter_contents.cc | 6 +++++- .../contents/filters/srgb_to_linear_filter_contents.cc | 6 +++++- impeller/entity/shaders/blending/blend.frag | 9 ++++++++- impeller/entity/shaders/border_mask_blur.frag | 9 ++++++++- impeller/entity/shaders/linear_to_srgb_filter.frag | 8 +++++++- impeller/entity/shaders/srgb_to_linear_filter.frag | 8 +++++++- 8 files changed, 50 insertions(+), 11 deletions(-) diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 69968adfb284e..efc2627b1c7fe 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -192,9 +192,11 @@ static std::optional PipelineBlend( frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * Matrix::MakeTranslation(-coverage.origin) * input->transform; - - auto uniform_view = host_buffer.EmplaceUniform(frame_info); - VS::BindFrameInfo(cmd, uniform_view); + FS::FragInfo frag_info; + frag_info.texture_sampler_y_coord_scale = + input->texture->GetYCoordScale(); + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); + VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); pass.AddCommand(cmd); return true; diff --git a/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc b/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc index a7d578531d9e0..6d6fdef5f19dc 100644 --- a/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc @@ -108,8 +108,11 @@ std::optional BorderMaskBlurFilterContents::RenderFilter( frame_info.src_factor = src_color_factor_; frame_info.inner_blur_factor = inner_blur_factor_; frame_info.outer_blur_factor = outer_blur_factor_; - auto uniform_view = host_buffer.EmplaceUniform(frame_info); - VS::BindFrameInfo(cmd, uniform_view); + FS::FragInfo frag_info; + frag_info.texture_sampler_y_coord_scale = + input_snapshot->texture->GetYCoordScale(); + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); + VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindTextureSampler(cmd, input_snapshot->texture, sampler); diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc index 445ffa9e46b47..e11781321272a 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc @@ -61,9 +61,13 @@ std::optional LinearToSrgbFilterContents::RenderFilter( VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); + FS::FragInfo frag_info; + frag_info.texture_sampler_y_coord_scale = + input_snapshot->texture->GetYCoordScale(); + auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); - + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); return pass.AddCommand(std::move(cmd)); diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc index 6f5a7bc143af1..1d0ad22b57eee 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc @@ -61,9 +61,13 @@ std::optional SrgbToLinearFilterContents::RenderFilter( VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); + FS::FragInfo frag_info; + frag_info.texture_sampler_y_coord_scale = + input_snapshot->texture->GetYCoordScale(); + auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); - + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); return pass.AddCommand(std::move(cmd)); diff --git a/impeller/entity/shaders/blending/blend.frag b/impeller/entity/shaders/blending/blend.frag index debce522d6b43..d5122145bb9b4 100644 --- a/impeller/entity/shaders/blending/blend.frag +++ b/impeller/entity/shaders/blending/blend.frag @@ -2,12 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + uniform sampler2D texture_sampler_src; +uniform FragInfo { + float texture_sampler_y_coord_scale; +} frag_info; + in vec2 v_texture_coords; out vec4 frag_color; void main() { - frag_color = texture(texture_sampler_src, v_texture_coords); + frag_color = IPSample(texture_sampler_src, v_texture_coords, + frag_info.texture_sampler_y_coord_scale); } diff --git a/impeller/entity/shaders/border_mask_blur.frag b/impeller/entity/shaders/border_mask_blur.frag index 4c018bf3ad367..d35280f8dfecf 100644 --- a/impeller/entity/shaders/border_mask_blur.frag +++ b/impeller/entity/shaders/border_mask_blur.frag @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + // Constant time mask blur for image borders. // // This mask blur extends the geometry of the source image (with clamp border @@ -13,6 +15,10 @@ uniform sampler2D texture_sampler; +uniform FragInfo { + float texture_sampler_y_coord_scale; +} frag_info; + in vec2 v_texture_coords; in vec2 v_sigma_uv; in float v_src_factor; @@ -48,7 +54,8 @@ float BoxBlurMask(vec2 uv) { } void main() { - vec4 image_color = texture(texture_sampler, v_texture_coords); + vec4 image_color = IPSample(texture_sampler, v_texture_coords, + frag_info.texture_sampler_y_coord_scale); float blur_factor = BoxBlurMask(v_texture_coords); float within_bounds = diff --git a/impeller/entity/shaders/linear_to_srgb_filter.frag b/impeller/entity/shaders/linear_to_srgb_filter.frag index fea911c14f1e5..562bb5e119846 100644 --- a/impeller/entity/shaders/linear_to_srgb_filter.frag +++ b/impeller/entity/shaders/linear_to_srgb_filter.frag @@ -3,6 +3,7 @@ // found in the LICENSE file. #include +#include // A color filter that applies the sRGB gamma curve to the color. // @@ -10,11 +11,16 @@ uniform sampler2D input_texture; +uniform FragInfo { + float texture_sampler_y_coord_scale; +} frag_info; + in vec2 v_position; out vec4 frag_color; void main() { - vec4 input_color = texture(input_texture, v_position); + vec4 input_color = IPSample(input_texture, v_position, + frag_info.texture_sampler_y_coord_scale); for (int i = 0; i < 4; i++) { if (input_color[i] <= 0.0031308) { diff --git a/impeller/entity/shaders/srgb_to_linear_filter.frag b/impeller/entity/shaders/srgb_to_linear_filter.frag index 6c51b59a1de4c..e18bd18f3b278 100644 --- a/impeller/entity/shaders/srgb_to_linear_filter.frag +++ b/impeller/entity/shaders/srgb_to_linear_filter.frag @@ -3,17 +3,23 @@ // found in the LICENSE file. #include +#include // Creates a color filter that applies the inverse of the sRGB gamma curve // to the RGB channels. uniform sampler2D input_texture; +uniform FragInfo { + float texture_sampler_y_coord_scale; +} frag_info; + in vec2 v_position; out vec4 frag_color; void main() { - vec4 input_color = texture(input_texture, v_position); + vec4 input_color = IPSample(input_texture, v_position, + frag_info.texture_sampler_y_coord_scale); for (int i = 0; i < 4; i++) { if (input_color[i] <= 0.04045) { From 4c04abe6039e232c98dd510cf7aed44ba12a5ede Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Mon, 26 Sep 2022 23:32:15 +0800 Subject: [PATCH 2/8] [Impeller] Defer applying opacity when saving layer --- impeller/aiks/paint_pass_delegate.cc | 1 + .../display_list/display_list_dispatcher.cc | 26 +++++--- .../display_list/display_list_unittests.cc | 65 +++++++++++++++++++ .../contents/filters/blend_filter_contents.cc | 50 ++++++++------ .../contents/filters/blend_filter_contents.h | 3 +- .../border_mask_blur_filter_contents.cc | 3 +- .../filters/color_matrix_filter_contents.cc | 10 ++- .../contents/filters/filter_contents.cc | 27 ++++++-- .../entity/contents/filters/filter_contents.h | 17 +++-- .../filters/gaussian_blur_filter_contents.cc | 3 +- .../filters/linear_to_srgb_filter_contents.cc | 10 ++- .../filters/morphology_filter_contents.cc | 3 +- .../filters/srgb_to_linear_filter_contents.cc | 10 ++- impeller/entity/contents/texture_contents.cc | 9 ++- impeller/entity/contents/texture_contents.h | 3 + .../shaders/blending/advanced_blend.glsl | 6 +- impeller/entity/shaders/blending/blend.frag | 4 +- .../shaders/color_matrix_color_filter.frag | 5 +- .../entity/shaders/linear_to_srgb_filter.frag | 4 +- .../entity/shaders/srgb_to_linear_filter.frag | 4 +- impeller/renderer/snapshot.h | 2 + 21 files changed, 205 insertions(+), 60 deletions(-) diff --git a/impeller/aiks/paint_pass_delegate.cc b/impeller/aiks/paint_pass_delegate.cc index faaacf12f5d8b..f80441aa6d027 100644 --- a/impeller/aiks/paint_pass_delegate.cc +++ b/impeller/aiks/paint_pass_delegate.cc @@ -39,6 +39,7 @@ std::shared_ptr PaintPassDelegate::CreateContentsForSubpassTarget( contents->SetTexture(target); contents->SetSourceRect(Rect::MakeSize(target->GetSize())); contents->SetOpacity(paint_.color.alpha); + contents->SetDeferApplyingOpacity(true); return paint_.WithFilters(std::move(contents), false, effect_transform); } diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index ad2eb4286d123..8301cc0bd536e 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -419,7 +419,8 @@ void DisplayListDispatcher::setColorSource( } static std::optional ToColorFilterProc( - const flutter::DlColorFilter* filter) { + const flutter::DlColorFilter* filter, + bool need_absorb_opacity = true) { if (filter == nullptr) { return std::nullopt; } @@ -428,25 +429,29 @@ static std::optional ToColorFilterProc( auto dl_blend = filter->asBlend(); auto blend_mode = ToBlendMode(dl_blend->mode()); auto color = ToColor(dl_blend->color()); - return [blend_mode, color](FilterInput::Ref input) { - return FilterContents::MakeBlend(blend_mode, {input}, color); + return [blend_mode, color, need_absorb_opacity](FilterInput::Ref input) { + return FilterContents::MakeBlend(blend_mode, {input}, color, + need_absorb_opacity); }; } case flutter::DlColorFilterType::kMatrix: { const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix(); impeller::FilterContents::ColorMatrix color_matrix; dl_matrix->get_matrix(color_matrix.array); - return [color_matrix](FilterInput::Ref input) { - return FilterContents::MakeColorMatrix({input}, color_matrix); + return [color_matrix, need_absorb_opacity](FilterInput::Ref input) { + return FilterContents::MakeColorMatrix({input}, color_matrix, + need_absorb_opacity); }; } case flutter::DlColorFilterType::kSrgbToLinearGamma: - return [](FilterInput::Ref input) { - return FilterContents::MakeSrgbToLinearFilter({input}); + return [need_absorb_opacity](FilterInput::Ref input) { + return FilterContents::MakeSrgbToLinearFilter({input}, + need_absorb_opacity); }; case flutter::DlColorFilterType::kLinearToSrgbGamma: - return [](FilterInput::Ref input) { - return FilterContents::MakeLinearToSrgbFilter({input}); + return [need_absorb_opacity](FilterInput::Ref input) { + return FilterContents::MakeLinearToSrgbFilter({input}, + need_absorb_opacity); }; case flutter::DlColorFilterType::kUnknown: FML_LOG(ERROR) << "requested DlColorFilterType::kUnknown"; @@ -612,7 +617,8 @@ static std::optional ToImageFilterProc( auto color_filter_image_filter = filter->asColorFilter(); FML_DCHECK(color_filter_image_filter); auto color_filter_proc = - ToColorFilterProc(color_filter_image_filter->color_filter().get()); + ToColorFilterProc(color_filter_image_filter->color_filter().get(), + /*need_absorb_opacity=*/false); if (!color_filter_proc.has_value()) { return std::nullopt; } diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index f80888d2b5699..827b42c738a80 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -815,5 +815,70 @@ TEST_P(DisplayListTest, CanDrawPaintWithColorSource) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(DisplayListTest, SaveLayerWithFiltersAndAlphaDrawCorrectly) { + auto texture = CreateTextureForFixture("boston.jpg"); + bool first_frame = true; + enum class Type { kUseAsImageFilter, kUseAsColorFilter, kDisableFilter }; + auto callback = [&]() { + if (first_frame) { + first_frame = false; + ImGui::SetNextWindowPos({10, 10}); + } + + static float alpha = 0.5; + static int selected_type = 0; + const char* names[] = {"Use as image filter", "Use as color filter", + "Disable filter"}; + + static float color_matrix[20] = { + 1, 0, 0, 0, 0, // + 0, 1, 0, 0, 0, // + 0, 0, 1, 0, 0, // + 0, 0, 0, 2, 0, // + }; + + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::SliderFloat("Alpha", &alpha, 0, 1); + + ImGui::Combo("Type", &selected_type, names, sizeof(names) / sizeof(char*)); + std::string label = "##1"; + for (int i = 0; i < 20; i += 5) { + ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, + &(color_matrix[i]), 5, nullptr, nullptr, "%.2f", 0); + label[2]++; + } + ImGui::End(); + + flutter::DisplayListBuilder builder; + flutter::DlPaint save_paint; + save_paint.setAlpha(static_cast(255 * alpha)); + auto color_filter = + std::make_shared(color_matrix); + Type type = static_cast(selected_type); + switch (type) { + case Type::kUseAsImageFilter: { + auto image_filter = + std::make_shared(color_filter); + save_paint.setImageFilter(image_filter); + break; + } + case Type::kUseAsColorFilter: { + save_paint.setColorFilter(color_filter); + break; + } + case Type::kDisableFilter: + break; + } + builder.saveLayer(nullptr, &save_paint); + flutter::DlPaint draw_paint; + builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &draw_paint); + builder.restore(); + return builder.Build(); + }; + + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index efc2627b1c7fe..35262748596aa 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -35,6 +35,7 @@ static std::optional AdvancedBlend( const Entity& entity, const Rect& coverage, std::optional foreground_color, + bool need_absorb_opacity, PipelineProc pipeline_proc) { using VS = typename TPipeline::VertexShader; using FS = typename TPipeline::FragmentShader; @@ -107,6 +108,8 @@ static std::optional AdvancedBlend( auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, sampler); blend_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale(); + blend_info.dst_input_alpha = + need_absorb_opacity ? dst_snapshot->opacity : 1.0f; if (foreground_color.has_value()) { blend_info.color_factor = 1; @@ -139,9 +142,11 @@ static std::optional AdvancedBlend( } out_texture->SetLabel("Advanced Blend Filter Texture"); - return Snapshot{.texture = out_texture, - .transform = Matrix::MakeTranslation(coverage.origin), - .sampler_descriptor = dst_snapshot->sampler_descriptor}; + return Snapshot{ + .texture = out_texture, + .transform = Matrix::MakeTranslation(coverage.origin), + .sampler_descriptor = dst_snapshot->sampler_descriptor, + .opacity = need_absorb_opacity ? 1.0f : dst_snapshot->opacity}; } static std::optional PipelineBlend( @@ -150,10 +155,13 @@ static std::optional PipelineBlend( const Entity& entity, const Rect& coverage, BlendMode pipeline_blend, - std::optional foreground_color) { + std::optional foreground_color, + bool need_absorb_opacity) { using VS = BlendPipeline::VertexShader; using FS = BlendPipeline::FragmentShader; + auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity); + ContentContext::SubpassCallback callback = [&](const ContentContext& renderer, RenderPass& pass) { auto& host_buffer = pass.GetTransientsBuffer(); @@ -195,6 +203,7 @@ static std::optional PipelineBlend( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input->texture->GetYCoordScale(); + frag_info.input_alpha = need_absorb_opacity ? input->opacity : 1.0f; FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); @@ -203,10 +212,9 @@ static std::optional PipelineBlend( }; // Draw the first texture using kSource. - options.blend_mode = BlendMode::kSource; cmd.pipeline = renderer.GetBlendPipeline(options); - if (!add_blend_command(inputs[0]->GetSnapshot(renderer, entity))) { + if (!add_blend_command(input_snapshot)) { return true; } @@ -255,19 +263,21 @@ static std::optional PipelineBlend( .texture = out_texture, .transform = Matrix::MakeTranslation(coverage.origin), .sampler_descriptor = - inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor}; + inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor, + .opacity = need_absorb_opacity ? 1.0f : input_snapshot->opacity}; } -#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) { \ - PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ - return AdvancedBlend(inputs, renderer, entity, \ - coverage, fg_color, p); \ - }; \ +#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 need_absorb_opacity) { \ + PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ + return AdvancedBlend(inputs, renderer, entity, \ + coverage, fg_color, \ + need_absorb_opacity, p); \ + }; \ break; void BlendFilterContents::SetBlendMode(BlendMode blend_mode) { @@ -318,17 +328,17 @@ std::optional BlendFilterContents::RenderFilter( if (inputs.size() == 1 && !foreground_color_.has_value()) { // Nothing to blend. return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource, - std::nullopt); + std::nullopt, GetNeedAbsorbOpacity()); } if (blend_mode_ <= Entity::kLastPipelineBlendMode) { return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_, - foreground_color_); + foreground_color_, GetNeedAbsorbOpacity()); } if (blend_mode_ <= Entity::kLastAdvancedBlendMode) { return advanced_blend_proc_(inputs, renderer, entity, coverage, - foreground_color_); + foreground_color_, GetNeedAbsorbOpacity()); } FML_UNREACHABLE(); } diff --git a/impeller/entity/contents/filters/blend_filter_contents.h b/impeller/entity/contents/filters/blend_filter_contents.h index 466842e61d762..4dbc08d830492 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.h +++ b/impeller/entity/contents/filters/blend_filter_contents.h @@ -16,7 +16,8 @@ class BlendFilterContents : public FilterContents { const ContentContext& renderer, const Entity& entity, const Rect& coverage, - std::optional foreground_color)>; + std::optional foreground_color, + bool need_absorb_opacity)>; BlendFilterContents(); diff --git a/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc b/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc index 6d6fdef5f19dc..847cfafa8815f 100644 --- a/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc @@ -127,7 +127,8 @@ std::optional BorderMaskBlurFilterContents::RenderFilter( out_texture->SetLabel("BorderMaskBlurFilter Texture"); return Snapshot{.texture = out_texture, - .transform = Matrix::MakeTranslation(coverage.origin)}; + .transform = Matrix::MakeTranslation(coverage.origin), + .opacity = input_snapshot->opacity}; } std::optional BorderMaskBlurFilterContents::GetFilterCoverage( diff --git a/impeller/entity/contents/filters/color_matrix_filter_contents.cc b/impeller/entity/contents/filters/color_matrix_filter_contents.cc index eba9d3a867473..96e68ba3c6595 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.cc +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.cc @@ -87,6 +87,8 @@ std::optional ColorMatrixFilterContents::RenderFilter( matrix[3], matrix[8], matrix[13], matrix[18] ); // clang-format on + frag_info.input_alpha = + GetNeedAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); @@ -103,9 +105,11 @@ std::optional ColorMatrixFilterContents::RenderFilter( } out_texture->SetLabel("ColorMatrixFilter Texture"); - return Snapshot{.texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor}; + return Snapshot{ + .texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = GetNeedAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index 06f49b2557055..b645bf864e712 100644 --- a/impeller/entity/contents/filters/filter_contents.cc +++ b/impeller/entity/contents/filters/filter_contents.cc @@ -36,7 +36,8 @@ namespace impeller { std::shared_ptr FilterContents::MakeBlend( BlendMode blend_mode, FilterInput::Vector inputs, - std::optional foreground_color) { + std::optional foreground_color, + bool need_absorb_opacity) { if (blend_mode > Entity::kLastAdvancedBlendMode) { VALIDATION_LOG << "Invalid blend mode " << static_cast(blend_mode) << " passed to FilterContents::MakeBlend."; @@ -49,6 +50,7 @@ std::shared_ptr FilterContents::MakeBlend( blend->SetInputs(inputs); blend->SetBlendMode(blend_mode); blend->SetForegroundColor(foreground_color); + blend->SetNeedAbsorbOpacity(need_absorb_opacity); return blend; } @@ -58,6 +60,7 @@ std::shared_ptr FilterContents::MakeBlend( new_blend = std::make_shared(); new_blend->SetInputs({*in_i, blend_input}); new_blend->SetBlendMode(blend_mode); + new_blend->SetNeedAbsorbOpacity(need_absorb_opacity); if (in_i < inputs.end() - 1 || foreground_color.has_value()) { blend_input = FilterInput::Make( std::static_pointer_cast(new_blend)); @@ -69,6 +72,7 @@ std::shared_ptr FilterContents::MakeBlend( new_blend->SetInputs({blend_input}); new_blend->SetBlendMode(blend_mode); new_blend->SetForegroundColor(foreground_color); + new_blend->SetNeedAbsorbOpacity(need_absorb_opacity); } return new_blend; @@ -156,24 +160,30 @@ std::shared_ptr FilterContents::MakeMorphology( std::shared_ptr FilterContents::MakeColorMatrix( FilterInput::Ref input, - const ColorMatrix& color_matrix) { + const ColorMatrix& color_matrix, + bool need_absorb_opacity) { auto filter = std::make_shared(); filter->SetInputs({input}); filter->SetMatrix(color_matrix); + filter->SetNeedAbsorbOpacity(need_absorb_opacity); return filter; } std::shared_ptr FilterContents::MakeLinearToSrgbFilter( - FilterInput::Ref input) { + FilterInput::Ref input, + bool need_absorb_opacity) { auto filter = std::make_shared(); filter->SetInputs({input}); + filter->SetNeedAbsorbOpacity(need_absorb_opacity); return filter; } std::shared_ptr FilterContents::MakeSrgbToLinearFilter( - FilterInput::Ref input) { + FilterInput::Ref input, + bool need_absorb_opacity) { auto filter = std::make_shared(); filter->SetInputs({input}); + filter->SetNeedAbsorbOpacity(need_absorb_opacity); return filter; } @@ -236,6 +246,7 @@ bool FilterContents::Render(const ContentContext& renderer, contents->SetTexture(snapshot.texture); contents->SetSamplerDescriptor(snapshot.sampler_descriptor); contents->SetSourceRect(texture_rect); + contents->SetOpacity(snapshot.opacity); Entity e; e.SetBlendMode(entity.GetBlendMode()); @@ -313,4 +324,12 @@ Matrix FilterContents::GetTransform(const Matrix& parent_transform) const { return parent_transform * GetLocalTransform(parent_transform); } +void FilterContents::SetNeedAbsorbOpacity(bool need_absorb_opacity) { + need_absorb_opacity_ = need_absorb_opacity; +} + +bool FilterContents::GetNeedAbsorbOpacity() const { + return need_absorb_opacity_; +} + } // namespace impeller diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index af1f1d4b88b35..2fbfe84541c97 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -39,7 +39,8 @@ class FilterContents : public Contents { static std::shared_ptr MakeBlend( BlendMode blend_mode, FilterInput::Vector inputs, - std::optional foreground_color = std::nullopt); + std::optional foreground_color = std::nullopt, + bool need_absorb_opacity = true); static std::shared_ptr MakeDirectionalGaussianBlur( FilterInput::Ref input, @@ -82,13 +83,16 @@ class FilterContents : public Contents { static std::shared_ptr MakeColorMatrix( FilterInput::Ref input, - const ColorMatrix& color_matrix); + const ColorMatrix& color_matrix, + bool need_absorb_opacity = true); static std::shared_ptr MakeLinearToSrgbFilter( - FilterInput::Ref input); + FilterInput::Ref input, + bool need_absorb_opacity = true); static std::shared_ptr MakeSrgbToLinearFilter( - FilterInput::Ref input); + FilterInput::Ref input, + bool need_absorb_opacity = true); static std::shared_ptr MakeMatrixFilter( FilterInput::Ref input, @@ -133,6 +137,10 @@ class FilterContents : public Contents { Matrix GetTransform(const Matrix& parent_transform) const; + void SetNeedAbsorbOpacity(bool need_absorb_opacity); + + bool GetNeedAbsorbOpacity() const; + private: virtual std::optional GetFilterCoverage( const FilterInput::Vector& inputs, @@ -152,6 +160,7 @@ class FilterContents : public Contents { FilterInput::Vector inputs_; std::optional coverage_crop_; Matrix effect_transform_; + bool need_absorb_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(FilterContents); }; diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 50fd91a40669e..67de116f266b6 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -258,7 +258,8 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( texture_rotate.Invert() * Matrix::MakeTranslation(pass_texture_rect.origin) * Matrix::MakeScale((1 / scale) * (scaled_size / floored_size)), - .sampler_descriptor = sampler_desc}; + .sampler_descriptor = sampler_desc, + .opacity = input_snapshot->opacity}; } std::optional DirectionalGaussianBlurFilterContents::GetFilterCoverage( diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc index e11781321272a..f318ea15ad2f9 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc @@ -64,6 +64,8 @@ std::optional LinearToSrgbFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); + frag_info.input_alpha = + GetNeedAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -80,9 +82,11 @@ std::optional LinearToSrgbFilterContents::RenderFilter( } out_texture->SetLabel("LinearToSrgb Texture"); - return Snapshot{.texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor}; + return Snapshot{ + .texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = GetNeedAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/morphology_filter_contents.cc b/impeller/entity/contents/filters/morphology_filter_contents.cc index 9156a55397c44..42c1d79afc3b9 100644 --- a/impeller/entity/contents/filters/morphology_filter_contents.cc +++ b/impeller/entity/contents/filters/morphology_filter_contents.cc @@ -141,7 +141,8 @@ std::optional DirectionalMorphologyFilterContents::RenderFilter( return Snapshot{.texture = out_texture, .transform = Matrix::MakeTranslation(coverage.origin), - .sampler_descriptor = sampler_desc}; + .sampler_descriptor = sampler_desc, + .opacity = input_snapshot->opacity}; } std::optional DirectionalMorphologyFilterContents::GetFilterCoverage( diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc index 1d0ad22b57eee..d6aef19b8d769 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc @@ -64,6 +64,8 @@ std::optional SrgbToLinearFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); + frag_info.input_alpha = + GetNeedAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -80,9 +82,11 @@ std::optional SrgbToLinearFilterContents::RenderFilter( } out_texture->SetLabel("SrgbToLinear Texture"); - return Snapshot{.texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor}; + return Snapshot{ + .texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = GetNeedAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index 282e8c0a54fd5..09bc90cc6a6a7 100644 --- a/impeller/entity/contents/texture_contents.cc +++ b/impeller/entity/contents/texture_contents.cc @@ -74,13 +74,14 @@ std::optional TextureContents::RenderToSnapshot( // Passthrough textures that have simple rectangle paths and complete source // rects. if (is_rect_ && source_rect_ == Rect::MakeSize(texture_->GetSize()) && - opacity_ >= 1 - kEhCloseEnough) { + (opacity_ >= 1 - kEhCloseEnough || defer_applying_opacity_)) { auto scale = Vector2(bounds->size / Size(texture_->GetSize())); return Snapshot{.texture = texture_, .transform = entity.GetTransformation() * Matrix::MakeTranslation(bounds->origin) * Matrix::MakeScale(scale), - .sampler_descriptor = sampler_descriptor_}; + .sampler_descriptor = sampler_descriptor_, + .opacity = opacity_}; } return Contents::RenderToSnapshot(renderer, entity); } @@ -190,4 +191,8 @@ const SamplerDescriptor& TextureContents::GetSamplerDescriptor() const { return sampler_descriptor_; } +void TextureContents::SetDeferApplyingOpacity(bool defer_applying_opacity) { + defer_applying_opacity_ = defer_applying_opacity; +} + } // namespace impeller diff --git a/impeller/entity/contents/texture_contents.h b/impeller/entity/contents/texture_contents.h index 4cac643109fe8..8cdf8e767cd60 100644 --- a/impeller/entity/contents/texture_contents.h +++ b/impeller/entity/contents/texture_contents.h @@ -60,6 +60,8 @@ class TextureContents final : public Contents { const Entity& entity, RenderPass& pass) const override; + void SetDeferApplyingOpacity(bool defer_applying_opacity); + private: std::string label_; @@ -71,6 +73,7 @@ class TextureContents final : public Contents { SamplerDescriptor sampler_descriptor_ = {}; Rect source_rect_; Scalar opacity_ = 1.0f; + bool defer_applying_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(TextureContents); }; diff --git a/impeller/entity/shaders/blending/advanced_blend.glsl b/impeller/entity/shaders/blending/advanced_blend.glsl index 84e4781d99a32..8a061288e2355 100644 --- a/impeller/entity/shaders/blending/advanced_blend.glsl +++ b/impeller/entity/shaders/blending/advanced_blend.glsl @@ -7,12 +7,12 @@ #include uniform BlendInfo { + float dst_input_alpha; float dst_y_coord_scale; float src_y_coord_scale; float color_factor; vec4 color; // This color input is expected to be unpremultiplied. -} -blend_info; +} blend_info; uniform sampler2D texture_sampler_dst; uniform sampler2D texture_sampler_src; @@ -28,7 +28,7 @@ void main() { v_dst_texture_coords, // texture coordinates blend_info.dst_y_coord_scale, // y coordinate scale kTileModeDecal // tile mode - )); + ) * blend_info.dst_input_alpha); vec4 src = blend_info.color_factor > 0 ? blend_info.color : IPUnpremultiply(IPSampleWithTileMode( diff --git a/impeller/entity/shaders/blending/blend.frag b/impeller/entity/shaders/blending/blend.frag index d5122145bb9b4..c3f89be765349 100644 --- a/impeller/entity/shaders/blending/blend.frag +++ b/impeller/entity/shaders/blending/blend.frag @@ -8,6 +8,7 @@ uniform sampler2D texture_sampler_src; uniform FragInfo { float texture_sampler_y_coord_scale; + float input_alpha; } frag_info; in vec2 v_texture_coords; @@ -16,5 +17,6 @@ out vec4 frag_color; void main() { frag_color = IPSample(texture_sampler_src, v_texture_coords, - frag_info.texture_sampler_y_coord_scale); + frag_info.texture_sampler_y_coord_scale) * + frag_info.input_alpha; } diff --git a/impeller/entity/shaders/color_matrix_color_filter.frag b/impeller/entity/shaders/color_matrix_color_filter.frag index a2baf4291d03a..43aa4c8c93976 100644 --- a/impeller/entity/shaders/color_matrix_color_filter.frag +++ b/impeller/entity/shaders/color_matrix_color_filter.frag @@ -30,6 +30,7 @@ uniform FragInfo { mat4 color_m; vec4 color_v; float texture_sampler_y_coord_scale; + float input_alpha; } frag_info; uniform sampler2D input_texture; @@ -39,7 +40,9 @@ out vec4 frag_color; void main() { vec4 input_color = IPSample(input_texture, v_position, - frag_info.texture_sampler_y_coord_scale); + frag_info.texture_sampler_y_coord_scale) * + frag_info.input_alpha; + // unpremultiply first, as filter inputs are premultiplied. vec4 color = IPUnpremultiply(input_color); diff --git a/impeller/entity/shaders/linear_to_srgb_filter.frag b/impeller/entity/shaders/linear_to_srgb_filter.frag index 562bb5e119846..119892763e626 100644 --- a/impeller/entity/shaders/linear_to_srgb_filter.frag +++ b/impeller/entity/shaders/linear_to_srgb_filter.frag @@ -13,6 +13,7 @@ uniform sampler2D input_texture; uniform FragInfo { float texture_sampler_y_coord_scale; + float input_alpha; } frag_info; in vec2 v_position; @@ -20,7 +21,8 @@ out vec4 frag_color; void main() { vec4 input_color = IPSample(input_texture, v_position, - frag_info.texture_sampler_y_coord_scale); + frag_info.texture_sampler_y_coord_scale) * + frag_info.input_alpha; for (int i = 0; i < 4; i++) { if (input_color[i] <= 0.0031308) { diff --git a/impeller/entity/shaders/srgb_to_linear_filter.frag b/impeller/entity/shaders/srgb_to_linear_filter.frag index e18bd18f3b278..8870c9685cfd9 100644 --- a/impeller/entity/shaders/srgb_to_linear_filter.frag +++ b/impeller/entity/shaders/srgb_to_linear_filter.frag @@ -12,6 +12,7 @@ uniform sampler2D input_texture; uniform FragInfo { float texture_sampler_y_coord_scale; + float input_alpha; } frag_info; in vec2 v_position; @@ -19,7 +20,8 @@ out vec4 frag_color; void main() { vec4 input_color = IPSample(input_texture, v_position, - frag_info.texture_sampler_y_coord_scale); + frag_info.texture_sampler_y_coord_scale) * + frag_info.input_alpha; for (int i = 0; i < 4; i++) { if (input_color[i] <= 0.04045) { diff --git a/impeller/renderer/snapshot.h b/impeller/renderer/snapshot.h index 65a4c9a73cfb7..26fe49d894d2d 100644 --- a/impeller/renderer/snapshot.h +++ b/impeller/renderer/snapshot.h @@ -27,6 +27,8 @@ struct Snapshot { SamplerDescriptor sampler_descriptor; + Scalar opacity = 1.0f; + std::optional GetCoverage() const; /// @brief Get the transform that converts screen space coordinates to the UV From 320cf345bf6c6c1f3da41fbe4d4fdf9522dbd1cd Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Tue, 27 Sep 2022 18:19:30 +0800 Subject: [PATCH 3/8] Add more test --- .../display_list/display_list_unittests.cc | 182 +++++++++++------- impeller/entity/contents/content_context.cc | 4 +- 2 files changed, 119 insertions(+), 67 deletions(-) diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 827b42c738a80..049b94dee737a 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -359,6 +359,123 @@ TEST_P(DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(DisplayListTest, SaveLayerWithColorMatrixFiltersAndAlphaDrawCorrectly) { + auto texture = CreateTextureForFixture("boston.jpg"); + bool first_frame = true; + enum class Type { kUseAsImageFilter, kUseAsColorFilter, kDisableFilter }; + auto callback = [&]() { + if (first_frame) { + first_frame = false; + ImGui::SetNextWindowPos({10, 10}); + } + + static float alpha = 0.5; + static int selected_type = 0; + const char* names[] = {"Use as image filter", "Use as color filter", + "Disable filter"}; + + static float color_matrix[20] = { + 1, 0, 0, 0, 0, // + 0, 1, 0, 0, 0, // + 0, 0, 1, 0, 0, // + 0, 0, 0, 2, 0, // + }; + + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::SliderFloat("Alpha", &alpha, 0, 1); + + ImGui::Combo("Type", &selected_type, names, sizeof(names) / sizeof(char*)); + std::string label = "##1"; + for (int i = 0; i < 20; i += 5) { + ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, + &(color_matrix[i]), 5, nullptr, nullptr, "%.2f", 0); + label[2]++; + } + ImGui::End(); + + flutter::DisplayListBuilder builder; + flutter::DlPaint save_paint; + save_paint.setAlpha(static_cast(255 * alpha)); + auto color_filter = + std::make_shared(color_matrix); + Type type = static_cast(selected_type); + switch (type) { + case Type::kUseAsImageFilter: { + auto image_filter = + std::make_shared(color_filter); + save_paint.setImageFilter(image_filter); + break; + } + case Type::kUseAsColorFilter: { + save_paint.setColorFilter(color_filter); + break; + } + case Type::kDisableFilter: + break; + } + builder.saveLayer(nullptr, &save_paint); + flutter::DlPaint draw_paint; + builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &draw_paint); + builder.restore(); + return builder.Build(); + }; + + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + +TEST_P(DisplayListTest, SaveLayerWithBlendFiltersAndAlphaDrawCorrectly) { + auto texture = CreateTextureForFixture("boston.jpg"); + bool first_frame = true; + enum class Type { kUseAsImageFilter, kUseAsColorFilter, kDisableFilter }; + auto callback = [&]() { + if (first_frame) { + first_frame = false; + ImGui::SetNextWindowPos({10, 10}); + } + + static float alpha = 0.5; + static int selected_type = 0; + const char* names[] = {"Use as image filter", "Use as color filter", + "Disable filter"}; + + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::SliderFloat("Alpha", &alpha, 0, 1); + + ImGui::Combo("Type", &selected_type, names, sizeof(names) / sizeof(char*)); + ImGui::End(); + + flutter::DisplayListBuilder builder; + flutter::DlPaint save_paint; + save_paint.setAlpha(static_cast(255 * alpha)); + auto color_filter = std::make_shared( + flutter::DlColor::kRed(), flutter::DlBlendMode::kDstOver); + Type type = static_cast(selected_type); + switch (type) { + case Type::kUseAsImageFilter: { + auto image_filter = + std::make_shared(color_filter); + save_paint.setImageFilter(image_filter); + break; + } + case Type::kUseAsColorFilter: { + save_paint.setColorFilter(color_filter); + break; + } + case Type::kDisableFilter: + break; + } + builder.saveLayer(nullptr, &save_paint); + flutter::DlPaint draw_paint; + draw_paint.setColor(flutter::DlColor::kBlue()); + builder.drawRect(SkRect::MakeLTRB(100, 100, 400, 400), draw_paint); + builder.restore(); + return builder.Build(); + }; + + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + TEST_P(DisplayListTest, CanDrawBackdropFilter) { auto texture = CreateTextureForFixture("embarcadero.jpg"); @@ -815,70 +932,5 @@ TEST_P(DisplayListTest, CanDrawPaintWithColorSource) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } -TEST_P(DisplayListTest, SaveLayerWithFiltersAndAlphaDrawCorrectly) { - auto texture = CreateTextureForFixture("boston.jpg"); - bool first_frame = true; - enum class Type { kUseAsImageFilter, kUseAsColorFilter, kDisableFilter }; - auto callback = [&]() { - if (first_frame) { - first_frame = false; - ImGui::SetNextWindowPos({10, 10}); - } - - static float alpha = 0.5; - static int selected_type = 0; - const char* names[] = {"Use as image filter", "Use as color filter", - "Disable filter"}; - - static float color_matrix[20] = { - 1, 0, 0, 0, 0, // - 0, 1, 0, 0, 0, // - 0, 0, 1, 0, 0, // - 0, 0, 0, 2, 0, // - }; - - ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); - ImGui::SliderFloat("Alpha", &alpha, 0, 1); - - ImGui::Combo("Type", &selected_type, names, sizeof(names) / sizeof(char*)); - std::string label = "##1"; - for (int i = 0; i < 20; i += 5) { - ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, - &(color_matrix[i]), 5, nullptr, nullptr, "%.2f", 0); - label[2]++; - } - ImGui::End(); - - flutter::DisplayListBuilder builder; - flutter::DlPaint save_paint; - save_paint.setAlpha(static_cast(255 * alpha)); - auto color_filter = - std::make_shared(color_matrix); - Type type = static_cast(selected_type); - switch (type) { - case Type::kUseAsImageFilter: { - auto image_filter = - std::make_shared(color_filter); - save_paint.setImageFilter(image_filter); - break; - } - case Type::kUseAsColorFilter: { - save_paint.setColorFilter(color_filter); - break; - } - case Type::kDisableFilter: - break; - } - builder.saveLayer(nullptr, &save_paint); - flutter::DlPaint draw_paint; - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, &draw_paint); - builder.restore(); - return builder.Build(); - }; - - ASSERT_TRUE(OpenPlaygroundHere(callback)); -} - } // namespace testing } // namespace impeller diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 54301ae662700..a4ec8a5f5f6f4 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -44,7 +44,7 @@ void ContentContextOptions::ApplyToPipelineDescriptor( color0.src_color_blend_factor = BlendFactor::kOne; break; case BlendMode::kDestination: - color0.dst_alpha_blend_factor = BlendFactor::kDestinationAlpha; + color0.dst_alpha_blend_factor = BlendFactor::kOne; color0.dst_color_blend_factor = BlendFactor::kOne; color0.src_alpha_blend_factor = BlendFactor::kZero; color0.src_color_blend_factor = BlendFactor::kZero; @@ -56,7 +56,7 @@ void ContentContextOptions::ApplyToPipelineDescriptor( color0.src_color_blend_factor = BlendFactor::kOne; break; case BlendMode::kDestinationOver: - color0.dst_alpha_blend_factor = BlendFactor::kDestinationAlpha; + color0.dst_alpha_blend_factor = BlendFactor::kOne; color0.dst_color_blend_factor = BlendFactor::kOne; color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha; color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha; From a53f46ff3e70638ad3bf59f5a3c27587dd409707 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Fri, 30 Sep 2022 21:53:44 +0800 Subject: [PATCH 4/8] Rename to 'absorb_opacity_' and put them in each filter --- .../display_list/display_list_dispatcher.cc | 22 ++++---- .../contents/filters/blend_filter_contents.cc | 52 ++++++++++--------- .../contents/filters/blend_filter_contents.h | 5 +- .../filters/color_matrix_filter_contents.cc | 16 +++--- .../filters/color_matrix_filter_contents.h | 3 ++ .../contents/filters/filter_contents.cc | 28 ++++------ .../entity/contents/filters/filter_contents.h | 13 ++--- .../filters/linear_to_srgb_filter_contents.cc | 16 +++--- .../filters/linear_to_srgb_filter_contents.h | 4 ++ .../filters/srgb_to_linear_filter_contents.cc | 16 +++--- .../filters/srgb_to_linear_filter_contents.h | 4 ++ 11 files changed, 93 insertions(+), 86 deletions(-) diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index d84d09fbf6a84..137601b9c232d 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -438,7 +438,7 @@ void DisplayListDispatcher::setColorSource( static std::optional ToColorFilterProc( const flutter::DlColorFilter* filter, - bool need_absorb_opacity = true) { + bool absorb_opacity = true) { if (filter == nullptr) { return std::nullopt; } @@ -447,29 +447,27 @@ static std::optional ToColorFilterProc( auto dl_blend = filter->asBlend(); auto blend_mode = ToBlendMode(dl_blend->mode()); auto color = ToColor(dl_blend->color()); - return [blend_mode, color, need_absorb_opacity](FilterInput::Ref input) { + return [blend_mode, color, absorb_opacity](FilterInput::Ref input) { return FilterContents::MakeBlend(blend_mode, {input}, color, - need_absorb_opacity); + absorb_opacity); }; } case flutter::DlColorFilterType::kMatrix: { const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix(); impeller::FilterContents::ColorMatrix color_matrix; dl_matrix->get_matrix(color_matrix.array); - return [color_matrix, need_absorb_opacity](FilterInput::Ref input) { + return [color_matrix, absorb_opacity](FilterInput::Ref input) { return FilterContents::MakeColorMatrix({input}, color_matrix, - need_absorb_opacity); + absorb_opacity); }; } case flutter::DlColorFilterType::kSrgbToLinearGamma: - return [need_absorb_opacity](FilterInput::Ref input) { - return FilterContents::MakeSrgbToLinearFilter({input}, - need_absorb_opacity); + return [absorb_opacity](FilterInput::Ref input) { + return FilterContents::MakeSrgbToLinearFilter({input}, absorb_opacity); }; case flutter::DlColorFilterType::kLinearToSrgbGamma: - return [need_absorb_opacity](FilterInput::Ref input) { - return FilterContents::MakeLinearToSrgbFilter({input}, - need_absorb_opacity); + return [absorb_opacity](FilterInput::Ref input) { + return FilterContents::MakeLinearToSrgbFilter({input}, absorb_opacity); }; case flutter::DlColorFilterType::kUnknown: FML_LOG(ERROR) << "requested DlColorFilterType::kUnknown"; @@ -636,7 +634,7 @@ static std::optional ToImageFilterProc( FML_DCHECK(color_filter_image_filter); auto color_filter_proc = ToColorFilterProc(color_filter_image_filter->color_filter().get(), - /*need_absorb_opacity=*/false); + /*absorb_opacity=*/false); if (!color_filter_proc.has_value()) { return std::nullopt; } diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 35262748596aa..776d1e0173fc3 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -35,7 +35,7 @@ static std::optional AdvancedBlend( const Entity& entity, const Rect& coverage, std::optional foreground_color, - bool need_absorb_opacity, + bool absorb_opacity, PipelineProc pipeline_proc) { using VS = typename TPipeline::VertexShader; using FS = typename TPipeline::FragmentShader; @@ -108,8 +108,7 @@ static std::optional AdvancedBlend( auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, sampler); blend_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale(); - blend_info.dst_input_alpha = - need_absorb_opacity ? dst_snapshot->opacity : 1.0f; + blend_info.dst_input_alpha = absorb_opacity ? dst_snapshot->opacity : 1.0f; if (foreground_color.has_value()) { blend_info.color_factor = 1; @@ -142,11 +141,10 @@ static std::optional AdvancedBlend( } out_texture->SetLabel("Advanced Blend Filter Texture"); - return Snapshot{ - .texture = out_texture, - .transform = Matrix::MakeTranslation(coverage.origin), - .sampler_descriptor = dst_snapshot->sampler_descriptor, - .opacity = need_absorb_opacity ? 1.0f : dst_snapshot->opacity}; + return Snapshot{.texture = out_texture, + .transform = Matrix::MakeTranslation(coverage.origin), + .sampler_descriptor = dst_snapshot->sampler_descriptor, + .opacity = absorb_opacity ? 1.0f : dst_snapshot->opacity}; } static std::optional PipelineBlend( @@ -156,7 +154,7 @@ static std::optional PipelineBlend( const Rect& coverage, BlendMode pipeline_blend, std::optional foreground_color, - bool need_absorb_opacity) { + bool absorb_opacity) { using VS = BlendPipeline::VertexShader; using FS = BlendPipeline::FragmentShader; @@ -203,7 +201,7 @@ static std::optional PipelineBlend( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input->texture->GetYCoordScale(); - frag_info.input_alpha = need_absorb_opacity ? input->opacity : 1.0f; + frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0f; FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); @@ -264,20 +262,20 @@ static std::optional PipelineBlend( .transform = Matrix::MakeTranslation(coverage.origin), .sampler_descriptor = inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor, - .opacity = need_absorb_opacity ? 1.0f : input_snapshot->opacity}; + .opacity = absorb_opacity ? 1.0f : input_snapshot->opacity}; } -#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 need_absorb_opacity) { \ - PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ - return AdvancedBlend(inputs, renderer, entity, \ - coverage, fg_color, \ - need_absorb_opacity, p); \ - }; \ +#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) { \ + PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ + return AdvancedBlend( \ + inputs, renderer, entity, coverage, fg_color, absorb_opacity, p); \ + }; \ break; void BlendFilterContents::SetBlendMode(BlendMode blend_mode) { @@ -315,6 +313,10 @@ void BlendFilterContents::SetForegroundColor(std::optional color) { foreground_color_ = color; } +void BlendFilterContents::SetAbsorbOpacity(bool absorb_opacity) { + absorb_opacity_ = absorb_opacity; +} + std::optional BlendFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -328,17 +330,17 @@ std::optional BlendFilterContents::RenderFilter( if (inputs.size() == 1 && !foreground_color_.has_value()) { // Nothing to blend. return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource, - std::nullopt, GetNeedAbsorbOpacity()); + std::nullopt, absorb_opacity_); } if (blend_mode_ <= Entity::kLastPipelineBlendMode) { return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_, - foreground_color_, GetNeedAbsorbOpacity()); + foreground_color_, absorb_opacity_); } if (blend_mode_ <= Entity::kLastAdvancedBlendMode) { return advanced_blend_proc_(inputs, renderer, entity, coverage, - foreground_color_, GetNeedAbsorbOpacity()); + foreground_color_, absorb_opacity_); } FML_UNREACHABLE(); } diff --git a/impeller/entity/contents/filters/blend_filter_contents.h b/impeller/entity/contents/filters/blend_filter_contents.h index 4dbc08d830492..60c8352f675d8 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.h +++ b/impeller/entity/contents/filters/blend_filter_contents.h @@ -17,7 +17,7 @@ class BlendFilterContents : public FilterContents { const Entity& entity, const Rect& coverage, std::optional foreground_color, - bool need_absorb_opacity)>; + bool absorb_opacity)>; BlendFilterContents(); @@ -29,6 +29,8 @@ class BlendFilterContents : public FilterContents { /// been blended. void SetForegroundColor(std::optional color); + void SetAbsorbOpacity(bool absorb_opacity); + private: // |FilterContents| std::optional RenderFilter(const FilterInput::Vector& inputs, @@ -40,6 +42,7 @@ class BlendFilterContents : public FilterContents { BlendMode blend_mode_ = BlendMode::kSourceOver; AdvancedBlendProc advanced_blend_proc_; std::optional foreground_color_; + bool absorb_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(BlendFilterContents); }; diff --git a/impeller/entity/contents/filters/color_matrix_filter_contents.cc b/impeller/entity/contents/filters/color_matrix_filter_contents.cc index 96e68ba3c6595..ea976b2552b8a 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.cc +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.cc @@ -23,6 +23,10 @@ void ColorMatrixFilterContents::SetMatrix(const ColorMatrix& matrix) { matrix_ = matrix; } +void ColorMatrixFilterContents::SetAbsorbOpacity(bool absorb_opacity) { + absorb_opacity_ = absorb_opacity; +} + std::optional ColorMatrixFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -87,8 +91,7 @@ std::optional ColorMatrixFilterContents::RenderFilter( matrix[3], matrix[8], matrix[13], matrix[18] ); // clang-format on - frag_info.input_alpha = - GetNeedAbsorbOpacity() ? input_snapshot->opacity : 1.0f; + frag_info.input_alpha = absorb_opacity_ ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); @@ -105,11 +108,10 @@ std::optional ColorMatrixFilterContents::RenderFilter( } out_texture->SetLabel("ColorMatrixFilter Texture"); - return Snapshot{ - .texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor, - .opacity = GetNeedAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; + return Snapshot{.texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = absorb_opacity_ ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/color_matrix_filter_contents.h b/impeller/entity/contents/filters/color_matrix_filter_contents.h index b725249019106..a24ae43f54cb4 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.h +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.h @@ -22,6 +22,8 @@ class ColorMatrixFilterContents final : public FilterContents { void SetMatrix(const ColorMatrix& matrix); + void SetAbsorbOpacity(bool absorb_opacity); + private: // |FilterContents| std::optional RenderFilter( @@ -32,6 +34,7 @@ class ColorMatrixFilterContents final : public FilterContents { const Rect& coverage) const override; ColorMatrix matrix_; + bool absorb_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(ColorMatrixFilterContents); }; diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index b645bf864e712..e2c7f9376b9ab 100644 --- a/impeller/entity/contents/filters/filter_contents.cc +++ b/impeller/entity/contents/filters/filter_contents.cc @@ -37,7 +37,7 @@ std::shared_ptr FilterContents::MakeBlend( BlendMode blend_mode, FilterInput::Vector inputs, std::optional foreground_color, - bool need_absorb_opacity) { + bool absorb_opacity) { if (blend_mode > Entity::kLastAdvancedBlendMode) { VALIDATION_LOG << "Invalid blend mode " << static_cast(blend_mode) << " passed to FilterContents::MakeBlend."; @@ -50,7 +50,7 @@ std::shared_ptr FilterContents::MakeBlend( blend->SetInputs(inputs); blend->SetBlendMode(blend_mode); blend->SetForegroundColor(foreground_color); - blend->SetNeedAbsorbOpacity(need_absorb_opacity); + blend->SetAbsorbOpacity(absorb_opacity); return blend; } @@ -60,7 +60,7 @@ std::shared_ptr FilterContents::MakeBlend( new_blend = std::make_shared(); new_blend->SetInputs({*in_i, blend_input}); new_blend->SetBlendMode(blend_mode); - new_blend->SetNeedAbsorbOpacity(need_absorb_opacity); + new_blend->SetAbsorbOpacity(absorb_opacity); if (in_i < inputs.end() - 1 || foreground_color.has_value()) { blend_input = FilterInput::Make( std::static_pointer_cast(new_blend)); @@ -72,7 +72,7 @@ std::shared_ptr FilterContents::MakeBlend( new_blend->SetInputs({blend_input}); new_blend->SetBlendMode(blend_mode); new_blend->SetForegroundColor(foreground_color); - new_blend->SetNeedAbsorbOpacity(need_absorb_opacity); + new_blend->SetAbsorbOpacity(absorb_opacity); } return new_blend; @@ -161,29 +161,29 @@ std::shared_ptr FilterContents::MakeMorphology( std::shared_ptr FilterContents::MakeColorMatrix( FilterInput::Ref input, const ColorMatrix& color_matrix, - bool need_absorb_opacity) { + bool absorb_opacity) { auto filter = std::make_shared(); filter->SetInputs({input}); filter->SetMatrix(color_matrix); - filter->SetNeedAbsorbOpacity(need_absorb_opacity); + filter->SetAbsorbOpacity(absorb_opacity); return filter; } std::shared_ptr FilterContents::MakeLinearToSrgbFilter( FilterInput::Ref input, - bool need_absorb_opacity) { + bool absorb_opacity) { auto filter = std::make_shared(); filter->SetInputs({input}); - filter->SetNeedAbsorbOpacity(need_absorb_opacity); + filter->SetAbsorbOpacity(absorb_opacity); return filter; } std::shared_ptr FilterContents::MakeSrgbToLinearFilter( FilterInput::Ref input, - bool need_absorb_opacity) { + bool absorb_opacity) { auto filter = std::make_shared(); filter->SetInputs({input}); - filter->SetNeedAbsorbOpacity(need_absorb_opacity); + filter->SetAbsorbOpacity(absorb_opacity); return filter; } @@ -324,12 +324,4 @@ Matrix FilterContents::GetTransform(const Matrix& parent_transform) const { return parent_transform * GetLocalTransform(parent_transform); } -void FilterContents::SetNeedAbsorbOpacity(bool need_absorb_opacity) { - need_absorb_opacity_ = need_absorb_opacity; -} - -bool FilterContents::GetNeedAbsorbOpacity() const { - return need_absorb_opacity_; -} - } // namespace impeller diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index 2fbfe84541c97..1bdc650a1095e 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -40,7 +40,7 @@ class FilterContents : public Contents { BlendMode blend_mode, FilterInput::Vector inputs, std::optional foreground_color = std::nullopt, - bool need_absorb_opacity = true); + bool absorb_opacity = true); static std::shared_ptr MakeDirectionalGaussianBlur( FilterInput::Ref input, @@ -84,15 +84,15 @@ class FilterContents : public Contents { static std::shared_ptr MakeColorMatrix( FilterInput::Ref input, const ColorMatrix& color_matrix, - bool need_absorb_opacity = true); + bool absorb_opacity = true); static std::shared_ptr MakeLinearToSrgbFilter( FilterInput::Ref input, - bool need_absorb_opacity = true); + bool absorb_opacity = true); static std::shared_ptr MakeSrgbToLinearFilter( FilterInput::Ref input, - bool need_absorb_opacity = true); + bool absorb_opacity = true); static std::shared_ptr MakeMatrixFilter( FilterInput::Ref input, @@ -137,10 +137,6 @@ class FilterContents : public Contents { Matrix GetTransform(const Matrix& parent_transform) const; - void SetNeedAbsorbOpacity(bool need_absorb_opacity); - - bool GetNeedAbsorbOpacity() const; - private: virtual std::optional GetFilterCoverage( const FilterInput::Vector& inputs, @@ -160,7 +156,6 @@ class FilterContents : public Contents { FilterInput::Vector inputs_; std::optional coverage_crop_; Matrix effect_transform_; - bool need_absorb_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(FilterContents); }; diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc index f318ea15ad2f9..10239fa00e246 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc @@ -17,6 +17,10 @@ LinearToSrgbFilterContents::LinearToSrgbFilterContents() = default; LinearToSrgbFilterContents::~LinearToSrgbFilterContents() = default; +void LinearToSrgbFilterContents::SetAbsorbOpacity(bool absorb_opacity) { + absorb_opacity_ = absorb_opacity; +} + std::optional LinearToSrgbFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -64,8 +68,7 @@ std::optional LinearToSrgbFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); - frag_info.input_alpha = - GetNeedAbsorbOpacity() ? input_snapshot->opacity : 1.0f; + frag_info.input_alpha = absorb_opacity_ ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -82,11 +85,10 @@ std::optional LinearToSrgbFilterContents::RenderFilter( } out_texture->SetLabel("LinearToSrgb Texture"); - return Snapshot{ - .texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor, - .opacity = GetNeedAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; + return Snapshot{.texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = absorb_opacity_ ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h index 271ac250ca711..8e0ef1811e69a 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h @@ -15,6 +15,8 @@ class LinearToSrgbFilterContents final : public FilterContents { ~LinearToSrgbFilterContents() override; + void SetAbsorbOpacity(bool absorb_opacity); + private: // |FilterContents| std::optional RenderFilter( @@ -24,6 +26,8 @@ class LinearToSrgbFilterContents final : public FilterContents { const Matrix& effect_transform, const Rect& coverage) const override; + bool absorb_opacity_ = false; + FML_DISALLOW_COPY_AND_ASSIGN(LinearToSrgbFilterContents); }; diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc index d6aef19b8d769..977d73f14a369 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc @@ -17,6 +17,10 @@ SrgbToLinearFilterContents::SrgbToLinearFilterContents() = default; SrgbToLinearFilterContents::~SrgbToLinearFilterContents() = default; +void SrgbToLinearFilterContents::SetAbsorbOpacity(bool absorb_opacity) { + absorb_opacity_ = absorb_opacity; +} + std::optional SrgbToLinearFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -64,8 +68,7 @@ std::optional SrgbToLinearFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); - frag_info.input_alpha = - GetNeedAbsorbOpacity() ? input_snapshot->opacity : 1.0f; + frag_info.input_alpha = absorb_opacity_ ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -82,11 +85,10 @@ std::optional SrgbToLinearFilterContents::RenderFilter( } out_texture->SetLabel("SrgbToLinear Texture"); - return Snapshot{ - .texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor, - .opacity = GetNeedAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; + return Snapshot{.texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = absorb_opacity_ ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h index 11d0dc762cffa..31c9ab89d1231 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h @@ -15,6 +15,8 @@ class SrgbToLinearFilterContents final : public FilterContents { ~SrgbToLinearFilterContents() override; + void SetAbsorbOpacity(bool absorb_opacity); + private: // |FilterContents| std::optional RenderFilter( @@ -24,6 +26,8 @@ class SrgbToLinearFilterContents final : public FilterContents { const Matrix& effect_transform, const Rect& coverage) const override; + bool absorb_opacity_ = false; + FML_DISALLOW_COPY_AND_ASSIGN(SrgbToLinearFilterContents); }; From a2bc5b5ecdd5f777cafa0fcf070af2b0836b1986 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Sat, 8 Oct 2022 14:49:02 +0800 Subject: [PATCH 5/8] Add a new method 'Paint::WithFiltersForSubpassTarget' and a new class 'ColorFilterContents' --- impeller/aiks/paint.cc | 25 +++++ impeller/aiks/paint.h | 15 ++- impeller/aiks/paint_pass_delegate.cc | 4 +- .../display_list/display_list_dispatcher.cc | 24 ++--- impeller/entity/BUILD.gn | 2 + .../contents/filters/blend_filter_contents.cc | 10 +- .../contents/filters/blend_filter_contents.h | 7 +- .../contents/filters/color_filter_contents.cc | 91 +++++++++++++++++++ .../contents/filters/color_filter_contents.h | 53 +++++++++++ .../filters/color_matrix_filter_contents.cc | 15 ++- .../filters/color_matrix_filter_contents.h | 7 +- .../contents/filters/filter_contents.cc | 79 ---------------- .../entity/contents/filters/filter_contents.h | 19 ---- .../filters/linear_to_srgb_filter_contents.cc | 15 ++- .../filters/linear_to_srgb_filter_contents.h | 8 +- .../filters/srgb_to_linear_filter_contents.cc | 15 ++- .../filters/srgb_to_linear_filter_contents.h | 8 +- impeller/entity/entity_pass.cc | 4 +- impeller/entity/entity_unittests.cc | 27 +++--- 19 files changed, 243 insertions(+), 185 deletions(-) create mode 100644 impeller/entity/contents/filters/color_filter_contents.cc create mode 100644 impeller/entity/contents/filters/color_filter_contents.h diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index c38d2c2bedf92..b05c7db23e4cc 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -67,6 +67,31 @@ std::shared_ptr Paint::WithFilters( return input; } +std::shared_ptr Paint::WithFiltersForSubpassTarget( + std::shared_ptr input, + const Matrix& effect_transform) const { + if (mask_blur_descriptor.has_value()) { + input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input), + false, effect_transform); + } + + if (image_filter.has_value()) { + const ImageFilterProc& filter = image_filter.value(); + input = filter(FilterInput::Make(input), effect_transform); + } + + if (color_filter.has_value()) { + const ColorFilterProc& filter = color_filter.value(); + auto color_filter_contents = filter(FilterInput::Make(input)); + if (color_filter_contents) { + color_filter_contents->SetAbsorbOpacity(true); + } + input = color_filter_contents; + } + + return input; +} + std::shared_ptr Paint::MaskBlurDescriptor::CreateMaskBlur( FilterInput::Ref input, bool is_solid_color, diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index d5c156ac180bc..a42d7117554cb 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -8,6 +8,7 @@ #include "flutter/fml/macros.h" #include "impeller/entity/contents/contents.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/linear_gradient_contents.h" #include "impeller/entity/contents/radial_gradient_contents.h" @@ -23,7 +24,7 @@ struct Paint { FilterInput::Ref, const Matrix& effect_transform)>; using ColorFilterProc = - std::function(FilterInput::Ref)>; + std::function(FilterInput::Ref)>; using MaskFilterProc = std::function( FilterInput::Ref, bool is_solid_color, @@ -75,6 +76,18 @@ struct Paint { std::optional is_solid_color = std::nullopt, const Matrix& effect_transform = Matrix()) const; + /// @brief Wrap this paint's configured filters to the given contents of + /// subpass target. + /// @param[in] input The contents of subpass target to wrap with paint's + /// filters. + /// + /// @return The filter-wrapped contents. If there are no filters that need + /// to be wrapped for the current paint configuration, the + /// original contents is returned. + std::shared_ptr WithFiltersForSubpassTarget( + std::shared_ptr input, + const Matrix& effect_transform = Matrix()) const; + std::shared_ptr CreateContentsForEntity(Path path = {}, bool cover = false) const; }; diff --git a/impeller/aiks/paint_pass_delegate.cc b/impeller/aiks/paint_pass_delegate.cc index f80441aa6d027..47e795f4ca1c2 100644 --- a/impeller/aiks/paint_pass_delegate.cc +++ b/impeller/aiks/paint_pass_delegate.cc @@ -40,8 +40,8 @@ std::shared_ptr PaintPassDelegate::CreateContentsForSubpassTarget( contents->SetSourceRect(Rect::MakeSize(target->GetSize())); contents->SetOpacity(paint_.color.alpha); contents->SetDeferApplyingOpacity(true); - - return paint_.WithFilters(std::move(contents), false, effect_transform); + return paint_.WithFiltersForSubpassTarget(std::move(contents), + effect_transform); } } // namespace impeller diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 137601b9c232d..024a6e460bce0 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -437,8 +437,7 @@ void DisplayListDispatcher::setColorSource( } static std::optional ToColorFilterProc( - const flutter::DlColorFilter* filter, - bool absorb_opacity = true) { + const flutter::DlColorFilter* filter) { if (filter == nullptr) { return std::nullopt; } @@ -447,27 +446,25 @@ static std::optional ToColorFilterProc( auto dl_blend = filter->asBlend(); auto blend_mode = ToBlendMode(dl_blend->mode()); auto color = ToColor(dl_blend->color()); - return [blend_mode, color, absorb_opacity](FilterInput::Ref input) { - return FilterContents::MakeBlend(blend_mode, {input}, color, - absorb_opacity); + return [blend_mode, color](FilterInput::Ref input) { + return ColorFilterContents::MakeBlend(blend_mode, {input}, color); }; } case flutter::DlColorFilterType::kMatrix: { const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix(); impeller::FilterContents::ColorMatrix color_matrix; dl_matrix->get_matrix(color_matrix.array); - return [color_matrix, absorb_opacity](FilterInput::Ref input) { - return FilterContents::MakeColorMatrix({input}, color_matrix, - absorb_opacity); + return [color_matrix](FilterInput::Ref input) { + return ColorFilterContents::MakeColorMatrix({input}, color_matrix); }; } case flutter::DlColorFilterType::kSrgbToLinearGamma: - return [absorb_opacity](FilterInput::Ref input) { - return FilterContents::MakeSrgbToLinearFilter({input}, absorb_opacity); + return [](FilterInput::Ref input) { + return ColorFilterContents::MakeSrgbToLinearFilter({input}); }; case flutter::DlColorFilterType::kLinearToSrgbGamma: - return [absorb_opacity](FilterInput::Ref input) { - return FilterContents::MakeLinearToSrgbFilter({input}, absorb_opacity); + return [](FilterInput::Ref input) { + return ColorFilterContents::MakeLinearToSrgbFilter({input}); }; case flutter::DlColorFilterType::kUnknown: FML_LOG(ERROR) << "requested DlColorFilterType::kUnknown"; @@ -633,8 +630,7 @@ static std::optional ToImageFilterProc( auto color_filter_image_filter = filter->asColorFilter(); FML_DCHECK(color_filter_image_filter); auto color_filter_proc = - ToColorFilterProc(color_filter_image_filter->color_filter().get(), - /*absorb_opacity=*/false); + ToColorFilterProc(color_filter_image_filter->color_filter().get()); if (!color_filter_proc.has_value()) { return std::nullopt; } diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index e2c9f4944da10..b2e0c93ee30b0 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -81,6 +81,8 @@ impeller_component("entity") { "contents/filters/blend_filter_contents.h", "contents/filters/border_mask_blur_filter_contents.cc", "contents/filters/border_mask_blur_filter_contents.h", + "contents/filters/color_filter_contents.cc", + "contents/filters/color_filter_contents.h", "contents/filters/color_matrix_filter_contents.cc", "contents/filters/color_matrix_filter_contents.h", "contents/filters/filter_contents.cc", diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 355a99d2c1187..8ce8a6a163d34 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -314,10 +314,6 @@ void BlendFilterContents::SetForegroundColor(std::optional color) { foreground_color_ = color; } -void BlendFilterContents::SetAbsorbOpacity(bool absorb_opacity) { - absorb_opacity_ = absorb_opacity; -} - std::optional BlendFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -331,17 +327,17 @@ std::optional BlendFilterContents::RenderFilter( if (inputs.size() == 1 && !foreground_color_.has_value()) { // Nothing to blend. return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource, - std::nullopt, absorb_opacity_); + std::nullopt, GetAbsorbOpacity()); } if (blend_mode_ <= Entity::kLastPipelineBlendMode) { return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_, - foreground_color_, absorb_opacity_); + foreground_color_, GetAbsorbOpacity()); } if (blend_mode_ <= Entity::kLastAdvancedBlendMode) { return advanced_blend_proc_(inputs, renderer, entity, coverage, - foreground_color_, absorb_opacity_); + foreground_color_, GetAbsorbOpacity()); } FML_UNREACHABLE(); } diff --git a/impeller/entity/contents/filters/blend_filter_contents.h b/impeller/entity/contents/filters/blend_filter_contents.h index 60c8352f675d8..5276eb81f05f1 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.h +++ b/impeller/entity/contents/filters/blend_filter_contents.h @@ -4,12 +4,12 @@ #pragma once -#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" namespace impeller { -class BlendFilterContents : public FilterContents { +class BlendFilterContents : public ColorFilterContents { public: using AdvancedBlendProc = std::function( const FilterInput::Vector& inputs, @@ -29,8 +29,6 @@ class BlendFilterContents : public FilterContents { /// been blended. void SetForegroundColor(std::optional color); - void SetAbsorbOpacity(bool absorb_opacity); - private: // |FilterContents| std::optional RenderFilter(const FilterInput::Vector& inputs, @@ -42,7 +40,6 @@ class BlendFilterContents : public FilterContents { BlendMode blend_mode_ = BlendMode::kSourceOver; AdvancedBlendProc advanced_blend_proc_; std::optional foreground_color_; - bool absorb_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(BlendFilterContents); }; diff --git a/impeller/entity/contents/filters/color_filter_contents.cc b/impeller/entity/contents/filters/color_filter_contents.cc new file mode 100644 index 0000000000000..10fdcec47bd84 --- /dev/null +++ b/impeller/entity/contents/filters/color_filter_contents.cc @@ -0,0 +1,91 @@ +// 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/entity/contents/filters/color_filter_contents.h" + +#include "impeller/base/validation.h" +#include "impeller/entity/contents/filters/blend_filter_contents.h" +#include "impeller/entity/contents/filters/color_matrix_filter_contents.h" +#include "impeller/entity/contents/filters/linear_to_srgb_filter_contents.h" +#include "impeller/entity/contents/filters/srgb_to_linear_filter_contents.h" + +namespace impeller { + +std::shared_ptr ColorFilterContents::MakeBlend( + BlendMode blend_mode, + FilterInput::Vector inputs, + std::optional foreground_color) { + if (blend_mode > Entity::kLastAdvancedBlendMode) { + VALIDATION_LOG << "Invalid blend mode " << static_cast(blend_mode) + << " passed to ColorFilterContents::MakeBlend."; + return nullptr; + } + + size_t total_inputs = inputs.size() + (foreground_color.has_value() ? 1 : 0); + if (total_inputs < 2 || blend_mode <= Entity::kLastPipelineBlendMode) { + auto blend = std::make_shared(); + blend->SetInputs(inputs); + blend->SetBlendMode(blend_mode); + blend->SetForegroundColor(foreground_color); + return blend; + } + + auto blend_input = inputs[0]; + std::shared_ptr new_blend; + for (auto in_i = inputs.begin() + 1; in_i < inputs.end(); in_i++) { + new_blend = std::make_shared(); + new_blend->SetInputs({*in_i, blend_input}); + new_blend->SetBlendMode(blend_mode); + if (in_i < inputs.end() - 1 || foreground_color.has_value()) { + blend_input = FilterInput::Make( + std::static_pointer_cast(new_blend)); + } + } + + if (foreground_color.has_value()) { + new_blend = std::make_shared(); + new_blend->SetInputs({blend_input}); + new_blend->SetBlendMode(blend_mode); + new_blend->SetForegroundColor(foreground_color); + } + + return new_blend; +} + +std::shared_ptr ColorFilterContents::MakeColorMatrix( + FilterInput::Ref input, + const ColorMatrix& color_matrix) { + auto filter = std::make_shared(); + filter->SetInputs({input}); + filter->SetMatrix(color_matrix); + return filter; +} + +std::shared_ptr +ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Ref input) { + auto filter = std::make_shared(); + filter->SetInputs({input}); + return filter; +} + +std::shared_ptr +ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Ref input) { + auto filter = std::make_shared(); + filter->SetInputs({input}); + return filter; +} + +ColorFilterContents::ColorFilterContents() = default; + +ColorFilterContents::~ColorFilterContents() = default; + +void ColorFilterContents::SetAbsorbOpacity(bool absorb_opacity) { + absorb_opacity_ = absorb_opacity; +} + +bool ColorFilterContents::GetAbsorbOpacity() const { + return absorb_opacity_; +} + +} // namespace impeller diff --git a/impeller/entity/contents/filters/color_filter_contents.h b/impeller/entity/contents/filters/color_filter_contents.h new file mode 100644 index 0000000000000..0307dbd94894d --- /dev/null +++ b/impeller/entity/contents/filters/color_filter_contents.h @@ -0,0 +1,53 @@ +// 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 "impeller/entity/contents/filters/filter_contents.h" + +namespace impeller { + +class ColorFilterContents : public FilterContents { + public: + static std::shared_ptr MakeBlend( + BlendMode blend_mode, + FilterInput::Vector inputs, + std::optional foreground_color = std::nullopt); + + static std::shared_ptr MakeColorMatrix( + FilterInput::Ref input, + const ColorMatrix& color_matrix); + + static std::shared_ptr MakeLinearToSrgbFilter( + FilterInput::Ref input); + + static std::shared_ptr MakeSrgbToLinearFilter( + FilterInput::Ref input); + + ColorFilterContents(); + + ~ColorFilterContents() override; + + void SetAbsorbOpacity(bool absorb_opacity); + bool GetAbsorbOpacity() const; + + private: + bool absorb_opacity_ = false; + // virtual std::optional GetFilterCoverage( + // const FilterInput::Vector& inputs, + // const Entity& entity, + // const Matrix& effect_transform) const; + + // /// @brief Converts zero or more filter inputs into a new texture. + // virtual std::optional RenderFilter( + // const FilterInput::Vector& inputs, + // const ContentContext& renderer, + // const Entity& entity, + // const Matrix& effect_transform, + // const Rect& coverage) const = 0; + + FML_DISALLOW_COPY_AND_ASSIGN(ColorFilterContents); +}; + +} // namespace impeller diff --git a/impeller/entity/contents/filters/color_matrix_filter_contents.cc b/impeller/entity/contents/filters/color_matrix_filter_contents.cc index ea976b2552b8a..66e8464f81d49 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.cc +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.cc @@ -23,10 +23,6 @@ void ColorMatrixFilterContents::SetMatrix(const ColorMatrix& matrix) { matrix_ = matrix; } -void ColorMatrixFilterContents::SetAbsorbOpacity(bool absorb_opacity) { - absorb_opacity_ = absorb_opacity; -} - std::optional ColorMatrixFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -91,7 +87,7 @@ std::optional ColorMatrixFilterContents::RenderFilter( matrix[3], matrix[8], matrix[13], matrix[18] ); // clang-format on - frag_info.input_alpha = absorb_opacity_ ? input_snapshot->opacity : 1.0f; + frag_info.input_alpha = GetAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); @@ -108,10 +104,11 @@ std::optional ColorMatrixFilterContents::RenderFilter( } out_texture->SetLabel("ColorMatrixFilter Texture"); - return Snapshot{.texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor, - .opacity = absorb_opacity_ ? 1.0f : input_snapshot->opacity}; + return Snapshot{ + .texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = GetAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/color_matrix_filter_contents.h b/impeller/entity/contents/filters/color_matrix_filter_contents.h index a24ae43f54cb4..3486365a5a642 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.h +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.h @@ -7,14 +7,14 @@ #include #include -#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" namespace impeller { // Look at example at: https://github.com/flutter/impeller/pull/132 -class ColorMatrixFilterContents final : public FilterContents { +class ColorMatrixFilterContents final : public ColorFilterContents { public: ColorMatrixFilterContents(); @@ -22,8 +22,6 @@ class ColorMatrixFilterContents final : public FilterContents { void SetMatrix(const ColorMatrix& matrix); - void SetAbsorbOpacity(bool absorb_opacity); - private: // |FilterContents| std::optional RenderFilter( @@ -34,7 +32,6 @@ class ColorMatrixFilterContents final : public FilterContents { const Rect& coverage) const override; ColorMatrix matrix_; - bool absorb_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(ColorMatrixFilterContents); }; diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index e2c7f9376b9ab..671101dbcbd53 100644 --- a/impeller/entity/contents/filters/filter_contents.cc +++ b/impeller/entity/contents/filters/filter_contents.cc @@ -12,18 +12,13 @@ #include #include "flutter/fml/logging.h" -#include "impeller/base/validation.h" #include "impeller/entity/contents/content_context.h" -#include "impeller/entity/contents/filters/blend_filter_contents.h" #include "impeller/entity/contents/filters/border_mask_blur_filter_contents.h" -#include "impeller/entity/contents/filters/color_matrix_filter_contents.h" #include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" -#include "impeller/entity/contents/filters/linear_to_srgb_filter_contents.h" #include "impeller/entity/contents/filters/local_matrix_filter_contents.h" #include "impeller/entity/contents/filters/matrix_filter_contents.h" #include "impeller/entity/contents/filters/morphology_filter_contents.h" -#include "impeller/entity/contents/filters/srgb_to_linear_filter_contents.h" #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" #include "impeller/geometry/path_builder.h" @@ -33,51 +28,6 @@ namespace impeller { -std::shared_ptr FilterContents::MakeBlend( - BlendMode blend_mode, - FilterInput::Vector inputs, - std::optional foreground_color, - bool absorb_opacity) { - if (blend_mode > Entity::kLastAdvancedBlendMode) { - VALIDATION_LOG << "Invalid blend mode " << static_cast(blend_mode) - << " passed to FilterContents::MakeBlend."; - return nullptr; - } - - size_t total_inputs = inputs.size() + (foreground_color.has_value() ? 1 : 0); - if (total_inputs < 2 || blend_mode <= Entity::kLastPipelineBlendMode) { - auto blend = std::make_shared(); - blend->SetInputs(inputs); - blend->SetBlendMode(blend_mode); - blend->SetForegroundColor(foreground_color); - blend->SetAbsorbOpacity(absorb_opacity); - return blend; - } - - auto blend_input = inputs[0]; - std::shared_ptr new_blend; - for (auto in_i = inputs.begin() + 1; in_i < inputs.end(); in_i++) { - new_blend = std::make_shared(); - new_blend->SetInputs({*in_i, blend_input}); - new_blend->SetBlendMode(blend_mode); - new_blend->SetAbsorbOpacity(absorb_opacity); - if (in_i < inputs.end() - 1 || foreground_color.has_value()) { - blend_input = FilterInput::Make( - std::static_pointer_cast(new_blend)); - } - } - - if (foreground_color.has_value()) { - new_blend = std::make_shared(); - new_blend->SetInputs({blend_input}); - new_blend->SetBlendMode(blend_mode); - new_blend->SetForegroundColor(foreground_color); - new_blend->SetAbsorbOpacity(absorb_opacity); - } - - return new_blend; -} - std::shared_ptr FilterContents::MakeDirectionalGaussianBlur( FilterInput::Ref input, Sigma sigma, @@ -158,35 +108,6 @@ std::shared_ptr FilterContents::MakeMorphology( return y_morphology; } -std::shared_ptr FilterContents::MakeColorMatrix( - FilterInput::Ref input, - const ColorMatrix& color_matrix, - bool absorb_opacity) { - auto filter = std::make_shared(); - filter->SetInputs({input}); - filter->SetMatrix(color_matrix); - filter->SetAbsorbOpacity(absorb_opacity); - return filter; -} - -std::shared_ptr FilterContents::MakeLinearToSrgbFilter( - FilterInput::Ref input, - bool absorb_opacity) { - auto filter = std::make_shared(); - filter->SetInputs({input}); - filter->SetAbsorbOpacity(absorb_opacity); - return filter; -} - -std::shared_ptr FilterContents::MakeSrgbToLinearFilter( - FilterInput::Ref input, - bool absorb_opacity) { - auto filter = std::make_shared(); - filter->SetInputs({input}); - filter->SetAbsorbOpacity(absorb_opacity); - return filter; -} - std::shared_ptr FilterContents::MakeMatrixFilter( FilterInput::Ref input, const Matrix& matrix, diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index 1bdc650a1095e..bfb25aa7c8f01 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -36,12 +36,6 @@ class FilterContents : public Contents { enum class MorphType { kDilate, kErode }; - static std::shared_ptr MakeBlend( - BlendMode blend_mode, - FilterInput::Vector inputs, - std::optional foreground_color = std::nullopt, - bool absorb_opacity = true); - static std::shared_ptr MakeDirectionalGaussianBlur( FilterInput::Ref input, Sigma sigma, @@ -81,19 +75,6 @@ class FilterContents : public Contents { MorphType morph_type, const Matrix& effect_transform = Matrix()); - static std::shared_ptr MakeColorMatrix( - FilterInput::Ref input, - const ColorMatrix& color_matrix, - bool absorb_opacity = true); - - static std::shared_ptr MakeLinearToSrgbFilter( - FilterInput::Ref input, - bool absorb_opacity = true); - - static std::shared_ptr MakeSrgbToLinearFilter( - FilterInput::Ref input, - bool absorb_opacity = true); - static std::shared_ptr MakeMatrixFilter( FilterInput::Ref input, const Matrix& matrix, diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc index 10239fa00e246..98d397a727008 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc @@ -17,10 +17,6 @@ LinearToSrgbFilterContents::LinearToSrgbFilterContents() = default; LinearToSrgbFilterContents::~LinearToSrgbFilterContents() = default; -void LinearToSrgbFilterContents::SetAbsorbOpacity(bool absorb_opacity) { - absorb_opacity_ = absorb_opacity; -} - std::optional LinearToSrgbFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -68,7 +64,7 @@ std::optional LinearToSrgbFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); - frag_info.input_alpha = absorb_opacity_ ? input_snapshot->opacity : 1.0f; + frag_info.input_alpha = GetAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -85,10 +81,11 @@ std::optional LinearToSrgbFilterContents::RenderFilter( } out_texture->SetLabel("LinearToSrgb Texture"); - return Snapshot{.texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor, - .opacity = absorb_opacity_ ? 1.0f : input_snapshot->opacity}; + return Snapshot{ + .texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = GetAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h index 8e0ef1811e69a..00b7116420a55 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.h @@ -4,19 +4,17 @@ #pragma once -#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" namespace impeller { -class LinearToSrgbFilterContents final : public FilterContents { +class LinearToSrgbFilterContents final : public ColorFilterContents { public: LinearToSrgbFilterContents(); ~LinearToSrgbFilterContents() override; - void SetAbsorbOpacity(bool absorb_opacity); - private: // |FilterContents| std::optional RenderFilter( @@ -26,8 +24,6 @@ class LinearToSrgbFilterContents final : public FilterContents { const Matrix& effect_transform, const Rect& coverage) const override; - bool absorb_opacity_ = false; - FML_DISALLOW_COPY_AND_ASSIGN(LinearToSrgbFilterContents); }; diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc index 977d73f14a369..ee483b6ed5e93 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc @@ -17,10 +17,6 @@ SrgbToLinearFilterContents::SrgbToLinearFilterContents() = default; SrgbToLinearFilterContents::~SrgbToLinearFilterContents() = default; -void SrgbToLinearFilterContents::SetAbsorbOpacity(bool absorb_opacity) { - absorb_opacity_ = absorb_opacity; -} - std::optional SrgbToLinearFilterContents::RenderFilter( const FilterInput::Vector& inputs, const ContentContext& renderer, @@ -68,7 +64,7 @@ std::optional SrgbToLinearFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); - frag_info.input_alpha = absorb_opacity_ ? input_snapshot->opacity : 1.0f; + frag_info.input_alpha = GetAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -85,10 +81,11 @@ std::optional SrgbToLinearFilterContents::RenderFilter( } out_texture->SetLabel("SrgbToLinear Texture"); - return Snapshot{.texture = out_texture, - .transform = input_snapshot->transform, - .sampler_descriptor = input_snapshot->sampler_descriptor, - .opacity = absorb_opacity_ ? 1.0f : input_snapshot->opacity}; + return Snapshot{ + .texture = out_texture, + .transform = input_snapshot->transform, + .sampler_descriptor = input_snapshot->sampler_descriptor, + .opacity = GetAbsorbOpacity() ? 1.0f : input_snapshot->opacity}; } } // namespace impeller diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h index 31c9ab89d1231..07b3307159c74 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.h @@ -4,19 +4,17 @@ #pragma once -#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" namespace impeller { -class SrgbToLinearFilterContents final : public FilterContents { +class SrgbToLinearFilterContents final : public ColorFilterContents { public: SrgbToLinearFilterContents(); ~SrgbToLinearFilterContents() override; - void SetAbsorbOpacity(bool absorb_opacity); - private: // |FilterContents| std::optional RenderFilter( @@ -26,8 +24,6 @@ class SrgbToLinearFilterContents final : public FilterContents { const Matrix& effect_transform, const Rect& coverage) const override; - bool absorb_opacity_ = false; - FML_DISALLOW_COPY_AND_ASSIGN(SrgbToLinearFilterContents); }; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 71a7bd735c51e..8a6f2bd3a2bf0 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -12,7 +12,7 @@ #include "flutter/fml/trace_event.h" #include "impeller/base/validation.h" #include "impeller/entity/contents/content_context.h" -#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" @@ -532,7 +532,7 @@ bool EntityPass::OnRender( FilterInput::Make(texture, result.entity.GetTransformation().Invert())}; auto contents = - FilterContents::MakeBlend(result.entity.GetBlendMode(), inputs); + ColorFilterContents::MakeBlend(result.entity.GetBlendMode(), inputs); contents->SetCoverageCrop(result.entity.GetCoverage()); result.entity.SetContents(std::move(contents)); result.entity.SetBlendMode(BlendMode::kSourceOver); diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index b5b2e50a6f91b..c56dba23e4afd 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -15,6 +15,7 @@ #include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/contents.h" #include "impeller/entity/contents/filters/blend_filter_contents.h" +#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/entity/contents/rrect_shadow_contents.h" @@ -151,8 +152,8 @@ TEST_P(EntityTest, EntityPassCoverageRespectsCoverageLimit) { TEST_P(EntityTest, FilterCoverageRespectsCropRect) { auto image = CreateTextureForFixture("boston.jpg"); - auto filter = FilterContents::MakeBlend(BlendMode::kSoftLight, - FilterInput::Make({image})); + auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight, + FilterInput::Make({image})); // Without the crop rect (default behavior). { @@ -840,10 +841,10 @@ TEST_P(EntityTest, Filters) { auto fi_boston = FilterInput::Make(boston); auto fi_kalimba = FilterInput::Make(kalimba); - auto blend0 = FilterContents::MakeBlend(BlendMode::kModulate, - {fi_kalimba, fi_boston}); + std::shared_ptr blend0 = ColorFilterContents::MakeBlend( + BlendMode::kModulate, {fi_kalimba, fi_boston}); - auto blend1 = FilterContents::MakeBlend( + auto blend1 = ColorFilterContents::MakeBlend( BlendMode::kScreen, {fi_bridge, FilterInput::Make(blend0), fi_bridge, fi_bridge}); @@ -1583,7 +1584,7 @@ TEST_P(EntityTest, ColorMatrixFilterCoverageIsCorrect) { }; auto filter = - FilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix); + ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix); Entity e; e.SetTransformation(Matrix()); @@ -1640,8 +1641,8 @@ TEST_P(EntityTest, ColorMatrixFilterEditable) { ImGui::End(); // Set the color matrix filter. - auto filter = FilterContents::MakeColorMatrix(FilterInput::Make(bay_bridge), - color_matrix); + auto filter = ColorFilterContents::MakeColorMatrix( + FilterInput::Make(bay_bridge), color_matrix); // Define the entity with the color matrix filter. Entity entity; @@ -1668,7 +1669,8 @@ TEST_P(EntityTest, LinearToSrgbFilterCoverageIsCorrect) { PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath())); fill->SetColor(Color::MintCream()); - auto filter = FilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill)); + auto filter = + ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill)); Entity e; e.SetTransformation(Matrix()); @@ -1687,7 +1689,7 @@ TEST_P(EntityTest, LinearToSrgbFilter) { auto callback = [&](ContentContext& context, RenderPass& pass) -> bool { auto filtered = - FilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image)); + ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image)); // Define the entity that will serve as the control image as a Gaussian blur // filter with no filter at all. @@ -1719,7 +1721,8 @@ TEST_P(EntityTest, SrgbToLinearFilterCoverageIsCorrect) { PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath())); fill->SetColor(Color::DeepPink()); - auto filter = FilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill)); + auto filter = + ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill)); Entity e; e.SetTransformation(Matrix()); @@ -1738,7 +1741,7 @@ TEST_P(EntityTest, SrgbToLinearFilter) { auto callback = [&](ContentContext& context, RenderPass& pass) -> bool { auto filtered = - FilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image)); + ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image)); // Define the entity that will serve as the control image as a Gaussian blur // filter with no filter at all. From dd4b4333cd8859d4f539ec3151056e9b8b8a5f62 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Sat, 8 Oct 2022 15:02:02 +0800 Subject: [PATCH 6/8] Update licenses_flutter --- ci/licenses_golden/licenses_flutter | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index cb9bd0c1f3b05..9c8de3cf5a534 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1175,6 +1175,8 @@ FILE: ../../../flutter/impeller/entity/contents/filters/blend_filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/blend_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/border_mask_blur_filter_contents.h +FILE: ../../../flutter/impeller/entity/contents/filters/color_filter_contents.cc +FILE: ../../../flutter/impeller/entity/contents/filters/color_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/color_matrix_filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/color_matrix_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.cc From c20563d65505e37a12dc10f1ae4b1a0d46934358 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Sat, 8 Oct 2022 15:04:27 +0800 Subject: [PATCH 7/8] Clean code --- .../entity/contents/filters/color_filter_contents.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/impeller/entity/contents/filters/color_filter_contents.h b/impeller/entity/contents/filters/color_filter_contents.h index 0307dbd94894d..17e54b56039f0 100644 --- a/impeller/entity/contents/filters/color_filter_contents.h +++ b/impeller/entity/contents/filters/color_filter_contents.h @@ -30,22 +30,11 @@ class ColorFilterContents : public FilterContents { ~ColorFilterContents() override; void SetAbsorbOpacity(bool absorb_opacity); + bool GetAbsorbOpacity() const; private: bool absorb_opacity_ = false; - // virtual std::optional GetFilterCoverage( - // const FilterInput::Vector& inputs, - // const Entity& entity, - // const Matrix& effect_transform) const; - - // /// @brief Converts zero or more filter inputs into a new texture. - // virtual std::optional RenderFilter( - // const FilterInput::Vector& inputs, - // const ContentContext& renderer, - // const Entity& entity, - // const Matrix& effect_transform, - // const Rect& coverage) const = 0; FML_DISALLOW_COPY_AND_ASSIGN(ColorFilterContents); }; From 6e1bf7065321e4d59bf52b002a01045bd7c74c6d Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Sat, 8 Oct 2022 15:22:45 +0800 Subject: [PATCH 8/8] Reuse logic --- impeller/aiks/paint.cc | 46 ++++++++++++++++++++++++------------------ impeller/aiks/paint.h | 12 +++++++++++ 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index b05c7db23e4cc..76853dc6ecaa1 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -48,47 +48,53 @@ std::shared_ptr Paint::WithFilters( std::optional is_solid_color, const Matrix& effect_transform) const { bool is_solid_color_val = is_solid_color.value_or(!color_source); - - if (mask_blur_descriptor.has_value()) { - input = mask_blur_descriptor->CreateMaskBlur( - FilterInput::Make(input), is_solid_color_val, effect_transform); - } - - if (image_filter.has_value()) { - const ImageFilterProc& filter = image_filter.value(); - input = filter(FilterInput::Make(input), effect_transform); - } - - if (color_filter.has_value()) { - const ColorFilterProc& filter = color_filter.value(); - input = filter(FilterInput::Make(input)); - } - + input = WithMaskBlur(input, is_solid_color_val, effect_transform); + input = WithImageFilter(input, effect_transform); + input = WithColorFilter(input); return input; } std::shared_ptr Paint::WithFiltersForSubpassTarget( std::shared_ptr input, const Matrix& effect_transform) const { + input = WithMaskBlur(input, false, effect_transform); + input = WithImageFilter(input, effect_transform); + input = WithColorFilter(input, /**absorb_opacity=*/true); + return input; +} + +std::shared_ptr Paint::WithMaskBlur( + std::shared_ptr input, + bool is_solid_color, + const Matrix& effect_transform) const { if (mask_blur_descriptor.has_value()) { - input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input), - false, effect_transform); + input = mask_blur_descriptor->CreateMaskBlur( + FilterInput::Make(input), is_solid_color, effect_transform); } + return input; +} +std::shared_ptr Paint::WithImageFilter( + std::shared_ptr input, + const Matrix& effect_transform) const { if (image_filter.has_value()) { const ImageFilterProc& filter = image_filter.value(); input = filter(FilterInput::Make(input), effect_transform); } + return input; +} +std::shared_ptr Paint::WithColorFilter( + std::shared_ptr input, + bool absorb_opacity) const { if (color_filter.has_value()) { const ColorFilterProc& filter = color_filter.value(); auto color_filter_contents = filter(FilterInput::Make(input)); if (color_filter_contents) { - color_filter_contents->SetAbsorbOpacity(true); + color_filter_contents->SetAbsorbOpacity(absorb_opacity); } input = color_filter_contents; } - return input; } diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index a42d7117554cb..9fa85057019ed 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -90,6 +90,18 @@ struct Paint { std::shared_ptr CreateContentsForEntity(Path path = {}, bool cover = false) const; + + private: + std::shared_ptr WithMaskBlur(std::shared_ptr input, + bool is_solid_color, + const Matrix& effect_transform) const; + + std::shared_ptr WithImageFilter( + std::shared_ptr input, + const Matrix& effect_transform) const; + + std::shared_ptr WithColorFilter(std::shared_ptr input, + bool absorb_opacity = false) const; }; } // namespace impeller