From 58bc9643b56a2053b55c9dbe512771dcc2adba38 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Mon, 10 Feb 2025 11:23:16 -0800 Subject: [PATCH] [Impeller] rrect_blur: scale max radius clamp by transform (#161238) migrated PR https://github.com/flutter/engine/pull/54350 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --- .../display_list/dl_golden_blur_unittests.cc | 33 ++++++++++++++++++- .../contents/solid_rrect_blur_contents.cc | 11 +++++-- .../testing/impeller_golden_tests_output.txt | 3 ++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/engine/src/flutter/impeller/display_list/dl_golden_blur_unittests.cc b/engine/src/flutter/impeller/display_list/dl_golden_blur_unittests.cc index 9b42a4d1bf..16ad75f064 100644 --- a/engine/src/flutter/impeller/display_list/dl_golden_blur_unittests.cc +++ b/engine/src/flutter/impeller/display_list/dl_golden_blur_unittests.cc @@ -154,7 +154,6 @@ TEST_P(DlGoldenTest, ShimmerTest) { TEST_P(DlGoldenTest, StrokedRRectFastBlur) { impeller::Point content_scale = GetContentScale(); - DlRect rect = DlRect::MakeXYWH(50, 50, 100, 100); DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 10.0f); DlPaint fill = DlPaint().setColor(DlColor::kBlue()); @@ -176,5 +175,37 @@ TEST_P(DlGoldenTest, StrokedRRectFastBlur) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +// Top left and bottom right circles are expected to be comparable (not exactly +// equal). +// See also: https://github.com/flutter/flutter/issues/152778 +TEST_P(DlGoldenTest, LargeDownscaleRrect) { + impeller::Point content_scale = GetContentScale(); + auto draw = [&](DlCanvas* canvas, const std::vector>& images) { + canvas->Scale(content_scale.x, content_scale.y); + canvas->DrawColor(DlColor(0xff111111)); + { + canvas->Save(); + canvas->Scale(0.25, 0.25); + DlPaint paint; + paint.setColor(DlColor::kYellow()); + paint.setMaskFilter( + DlBlurMaskFilter::Make(DlBlurStyle::kNormal, /*sigma=*/1000)); + canvas->DrawCircle(SkPoint::Make(0, 0), 1200, paint); + canvas->Restore(); + } + + DlPaint paint; + paint.setColor(DlColor::kYellow()); + paint.setMaskFilter( + DlBlurMaskFilter::Make(DlBlurStyle::kNormal, /*sigma=*/250)); + canvas->DrawCircle(SkPoint::Make(1024, 768), 300, paint); + }; + + DisplayListBuilder builder; + draw(&builder, /*images=*/{}); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + } // namespace testing } // namespace flutter diff --git a/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc b/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc index 2e69cff52a..c38f553469 100644 --- a/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc @@ -128,10 +128,15 @@ bool SolidRRectBlurContents::Render(const ContentContext& renderer, using VS = RRectBlurPipeline::VertexShader; using FS = RRectBlurPipeline::FragmentShader; - // Clamp the max kernel width/height to 1000 to limit the extent + Matrix basis_invert = entity.GetTransform().Basis().Invert(); + Vector2 max_sigmas = + Vector2((basis_invert * Vector2(500.f, 0.f)).GetLength(), + (basis_invert * Vector2(0.f, 500.f)).GetLength()); + Scalar max_sigma = std::min(max_sigmas.x, max_sigmas.y); + // Clamp the max kernel width/height to 1000 (@ 2x) to limit the extent // of the blur and to kEhCloseEnough to prevent NaN calculations - // trying to evaluate a Guassian distribution with a sigma of 0. - Scalar blur_sigma = std::clamp(sigma_.sigma, kEhCloseEnough, 250.0f); + // trying to evaluate a Gaussian distribution with a sigma of 0. + auto blur_sigma = std::clamp(sigma_.sigma, kEhCloseEnough, max_sigma); // Increase quality by making the radius a bit bigger than the typical // sigma->radius conversion we use for slower blurs. Scalar blur_radius = PadForSigma(blur_sigma); diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index d1af556ad9..5cb5a2cc76 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -988,6 +988,9 @@ impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaled_Vulkan.png impeller_Play_DlGoldenTest_GaussianVsRRectBlur_Metal.png impeller_Play_DlGoldenTest_GaussianVsRRectBlur_OpenGLES.png impeller_Play_DlGoldenTest_GaussianVsRRectBlur_Vulkan.png +impeller_Play_DlGoldenTest_LargeDownscaleRrect_Metal.png +impeller_Play_DlGoldenTest_LargeDownscaleRrect_OpenGLES.png +impeller_Play_DlGoldenTest_LargeDownscaleRrect_Vulkan.png impeller_Play_DlGoldenTest_SaveLayerAtFractionalValue_Metal.png impeller_Play_DlGoldenTest_SaveLayerAtFractionalValue_OpenGLES.png impeller_Play_DlGoldenTest_SaveLayerAtFractionalValue_Vulkan.png