[Impeller] Avoid NaN values when setting up for the fast squircle blu… (#162485)

Fixes https://github.com/flutter/flutter/issues/162128

Zero dimensioned rectangle blurs were causing the setup code to generate NaN values. This condition could also happen for some very thin or short rectangles so rather than just rule out zero-dimensioned rectangles, the uniforms are checked for NaN values and the operation is skipped in those cases.
This commit is contained in:
Jim Graham 2025-01-31 07:16:29 -08:00 committed by GitHub
parent 3d63c78e51
commit 5000ea89b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 3 deletions

View File

@ -472,6 +472,28 @@ TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, MaskBlurOnZeroDimensionIsSkippedWideGamut) {
// Making sure this test is run on a wide gamut enabled backend
EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
PixelFormat::kB10G10R10A10XR);
DisplayListBuilder builder;
builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
DlPaint paint;
paint.setColor(DlColor::kBlue());
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
// Zero height above
builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
// Regular rect
builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
// Zero width to the right
builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
struct MaskBlurTestConfig {
DlBlurStyle style = DlBlurStyle::kNormal;
Scalar sigma = 1.0f;

View File

@ -68,7 +68,7 @@ static Point NegPos(Scalar v) {
return {std::min(v, 0.0f), std::max(v, 0.0f)};
}
static void SetupFragInfo(
static bool SetupFragInfo(
RRectBlurPipeline::FragmentShader::FragInfo& frag_info,
Scalar blurSigma,
Point center,
@ -96,6 +96,15 @@ static void SetupFragInfo(
frag_info.scale =
0.5 * computeErf7(frag_info.sInv * 0.5 *
(std::max(rSize.x, rSize.y) - 0.5 * radius));
return frag_info.center.IsFinite() && //
frag_info.adjust.IsFinite() && //
std::isfinite(frag_info.minEdge) && //
std::isfinite(frag_info.r1) && //
std::isfinite(frag_info.exponent) && //
std::isfinite(frag_info.sInv) && //
std::isfinite(frag_info.exponentInv) && //
std::isfinite(frag_info.scale);
}
std::optional<Rect> SolidRRectBlurContents::GetCoverage(
@ -159,8 +168,11 @@ bool SolidRRectBlurContents::Render(const ContentContext& renderer,
positive_rect.GetWidth() * 0.5f),
std::clamp(corner_radii_.height, kEhCloseEnough,
positive_rect.GetHeight() * 0.5f));
SetupFragInfo(frag_info, blur_sigma, positive_rect.GetCenter(),
Point(positive_rect.GetSize()), radius);
if (!SetupFragInfo(frag_info, blur_sigma, positive_rect.GetCenter(),
Point(positive_rect.GetSize()), radius)) {
return true;
}
auto& host_buffer = renderer.GetTransientsBuffer();
pass.SetCommandLabel("RRect Shadow");
pass.SetPipeline(renderer.GetRRectBlurPipeline(opts));

View File

@ -799,6 +799,7 @@ impeller_Play_AiksTest_LinearToSrgbFilterSubpassCollapseOptimization_Vulkan.png
impeller_Play_AiksTest_MaskBlurDoesntStretchContents_Metal.png
impeller_Play_AiksTest_MaskBlurDoesntStretchContents_OpenGLES.png
impeller_Play_AiksTest_MaskBlurDoesntStretchContents_Vulkan.png
impeller_Play_AiksTest_MaskBlurOnZeroDimensionIsSkippedWideGamut_Metal.png
impeller_Play_AiksTest_MaskBlurTexture_Metal.png
impeller_Play_AiksTest_MaskBlurTexture_OpenGLES.png
impeller_Play_AiksTest_MaskBlurTexture_Vulkan.png