ccpr: Pack wind into existing varyings

Bug: skia:
Change-Id: I189a22a6779af5d3fa7671992da50ede36eaaa8f
Reviewed-on: https://skia-review.googlesource.com/102067
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index 032d177..c875625 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -15,31 +15,13 @@
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
 #include "glsl/GrGLSLVertexGeoBuilder.h"
 
-void GrCCCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                                 GrGLSLVarying::Scope scope, SkString* code,
-                                                 const char* position, const char* coverage,
-                                                 const char* wind) {
-    SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
-    WindHandling windHandling = this->onEmitVaryings(varyingHandler, scope, code, position,
-                                                     coverage, wind);
-    if (WindHandling::kNotHandled == windHandling) {
-        fWind.reset(kHalf_GrSLType, scope);
-        varyingHandler->addFlatVarying("wind", &fWind);
-        code->appendf("%s = %s;", OutName(fWind), wind);
-    }
-}
-
 void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
                                                      GrGLSLPPFragmentBuilder* f,
                                                      const char* skOutputColor,
                                                      const char* skOutputCoverage) const {
     f->codeAppendf("half coverage = 0;");
     this->onEmitFragmentCode(f, "coverage");
-    if (fWind.fsIn()) {
-        f->codeAppendf("%s.a = coverage * %s;", skOutputColor, fWind.fsIn());
-    } else {
-        f->codeAppendf("%s.a = coverage;", skOutputColor);
-    }
+    f->codeAppendf("%s.a = coverage;", skOutputColor);
     f->codeAppendf("%s = half4(1);", skOutputCoverage);
 #ifdef SK_DEBUG
     if (proc.debugVisualizationsEnabled()) {
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h
index eeb2ace..1296e08 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.h
@@ -59,7 +59,7 @@
     enum class RenderPass {
         // For a Hull, the Impl generates a "conservative raster hull" around the input points. This
         // is the geometry that causes a pixel to be rasterized if it is touched anywhere by the
-        // input polygon. The initial coverage values sent to the Shader at each vertex are either
+        // input polygon. The input coverage values sent to the Shader at each vertex are either
         // null, or +1 all around if the Impl combines this pass with kTriangleEdges. Logically,
         // the conservative raster hull is equivalent to the convex hull of pixel size boxes
         // centered on each input point.
@@ -68,7 +68,7 @@
         kCubicHulls,
 
         // For Edges, the Impl generates conservative rasters around every input edge (i.e. convex
-        // hulls of two pixel-size boxes centered on both of the edge's endpoints). The initial
+        // hulls of two pixel-size boxes centered on both of the edge's endpoints). The input
         // coverage values sent to the Shader at each vertex are -1 on the outside border of the
         // edge geometry and 0 on the inside. This is the only geometry type that associates
         // coverage values with the output vertices. Interpolated, these coverage values convert
@@ -80,7 +80,7 @@
 
         // For Corners, the Impl Generates the conservative rasters of corner points (i.e.
         // pixel-size boxes). It generates 3 corner boxes for triangles and 2 for curves. The Shader
-        // specifies which corners. Initial coverage values sent to the Shader will be null.
+        // specifies which corners. Input coverage values sent to the Shader will be null.
         kTriangleCorners,
         kQuadraticCorners,
         kCubicCorners
@@ -162,8 +162,12 @@
                                    const char* repetitionID, const char* wind,
                                    GeometryVars*) const {}
 
-        void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
-                          const char* position, const char* coverage, const char* wind);
+        void emitVaryings(GrGLSLVaryingHandler* varyingHandler, GrGLSLVarying::Scope scope,
+                          SkString* code, const char* position, const char* inputCoverage,
+                          const char* wind) {
+            SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
+            this->onEmitVaryings(varyingHandler, scope, code, position, inputCoverage, wind);
+        }
 
         void emitFragmentCode(const GrCCCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
                               const char* skOutputColor, const char* skOutputCoverage) const;
@@ -178,25 +182,16 @@
         virtual ~Shader() {}
 
     protected:
-        enum class WindHandling : bool {
-            kHandled,
-            kNotHandled
-        };
-
         // Here the subclass adds its internal varyings to the handler and produces code to
-        // initialize those varyings from a given position, coverage value, and wind.
+        // initialize those varyings from a given position, input coverage value, and wind.
         //
-        // Returns whether the subclass will handle wind modulation or if this base class should
-        // take charge of multiplying the final coverage output by "wind".
-        //
-        // NOTE: the coverage parameter is only relevant for edges (see comments in RenderPass).
+        // NOTE: the coverage input is only relevant for edges (see comments in RenderPass).
         // Otherwise it is +1 all around.
-        virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope,
-                                            SkString* code, const char* position,
-                                            const char* coverage, const char* wind) = 0;
+        virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+                                    const char* position, const char* inputCoverage,
+                                    const char* wind) = 0;
 
-        // Emits the fragment code that calculates a pixel's coverage value. If using
-        // WindHandling::kHandled, this value must be signed appropriately.
+        // Emits the fragment code that calculates a pixel's signed coverage value.
         virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
                                         const char* outputCoverage) const = 0;
 
@@ -213,9 +208,6 @@
         //
         // Returns the number of samples.
         static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
-
-    private:
-        GrGLSLVarying fWind;
     };
 
     class GSImpl;
diff --git a/src/gpu/ccpr/GrCCCubicShader.cpp b/src/gpu/ccpr/GrCCCubicShader.cpp
index 295de0c..fbaf7d9 100644
--- a/src/gpu/ccpr/GrCCCubicShader.cpp
+++ b/src/gpu/ccpr/GrCCCubicShader.cpp
@@ -58,12 +58,14 @@
     // Evaluate the cubic at T=.5 for a mid-ish point.
     s->codeAppendf("float2 midpoint = %s * float4(.125, .375, .375, .125);", pts);
 
-    // Orient the KLM matrix so we fill the correct side of the curve.
+    // Orient the KLM matrix so L & M have matching signs on the side of the curve we wish to fill.
+    // We give L & M both the same sign as wind, in order to pass this value to the fragment shader.
+    // (Cubics are pre-chopped such that L & M do not change sign within any individual segment).
     s->codeAppendf("float2 orientation = sign(float3(midpoint, 1) * float2x3(%s[1], %s[2]));",
                    fKLMMatrix.c_str(), fKLMMatrix.c_str());
     s->codeAppendf("%s *= float3x3(orientation[0] * orientation[1], 0, 0, "
-                                  "0, orientation[0], 0, "
-                                  "0, 0, orientation[1]);", fKLMMatrix.c_str());
+                                  "0, orientation[0] * %s, 0, "
+                                  "0, 0, orientation[1] * %s);", fKLMMatrix.c_str(), wind, wind);
 
     // Determine the amount of additional coverage to subtract out for the flat edge (P3 -> P0).
     s->declareGlobal(fEdgeDistanceEquation);
@@ -75,11 +77,11 @@
     this->onEmitSetupCode(s, pts, repetitionID, vars);
 }
 
-Shader::WindHandling GrCCCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                                     GrGLSLVarying::Scope scope,
-                                                     SkString* code, const char* position,
-                                                     const char* coverage, const char* /*wind*/) {
-    SkASSERT(!coverage);
+void GrCCCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+                                     GrGLSLVarying::Scope scope, SkString* code,
+                                     const char* position, const char* inputCoverage,
+                                     const char* /*wind*/) {
+    SkASSERT(!inputCoverage);
 
     fKLMD.reset(kFloat4_GrSLType, scope);
     varyingHandler->addVarying("klmd", &fKLMD);
@@ -88,7 +90,20 @@
     code->appendf("%s = float4(klm, d);", OutName(fKLMD));
 
     this->onEmitVaryings(varyingHandler, scope, code);
-    return WindHandling::kNotHandled;
+}
+
+void GrCCCubicShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
+                                         const char* outputCoverage) const {
+    f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
+                   fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
+
+    this->emitCoverage(f, outputCoverage);
+
+    // Wind is the sign of both L and/or M. Take the sign of whichever has the larger magnitude.
+    // (In reality, either would be fine because we chop cubics with more than a half pixel of
+    // padding around the L & M lines, so neither should approach zero.)
+    f->codeAppend ("half wind = sign(l + m);");
+    f->codeAppendf("%s *= wind;", outputCoverage);
 }
 
 void GrCCCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
@@ -101,14 +116,13 @@
                     OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str());
 }
 
-void GrCCCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
-                                             const char* outputCoverage) const {
-    f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
-                   fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
+void GrCCCubicHullShader::emitCoverage(GrGLSLPPFragmentBuilder* f,
+                                       const char* outputCoverage) const {
+    // k,l,m,d are defined by the base class.
     f->codeAppend ("float f = k*k*k - l*m;");
     f->codeAppendf("float2 grad_f = %s * float2(k, 1);", fGradMatrix.fsIn());
     f->codeAppendf("%s = clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);", outputCoverage);
-    f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat closing edge.
+    f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat edge opposite the curve.
 }
 
 void GrCCCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
@@ -132,14 +146,13 @@
                   fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
 }
 
-void GrCCCubicCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
-                                               const char* outputCoverage) const {
+void GrCCCubicCornerShader::emitCoverage(GrGLSLPPFragmentBuilder* f,
+                                         const char* outputCoverage) const {
     f->codeAppendf("float2x4 grad_klmd = float2x4(%s, %s);", fdKLMDdx.fsIn(), fdKLMDdy.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->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
-                   fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
+    // k,l,m,d are defined by the base class.
     f->codeAppend ("float f = k*k*k - l*m;");
     f->codeAppend ("float2 grad_f = float3(3*k*k, -m, -l) * float2x3(grad_klmd);");
     f->codeAppendf("%s = -clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);",
diff --git a/src/gpu/ccpr/GrCCCubicShader.h b/src/gpu/ccpr/GrCCCubicShader.h
index a9875b6..ffb9103 100644
--- a/src/gpu/ccpr/GrCCCubicShader.h
+++ b/src/gpu/ccpr/GrCCCubicShader.h
@@ -25,15 +25,16 @@
 protected:
     void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                        const char* wind, GeometryVars*) const final;
-
     virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                                  GeometryVars*) const {}
 
-    WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
-                                const char* position, const char* coverage, const char* wind) final;
-
+    void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+                        const char* position, const char* inputCoverage, const char* wind) final;
     virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) = 0;
 
+    void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const final;
+    virtual void emitCoverage(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const = 0;
+
     GrShaderVar fKLMMatrix{"klm_matrix", kFloat3x3_GrSLType};
     GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
     GrGLSLVarying fKLMD;
@@ -41,7 +42,7 @@
 
 class GrCCCubicHullShader : public GrCCCubicShader {
     void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
-    void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
+    void emitCoverage(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
 
     GrGLSLVarying fGradMatrix;
 };
@@ -50,7 +51,7 @@
     void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                          GeometryVars*) const override;
     void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
-    void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
+    void emitCoverage(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
 
     GrGLSLVarying fdKLMDdx;
     GrGLSLVarying fdKLMDdy;
diff --git a/src/gpu/ccpr/GrCCQuadraticShader.cpp b/src/gpu/ccpr/GrCCQuadraticShader.cpp
index d08026a..002fcfd 100644
--- a/src/gpu/ccpr/GrCCQuadraticShader.cpp
+++ b/src/gpu/ccpr/GrCCQuadraticShader.cpp
@@ -33,23 +33,28 @@
     this->onEmitSetupCode(s, pts, repetitionID, vars);
 }
 
-Shader::WindHandling GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                                         GrGLSLVarying::Scope scope,
-                                                         SkString* code, const char* position,
-                                                         const char* coverage,
-                                                         const char* /*wind*/) {
-    SkASSERT(!coverage);
+void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+                                         GrGLSLVarying::Scope scope, SkString* code,
+                                         const char* position, const char* inputCoverage,
+                                         const char* wind) {
+    SkASSERT(!inputCoverage);
 
-    fXYD.reset(kFloat3_GrSLType, scope);
-    varyingHandler->addVarying("xyd", &fXYD);
+    fXYDW.reset(kFloat4_GrSLType, scope);
+    varyingHandler->addVarying("xydw", &fXYDW);
     code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
-                  OutName(fXYD), fCanonicalMatrix.c_str(), position);
+                  OutName(fXYDW), fCanonicalMatrix.c_str(), position);
     code->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
-                  OutName(fXYD), fEdgeDistanceEquation.c_str(), position,
+                  OutName(fXYDW), fEdgeDistanceEquation.c_str(), position,
                   fEdgeDistanceEquation.c_str());
+    code->appendf("%s.w = %s;", OutName(fXYDW), wind);
 
     this->onEmitVaryings(varyingHandler, scope, code);
-    return WindHandling::kNotHandled;
+}
+
+void GrCCQuadraticShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* 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,
@@ -76,15 +81,15 @@
     fGrad.reset(kFloat2_GrSLType, scope);
     varyingHandler->addVarying("grad", &fGrad);
     code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
-                  OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str());
+                  OutName(fGrad), OutName(fXYDW), fCanonicalMatrix.c_str());
 }
 
-void GrCCQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
-                                                 const char* outputCoverage) const {
+void GrCCQuadraticHullShader::emitCoverage(GrGLSLPPFragmentBuilder* f,
+                                           const char* outputCoverage) const {
     f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
-                   fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGrad.fsIn(), fGrad.fsIn());
+                   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, fXYD.fsIn()); // Flat closing edge.
+    f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYDW.fsIn()); // Flat closing edge.
 }
 
 void GrCCQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
@@ -95,7 +100,7 @@
 }
 
 void GrCCQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                                 GrGLSLVarying::Scope scope, SkString* code) {
+                                               GrGLSLVarying::Scope scope, SkString* code) {
     fdXYDdx.reset(kFloat3_GrSLType, scope);
     varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx);
     code->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);",
@@ -109,10 +114,10 @@
                   fEdgeDistanceEquation.c_str());
 }
 
-void GrCCQuadraticCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
-                                                   const char* outputCoverage) const {
+void GrCCQuadraticCornerShader::emitCoverage(GrGLSLPPFragmentBuilder* f,
+                                             const char* outputCoverage) const {
     f->codeAppendf("float x = %s.x, y = %s.y, d = %s.z;",
-                   fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn());
+                   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
@@ -124,7 +129,7 @@
 
     // 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);", fXYD.fsIn(), fXYD.fsIn());
+    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.
diff --git a/src/gpu/ccpr/GrCCQuadraticShader.h b/src/gpu/ccpr/GrCCQuadraticShader.h
index 09fe01c..bba3d36 100644
--- a/src/gpu/ccpr/GrCCQuadraticShader.h
+++ b/src/gpu/ccpr/GrCCQuadraticShader.h
@@ -24,18 +24,19 @@
 protected:
     void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                        const char* wind, GeometryVars*) const final;
-
     virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                                  GeometryVars*) const = 0;
 
-    WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
-                                const char* position, const char* coverage, const char* wind) final;
-
+    void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+                        const char* position, const char* inputCoverage, const char* wind) final;
     virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) {}
 
+    void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const final;
+    virtual void emitCoverage(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const = 0;
+
     const GrShaderVar fCanonicalMatrix{"canonical_matrix", kFloat3x3_GrSLType};
     const GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
-    GrGLSLVarying fXYD;
+    GrGLSLVarying fXYDW;
 };
 
 /**
@@ -48,7 +49,7 @@
     void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                          GeometryVars*) const override;
     void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
-    void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
+    void emitCoverage(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
 
     GrGLSLVarying fGrad;
 };
@@ -60,7 +61,7 @@
     void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                          GeometryVars*) const override;
     void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
-    void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
+    void emitCoverage(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
 
     GrGLSLVarying fdXYDdx;
     GrGLSLVarying fdXYDdy;
diff --git a/src/gpu/ccpr/GrCCTriangleShader.cpp b/src/gpu/ccpr/GrCCTriangleShader.cpp
index b507b37..6e9b13e 100644
--- a/src/gpu/ccpr/GrCCTriangleShader.cpp
+++ b/src/gpu/ccpr/GrCCTriangleShader.cpp
@@ -12,19 +12,18 @@
 
 using Shader = GrCCCoverageProcessor::Shader;
 
-Shader::WindHandling GrCCTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                                        GrGLSLVarying::Scope scope,
-                                                        SkString* code, const char* /*position*/,
-                                                        const char* coverage, const char* wind) {
+void GrCCTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+                                        GrGLSLVarying::Scope scope, SkString* code,
+                                        const char* /*position*/, const char* inputCoverage,
+                                        const char* wind) {
     fCoverageTimesWind.reset(kHalf_GrSLType, scope);
-    if (!coverage) {
+    if (!inputCoverage) {
         varyingHandler->addFlatVarying("wind", &fCoverageTimesWind);
         code->appendf("%s = %s;", OutName(fCoverageTimesWind), wind);
     } else {
         varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
-        code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), coverage, wind);
+        code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), inputCoverage, wind);
     }
-    return WindHandling::kHandled;
 }
 
 void GrCCTriangleShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
@@ -86,12 +85,11 @@
     s->codeAppend ("}");
 }
 
-Shader::WindHandling
-GrCCTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                         GrGLSLVarying::Scope scope, SkString* code,
-                                         const char* position, const char* coverage,
-                                         const char* /*wind*/) {
-    SkASSERT(!coverage);
+void GrCCTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+                                              GrGLSLVarying::Scope scope, SkString* code,
+                                              const char* position, const char* inputCoverage,
+                                              const char* wind) {
+    SkASSERT(!inputCoverage);
 
     fCornerLocationInAABoxes.reset(kFloat2x2_GrSLType, scope);
     varyingHandler->addVarying("corner_location_in_aa_boxes", &fCornerLocationInAABoxes);
@@ -106,7 +104,9 @@
     code->appendf(    "%s[i] = %s[i];", OutName(fBisectInAABoxes), fGeoShaderBisects.c_str());
     code->appendf("}");
 
-    return WindHandling::kNotHandled;
+    fWindTimesHalf.reset(kHalf_GrSLType, scope);
+    varyingHandler->addFlatVarying("wind_times_half", &fWindTimesHalf);
+    code->appendf("%s = %s * .5;", OutName(fWindTimesHalf), wind);
 }
 
 void GrCCTriangleCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
@@ -148,5 +148,5 @@
     f->codeAppendf(    "%s += (corner.x - 1) * exit.y;", outputCoverage);
     f->codeAppendf("}");
 
-    f->codeAppendf("%s *= .5;", outputCoverage);
+    f->codeAppendf("%s *= %s;", outputCoverage, fWindTimesHalf.fsIn());
 }
diff --git a/src/gpu/ccpr/GrCCTriangleShader.h b/src/gpu/ccpr/GrCCTriangleShader.h
index d40c236..cc7bd0e 100644
--- a/src/gpu/ccpr/GrCCTriangleShader.h
+++ b/src/gpu/ccpr/GrCCTriangleShader.h
@@ -17,9 +17,8 @@
  *              implement these steps in either one or two actual render passes.
  */
 class GrCCTriangleShader : public GrCCCoverageProcessor::Shader {
-    WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
-                                const char* position, const char* coverage,
-                                const char* wind) override;
+    void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+                        const char* position, const char* inputCoverage, const char* wind) override;
     void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
 
     GrGLSLVarying fCoverageTimesWind;
@@ -33,9 +32,8 @@
 class GrCCTriangleCornerShader : public GrCCCoverageProcessor::Shader {
     void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
                        const char* wind, GeometryVars*) const override;
-    WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
-                                const char* position, const char* coverage,
-                                const char* wind) override;
+    void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+                        const char* position, const char* inputCoverage, const char* wind) override;
     void onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, const char* outputCoverage) const override;
 
     GrShaderVar fAABoxMatrices{"aa_box_matrices", kFloat2x2_GrSLType, 2};
@@ -43,6 +41,7 @@
     GrShaderVar fGeoShaderBisects{"bisects", kFloat2_GrSLType, 2};
     GrGLSLVarying fCornerLocationInAABoxes;
     GrGLSLVarying fBisectInAABoxes;
+    GrGLSLVarying fWindTimesHalf;
 };
 
 #endif