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 diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index c38d2c2bedf92..76853dc6ecaa1 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -48,22 +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); + 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), is_solid_color_val, effect_transform); + 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(); - input = filter(FilterInput::Make(input)); + auto color_filter_contents = filter(FilterInput::Make(input)); + if (color_filter_contents) { + 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 d5c156ac180bc..9fa85057019ed 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,8 +76,32 @@ 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; + + 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 diff --git a/impeller/aiks/paint_pass_delegate.cc b/impeller/aiks/paint_pass_delegate.cc index faaacf12f5d8b..47e795f4ca1c2 100644 --- a/impeller/aiks/paint_pass_delegate.cc +++ b/impeller/aiks/paint_pass_delegate.cc @@ -39,8 +39,9 @@ std::shared_ptr PaintPassDelegate::CreateContentsForSubpassTarget( contents->SetTexture(target); contents->SetSourceRect(Rect::MakeSize(target->GetSize())); contents->SetOpacity(paint_.color.alpha); - - return paint_.WithFilters(std::move(contents), false, effect_transform); + contents->SetDeferApplyingOpacity(true); + 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 1da0db438cb8b..024a6e460bce0 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -447,7 +447,7 @@ static std::optional ToColorFilterProc( 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 ColorFilterContents::MakeBlend(blend_mode, {input}, color); }; } case flutter::DlColorFilterType::kMatrix: { @@ -455,16 +455,16 @@ static std::optional ToColorFilterProc( 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 ColorFilterContents::MakeColorMatrix({input}, color_matrix); }; } case flutter::DlColorFilterType::kSrgbToLinearGamma: return [](FilterInput::Ref input) { - return FilterContents::MakeSrgbToLinearFilter({input}); + return ColorFilterContents::MakeSrgbToLinearFilter({input}); }; case flutter::DlColorFilterType::kLinearToSrgbGamma: return [](FilterInput::Ref input) { - return FilterContents::MakeLinearToSrgbFilter({input}); + return ColorFilterContents::MakeLinearToSrgbFilter({input}); }; case flutter::DlColorFilterType::kUnknown: FML_LOG(ERROR) << "requested DlColorFilterType::kUnknown"; diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 201371839b172..b5762bbbd45e5 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"); diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index bce02deec6153..8a417d30fbd7c 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -79,6 +79,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 682e8af1195be..754c716913b77 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 absorb_opacity, PipelineProc pipeline_proc) { using VS = typename TPipeline::VertexShader; using FS = typename TPipeline::FragmentShader; @@ -108,6 +109,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 = absorb_opacity ? dst_snapshot->opacity : 1.0f; if (foreground_color.has_value()) { blend_info.color_factor = 1; @@ -142,7 +144,8 @@ static std::optional AdvancedBlend( return Snapshot{.texture = out_texture, .transform = Matrix::MakeTranslation(coverage.origin), - .sampler_descriptor = dst_snapshot->sampler_descriptor}; + .sampler_descriptor = dst_snapshot->sampler_descriptor, + .opacity = absorb_opacity ? 1.0f : dst_snapshot->opacity}; } static std::optional PipelineBlend( @@ -151,10 +154,13 @@ static std::optional PipelineBlend( const Entity& entity, const Rect& coverage, BlendMode pipeline_blend, - std::optional foreground_color) { + std::optional foreground_color, + bool 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(); @@ -196,6 +202,7 @@ static std::optional PipelineBlend( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input->texture->GetYCoordScale(); + 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)); @@ -204,10 +211,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; } @@ -257,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 = 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 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) { @@ -320,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, GetAbsorbOpacity()); } if (blend_mode_ <= Entity::kLastPipelineBlendMode) { return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_, - foreground_color_); + foreground_color_, GetAbsorbOpacity()); } if (blend_mode_ <= Entity::kLastAdvancedBlendMode) { return advanced_blend_proc_(inputs, renderer, entity, coverage, - foreground_color_); + 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 466842e61d762..5276eb81f05f1 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.h +++ b/impeller/entity/contents/filters/blend_filter_contents.h @@ -4,19 +4,20 @@ #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, const ContentContext& renderer, const Entity& entity, const Rect& coverage, - std::optional foreground_color)>; + std::optional foreground_color, + bool 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_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..17e54b56039f0 --- /dev/null +++ b/impeller/entity/contents/filters/color_filter_contents.h @@ -0,0 +1,42 @@ +// 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; + + 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 eba9d3a867473..66e8464f81d49 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.cc +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.cc @@ -87,6 +87,7 @@ std::optional ColorMatrixFilterContents::RenderFilter( matrix[3], matrix[8], matrix[13], matrix[18] ); // clang-format on + 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)); @@ -103,9 +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}; + 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 b725249019106..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(); diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index 06f49b2557055..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,47 +28,6 @@ namespace impeller { -std::shared_ptr FilterContents::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 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); - 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 FilterContents::MakeDirectionalGaussianBlur( FilterInput::Ref input, Sigma sigma, @@ -154,29 +108,6 @@ std::shared_ptr FilterContents::MakeMorphology( return y_morphology; } -std::shared_ptr FilterContents::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 FilterContents::MakeLinearToSrgbFilter( - FilterInput::Ref input) { - auto filter = std::make_shared(); - filter->SetInputs({input}); - return filter; -} - -std::shared_ptr FilterContents::MakeSrgbToLinearFilter( - FilterInput::Ref input) { - auto filter = std::make_shared(); - filter->SetInputs({input}); - return filter; -} - std::shared_ptr FilterContents::MakeMatrixFilter( FilterInput::Ref input, const Matrix& matrix, @@ -236,6 +167,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()); diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index af1f1d4b88b35..bfb25aa7c8f01 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -36,11 +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); - static std::shared_ptr MakeDirectionalGaussianBlur( FilterInput::Ref input, Sigma sigma, @@ -80,16 +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); - - static std::shared_ptr MakeLinearToSrgbFilter( - FilterInput::Ref input); - - static std::shared_ptr MakeSrgbToLinearFilter( - FilterInput::Ref input); - static std::shared_ptr MakeMatrixFilter( FilterInput::Ref input, const Matrix& matrix, 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..98d397a727008 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,7 @@ std::optional LinearToSrgbFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); + frag_info.input_alpha = GetAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -80,9 +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}; + 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 271ac250ca711..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,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 LinearToSrgbFilterContents final : public FilterContents { +class LinearToSrgbFilterContents final : public ColorFilterContents { public: LinearToSrgbFilterContents(); 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..ee483b6ed5e93 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,7 @@ std::optional SrgbToLinearFilterContents::RenderFilter( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); + frag_info.input_alpha = GetAbsorbOpacity() ? input_snapshot->opacity : 1.0f; auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindInputTexture(cmd, input_snapshot->texture, sampler); @@ -80,9 +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}; + 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 11d0dc762cffa..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,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 SrgbToLinearFilterContents final : public FilterContents { +class SrgbToLinearFilterContents final : public ColorFilterContents { public: SrgbToLinearFilterContents(); diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index 119a921bbe5cc..d57b1e9e67cca 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/entity_pass.cc b/impeller/entity/entity_pass.cc index a2b5dfd5e11df..721e14a89f5df 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::kSource); 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. diff --git a/impeller/entity/shaders/blending/advanced_blend.glsl b/impeller/entity/shaders/blending/advanced_blend.glsl index 066644229e9b9..6ff1d93ab6810 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 dst = IPUnpremultiply(dst_sample); vec4 src = blend_info.color_factor > 0 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 4d32b147dfe35..e4fb50b1a2ead 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; vec4 color = IPUnpremultiply(input_color); for (int i = 0; i < 3; i++) { diff --git a/impeller/entity/shaders/srgb_to_linear_filter.frag b/impeller/entity/shaders/srgb_to_linear_filter.frag index a8a82436ac5be..7c524fe80c291 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; vec4 color = IPUnpremultiply(input_color); for (int i = 0; i < 3; i++) { 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