Force input coverage to be only a byte in gpu shaders.

Prime coverage invariant output calculations with single component

BUG=skia:

Review URL: https://codereview.chromium.org/649783003
diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h
index 0bae612..75c987f 100644
--- a/include/gpu/GrTypesPriv.h
+++ b/include/gpu/GrTypesPriv.h
@@ -70,6 +70,8 @@
     kVec2f_GrVertexAttribType,
     kVec3f_GrVertexAttribType,
     kVec4f_GrVertexAttribType,
+
+    kUByte_GrVertexAttribType,   // unsigned byte, e.g. coverage
     kVec4ub_GrVertexAttribType,   // vector of 4 unsigned bytes, e.g. colors
 
     kLast_GrVertexAttribType = kVec4ub_GrVertexAttribType
@@ -81,14 +83,15 @@
  */
 static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) {
     SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount);
-    static const int kCounts[] = { 1, 2, 3, 4, 4 };
+    static const int kCounts[] = { 1, 2, 3, 4, 1, 4 };
     return kCounts[type];
 
     GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
     GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
     GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
     GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
-    GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+    GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
+    GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kCounts) == kGrVertexAttribTypeCount);
 }
 
@@ -102,6 +105,7 @@
         2*sizeof(float),        // kVec2f_GrVertexAttribType
         3*sizeof(float),        // kVec3f_GrVertexAttribType
         4*sizeof(float),        // kVec4f_GrVertexAttribType
+        1*sizeof(char),         // kUByte_GrVertexAttribType
         4*sizeof(char)          // kVec4ub_GrVertexAttribType
     };
     return kSizes[type];
@@ -110,7 +114,8 @@
     GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
     GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
     GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
-    GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+    GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
+    GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kSizes) == kGrVertexAttribTypeCount);
 }
 
@@ -123,7 +128,7 @@
     kPosition_GrVertexAttribBinding,    // required, must have vector count of 2
     kLocalCoord_GrVertexAttribBinding,  // must have vector count of 2
     kColor_GrVertexAttribBinding,       // must have vector count of 4
-    kCoverage_GrVertexAttribBinding,    // must have vector count of 4
+    kCoverage_GrVertexAttribBinding,    // must have a single byte
 
     kLastFixedFunction_GrVertexAttribBinding = kCoverage_GrVertexAttribBinding,
 
@@ -139,7 +144,7 @@
 
 static inline int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) {
     SkASSERT(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt);
-    static const int kVecCounts[] = { 2, 2, 4, 4 };
+    static const int kVecCounts[] = { 2, 2, 4, 1 };
 
     return kVecCounts[binding];
 
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 6990b7e..0ffbc9d 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -650,7 +650,7 @@
 // position + coverage
 extern const GrVertexAttrib gHairlineLineAttribs[] = {
     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
+    {kUByte_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
 };
 
 };
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index ae8a06c..6843aca 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -265,7 +265,7 @@
 extern const GrVertexAttrib gAARectAttribs[] = {
     {kVec2f_GrVertexAttribType,  0,                                 kPosition_GrVertexAttribBinding},
     {kVec4ub_GrVertexAttribType, sizeof(SkPoint),                   kColor_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding},
+    {kUByte_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding},
 };
 
 // Should the coverage be multiplied into the color attrib or use a separate attrib.
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index c4b8154..d300f2b 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -389,7 +389,7 @@
     }
 
     GrProcessor::InvariantOutput inout;
-    inout.fIsSingleComponent = false;
+    inout.fIsSingleComponent = true;
     // Initialize to an unknown starting coverage if per-vertex coverage is specified.
     if (this->hasCoverageVertexAttribute()) {
         inout.fValidFlags = 0;
@@ -738,7 +738,7 @@
         // The shader generated for coverage drawing runs the full coverage computation and then
         // makes the shader output be the multiplication of color and coverage. We mirror that here.
         GrProcessor::InvariantOutput inoutCoverage;
-        inoutCoverage.fIsSingleComponent = false;
+        inoutCoverage.fIsSingleComponent = true;
         if (this->hasCoverageVertexAttribute()) {
             inoutCoverage.fValidFlags = 0;
             inoutCoverage.fColor = 0; // suppresses any warnings.
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index ffde5f9..94ea291 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -55,7 +55,7 @@
     GrProcessor::InvariantOutput inout;
     inout.fColor = GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
     inout.fValidFlags = kRGBA_GrColorComponentFlags;
-    inout.fIsSingleComponent = false;
+    inout.fIsSingleComponent = true;
     int count = fCoverageStages.count();
     for (int i = 0; i < count; ++i) {
         fCoverageStages[i].getProcessor()->computeInvariantOutput(&inout);
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index f152173..319dcce 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -63,7 +63,7 @@
                          GrGLInstalledGeoProc* geometryProcessor,
                          GrGLInstalledFragProcs* fragmentProcessors)
     : fColor(GrColor_ILLEGAL)
-    , fCoverage(GrColor_ILLEGAL)
+    , fCoverage(0)
     , fDstCopyTexUnit(-1)
     , fBuiltinUniformHandles(builtinUniforms)
     , fProgramID(programID)
@@ -131,7 +131,7 @@
                           GrGpu::DrawType drawType,
                           const GrDeviceCoordTexture* dstCopy) {
     GrColor color = optState.getColor();
-    GrColor coverage = optState.getCoverageColor();
+    uint8_t coverage = optState.getCoverage();
 
     this->setColor(optState, color);
     this->setCoverage(optState, coverage);
@@ -223,7 +223,7 @@
     }
 }
 
-void GrGLProgram::setCoverage(const GrOptDrawState& optState, GrColor coverage) {
+void GrGLProgram::setCoverage(const GrOptDrawState& optState, uint8_t coverage) {
     const GrProgramDesc::KeyHeader& header = fDesc.header();
     switch (header.fCoverageInput) {
         case GrProgramDesc::kAttribute_ColorInput:
@@ -232,9 +232,9 @@
         case GrProgramDesc::kUniform_ColorInput:
             if (fCoverage != coverage) {
                 // OpenGL ES doesn't support unsigned byte varieties of glUniform
-                GrGLfloat c[4];
-                GrColorToRGBAFloat(coverage, c);
-                fProgramDataManager.set4fv(fBuiltinUniformHandles.fCoverageUni, 1, c);
+                static const float ONE_OVER_255 = 1.f / 255.f;
+                GrGLfloat c = coverage * ONE_OVER_255;
+                fProgramDataManager.set1f(fBuiltinUniformHandles.fCoverageUni, c);
                 fCoverage = coverage;
             }
             break;
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index d7a7cf8..e37d54d 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -155,7 +155,7 @@
 
     // Helper for setData(). Makes GL calls to specify the initial coverage when there is not
     // per-vertex coverages.
-    void setCoverage(const GrOptDrawState&, GrColor coverage);
+    void setCoverage(const GrOptDrawState&, uint8_t coverage);
 
     // A templated helper to loop over effects, set the transforms(via subclass) and bind textures
     void setFragmentData(const GrOptDrawState&);
@@ -175,7 +175,7 @@
     // these reflect the current values of uniforms (GL uniform values travel with program)
     MatrixState fMatrixState;
     GrColor fColor;
-    GrColor fCoverage;
+    uint8_t fCoverage;
     int fDstCopyTexUnit;
     BuiltinUniformHandles fBuiltinUniformHandles;
     GrGLuint fProgramID;
diff --git a/src/gpu/gl/GrGLVertexArray.h b/src/gpu/gl/GrGLVertexArray.h
index f4eb3d5..96e90bc 100644
--- a/src/gpu/gl/GrGLVertexArray.h
+++ b/src/gpu/gl/GrGLVertexArray.h
@@ -32,13 +32,15 @@
         {2, GR_GL_FLOAT, false},         // kVec2f_GrVertexAttribType
         {3, GR_GL_FLOAT, false},         // kVec3f_GrVertexAttribType
         {4, GR_GL_FLOAT, false},         // kVec4f_GrVertexAttribType
+        {1, GR_GL_UNSIGNED_BYTE, true},  // kUByte_GrVertexAttribType
         {4, GR_GL_UNSIGNED_BYTE, true},  // kVec4ub_GrVertexAttribType
     };
     GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
     GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
     GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
     GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
-    GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+    GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
+    GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayouts) == kGrVertexAttribTypeCount);
     return kLayouts[type];
 }
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 569fd2e..8fc6020 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -48,7 +48,8 @@
     }
 
     // get the initial color and coverage to feed into the first effect in each effect chain
-    GrGLSLExpr4 inputColor, inputCoverage;
+    GrGLSLExpr4 inputColor;
+    GrGLSLExpr1 inputCoverage;
     pb->setupUniformColorAndCoverageIfNeeded(&inputColor,  &inputCoverage);
 
     // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
@@ -70,7 +71,11 @@
         }
     }
 
-    pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage);
+    // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
+    // remove this cast to a vec4.
+    GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage);
+
+    pb->emitAndInstallProcs(optState, &inputColor, &inputCoverageVec4);
 
     if (hasVertexShader) {
         pb->fVS.transformSkiaToGLCoords();
@@ -78,10 +83,10 @@
 
     // write the secondary color output if necessary
     if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
-        pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
+        pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4);
     }
 
-    pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
+    pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4);
 
     return pb->finalize();
 }
@@ -199,7 +204,7 @@
 }
 
 void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
-                                                              GrGLSLExpr4* inputCoverage) {
+                                                              GrGLSLExpr1* inputCoverage) {
     const GrProgramDesc::KeyHeader& header = this->header();
     if (GrProgramDesc::kUniform_ColorInput == header.fColorInput) {
         const char* name;
@@ -216,12 +221,12 @@
         const char* name;
         fUniformHandles.fCoverageUni =
             this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                             kVec4f_GrSLType,
+                             kFloat_GrSLType,
                              "Coverage",
                              &name);
-        *inputCoverage = GrGLSLExpr4(name);
+        *inputCoverage = GrGLSLExpr1(name);
     } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
-        *inputCoverage = GrGLSLExpr4(1);
+        *inputCoverage = GrGLSLExpr1(1);
     }
 }
 
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index 0abdf0a..4bcf50b 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -240,7 +240,7 @@
     // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
     // generating stage code.
     void nameVariable(SkString* out, char prefix, const char* name);
-    void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
+    void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
     void emitAndInstallProcs(const GrOptDrawState& optState,
                              GrGLSLExpr4* inputColor,
                              GrGLSLExpr4* inputCoverage);
diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
index 5a65f71..2bef113 100644
--- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
@@ -57,6 +57,19 @@
     this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);", viewMName, fPositionVar->c_str());
 }
 
+void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr1* out) {
+    GrGLVertToFrag v(kFloat_GrSLType);
+    fProgramBuilder->addVarying(inName, &v);
+    SkString name(inName);
+    name.prepend("in");
+    this->addAttribute(GrShaderVar(name.c_str(),
+                                   kFloat_GrSLType,
+                                   GrShaderVar::kAttribute_TypeModifier));
+    this->codeAppendf("%s = %s;", v.vsOut(), name.c_str());
+    *out = v.fsIn();
+    fEffectAttribOffset++;
+}
+
 void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out) {
     GrGLVertToFrag v(kVec4f_GrSLType);
     fProgramBuilder->addVarying(inName, &v);
diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h
index 31b4ad4..2f14bd7 100644
--- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h
+++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h
@@ -42,6 +42,7 @@
      */
     void setupLocalCoords();
     void transformGLToSkiaCoords();
+    void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr1* out);
     void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out);
     void emitAttributes(const GrGeometryProcessor& gp);
     void transformSkiaToGLCoords();
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 100752e..c643bd5 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -188,7 +188,7 @@
                               random, &attribIndex, &runningStride);
 
     // coverage
-    setup_random_ff_attribute(kCoverage_GrVertexAttribBinding, kVec4f_GrVertexAttribType,
+    setup_random_ff_attribute(kCoverage_GrVertexAttribBinding, kUByte_GrVertexAttribType,
                               random, &attribIndex, &runningStride);
 
     // Update the geometry processor attributes