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/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 79b3da8..2169fc7 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -88,12 +88,30 @@
     if (vertexLayout & kColor_VertexLayoutBit) {
         size += sizeof(GrColor);
     }
+    if (vertexLayout & kCoverage_VertexLayoutBit) {
+        size += sizeof(GrColor);
+    }
     if (vertexLayout & kEdge_VertexLayoutBit) {
         size += 4 * sizeof(GrScalar);
     }
     return size;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Functions for computing offsets of various components from the layout
+ * bitfield.
+ * 
+ * Order of vertex components:
+ * Position
+ * Tex Coord 0
+ * ...
+ * Tex Coord kMaxTexCoords-1
+ * Color
+ * Coverage
+ */
+
 int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
     GrAssert(check_layout(vertexLayout));
     if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
@@ -121,7 +139,6 @@
 int  GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
     GrAssert(check_layout(vertexLayout));
 
-    // color is after the pos and tex coords
     if (vertexLayout & kColor_VertexLayoutBit) {
         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
                                     sizeof(GrGpuTextVertex) :
@@ -131,6 +148,23 @@
     return -1;
 }
 
+int  GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
+    GrAssert(check_layout(vertexLayout));
+
+    if (vertexLayout & kCoverage_VertexLayoutBit) {
+        int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
+                                    sizeof(GrGpuTextVertex) :
+                                    sizeof(GrPoint);
+
+        int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
+        if (vertexLayout & kColor_VertexLayoutBit) {
+            offset += sizeof(GrColor);
+        }
+        return offset;
+    }
+    return -1;
+}
+
 int  GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
     GrAssert(check_layout(vertexLayout));
 
@@ -143,21 +177,21 @@
         if (vertexLayout & kColor_VertexLayoutBit) {
             offset += sizeof(GrColor);
         }
+        if (vertexLayout & kCoverage_VertexLayoutBit) {
+            offset += sizeof(GrColor);
+        }
         return offset;
     }
     return -1;
 }
 
 int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
-                                             int texCoordOffsetsByIdx[kMaxTexCoords],
-                                             int* colorOffset,
-                                             int* edgeOffset) {
+                                            int texCoordOffsetsByIdx[kMaxTexCoords],
+                                            int* colorOffset,
+                                            int* coverageOffset,
+                                            int* edgeOffset) {
     GrAssert(check_layout(vertexLayout));
 
-    GrAssert(NULL != texCoordOffsetsByIdx);
-    GrAssert(NULL != colorOffset);
-    GrAssert(NULL != edgeOffset);
-
     int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
                                                     sizeof(GrGpuTextVertex) :
                                                     sizeof(GrPoint);
@@ -165,23 +199,45 @@
 
     for (int t = 0; t < kMaxTexCoords; ++t) {
         if (tex_coord_idx_mask(t) & vertexLayout) {
-            texCoordOffsetsByIdx[t] = size;
+            if (NULL != texCoordOffsetsByIdx) {
+                texCoordOffsetsByIdx[t] = size;
+            }
             size += vecSize;
         } else {
-            texCoordOffsetsByIdx[t] = -1;
+            if (NULL != texCoordOffsetsByIdx) {
+                texCoordOffsetsByIdx[t] = -1;
+            }
         }
     }
     if (kColor_VertexLayoutBit & vertexLayout) {
-        *colorOffset = size;
+        if (NULL != colorOffset) {
+            *colorOffset = size;
+        }
         size += sizeof(GrColor);
     } else {
-        *colorOffset = -1;
+        if (NULL != colorOffset) {
+            *colorOffset = -1;
+        }
+    }
+    if (kCoverage_VertexLayoutBit & vertexLayout) {
+        if (NULL != coverageOffset) {
+            *coverageOffset = size;
+        }
+        size += sizeof(GrColor);
+    } else {
+        if (NULL != coverageOffset) {
+            *coverageOffset = -1;
+        }
     }
     if (kEdge_VertexLayoutBit & vertexLayout) {
-        *edgeOffset = size;
+        if (NULL != edgeOffset) {
+            *edgeOffset = size;
+        }
         size += 4 * sizeof(GrScalar);
     } else {
-        *edgeOffset = -1;
+        if (NULL != edgeOffset) {
+            *edgeOffset = -1;
+        }
     }
     return size;
 }
@@ -189,31 +245,35 @@
 int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
                                               int texCoordOffsetsByStage[kNumStages],
                                               int* colorOffset,
+                                              int* coverageOffset,
                                               int* edgeOffset) {
     GrAssert(check_layout(vertexLayout));
 
-    GrAssert(NULL != texCoordOffsetsByStage);
-    GrAssert(NULL != colorOffset);
-    GrAssert(NULL != edgeOffset);
-
     int texCoordOffsetsByIdx[kMaxTexCoords];
     int size = VertexSizeAndOffsetsByIdx(vertexLayout,
-                                         texCoordOffsetsByIdx,
+                                         (NULL == texCoordOffsetsByStage) ?
+                                               NULL :
+                                               texCoordOffsetsByIdx,
                                          colorOffset,
+                                         coverageOffset,
                                          edgeOffset);
-    for (int s = 0; s < kNumStages; ++s) {
-        int tcIdx;
-        if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
-            texCoordOffsetsByStage[s] = 0;
-        } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
-            texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
-        } else {
-            texCoordOffsetsByStage[s] = -1;
+    if (NULL != texCoordOffsetsByStage) {
+        for (int s = 0; s < kNumStages; ++s) {
+            int tcIdx;
+            if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
+                texCoordOffsetsByStage[s] = 0;
+            } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
+                texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
+            } else {
+                texCoordOffsetsByStage[s] = -1;
+            }
         }
     }
     return size;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
 bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
     GrAssert(stage < kNumStages);
     GrAssert(check_layout(vertexLayout));
@@ -241,6 +301,8 @@
     return -1;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
 void GrDrawTarget::VertexLayoutUnitTest() {
     // not necessarily exhaustive
     static bool run;
@@ -286,9 +348,11 @@
                 }
                 GrAssert(-1 == VertexEdgeOffset(tcMask));
                 GrAssert(-1 == VertexColorOffset(tcMask));
+                GrAssert(-1 == VertexCoverageOffset(tcMask));
             #if GR_DEBUG
                 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
             #endif
+                GrAssert(-1 == VertexCoverageOffset(withColor));
                 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
             #if GR_DEBUG
@@ -303,6 +367,19 @@
                 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
                 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
+            #if GR_DEBUG
+                GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
+            #endif
+                GrAssert(-1 == VertexColorOffset(withCoverage));
+                GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
+                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
+            #if GR_DEBUG
+                GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
+                                                      kColor_VertexLayoutBit;
+            #endif
+                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
+                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
+                GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
             }
             GrAssert(tex_coord_idx_mask(t) == tcMask);
             GrAssert(check_layout(tcMask));
@@ -310,10 +387,13 @@
             int stageOffsets[kNumStages];
             int colorOffset;
             int edgeOffset;
+            int coverageOffset;
             int size;
-            size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset, &edgeOffset);
+            size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset,
+                                               &coverageOffset, &edgeOffset);
             GrAssert(2*sizeof(GrPoint) == size);
             GrAssert(-1 == colorOffset);
+            GrAssert(-1 == coverageOffset);
             GrAssert(-1 == edgeOffset);
             for (int s = 0; s < kNumStages; ++s) {
                 GrAssert(VertexUsesStage(s, tcMask));
@@ -765,8 +845,9 @@
 bool GrDrawTarget::CanDisableBlend(GrVertexLayout layout, const DrState& state) {
     // If we compute a coverage value (using edge AA or a coverage stage) then
     // we can't force blending off.
-    if (state.fEdgeAANumEdges > 0 || 
-        layout & kEdge_VertexLayoutBit) {
+    if (state.fEdgeAANumEdges > 0 ||
+        (layout & kEdge_VertexLayoutBit) ||
+        (layout & kCoverage_VertexLayoutBit)) {
         return false;
     }
     for (int s = state.fFirstCoverageStage; s < kNumStages; ++s) {
@@ -910,14 +991,10 @@
 #endif
 
     int stageOffsets[kNumStages];
-    int colorOffset;
-    int edgeOffset;
-    int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, 
-                                            &colorOffset, &edgeOffset);
-    GrAssert(-1 == colorOffset);
-    GrAssert(-1 == edgeOffset);
+    int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
+                                            NULL, NULL, NULL);
 
-    GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop, 
+    GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
                                             rect.fRight, rect.fBottom,
                                             vsize);
     if (NULL != matrix) {
@@ -926,10 +1003,10 @@
 
     for (int i = 0; i < kNumStages; ++i) {
         if (stageOffsets[i] > 0) {
-            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) + 
+            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
                                                 stageOffsets[i]);
             coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
-                               srcRects[i]->fRight, srcRects[i]->fBottom, 
+                               srcRects[i]->fRight, srcRects[i]->fBottom,
                                vsize);
             if (NULL != srcMatrices && NULL != srcMatrices[i]) {
                 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);