From f4594d1d5bd3eb7c82a6634a165039acba1386df Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Mon, 19 Oct 2020 17:32:09 -0400 Subject: [PATCH] Perform bounding rect-relative calcs in full float in GrRRectBlurEffect Add GM that tests very wide/tall SkRRects with blurs Bug: chromium:1138810 Change-Id: Ib5a2e04de50c441f57f5e4b6194c3f9829323dc9 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/328383 Commit-Queue: Brian Salomon Reviewed-by: Michael Ludwig --- gm/blurroundrect.cpp | 18 +++++++++++ src/gpu/effects/GrRRectBlurEffect.fp | 20 ++++++------- .../effects/generated/GrRRectBlurEffect.cpp | 30 +++++++++---------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/gm/blurroundrect.cpp b/gm/blurroundrect.cpp index fe608c5b6f..8e10957491 100644 --- a/gm/blurroundrect.cpp +++ b/gm/blurroundrect.cpp @@ -101,3 +101,21 @@ class SimpleBlurRoundRectGM : public skiagm::GM { //DEF_GM(return new BlurRoundRectGM(600, 5514, 6);) DEF_GM(return new SimpleBlurRoundRectGM();) + +// From crbug.com/1138810 +DEF_SIMPLE_GM(blur_large_rrects, canvas, 300, 300) { + SkPaint paint; + paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 20.f)); + + auto rect = SkRect::MakeLTRB(5.f, -20000.f, 240.f, 25.f); + SkRRect rrect = SkRRect::MakeRectXY(rect, 40.f, 40.f); + for (int i = 0; i < 4; ++i) { + SkColor4f color{(i & 1) ? 1.f : 0.f, + (i & 2) ? 1.f : 0.f, + (i < 2) ? 1.f : 0.f, + 1.f}; + paint.setColor(color); + canvas->drawRRect(rrect, paint); + canvas->rotate(90.f, 150.f, 150.f); + } +} diff --git a/src/gpu/effects/GrRRectBlurEffect.fp b/src/gpu/effects/GrRRectBlurEffect.fp index df41c09921..8ee69f96d9 100644 --- a/src/gpu/effects/GrRRectBlurEffect.fp +++ b/src/gpu/effects/GrRRectBlurEffect.fp @@ -373,37 +373,37 @@ uniform half blurRadius; void main() { // Warp the fragment position to the appropriate part of the 9-patch blur texture by snipping // out the middle section of the proxy rect. - half2 translatedFragPos = half2(sk_FragCoord.xy - proxyRect.LT); - half2 proxyCenter = half2((proxyRect.RB - proxyRect.LT) * 0.5); + float2 translatedFragPosFloat = sk_FragCoord.xy - proxyRect.LT; + float2 proxyCenter = (proxyRect.RB - proxyRect.LT) * 0.5; half edgeSize = 2.0 * blurRadius + cornerRadius + 0.5; // Position the fragment so that (0, 0) marks the center of the proxy rectangle. // Negative coordinates are on the left/top side and positive numbers are on the right/bottom. - translatedFragPos -= proxyCenter; + translatedFragPosFloat -= proxyCenter; // Temporarily strip off the fragment's sign. x/y are now strictly increasing as we move away // from the center. - half2 fragDirection = sign(translatedFragPos); - translatedFragPos = abs(translatedFragPos); + half2 fragDirection = half2(sign(translatedFragPosFloat)); + translatedFragPosFloat = abs(translatedFragPosFloat); // Our goal is to snip out the "middle section" of the proxy rect (everything but the edge). // We've repositioned our fragment position so that (0, 0) is the centerpoint and x/y are always // positive, so we can subtract here and interpret negative results as being within the middle // section. - translatedFragPos -= proxyCenter - edgeSize; + half2 translatedFragPosHalf = half2(translatedFragPosFloat - (proxyCenter - edgeSize)); // Remove the middle section by clamping to zero. - translatedFragPos = max(translatedFragPos, 0); + translatedFragPosHalf = max(translatedFragPosHalf, 0); // Reapply the fragment's sign, so that negative coordinates once again mean left/top side and // positive means bottom/right side. - translatedFragPos *= fragDirection; + translatedFragPosHalf *= fragDirection; // Offset the fragment so that (0, 0) marks the upper-left again, instead of the center point. - translatedFragPos += half2(edgeSize); + translatedFragPosHalf += half2(edgeSize); half2 proxyDims = half2(2.0 * edgeSize); - half2 texCoord = translatedFragPos / proxyDims; + half2 texCoord = translatedFragPosHalf / proxyDims; half4 inputColor = sample(inputFP); sk_OutColor = inputColor * sample(ninePatchFP, texCoord); diff --git a/src/gpu/effects/generated/GrRRectBlurEffect.cpp b/src/gpu/effects/generated/GrRRectBlurEffect.cpp index e93e6f2f61..255f8550c3 100644 --- a/src/gpu/effects/generated/GrRRectBlurEffect.cpp +++ b/src/gpu/effects/generated/GrRRectBlurEffect.cpp @@ -359,35 +359,35 @@ public: blurRadiusVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "blurRadius"); fragBuilder->codeAppendf( - R"SkSL(half2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy); -half2 proxyCenter = half2((%s.zw - %s.xy) * 0.5); + R"SkSL(float2 translatedFragPosFloat = sk_FragCoord.xy - %s.xy; +float2 proxyCenter = (%s.zw - %s.xy) * 0.5; half edgeSize = (2.0 * %s + %s) + 0.5; -translatedFragPos -= proxyCenter; -half2 fragDirection = sign(translatedFragPos); -translatedFragPos = abs(translatedFragPos); -translatedFragPos -= proxyCenter - edgeSize; -translatedFragPos = max(translatedFragPos, 0.0); -translatedFragPos *= fragDirection; -translatedFragPos += half2(edgeSize); +translatedFragPosFloat -= proxyCenter; +half2 fragDirection = half2(sign(translatedFragPosFloat)); +translatedFragPosFloat = abs(translatedFragPosFloat); +half2 translatedFragPosHalf = half2(translatedFragPosFloat - (proxyCenter - float(edgeSize))); +translatedFragPosHalf = max(translatedFragPosHalf, 0.0); +translatedFragPosHalf *= fragDirection; +translatedFragPosHalf += half2(edgeSize); half2 proxyDims = half2(2.0 * edgeSize); -half2 texCoord = translatedFragPos / proxyDims;)SkSL", +half2 texCoord = translatedFragPosHalf / proxyDims;)SkSL", args.fUniformHandler->getUniformCStr(proxyRectVar), args.fUniformHandler->getUniformCStr(proxyRectVar), args.fUniformHandler->getUniformCStr(proxyRectVar), args.fUniformHandler->getUniformCStr(blurRadiusVar), args.fUniformHandler->getUniformCStr(cornerRadiusVar)); - SkString _sample17184 = this->invokeChild(0, args); + SkString _sample17267 = this->invokeChild(0, args); fragBuilder->codeAppendf( R"SkSL( half4 inputColor = %s;)SkSL", - _sample17184.c_str()); - SkString _coords17232("float2(texCoord)"); - SkString _sample17232 = this->invokeChild(1, args, _coords17232.c_str()); + _sample17267.c_str()); + SkString _coords17315("float2(texCoord)"); + SkString _sample17315 = this->invokeChild(1, args, _coords17315.c_str()); fragBuilder->codeAppendf( R"SkSL( %s = inputColor * %s; )SkSL", - args.fOutputColor, _sample17232.c_str()); + args.fOutputColor, _sample17315.c_str()); } private: