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 <bsalomon@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Brian Salomon 2020-10-19 17:32:09 -04:00 committed by Skia Commit-Bot
parent e16eca95f5
commit f4594d1d5b
3 changed files with 43 additions and 25 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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: