Add per-vertex coverage field, use in AA rects when alpha tweak is not valid, add relevant sample/gm

Review URL: http://codereview.appspot.com/5181044/



git-svn-id: http://skia.googlecode.com/svn/trunk@2440 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 80f0268..3ca4346 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -219,6 +219,10 @@
         idx = (int)(random.nextF() * (kNumStages+1));
         pdesc.fFirstCoverageStage = idx;
 
+        pdesc.fVertexLayout |= (random.nextF() > .5f) ?
+                                    GrDrawTarget::kCoverage_VertexLayoutBit :
+                                    0;
+
 #if GR_GL_EXPERIMENTAL_GS
         pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport &&
                                 random.nextF() > .5f;
@@ -238,8 +242,8 @@
                 }
                 pdesc.fEdgeAANumEdges = 0;
             } else {
-                pdesc.fEdgeAANumEdges =  SkToS8(1 + random.nextF() *
-                                                this->getMaxEdges());
+                pdesc.fEdgeAANumEdges =  static_cast<int>(1 + random.nextF() *
+                                                          this->getMaxEdges());
                 pdesc.fEdgeAAConcave = random.nextF() > .5f;
             }
         } else {
@@ -312,6 +316,7 @@
 
     // Enable supported shader-releated caps
     fCaps.fShaderSupport = true;
+    fCaps.fSupportPerVertexCoverage = true;
     if (kDesktop_GrGLBinding == this->glBinding()) {
         fCaps.fDualSourceBlendingSupport =
                             this->glVersion() >= GR_GL_VER(3,3) ||
@@ -700,6 +705,7 @@
                                     int indexCount) {
 
     int newColorOffset;
+    int newCoverageOffset;
     int newTexCoordOffsets[kMaxTexCoords];
     int newEdgeOffset;
 
@@ -707,8 +713,10 @@
                                             this->getGeomSrc().fVertexLayout,
                                             newTexCoordOffsets,
                                             &newColorOffset,
+                                            &newCoverageOffset,
                                             &newEdgeOffset);
     int oldColorOffset;
+    int oldCoverageOffset;
     int oldTexCoordOffsets[kMaxTexCoords];
     int oldEdgeOffset;
 
@@ -716,6 +724,7 @@
                                             fHWGeometryState.fVertexLayout,
                                             oldTexCoordOffsets,
                                             &oldColorOffset,
+                                            &oldCoverageOffset,
                                             &oldEdgeOffset);
     bool indexed = NULL != startIndex;
 
@@ -792,6 +801,23 @@
         GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
     }
 
+    if (newCoverageOffset > 0) {
+        // bind just alpha channel.
+        GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset +
+                                             GrColor_INDEX_A);
+        int idx = GrGLProgram::CoverageAttributeIdx();
+        if (oldCoverageOffset <= 0) {
+            GL_CALL(EnableVertexAttribArray(idx));
+            GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE,
+                                        true, newStride, coverageOffset));
+        } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
+            GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE,
+                                        true, newStride, coverageOffset));
+        }
+    } else if (oldCoverageOffset > 0) {
+        GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
+    }
+
     if (newEdgeOffset > 0) {
         GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
         int idx = GrGLProgram::EdgeAttributeIdx();
@@ -954,13 +980,30 @@
     desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport;
 #endif
 
-    // use canonical value when coverage/color distinction won't affect
-    // generated code to prevent duplicate programs.
+    // we want to avoid generating programs with different "first cov stage"
+    // values when they would compute the same result.
+    // We set field in the desc to kNumStages when either there are no 
+    // coverage stages or the distinction between coverage and color is
+    // immaterial.
+    int firstCoverageStage = kNumStages;
     desc.fFirstCoverageStage = kNumStages;
-    if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) {
+    bool hasCoverage = fCurrDrawState.fFirstCoverageStage <= lastEnabledStage;
+    if (hasCoverage) {
+        firstCoverageStage = fCurrDrawState.fFirstCoverageStage;
+    }
+
+    // other coverage inputs
+    if (!hasCoverage) {
+        hasCoverage =
+               desc.fEdgeAANumEdges ||
+               (desc.fVertexLayout & GrDrawTarget::kCoverage_VertexLayoutBit) ||
+               (desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
+    }
+
+    if (hasCoverage) {
         // color filter is applied between color/coverage computation
         if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
-            desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
+            desc.fFirstCoverageStage = firstCoverageStage;
         }
 
         // We could consider cases where the final color is solid (0xff alpha)
@@ -972,17 +1015,17 @@
             if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
                 // write the coverage value to second color
                 desc.fDualSrcOutput =  ProgramDesc::kCoverage_DualSrcOutput;
-                desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
+                desc.fFirstCoverageStage = firstCoverageStage;
             } else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) {
                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially 
                 // cover
                 desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
-                desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
+                desc.fFirstCoverageStage = firstCoverageStage;
             } else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) {
                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
                 // cover
                 desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
-                desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
+                desc.fFirstCoverageStage = firstCoverageStage;
             }
         }
     }