ccpr: Fix very small edges

Fixes a bug in the vertex shader backend where a pixel could be hit
twice on very small, axis-aligned edges.

Improves the coverage calculations to be more accurate when dealing with
very small edges.

Bug: skia:
Change-Id: I4bac191695d7b7d73b6eef9df0fca3539503a965
Reviewed-on: https://skia-review.googlesource.com/111323
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index fc4409d..8c85a75 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -44,6 +44,41 @@
     s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt);
 }
 
+void GrCCCoverageProcessor::Shader::CalcEdgeCoverageAtBloatVertex(GrGLSLVertexGeoBuilder* s,
+                                                                  const char* leftPt,
+                                                                  const char* rightPt,
+                                                                  const char* rasterVertexDir,
+                                                                  const char* outputCoverage) {
+    // Here we find an edge's coverage at one corner of a conservative raster bloat box whose center
+    // falls on the edge in question. (A bloat box is axis-aligned and the size of one pixel.) We
+    // always set up coverage so it is -1 at the outermost corner, 0 at the innermost, and -.5 at
+    // the center. Interpolated, these coverage values convert jagged conservative raster edges into
+    // smooth antialiased edges.
+    //
+    // d1 == (P + sign(n) * bloat) dot n                   (Distance at the bloat box vertex whose
+    //    == P dot n + (abs(n.x) + abs(n.y)) * bloatSize    coverage=-1, where the bloat box is
+    //                                                      centered on P.)
+    //
+    // d0 == (P - sign(n) * bloat) dot n                   (Distance at the bloat box vertex whose
+    //    == P dot n - (abs(n.x) + abs(n.y)) * bloatSize    coverage=0, where the bloat box is
+    //                                                      centered on P.)
+    //
+    // d == (P + rasterVertexDir * bloatSize) dot n        (Distance at the bloat box vertex whose
+    //   == P dot n + (rasterVertexDir dot n) * bloatSize   coverage we wish to calculate.)
+    //
+    // coverage == -(d - d0) / (d1 - d0)                   (coverage=-1 at d=d1; coverage=0 at d=d0)
+    //
+    //          == (rasterVertexDir dot n) / (abs(n.x) + abs(n.y)) * -.5 - .5
+    //
+    s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
+                   rightPt, leftPt, leftPt, rightPt);
+    s->codeAppend ("float nwidth = abs(n.x) + abs(n.y);");
+    s->codeAppendf("float t = dot(%s, n);", rasterVertexDir);
+    // The below conditional guarantees we get exactly 1 on the divide when nwidth=t (in case the
+    // GPU divides by multiplying by the reciprocal?) It also guards against NaN when nwidth=0.
+    s->codeAppendf("%s = (abs(t) != nwidth ? t / nwidth : sign(t)) * -.5 - .5;", outputCoverage);
+}
+
 int GrCCCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLFPFragmentBuilder* f,
                                                              const char* samplesName) {
     // Standard DX11 sample locations.