From 2234d77a5616da0d874ed10e4debab73cd230c2e Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 25 Jun 2024 09:18:18 -0700 Subject: [PATCH 01/11] [Impeller] blur - cropped the downsample pass for backdrop filters --- .../filters/gaussian_blur_filter_contents.cc | 94 ++++++++++--------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index e5d9331b964c2..f37471bd8858f 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -156,6 +156,38 @@ std::optional GetSnapshot(const std::shared_ptr& input, return input_snapshot; } +/// Returns `rect` relative to `reference`, where Rect::MakeXYWH(0,0,1,1) will +/// be returned when `rect` == `reference`. +Rect MakeReferenceUVs(const Rect& reference, const Rect& rect) { + Rect result = Rect::MakeOriginSize(rect.GetOrigin() - reference.GetOrigin(), + rect.GetSize()); + return result.Scale(1.0f / Vector2(reference.GetSize())); +} + +Quad CalculateBlurUVs( + const Snapshot& input_snapshot, + const std::optional& source_expanded_coverage_hint) { + std::optional input_snapshot_coverage = input_snapshot.GetCoverage(); + Quad blur_uvs = {Point(0, 0), Point(1, 0), Point(0, 1), Point(1, 1)}; + FML_DCHECK(input_snapshot.transform.IsTranslationScaleOnly()); + if (source_expanded_coverage_hint.has_value() && + input_snapshot_coverage.has_value()) { + // Only process the uvs where the blur is happening, not the whole texture. + std::optional uvs = + MakeReferenceUVs(input_snapshot_coverage.value(), + source_expanded_coverage_hint.value()) + .Intersection(Rect::MakeSize(Size(1, 1))); + FML_DCHECK(uvs.has_value()); + if (uvs.has_value()) { + blur_uvs[0] = uvs->GetLeftTop(); + blur_uvs[1] = uvs->GetRightTop(); + blur_uvs[2] = uvs->GetLeftBottom(); + blur_uvs[3] = uvs->GetRightBottom(); + } + } + return blur_uvs; +} + struct DownsamplePassArgs { /// The output size of the down-sampling pass. ISize subpass_size; @@ -172,7 +204,8 @@ struct DownsamplePassArgs { DownsamplePassArgs CalculateDownsamplePassArgs( Vector2 scaled_sigma, Vector2 padding, - ISize input_snapshot_size, + const Snapshot& input_snapshot, + const std::optional& source_expanded_coverage_hint, const std::shared_ptr& input, const Entity& snapshot_entity) { Scalar desired_scalar = @@ -182,8 +215,6 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // 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_size); - Rect source_rect_padded = source_rect.Expand(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 @@ -192,14 +223,18 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // // !input_snapshot->GetCoverage()->Expand(-local_padding) // .Contains(coverage_hint.value())) - Vector2 downsampled_size = source_rect_padded.GetSize() * downsample_scalar; + ISize source_expanded_coverage_size = + ISize(ceil(source_expanded_coverage_hint->GetSize().width), + ceil(source_expanded_coverage_hint->GetSize().height)); + ISize source_size = source_expanded_coverage_hint.has_value() + ? source_expanded_coverage_size + : input_snapshot.texture->GetSize(); + Vector2 downsampled_size = source_size * downsample_scalar; ISize subpass_size = ISize(round(downsampled_size.x), round(downsampled_size.y)); - Vector2 effective_scalar = - Vector2(subpass_size) / source_rect_padded.GetSize(); + Vector2 effective_scalar = Vector2(subpass_size) / source_size; - Quad uvs = GaussianBlurFilterContents::CalculateUVs( - input, snapshot_entity, source_rect_padded, input_snapshot_size); + Quad uvs = CalculateBlurUVs(input_snapshot, source_expanded_coverage_hint); return { .subpass_size = subpass_size, .uvs = uvs, @@ -326,38 +361,6 @@ fml::StatusOr MakeBlurSubpass( } } -/// Returns `rect` relative to `reference`, where Rect::MakeXYWH(0,0,1,1) will -/// be returned when `rect` == `reference`. -Rect MakeReferenceUVs(const Rect& reference, const Rect& rect) { - Rect result = Rect::MakeOriginSize(rect.GetOrigin() - reference.GetOrigin(), - rect.GetSize()); - return result.Scale(1.0f / Vector2(reference.GetSize())); -} - -Quad CalculateBlurUVs( - const Snapshot& input_snapshot, - const std::optional& source_expanded_coverage_hint) { - std::optional input_snapshot_coverage = input_snapshot.GetCoverage(); - Quad blur_uvs = {Point(0, 0), Point(1, 0), Point(0, 1), Point(1, 1)}; - FML_DCHECK(input_snapshot.transform.IsTranslationScaleOnly()); - if (source_expanded_coverage_hint.has_value() && - input_snapshot_coverage.has_value()) { - // Only process the uvs where the blur is happening, not the whole texture. - std::optional uvs = - MakeReferenceUVs(input_snapshot_coverage.value(), - source_expanded_coverage_hint.value()) - .Intersection(Rect::MakeSize(Size(1, 1))); - FML_DCHECK(uvs.has_value()); - if (uvs.has_value()) { - blur_uvs[0] = uvs->GetLeftTop(); - blur_uvs[1] = uvs->GetRightTop(); - blur_uvs[2] = uvs->GetLeftBottom(); - blur_uvs[3] = uvs->GetRightBottom(); - } - } - return blur_uvs; -} - int ScaleBlurRadius(Scalar radius, Scalar scalar) { return static_cast(std::round(radius * scalar)); } @@ -597,8 +600,8 @@ std::optional GaussianBlurFilterContents::RenderFilter( } DownsamplePassArgs downsample_pass_args = CalculateDownsamplePassArgs( - blur_info.scaled_sigma, blur_info.padding, - input_snapshot->texture->GetSize(), inputs[0], snapshot_entity); + blur_info.scaled_sigma, blur_info.padding, input_snapshot.value(), + source_expanded_coverage_hint, inputs[0], snapshot_entity); fml::StatusOr pass1_out = MakeDownsampleSubpass( renderer, command_buffer, input_snapshot->texture, @@ -611,8 +614,7 @@ std::optional GaussianBlurFilterContents::RenderFilter( Vector2 pass1_pixel_size = 1.0 / Vector2(pass1_out.value().GetRenderTargetTexture()->GetSize()); - Quad blur_uvs = - CalculateBlurUVs(input_snapshot.value(), source_expanded_coverage_hint); + Quad blur_uvs = {Point(0, 0), Point(1, 0), Point(0, 1), Point(1, 1)}; fml::StatusOr pass2_out = MakeBlurSubpass( renderer, command_buffer, /*input_pass=*/pass1_out.value(), @@ -677,7 +679,9 @@ std::optional GaussianBlurFilterContents::RenderFilter( entity.GetTransform() * // Matrix::MakeScale(1.f / blur_info.source_space_scalar) * // input_snapshot->transform * // - Matrix::MakeTranslation(-blur_info.padding) * // + Matrix::MakeTranslation( + {source_expanded_coverage_hint->GetX(), + source_expanded_coverage_hint->GetY(), 0}) * Matrix::MakeScale(1 / downsample_pass_args.effective_scalar), .sampler_descriptor = sampler_desc, .opacity = input_snapshot->opacity}, From b2b314c5f513f7a8f05308bc66aa004c7d4db947 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 25 Jun 2024 14:10:02 -0700 Subject: [PATCH 02/11] got rid of the shimmering --- .../filters/gaussian_blur_filter_contents.cc | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index f37471bd8858f..a2b3a9bfdcfa2 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -188,6 +188,32 @@ Quad CalculateBlurUVs( return blur_uvs; } +Scalar CeilToDivisible(Scalar val, Scalar divisor) { + if (divisor == 0.0f) { + return val; + } + + Scalar remainder = fmod(val, divisor); + if (remainder != 0.0f) { + return val + (divisor - remainder); + } else { + return val; + } +} + +Scalar FloorToDivisible(Scalar val, Scalar divisor) { + if (divisor == 0.0f) { + return val; + } + + Scalar remainder = fmod(val, divisor); + if (remainder != 0.0f) { + return val - remainder; + } else { + return val; + } +} + struct DownsamplePassArgs { /// The output size of the down-sampling pass. ISize subpass_size; @@ -205,7 +231,7 @@ DownsamplePassArgs CalculateDownsamplePassArgs( Vector2 scaled_sigma, Vector2 padding, const Snapshot& input_snapshot, - const std::optional& source_expanded_coverage_hint, + std::optional& source_expanded_coverage_hint, const std::shared_ptr& input, const Entity& snapshot_entity) { Scalar desired_scalar = @@ -223,13 +249,32 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // // !input_snapshot->GetCoverage()->Expand(-local_padding) // .Contains(coverage_hint.value())) + + if (source_expanded_coverage_hint.has_value()) { + int32_t divisor = std::round(1.0f / desired_scalar); + source_expanded_coverage_hint = Rect::MakeLTRB( + FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor), + FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor), + source_expanded_coverage_hint->GetRight(), + source_expanded_coverage_hint->GetBottom()); + source_expanded_coverage_hint = Rect::MakeXYWH( + source_expanded_coverage_hint->GetX(), + source_expanded_coverage_hint->GetY(), + CeilToDivisible(source_expanded_coverage_hint->GetWidth(), divisor), + CeilToDivisible(source_expanded_coverage_hint->GetHeight(), divisor)); + } + ISize source_expanded_coverage_size = - ISize(ceil(source_expanded_coverage_hint->GetSize().width), - ceil(source_expanded_coverage_hint->GetSize().height)); + ISize(source_expanded_coverage_hint->GetSize().width, + source_expanded_coverage_hint->GetSize().height); ISize source_size = source_expanded_coverage_hint.has_value() ? source_expanded_coverage_size : input_snapshot.texture->GetSize(); Vector2 downsampled_size = source_size * downsample_scalar; + Scalar int_part; + FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f); + FML_DCHECK(std::modf(downsampled_size.y, &int_part) == 0.0f); + (void)int_part; ISize subpass_size = ISize(round(downsampled_size.x), round(downsampled_size.y)); Vector2 effective_scalar = Vector2(subpass_size) / source_size; From 203062b985d72fcc582cdaa7966dc5dbec6c0f23 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 25 Jun 2024 14:21:54 -0700 Subject: [PATCH 03/11] cleanup --- .../filters/gaussian_blur_filter_contents.cc | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index a2b3a9bfdcfa2..b160d7156194f 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -224,6 +224,9 @@ struct DownsamplePassArgs { /// This isn't usually exactly as we'd calculate because it has to be rounded /// to integer boundaries for generating the texture for the output. Vector2 effective_scalar; + /// The coverage hint that is aligned with the downsample scalar. + /// This is in the scaled source space and includes the padding. + std::optional aligned_coverage_hint; }; /// Calculates info required for the down-sampling pass. @@ -231,7 +234,7 @@ DownsamplePassArgs CalculateDownsamplePassArgs( Vector2 scaled_sigma, Vector2 padding, const Snapshot& input_snapshot, - std::optional& source_expanded_coverage_hint, + const std::optional& source_expanded_coverage_hint, const std::shared_ptr& input, const Entity& snapshot_entity) { Scalar desired_scalar = @@ -250,24 +253,24 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // !input_snapshot->GetCoverage()->Expand(-local_padding) // .Contains(coverage_hint.value())) + std::optional aligned_coverage_hint; if (source_expanded_coverage_hint.has_value()) { int32_t divisor = std::round(1.0f / desired_scalar); - source_expanded_coverage_hint = Rect::MakeLTRB( + aligned_coverage_hint = Rect::MakeLTRB( FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor), FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor), source_expanded_coverage_hint->GetRight(), source_expanded_coverage_hint->GetBottom()); - source_expanded_coverage_hint = Rect::MakeXYWH( - source_expanded_coverage_hint->GetX(), - source_expanded_coverage_hint->GetY(), - CeilToDivisible(source_expanded_coverage_hint->GetWidth(), divisor), - CeilToDivisible(source_expanded_coverage_hint->GetHeight(), divisor)); + aligned_coverage_hint = Rect::MakeXYWH( + aligned_coverage_hint->GetX(), aligned_coverage_hint->GetY(), + CeilToDivisible(aligned_coverage_hint->GetWidth(), divisor), + CeilToDivisible(aligned_coverage_hint->GetHeight(), divisor)); } ISize source_expanded_coverage_size = - ISize(source_expanded_coverage_hint->GetSize().width, - source_expanded_coverage_hint->GetSize().height); - ISize source_size = source_expanded_coverage_hint.has_value() + ISize(aligned_coverage_hint->GetSize().width, + aligned_coverage_hint->GetSize().height); + ISize source_size = aligned_coverage_hint.has_value() ? source_expanded_coverage_size : input_snapshot.texture->GetSize(); Vector2 downsampled_size = source_size * downsample_scalar; @@ -275,15 +278,16 @@ DownsamplePassArgs CalculateDownsamplePassArgs( FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f); FML_DCHECK(std::modf(downsampled_size.y, &int_part) == 0.0f); (void)int_part; - ISize subpass_size = - ISize(round(downsampled_size.x), round(downsampled_size.y)); + ISize subpass_size = ISize(downsampled_size.x, downsampled_size.y); Vector2 effective_scalar = Vector2(subpass_size) / source_size; + FML_DCHECK(effective_scalar == downsample_scalar); - Quad uvs = CalculateBlurUVs(input_snapshot, source_expanded_coverage_hint); + Quad uvs = CalculateBlurUVs(input_snapshot, aligned_coverage_hint); return { .subpass_size = subpass_size, .uvs = uvs, .effective_scalar = effective_scalar, + .aligned_coverage_hint = aligned_coverage_hint, }; } @@ -719,17 +723,18 @@ std::optional GaussianBlurFilterContents::RenderFilter( MinMagFilter::kLinear, SamplerAddressMode::kClampToEdge); Entity blur_output_entity = Entity::FromSnapshot( - Snapshot{.texture = pass3_out.value().GetRenderTargetTexture(), - .transform = - entity.GetTransform() * // - Matrix::MakeScale(1.f / blur_info.source_space_scalar) * // - input_snapshot->transform * // - Matrix::MakeTranslation( - {source_expanded_coverage_hint->GetX(), - source_expanded_coverage_hint->GetY(), 0}) * - Matrix::MakeScale(1 / downsample_pass_args.effective_scalar), - .sampler_descriptor = sampler_desc, - .opacity = input_snapshot->opacity}, + Snapshot{ + .texture = pass3_out.value().GetRenderTargetTexture(), + .transform = + entity.GetTransform() * // + Matrix::MakeScale(1.f / blur_info.source_space_scalar) * // + input_snapshot->transform * // + Matrix::MakeTranslation( + {downsample_pass_args.aligned_coverage_hint->GetX(), + downsample_pass_args.aligned_coverage_hint->GetY(), 0}) * + Matrix::MakeScale(1 / downsample_pass_args.effective_scalar), + .sampler_descriptor = sampler_desc, + .opacity = input_snapshot->opacity}, entity.GetBlendMode()); return ApplyBlurStyle(mask_blur_style_, entity, inputs[0], From 8beff0c79ef1fd323e00d852073c2e51b9e5905b Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 25 Jun 2024 14:29:21 -0700 Subject: [PATCH 04/11] fix tidy --- .../filters/gaussian_blur_filter_contents.cc | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index b160d7156194f..21e4e862b9029 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -226,7 +226,7 @@ struct DownsamplePassArgs { Vector2 effective_scalar; /// The coverage hint that is aligned with the downsample scalar. /// This is in the scaled source space and includes the padding. - std::optional aligned_coverage_hint; + Rect aligned_coverage_hint; }; /// Calculates info required for the down-sampling pass. @@ -253,7 +253,7 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // !input_snapshot->GetCoverage()->Expand(-local_padding) // .Contains(coverage_hint.value())) - std::optional aligned_coverage_hint; + Rect aligned_coverage_hint; if (source_expanded_coverage_hint.has_value()) { int32_t divisor = std::round(1.0f / desired_scalar); aligned_coverage_hint = Rect::MakeLTRB( @@ -262,17 +262,14 @@ DownsamplePassArgs CalculateDownsamplePassArgs( source_expanded_coverage_hint->GetRight(), source_expanded_coverage_hint->GetBottom()); aligned_coverage_hint = Rect::MakeXYWH( - aligned_coverage_hint->GetX(), aligned_coverage_hint->GetY(), - CeilToDivisible(aligned_coverage_hint->GetWidth(), divisor), - CeilToDivisible(aligned_coverage_hint->GetHeight(), divisor)); + aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), + CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor), + CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor)); + } else { + aligned_coverage_hint = Rect::MakeSize(input_snapshot.texture->GetSize()); } - - ISize source_expanded_coverage_size = - ISize(aligned_coverage_hint->GetSize().width, - aligned_coverage_hint->GetSize().height); - ISize source_size = aligned_coverage_hint.has_value() - ? source_expanded_coverage_size - : input_snapshot.texture->GetSize(); + ISize source_size = ISize(aligned_coverage_hint.GetSize().width, + aligned_coverage_hint.GetSize().height); Vector2 downsampled_size = source_size * downsample_scalar; Scalar int_part; FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f); @@ -723,18 +720,17 @@ std::optional GaussianBlurFilterContents::RenderFilter( MinMagFilter::kLinear, SamplerAddressMode::kClampToEdge); Entity blur_output_entity = Entity::FromSnapshot( - Snapshot{ - .texture = pass3_out.value().GetRenderTargetTexture(), - .transform = - entity.GetTransform() * // - Matrix::MakeScale(1.f / blur_info.source_space_scalar) * // - input_snapshot->transform * // - Matrix::MakeTranslation( - {downsample_pass_args.aligned_coverage_hint->GetX(), - downsample_pass_args.aligned_coverage_hint->GetY(), 0}) * - Matrix::MakeScale(1 / downsample_pass_args.effective_scalar), - .sampler_descriptor = sampler_desc, - .opacity = input_snapshot->opacity}, + Snapshot{.texture = pass3_out.value().GetRenderTargetTexture(), + .transform = + entity.GetTransform() * // + Matrix::MakeScale(1.f / blur_info.source_space_scalar) * // + input_snapshot->transform * // + Matrix::MakeTranslation( + {downsample_pass_args.aligned_coverage_hint.GetX(), + downsample_pass_args.aligned_coverage_hint.GetY(), 0}) * + Matrix::MakeScale(1 / downsample_pass_args.effective_scalar), + .sampler_descriptor = sampler_desc, + .opacity = input_snapshot->opacity}, entity.GetBlendMode()); return ApplyBlurStyle(mask_blur_style_, entity, inputs[0], From b963253cb69ac0105ea2aed187d4883f403fbd77 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 25 Jun 2024 14:32:23 -0700 Subject: [PATCH 05/11] renamed function --- .../entity/contents/filters/gaussian_blur_filter_contents.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 21e4e862b9029..c218b1c4d7201 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -164,7 +164,7 @@ Rect MakeReferenceUVs(const Rect& reference, const Rect& rect) { return result.Scale(1.0f / Vector2(reference.GetSize())); } -Quad CalculateBlurUVs( +Quad CalculateSnapshotUVs( const Snapshot& input_snapshot, const std::optional& source_expanded_coverage_hint) { std::optional input_snapshot_coverage = input_snapshot.GetCoverage(); @@ -279,7 +279,7 @@ DownsamplePassArgs CalculateDownsamplePassArgs( Vector2 effective_scalar = Vector2(subpass_size) / source_size; FML_DCHECK(effective_scalar == downsample_scalar); - Quad uvs = CalculateBlurUVs(input_snapshot, aligned_coverage_hint); + Quad uvs = CalculateSnapshotUVs(input_snapshot, aligned_coverage_hint); return { .subpass_size = subpass_size, .uvs = uvs, From 815ac5b3194448ae68dde40bb9773c74ec519bc9 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Jun 2024 10:13:32 -0700 Subject: [PATCH 06/11] fixed imagefilter --- .../filters/gaussian_blur_filter_contents.cc | 98 ++++++++++++------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index c218b1c4d7201..79071627e67b9 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -14,6 +14,8 @@ #include "impeller/renderer/render_pass.h" #include "impeller/renderer/vertex_buffer_builder.h" +#pragma GCC diagnostic ignored "-Wunused-function" + namespace impeller { using GaussianBlurVertexShader = GaussianBlurPipeline::VertexShader; @@ -224,9 +226,11 @@ struct DownsamplePassArgs { /// This isn't usually exactly as we'd calculate because it has to be rounded /// to integer boundaries for generating the texture for the output. Vector2 effective_scalar; - /// The coverage hint that is aligned with the downsample scalar. - /// This is in the scaled source space and includes the padding. - Rect aligned_coverage_hint; + /// Transforms from unrotated local space to position the output from the + /// down-sample pass. + /// This can differ if we request a coverage hint but it is rejected, as is + /// the case with backdrop filters. + Matrix transform; }; /// Calculates info required for the down-sampling pass. @@ -254,38 +258,59 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // .Contains(coverage_hint.value())) Rect aligned_coverage_hint; - if (source_expanded_coverage_hint.has_value()) { - int32_t divisor = std::round(1.0f / desired_scalar); - aligned_coverage_hint = Rect::MakeLTRB( - FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor), - FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor), - source_expanded_coverage_hint->GetRight(), - source_expanded_coverage_hint->GetBottom()); - aligned_coverage_hint = Rect::MakeXYWH( - aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), - CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor), - CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor)); + if (input_snapshot.transform.IsIdentity()) { + if (source_expanded_coverage_hint.has_value()) { + int32_t divisor = std::round(1.0f / desired_scalar); + aligned_coverage_hint = Rect::MakeLTRB( + FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor), + FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor), + source_expanded_coverage_hint->GetRight(), + source_expanded_coverage_hint->GetBottom()); + aligned_coverage_hint = Rect::MakeXYWH( + aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), + CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor), + CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor)); + } else { + aligned_coverage_hint = Rect::MakeSize(input_snapshot.texture->GetSize()); + } + ISize source_size = ISize(aligned_coverage_hint.GetSize().width, + aligned_coverage_hint.GetSize().height); + Vector2 downsampled_size = source_size * downsample_scalar; + Scalar int_part; + FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f); + FML_DCHECK(std::modf(downsampled_size.y, &int_part) == 0.0f); + (void)int_part; + ISize subpass_size = ISize(downsampled_size.x, downsampled_size.y); + Vector2 effective_scalar = Vector2(subpass_size) / source_size; + FML_DCHECK(effective_scalar == downsample_scalar); + + Quad uvs = CalculateSnapshotUVs(input_snapshot, aligned_coverage_hint); + return { + .subpass_size = subpass_size, + .uvs = uvs, + .effective_scalar = effective_scalar, + .transform = Matrix::MakeTranslation( + {aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), 0})}; } else { - aligned_coverage_hint = Rect::MakeSize(input_snapshot.texture->GetSize()); - } - ISize source_size = ISize(aligned_coverage_hint.GetSize().width, - aligned_coverage_hint.GetSize().height); - Vector2 downsampled_size = source_size * downsample_scalar; - Scalar int_part; - FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f); - FML_DCHECK(std::modf(downsampled_size.y, &int_part) == 0.0f); - (void)int_part; - ISize subpass_size = ISize(downsampled_size.x, downsampled_size.y); - Vector2 effective_scalar = Vector2(subpass_size) / source_size; - FML_DCHECK(effective_scalar == downsample_scalar); - - Quad uvs = CalculateSnapshotUVs(input_snapshot, aligned_coverage_hint); - return { - .subpass_size = subpass_size, - .uvs = uvs, - .effective_scalar = effective_scalar, - .aligned_coverage_hint = aligned_coverage_hint, - }; + ////////////////////////////////////////////////////////////////////////////// + auto input_snapshot_size = input_snapshot.texture->GetSize(); + Rect source_rect = Rect::MakeSize(input_snapshot_size); + Rect source_rect_padded = source_rect.Expand(padding); + Vector2 downsampled_size = source_rect_padded.GetSize() * downsample_scalar; + ISize subpass_size = + ISize(round(downsampled_size.x), round(downsampled_size.y)); + Vector2 effective_scalar = + Vector2(subpass_size) / source_rect_padded.GetSize(); + Quad uvs = GaussianBlurFilterContents::CalculateUVs( + input, snapshot_entity, source_rect_padded, input_snapshot_size); + return { + .subpass_size = subpass_size, + .uvs = uvs, + .effective_scalar = effective_scalar, + .transform = + input_snapshot.transform * Matrix::MakeTranslation(-padding), + }; + } } /// Makes a subpass that will render the scaled down input and add the @@ -724,10 +749,7 @@ std::optional GaussianBlurFilterContents::RenderFilter( .transform = entity.GetTransform() * // Matrix::MakeScale(1.f / blur_info.source_space_scalar) * // - input_snapshot->transform * // - Matrix::MakeTranslation( - {downsample_pass_args.aligned_coverage_hint.GetX(), - downsample_pass_args.aligned_coverage_hint.GetY(), 0}) * + downsample_pass_args.transform * // Matrix::MakeScale(1 / downsample_pass_args.effective_scalar), .sampler_descriptor = sampler_desc, .opacity = input_snapshot->opacity}, From 45f3f28e67fb9c25f5e005e1c41b366c190cd982 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Jun 2024 10:19:10 -0700 Subject: [PATCH 07/11] added comments --- .../filters/gaussian_blur_filter_contents.cc | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 79071627e67b9..2971d17b24a87 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -257,22 +257,25 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // !input_snapshot->GetCoverage()->Expand(-local_padding) // .Contains(coverage_hint.value())) - Rect aligned_coverage_hint; - if (input_snapshot.transform.IsIdentity()) { - if (source_expanded_coverage_hint.has_value()) { - int32_t divisor = std::round(1.0f / desired_scalar); - aligned_coverage_hint = Rect::MakeLTRB( - FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor), - FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor), - source_expanded_coverage_hint->GetRight(), - source_expanded_coverage_hint->GetBottom()); - aligned_coverage_hint = Rect::MakeXYWH( - aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), - CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor), - CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor)); - } else { - aligned_coverage_hint = Rect::MakeSize(input_snapshot.texture->GetSize()); - } + if (input_snapshot.transform.IsIdentity() && + source_expanded_coverage_hint.has_value()) { + // If the snapshot's transform is the identity transform and we have + // coverage hint, that means the coverage hint was ignored so we will trim + // out the area we are interested in the downsample pass. This usually means + // we have a backdrop image filter. + // + // The region we cut out will be aligned with the down-sample divisor to + // avoid pixel alignment problems that create shimmering. + int32_t divisor = std::round(1.0f / desired_scalar); + Rect aligned_coverage_hint = Rect::MakeLTRB( + FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor), + FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor), + source_expanded_coverage_hint->GetRight(), + source_expanded_coverage_hint->GetBottom()); + aligned_coverage_hint = Rect::MakeXYWH( + aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), + CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor), + CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor)); ISize source_size = ISize(aligned_coverage_hint.GetSize().width, aligned_coverage_hint.GetSize().height); Vector2 downsampled_size = source_size * downsample_scalar; From 85619deb9a011a31866cc23c3d2a604efcbb40a7 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Jun 2024 10:19:36 -0700 Subject: [PATCH 08/11] update comment --- .../entity/contents/filters/gaussian_blur_filter_contents.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 2971d17b24a87..8869f6131607c 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -261,8 +261,8 @@ DownsamplePassArgs CalculateDownsamplePassArgs( source_expanded_coverage_hint.has_value()) { // If the snapshot's transform is the identity transform and we have // coverage hint, that means the coverage hint was ignored so we will trim - // out the area we are interested in the downsample pass. This usually means - // we have a backdrop image filter. + // out the area we are interested in the down-sample pass. This usually + // means we have a backdrop image filter. // // The region we cut out will be aligned with the down-sample divisor to // avoid pixel alignment problems that create shimmering. From 3e9ca5eeb5cdfa5e61a470341be816cf350bd75a Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Jun 2024 11:28:13 -0700 Subject: [PATCH 09/11] started trimming in the downsample only if the expanded range fits inside of the snapshot --- .../contents/filters/gaussian_blur_filter_contents.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 8869f6131607c..3a988da2b84ac 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -258,11 +258,14 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // .Contains(coverage_hint.value())) if (input_snapshot.transform.IsIdentity() && - source_expanded_coverage_hint.has_value()) { + source_expanded_coverage_hint.has_value() && + input_snapshot.GetCoverage()->Contains( + source_expanded_coverage_hint.value())) { // If the snapshot's transform is the identity transform and we have - // coverage hint, that means the coverage hint was ignored so we will trim - // out the area we are interested in the down-sample pass. This usually - // means we have a backdrop image filter. + // coverage hint that fits inside of the snapshots coverage that means the + // coverage hint was ignored so we will trim out the area we are interested + // in the down-sample pass. This usually means we have a backdrop image + // filter. // // The region we cut out will be aligned with the down-sample divisor to // avoid pixel alignment problems that create shimmering. From e6d3ffebee838c74507fb077a0e54c78b2a1b5a8 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Jun 2024 12:38:59 -0700 Subject: [PATCH 10/11] tidy --- .../entity/contents/filters/gaussian_blur_filter_contents.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 3a988da2b84ac..f5fa4815416f3 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -257,10 +257,11 @@ DownsamplePassArgs CalculateDownsamplePassArgs( // !input_snapshot->GetCoverage()->Expand(-local_padding) // .Contains(coverage_hint.value())) + std::optional snapshot_coverage = input_snapshot.GetCoverage(); if (input_snapshot.transform.IsIdentity() && source_expanded_coverage_hint.has_value() && - input_snapshot.GetCoverage()->Contains( - source_expanded_coverage_hint.value())) { + snapshot_coverage.has_value() && + snapshot_coverage->Contains(source_expanded_coverage_hint.value())) { // If the snapshot's transform is the identity transform and we have // coverage hint that fits inside of the snapshots coverage that means the // coverage hint was ignored so we will trim out the area we are interested From 8d32b77e965ce17dd8b5e890b25095a6a5008ea6 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Jun 2024 13:19:36 -0700 Subject: [PATCH 11/11] removed stray pragma --- .../entity/contents/filters/gaussian_blur_filter_contents.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index f5fa4815416f3..fe35f8f784cd3 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -14,8 +14,6 @@ #include "impeller/renderer/render_pass.h" #include "impeller/renderer/vertex_buffer_builder.h" -#pragma GCC diagnostic ignored "-Wunused-function" - namespace impeller { using GaussianBlurVertexShader = GaussianBlurPipeline::VertexShader;