Optimize GrRRectBlurEffect by computing frag pos branchlessly.

This version computes X and Y in parallel and without branching.

Change-Id: I08dd7339f75c6cdd5b4130bf363cac1f527bf6ed
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/295572
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/effects/GrRRectBlurEffect.fp b/src/gpu/effects/GrRRectBlurEffect.fp
index b784b07..e76d07f 100644
--- a/src/gpu/effects/GrRRectBlurEffect.fp
+++ b/src/gpu/effects/GrRRectBlurEffect.fp
@@ -173,26 +173,38 @@
 }
 
 void main() {
-    // warp the fragment position to the appropriate part of the 9patch blur texture
+    // 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);
+    half edgeSize = 2.0 * blurRadius + cornerRadius + 0.5;
 
-    half2 rectCenter = half2((proxyRect.xy + proxyRect.zw) / 2.0);
-    half2 translatedFragPos = half2(sk_FragCoord.xy - proxyRect.xy);
-    half threshold = cornerRadius + 2.0 * blurRadius;
-    half2 middle = half2(proxyRect.zw - proxyRect.xy - 2.0 * threshold);
+    // 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;
 
-    if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x + threshold)) {
-        translatedFragPos.x = threshold;
-    } else if (translatedFragPos.x >= (middle.x + threshold)) {
-        translatedFragPos.x -= middle.x - 1.0;
-    }
+    // 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);
 
-    if (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y + threshold)) {
-        translatedFragPos.y = threshold;
-    } else if (translatedFragPos.y >= (middle.y + threshold)) {
-        translatedFragPos.y -= middle.y - 1.0;
-    }
+    // 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 proxyDims = half2(2.0 * threshold + 1.0);
+    // Remove the middle section by clamping to zero.
+    translatedFragPos = max(translatedFragPos, 0);
+
+    // Reapply the fragment's sign, so that negative coordinates once again mean left/top side and
+    // positive means bottom/right side.
+    translatedFragPos *= fragDirection;
+
+    // Offset the fragment so that (0, 0) marks the upper-left again, instead of the center point.
+    translatedFragPos += half2(edgeSize);
+
+    half2 proxyDims = half2(2.0 * edgeSize);
     half2 texCoord = translatedFragPos / proxyDims;
 
     half4 inputColor = sample(inputFP, sk_InColor);
diff --git a/src/gpu/effects/generated/GrRRectBlurEffect.cpp b/src/gpu/effects/generated/GrRRectBlurEffect.cpp
index 1034ede..0889cef 100644
--- a/src/gpu/effects/generated/GrRRectBlurEffect.cpp
+++ b/src/gpu/effects/generated/GrRRectBlurEffect.cpp
@@ -77,32 +77,30 @@
         blurRadiusVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
                                                          kHalf_GrSLType, "blurRadius");
         fragBuilder->codeAppendf(
-                "\nhalf2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy);\nhalf threshold = %s "
-                "+ 2.0 * %s;\nhalf2 middle = half2((%s.zw - %s.xy) - float(2.0 * threshold));\nif "
-                "(translatedFragPos.x >= threshold && translatedFragPos.x < middle.x + threshold) "
-                "{\n    translatedFragPos.x = threshold;\n} else if (translatedFragPos.x >= "
-                "middle.x + threshold) {\n    translatedFragPos.x -= middle.x - 1.0;\n}\nif "
-                "(translatedFragPos.y > threshold && translatedFragPos.y < middle.y + threshold) "
-                "{\n    translatedFragPos.y = threshold;",
+                "half2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy);\nhalf2 proxyCenter = "
+                "half2((%s.zw - %s.xy) * 0.5);\nhalf edgeSize = (2.0 * %s + %s) + "
+                "0.5;\ntranslatedFragPos -= proxyCenter;\nhalf2 fragDirection = "
+                "sign(translatedFragPos);\ntranslatedFragPos = "
+                "abs(translatedFragPos);\ntranslatedFragPos -= proxyCenter - "
+                "edgeSize;\ntranslatedFragPos = max(translatedFragPos, 0.0);\ntranslatedFragPos *= "
+                "fragDirection;\ntranslatedFragPos += half2(edgeSize);\nhalf2 proxyDims = "
+                "half2(2.0 * edgeSize);\nhalf2 texCoord = tra",
                 args.fUniformHandler->getUniformCStr(proxyRectVar),
-                args.fUniformHandler->getUniformCStr(cornerRadiusVar),
+                args.fUniformHandler->getUniformCStr(proxyRectVar),
+                args.fUniformHandler->getUniformCStr(proxyRectVar),
                 args.fUniformHandler->getUniformCStr(blurRadiusVar),
-                args.fUniformHandler->getUniformCStr(proxyRectVar),
-                args.fUniformHandler->getUniformCStr(proxyRectVar));
-        fragBuilder->codeAppendf(
-                "\n} else if (translatedFragPos.y >= middle.y + threshold) {\n    "
-                "translatedFragPos.y -= middle.y - 1.0;\n}\nhalf2 proxyDims = half2(2.0 * "
-                "threshold + 1.0);\nhalf2 texCoord = translatedFragPos / proxyDims;");
-        SkString _input8208 = SkStringPrintf("%s", args.fInputColor);
-        SkString _sample8208;
+                args.fUniformHandler->getUniformCStr(cornerRadiusVar));
+        fragBuilder->codeAppendf("nslatedFragPos / proxyDims;");
+        SkString _input8931 = SkStringPrintf("%s", args.fInputColor);
+        SkString _sample8931;
         if (_outer.inputFP_index >= 0) {
-            _sample8208 = this->invokeChild(_outer.inputFP_index, _input8208.c_str(), args);
+            _sample8931 = this->invokeChild(_outer.inputFP_index, _input8931.c_str(), args);
         } else {
-            _sample8208 = _input8208;
+            _sample8931 = _input8931;
         }
         fragBuilder->codeAppendf(
                 "\nhalf4 inputColor = %s;\n%s = inputColor * sample(%s, float2(texCoord)).%s;\n",
-                _sample8208.c_str(), args.fOutputColor,
+                _sample8931.c_str(), args.fOutputColor,
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
                 fragBuilder->getProgramBuilder()
                         ->samplerSwizzle(args.fTexSamplers[0])