ccpr: Draw curves in a single pass

Throws out the complicated MSAA curve corner shaders, and instead just
ramps coverage to zero at bloat vertices that fall outside the curve.

Updates SampleCCPRGeometry to better visualize this new geometry by
clearing to black and drawing with SkBlendMode::kPlus.

Bug: skia:
Change-Id: Ibe86cbc741d8b015127b10dd43e3b52e7cb35732
Reviewed-on: https://skia-review.googlesource.com/112626
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ccpr/GrCCQuadraticShader.cpp b/src/gpu/ccpr/GrCCQuadraticShader.cpp
index 090e29f..baa10fd 100644
--- a/src/gpu/ccpr/GrCCQuadraticShader.cpp
+++ b/src/gpu/ccpr/GrCCQuadraticShader.cpp
@@ -14,7 +14,7 @@
 using Shader = GrCCCoverageProcessor::Shader;
 
 void GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
-                                        const char* repetitionID, const char* wind,
+                                        const char* /*repetitionID*/, const char* /*wind*/,
                                         GeometryVars* vars) const {
     s->declareGlobal(fCanonicalMatrix);
     s->codeAppendf("%s = float3x3(0.0, 0, 1, "
@@ -25,41 +25,6 @@
                                          "%s[2], 1));",
                    fCanonicalMatrix.c_str(), pts, pts, pts);
 
-    s->declareGlobal(fEdgeDistanceEquation);
-    s->codeAppendf("float2 edgept0 = %s[%s > 0 ? 2 : 0];", pts, wind);
-    s->codeAppendf("float2 edgept1 = %s[%s > 0 ? 0 : 2];", pts, wind);
-    Shader::EmitEdgeDistanceEquation(s, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
-
-    this->onEmitSetupCode(s, pts, repetitionID, vars);
-}
-
-void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                         GrGLSLVarying::Scope scope, SkString* code,
-                                         const char* position, const char* inputCoverage,
-                                         const char* wind) {
-    SkASSERT(!inputCoverage);
-
-    fXYDW.reset(kFloat4_GrSLType, scope);
-    varyingHandler->addVarying("xydw", &fXYDW);
-    code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
-                  OutName(fXYDW), fCanonicalMatrix.c_str(), position);
-    code->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
-                  OutName(fXYDW), fEdgeDistanceEquation.c_str(), position,
-                  fEdgeDistanceEquation.c_str());
-    code->appendf("%s.w = %s;", OutName(fXYDW), wind);
-
-    this->onEmitVaryings(varyingHandler, scope, code);
-}
-
-void GrCCQuadraticShader::onEmitFragmentCode(GrGLSLFPFragmentBuilder* f,
-                                             const char* outputCoverage) const {
-    this->emitCoverage(f, outputCoverage);
-    f->codeAppendf("%s *= %s.w;", outputCoverage, fXYDW.fsIn()); // Sign by wind.
-}
-
-void GrCCQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
-                                              const char* /*repetitionID*/,
-                                              GeometryVars* vars) const {
     // Find the T value whose tangent is halfway between the tangents at the endpionts.
     s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts);
     s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts);
@@ -76,66 +41,31 @@
     vars->fHullVars.fAlternatePoints = "quadratic_hull";
 }
 
-void GrCCQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                             GrGLSLVarying::Scope scope, SkString* code) {
-    fGrad.reset(kFloat2_GrSLType, scope);
-    varyingHandler->addVarying("grad", &fGrad);
-    code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
-                  OutName(fGrad), OutName(fXYDW), fCanonicalMatrix.c_str());
+void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+                                         GrGLSLVarying::Scope scope, SkString* code,
+                                         const char* position, const char* inputCoverage,
+                                         const char* wind) {
+    fCoords.reset(kFloat4_GrSLType, scope);
+    varyingHandler->addVarying("coords", &fCoords);
+    code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
+                  OutName(fCoords), fCanonicalMatrix.c_str(), position);
+    code->appendf("%s.zw = float2(2 * %s.x, -1) * float2x2(%s);",
+                  OutName(fCoords), OutName(fCoords), fCanonicalMatrix.c_str());
+
+    fCoverageTimesWind.reset(kHalf_GrSLType, scope);
+    varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
+    code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), inputCoverage, wind);
 }
 
-void GrCCQuadraticHullShader::emitCoverage(GrGLSLFPFragmentBuilder* f,
-                                           const char* outputCoverage) const {
-    f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
-                   fXYDW.fsIn(), fXYDW.fsIn(), fXYDW.fsIn(), fGrad.fsIn(), fGrad.fsIn());
-    f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
-    f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYDW.fsIn()); // Flat closing edge.
-}
-
-void GrCCQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
-                                                const char* repetitionID,
-                                                GeometryVars* vars) const {
-    s->codeAppendf("float2 corner = %s[%s * 2];", pts, repetitionID);
-    vars->fCornerVars.fPoint = "corner";
-}
-
-void GrCCQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                               GrGLSLVarying::Scope scope, SkString* code) {
-    using Interpolation = GrGLSLVaryingHandler::Interpolation;
-
-    fdXYDdx.reset(kFloat3_GrSLType, scope);
-    varyingHandler->addVarying("dXYDdx", &fdXYDdx, Interpolation::kCanBeFlat);
-    code->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);",
-                  OutName(fdXYDdx), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
-                  fEdgeDistanceEquation.c_str());
-
-    fdXYDdy.reset(kFloat3_GrSLType, scope);
-    varyingHandler->addVarying("dXYDdy", &fdXYDdy, Interpolation::kCanBeFlat);
-    code->appendf("%s = float3(%s[1].x, %s[1].y, %s.y);",
-                  OutName(fdXYDdy), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
-                  fEdgeDistanceEquation.c_str());
-}
-
-void GrCCQuadraticCornerShader::emitCoverage(GrGLSLFPFragmentBuilder* f,
+void GrCCQuadraticShader::onEmitFragmentCode(const GrCCCoverageProcessor& proc,
+                                             GrGLSLFPFragmentBuilder* f,
                                              const char* outputCoverage) const {
-    f->codeAppendf("float x = %s.x, y = %s.y, d = %s.z;",
-                   fXYDW.fsIn(), fXYDW.fsIn(), fXYDW.fsIn());
-    f->codeAppendf("float2x3 grad_xyd = float2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn());
-
-    // Erase what the previous hull shader wrote. We don't worry about the two corners falling on
-    // the same pixel because those cases should have been weeded out by this point.
-    f->codeAppend ("float f = x*x - y;");
-    f->codeAppend ("float2 grad_f = float2(2*x, -1) * float2x2(grad_xyd);");
-    f->codeAppendf("%s = -(0.5 - f * inversesqrt(dot(grad_f, grad_f)));", outputCoverage);
-    f->codeAppendf("%s -= d;", outputCoverage);
-
-    // Use software msaa to approximate coverage at the corner pixels.
-    int sampleCount = Shader::DefineSoftSampleLocations(f, "samples");
-    f->codeAppendf("float3 xyd_center = float3(%s.xy, %s.z + 0.5);", fXYDW.fsIn(), fXYDW.fsIn());
-    f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
-    f->codeAppend (    "float3 xyd = grad_xyd * samples[i] + xyd_center;");
-    f->codeAppend (    "half f = xyd.y - xyd.x * xyd.x;"); // f > 0 -> inside curve.
-    f->codeAppendf(    "%s += all(greaterThan(float2(f,xyd.z), float2(0))) ? %f : 0;",
-                       outputCoverage, 1.0 / sampleCount);
-    f->codeAppendf("}");
+    f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s.zw, %s.zw));",
+                   fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn());
+#ifdef SK_DEBUG
+    if (proc.debugVisualizationsEnabled()) {
+        f->codeAppendf("d /= %f;", proc.debugBloat());
+    }
+#endif
+    f->codeAppendf("%s = clamp(0.5 - d, 0, 1) * %s;", outputCoverage, fCoverageTimesWind.fsIn());
 }