[Impeller] Avoid NaN values when setting up for the fast squircle blur shader (#162421)
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:
parent
01a9aec444
commit
e6185c3471
@ -470,6 +470,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;
|
||||
|
@ -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));
|
||||
|
@ -802,6 +802,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
|
||||
|
Loading…
x
Reference in New Issue
Block a user