Fewer operations in GrAARectEffect.

Change-Id: I57880b69302bab70be8e45d80387bcce052cf989
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/374599
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/effects/GrAARectEffect.fp b/src/gpu/effects/GrAARectEffect.fp
index f561387..89a7244 100644
--- a/src/gpu/effects/GrAARectEffect.fp
+++ b/src/gpu/effects/GrAARectEffect.fp
@@ -17,37 +17,35 @@
 }
 
 half4 main() {
-    half alpha;
+    half coverage;
     @switch (edgeType) {
         case GrClipEdgeType::kFillBW: // fall through
         case GrClipEdgeType::kInverseFillBW:
             // non-AA
-            alpha = all(greaterThan(float4(sk_FragCoord.xy, rectUniform.zw),
-                                    float4(rectUniform.xy, sk_FragCoord.xy))) ? 1 : 0;
+            coverage = all(greaterThan(float4(sk_FragCoord.xy, rectUniform.zw),
+                                       float4(rectUniform.xy, sk_FragCoord.xy))) ? 1 : 0;
             break;
         default:
-            // The amount of coverage removed in x and y by the edges is computed as a pair of
-            // negative numbers, xSub and ySub.
-            half xSub, ySub;
-            xSub = min(half(sk_FragCoord.x - rectUniform.x), 0.0);
-            xSub += min(half(rectUniform.z - sk_FragCoord.x), 0.0);
-            ySub = min(half(sk_FragCoord.y - rectUniform.y), 0.0);
-            ySub += min(half(rectUniform.w - sk_FragCoord.y), 0.0);
-            // Now compute coverage in x and y and multiply them to get the fraction of the pixel
-            // covered.
-            alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));
+            // compute coverage relative to left and right edges, add, then subtract 1 to account
+            // for double counting. And similar for top/bottom.
+            half4 dists4 = clamp(half4(1, 1, -1, -1) *
+                                 half4(sk_FragCoord.xyxy - rectUniform), 0, 1);
+            half2 dists2 = dists4.xy + dists4.zw - 1;
+            coverage = dists2.x * dists2.y;
     }
 
     @if (edgeType == GrClipEdgeType::kInverseFillBW || edgeType == GrClipEdgeType::kInverseFillAA) {
-        alpha = 1.0 - alpha;
+        coverage = 1.0 - coverage;
     }
-    return sample(inputFP) * alpha;
+    return sample(inputFP) * coverage;
 }
 
 @setData(pdman) {
     SkASSERT(rect.isSorted());
+    // The AA math in the shader evaluates to 0 at the uploaded coordinates, so outset by 0.5
+    // to interpolate from 0 at a half pixel inset and 1 at a half pixel outset of rect.
     const SkRect& newRect = GrProcessorEdgeTypeIsAA(edgeType) ?
-                            rect.makeInset(.5f, .5f) : rect;
+                            rect.makeOutset(.5f, .5f) : rect;
     if (newRect != prevRect) {
         pdman.set4f(rectUniform, newRect.fLeft, newRect.fTop, newRect.fRight, newRect.fBottom);
         prevRect = newRect;
diff --git a/src/gpu/effects/generated/GrAARectEffect.cpp b/src/gpu/effects/generated/GrAARectEffect.cpp
index 33f0020..3e34f1f 100644
--- a/src/gpu/effects/generated/GrAARectEffect.cpp
+++ b/src/gpu/effects/generated/GrAARectEffect.cpp
@@ -33,37 +33,29 @@
                                                           kFloat4_GrSLType, "rectUniform");
         fragBuilder->codeAppendf(
                 R"SkSL(float4 prevRect = float4(%f, %f, %f, %f);
-half alpha;
+half coverage;
 @switch (%d) {
     case 0:
     case 2:
-        alpha = half(all(greaterThan(float4(sk_FragCoord.xy, %s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);
+        coverage = half(all(greaterThan(float4(sk_FragCoord.xy, %s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);
         break;
     default:
-        half xSub;
-        half ySub;
-
-        xSub = min(half(sk_FragCoord.x - %s.x), 0.0);
-        xSub += min(half(%s.z - sk_FragCoord.x), 0.0);
-        ySub = min(half(sk_FragCoord.y - %s.y), 0.0);
-        ySub += min(half(%s.w - sk_FragCoord.y), 0.0);
-        alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));
+        half4 dists4 = clamp(half4(1.0, 1.0, -1.0, -1.0) * half4(sk_FragCoord.xyxy - %s), 0.0, 1.0);
+        half2 dists2 = (dists4.xy + dists4.zw) - 1.0;
+        coverage = dists2.x * dists2.y;
 }
 @if (%d == 2 || %d == 3) {
-    alpha = 1.0 - alpha;
+    coverage = 1.0 - coverage;
 })SkSL",
                 prevRect.left(), prevRect.top(), prevRect.right(), prevRect.bottom(),
                 (int)_outer.edgeType, args.fUniformHandler->getUniformCStr(rectUniformVar),
                 args.fUniformHandler->getUniformCStr(rectUniformVar),
-                args.fUniformHandler->getUniformCStr(rectUniformVar),
-                args.fUniformHandler->getUniformCStr(rectUniformVar),
-                args.fUniformHandler->getUniformCStr(rectUniformVar),
                 args.fUniformHandler->getUniformCStr(rectUniformVar), (int)_outer.edgeType,
                 (int)_outer.edgeType);
         SkString _sample0 = this->invokeChild(0, args);
         fragBuilder->codeAppendf(
                 R"SkSL(
-return %s * alpha;
+return %s * coverage;
 )SkSL",
                 _sample0.c_str());
     }
@@ -80,7 +72,10 @@
         (void)rectUniform;
 
         SkASSERT(rect.isSorted());
-        const SkRect& newRect = GrProcessorEdgeTypeIsAA(edgeType) ? rect.makeInset(.5f, .5f) : rect;
+        // The AA math in the shader evaluates to 0 at the uploaded coordinates, so outset by 0.5
+        // to interpolate from 0 at a half pixel inset and 1 at a half pixel outset of rect.
+        const SkRect& newRect =
+                GrProcessorEdgeTypeIsAA(edgeType) ? rect.makeOutset(.5f, .5f) : rect;
         if (newRect != prevRect) {
             pdman.set4f(rectUniform, newRect.fLeft, newRect.fTop, newRect.fRight, newRect.fBottom);
             prevRect = newRect;