From ed5919163bbf7e693424e3437328750ebac05db3 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:58:27 -0800 Subject: [PATCH] Revert "[Impeller] new blur: refactored math and fixed expanded padding size" (#49298) Reverts flutter/engine#49206 --- impeller/aiks/aiks_unittests.cc | 1 + .../filters/gaussian_blur_filter_contents.cc | 98 ++++++++++++------- .../filters/gaussian_blur_filter_contents.h | 6 +- ...gaussian_blur_filter_contents_unittests.cc | 4 +- 4 files changed, 65 insertions(+), 44 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 805c91cdb4850..54d0b1de62401 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -3976,5 +3976,6 @@ TEST_P(AiksTest, SubpassWithClearColorOptimization) { // will be filled with NaNs and may produce a magenta texture on macOS or iOS. ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } + } // namespace testing } // namespace impeller diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index d44928fffc669..f61439d7f047e 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -19,6 +19,16 @@ using GaussianBlurFragmentShader = GaussianBlurPipeline::FragmentShader; namespace { +std::optional ExpandCoverageHint(const std::optional& coverage_hint, + const Matrix& source_to_local_transform, + const Vector2& padding) { + if (!coverage_hint.has_value()) { + return std::nullopt; + } + Vector2 transformed_padding = (source_to_local_transform * padding).Abs(); + return coverage_hint->Expand(transformed_padding); +} + SamplerDescriptor MakeSamplerDescriptor(MinMagFilter filter, SamplerAddressMode address_mode) { SamplerDescriptor sampler_desc; @@ -38,6 +48,12 @@ void BindVertices(Command& cmd, cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer)); } +Matrix MakeAnchorScale(const Point& anchor, Vector2 scale) { + return Matrix::MakeTranslation({anchor.x, anchor.y, 0}) * + Matrix::MakeScale(scale) * + Matrix::MakeTranslation({-anchor.x, -anchor.y, 0}); +} + void SetTileMode(SamplerDescriptor* descriptor, const ContentContext& renderer, Entity::TileMode tile_mode) { @@ -71,6 +87,7 @@ std::shared_ptr MakeDownsampleSubpass( const SamplerDescriptor& sampler_descriptor, const Quad& uvs, const ISize& subpass_size, + const Vector2 padding, Entity::TileMode tile_mode) { ContentContext::SubpassCallback subpass_callback = [&](const ContentContext& renderer, RenderPass& pass) { @@ -87,13 +104,23 @@ std::shared_ptr MakeDownsampleSubpass( frame_info.texture_sampler_y_coord_scale = 1.0; frame_info.alpha = 1.0; - BindVertices(cmd, host_buffer, - { - {Point(0, 0), uvs[0]}, - {Point(1, 0), uvs[1]}, - {Point(0, 1), uvs[2]}, - {Point(1, 1), uvs[3]}, - }); + // Insert transparent gutter around the downsampled image so the blur + // creates a halo effect. This compensates for when the expanded clip + // region can't give us the full gutter we want. + Vector2 texture_size = Vector2(input_texture->GetSize()); + Quad guttered_uvs = + MakeAnchorScale({0.5, 0.5}, + (texture_size + padding * 2) / texture_size) + .Transform(uvs); + + BindVertices( + cmd, host_buffer, + { + {Point(0, 0), guttered_uvs[0]}, + {Point(1, 0), guttered_uvs[1]}, + {Point(0, 1), guttered_uvs[2]}, + {Point(1, 1), guttered_uvs[3]}, + }); SamplerDescriptor linear_sampler_descriptor = sampler_descriptor; SetTileMode(&linear_sampler_descriptor, renderer, tile_mode); @@ -243,17 +270,17 @@ std::optional GaussianBlurFilterContents::RenderFilter( Vector2 blur_radius = {CalculateBlurRadius(scaled_sigma.x), CalculateBlurRadius(scaled_sigma.y)}; Vector2 padding(ceil(blur_radius.x), ceil(blur_radius.y)); - Vector2 local_padding = - (entity.GetTransform().Basis() * effect_transform.Basis() * padding) - .Abs(); // Apply as much of the desired padding as possible from the source. This may // be ignored so must be accounted for in the downsample pass by adding a // transparent gutter. - std::optional expanded_coverage_hint; - if (coverage_hint.has_value()) { - expanded_coverage_hint = coverage_hint->Expand(local_padding); - } + std::optional expanded_coverage_hint = ExpandCoverageHint( + coverage_hint, entity.GetTransform() * effect_transform, padding); + // TODO(gaaclarke): How much of the gutter is thrown away can be used to + // adjust the padding that is added in the downsample pass. + // For example, if we get all the padding we requested from + // the expanded_coverage_hint, there is no need to add a + // transparent gutter. std::optional input_snapshot = inputs[0]->GetSnapshot("GaussianBlur", renderer, entity, @@ -273,28 +300,21 @@ std::optional GaussianBlurFilterContents::RenderFilter( // gutter from the expanded_coverage_hint, we can skip the downsample pass. // pass. Vector2 downsample_scalar(desired_scalar, desired_scalar); - Rect source_rect = Rect::MakeSize(input_snapshot->texture->GetSize()); - Rect source_rect_padded = source_rect.Expand(padding); - Matrix padding_snapshot_adjustment = Matrix::MakeTranslation(-padding); - // TODO(gaaclarke): The padding could be removed if we know it's not needed or - // resized to account for the expanded_clip_coverage. There doesn't appear - // to be the math to make those calculations though. The following - // optimization works, but causes a shimmer as a result of - // https://github.com/flutter/flutter/issues/140193 so it isn't applied. - // - // !input_snapshot->GetCoverage()->Expand(-local_padding) - // .Contains(coverage_hint.value())) - Vector2 downsampled_size = source_rect_padded.size * downsample_scalar; + Vector2 padded_size = + Vector2(input_snapshot->texture->GetSize()) + 2.0 * padding; + Vector2 downsampled_size = padded_size * downsample_scalar; + // TODO(gaaclarke): I don't think we are correctly handling this fractional + // amount we are throwing away. ISize subpass_size = ISize(round(downsampled_size.x), round(downsampled_size.y)); - Vector2 effective_scalar = Vector2(subpass_size) / source_rect_padded.size; + Vector2 effective_scalar = subpass_size / padded_size; - Quad uvs = CalculateUVs(inputs[0], entity, source_rect_padded, - input_snapshot->texture->GetSize()); + Quad uvs = + CalculateUVs(inputs[0], entity, input_snapshot->texture->GetSize()); std::shared_ptr pass1_out_texture = MakeDownsampleSubpass( renderer, input_snapshot->texture, input_snapshot->sampler_descriptor, - uvs, subpass_size, tile_mode_); + uvs, subpass_size, padding, tile_mode_); Vector2 pass1_pixel_size = 1.0 / Vector2(pass1_out_texture->GetSize()); @@ -323,12 +343,13 @@ std::optional GaussianBlurFilterContents::RenderFilter( MinMagFilter::kLinear, SamplerAddressMode::kClampToEdge); return Entity::FromSnapshot( - Snapshot{.texture = pass3_out_texture, - .transform = input_snapshot->transform * - padding_snapshot_adjustment * - Matrix::MakeScale(1 / effective_scalar), - .sampler_descriptor = sampler_desc, - .opacity = input_snapshot->opacity}, + Snapshot{ + .texture = pass3_out_texture, + .transform = input_snapshot->transform * + Matrix::MakeTranslation({-padding.x, -padding.y, 0}) * + Matrix::MakeScale(1 / effective_scalar), + .sampler_descriptor = sampler_desc, + .opacity = input_snapshot->opacity}, entity.GetBlendMode(), entity.GetClipDepth()); } @@ -339,10 +360,11 @@ Scalar GaussianBlurFilterContents::CalculateBlurRadius(Scalar sigma) { Quad GaussianBlurFilterContents::CalculateUVs( const std::shared_ptr& filter_input, const Entity& entity, - const Rect& source_rect, const ISize& texture_size) { Matrix input_transform = filter_input->GetLocalTransform(entity); - Quad coverage_quad = source_rect.GetTransformedPoints(input_transform); + Rect snapshot_rect = + Rect::MakeXYWH(0, 0, texture_size.width, texture_size.height); + Quad coverage_quad = snapshot_rect.GetTransformedPoints(input_transform); Matrix uv_transform = Matrix::MakeScale( {1.0f / texture_size.width, 1.0f / texture_size.height, 1.0f}); diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h index a139771b3f8b1..7932291fd9ee8 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h @@ -41,12 +41,10 @@ class GaussianBlurFilterContents final : public FilterContents { /// Calculate the UV coordinates for rendering the filter_input. /// @param filter_input The FilterInput that should be rendered. /// @param entity The associated entity for the filter_input. - /// @param source_rect The rect in source coordinates to convert to uvs. - /// @param texture_size The rect to convert in source coordinates. + /// @param texture_size The size of the texture_size the uvs will be used for. static Quad CalculateUVs(const std::shared_ptr& filter_input, const Entity& entity, - const Rect& source_rect, - const ISize& texture_size); + const ISize& pass_size); /// Calculate the scale factor for the downsample pass given a sigma value. /// diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents_unittests.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents_unittests.cc index 4350c9318b7c3..40e36406cf065 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents_unittests.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents_unittests.cc @@ -285,8 +285,8 @@ TEST_P(GaussianBlurFilterContentsTest, CalculateUVsSimple) { std::shared_ptr texture = MakeTexture(desc); auto filter_input = FilterInput::Make(texture); Entity entity; - Quad uvs = GaussianBlurFilterContents::CalculateUVs( - filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100)); + Quad uvs = GaussianBlurFilterContents::CalculateUVs(filter_input, entity, + ISize(100, 100)); std::optional uvs_bounds = Rect::MakePointBounds(uvs); EXPECT_TRUE(uvs_bounds.has_value()); if (uvs_bounds.has_value()) {