Use coverage stages for supersample AA resolve, edgeAA, and glyph masks. Expose a mask stage through GrPaint

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



git-svn-id: http://skia.googlecode.com/svn/trunk@1356 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 3a4233a..af777c1 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -106,6 +106,26 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+int GrContext::PaintStageVertexLayoutBits(
+                            const GrPaint& paint,
+                            const bool hasTexCoords[GrPaint::kTotalStages]) {
+    int stageMask = paint.getActiveStageMask();
+    int layout = 0;
+    for (int i = 0; i < GrPaint::kTotalStages; ++i) {
+        if ((1 << i) & stageMask) {
+            if (NULL != hasTexCoords && hasTexCoords[i]) {
+                layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
+            } else {
+                layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
+            }
+        }
+    }
+    return layout;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
 enum {
     kNPOTBit    = 0x1,
     kFilterBit  = 0x2,
@@ -576,6 +596,10 @@
     GrTexture* src = record->fEntry0->texture();
     int scale;
 
+    enum {
+        kOffscreenStage = GrPaint::kTotalStages,
+    };
+
     if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
         GrAssert(NULL != record->fEntry1);
         scale = 2;
@@ -605,11 +629,14 @@
     }
 
     // setup for draw back to main RT
+    int stageMask = paint.getActiveStageMask();
+
     target->restoreDrawState(record->fSavedState);
-    if (NULL != paint.getTexture()) {
+
+    if (stageMask) {
         GrMatrix invVM;
         if (target->getViewInverse(&invVM)) {
-            target->preConcatSamplerMatrix(0, invVM);
+            target->preConcatSamplerMatrices(stageMask, invVM);
         }
     }
     target->setViewMatrix(GrMatrix::I());
@@ -623,7 +650,7 @@
     target->setSamplerState(kOffscreenStage, sampler);
 
     GrRect dstRect;
-    int stages = (1 << kOffscreenStage) | (NULL == paint.getTexture() ? 0 : 1);
+    int stages = (1 << kOffscreenStage) | stageMask;
     dstRect.set(boundRect);
     target->drawSimpleRect(dstRect, NULL, stages);
 
@@ -661,11 +688,14 @@
 }
 
 static GrColor getColorForMesh(const GrPaint& paint) {
-    if (NULL == paint.getTexture()) {
-        return paint.fColor;
-    } else {
+    // FIXME: This was copied from SkGpuDevice, seems like
+    // we should have already smeared a in caller if that
+    // is what is desired.
+    if (paint.hasTexture()) {
         unsigned a = GrColorUnpackA(paint.fColor);
         return GrColorPackRGBA(a, a, a, a);
+    } else {
+        return paint.fColor;
     }
 }
 
@@ -741,10 +771,8 @@
                            const GrPaint& paint,
                            const GrRect& devRect) {
 
-    GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
-    if (NULL != paint.getTexture()) {
-        layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
-    }
+    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
+                            GrDrawTarget::kColor_VertexLayoutBit;
 
     size_t vsize = GrDrawTarget::VertexSize(layout);
 
@@ -782,11 +810,8 @@
     const GrScalar rx = GrMul(dx, GR_ScalarHalf);
     const GrScalar ry = GrMul(dy, GR_ScalarHalf);
 
-    GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
-
-    if (NULL != paint.getTexture()) {
-        layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
-    }
+    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
+                            GrDrawTarget::kColor_VertexLayoutBit;
 
     GrScalar spare;
     {
@@ -902,9 +927,9 @@
                          GrScalar width,
                          const GrMatrix* matrix) {
 
-    bool textured = NULL != paint.getTexture();
 
     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+    int stageMask = paint.getActiveStageMask();
 
     GrRect devRect = rect;
     GrMatrix combinedMatrix;
@@ -913,10 +938,10 @@
 
     if (doAA) {
         GrDrawTarget::AutoViewMatrixRestore avm(target);
-        if (textured) {
+        if (stageMask) {
             GrMatrix inv;
             if (combinedMatrix.invert(&inv)) {
-                target->preConcatSamplerMatrix(0, inv);
+                target->preConcatSamplerMatrices(stageMask, inv);
             }
         }
         target->setViewMatrix(GrMatrix::I());
@@ -940,9 +965,8 @@
         // TODO: consider making static vertex buffers for these cases.
         // Hairline could be done by just adding closing vertex to
         // unitSquareVertexBuffer()
-        GrVertexLayout layout = textured ?
-                            GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
-                            0;
+        GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
+
         static const int worstCaseVertCount = 10;
         GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
 
@@ -973,17 +997,14 @@
         if (NULL != matrix) {
             avmr.set(target);
             target->preConcatViewMatrix(*matrix);
-            if (textured) {
-                target->preConcatSamplerMatrix(0, *matrix);
-            }
+            target->preConcatSamplerMatrices(stageMask, *matrix);
         }
 
         target->drawNonIndexed(primType, 0, vertCount);
     } else {
         #if GR_STATIC_RECT_VB
-            GrVertexLayout layout = (textured) ?
-                            GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
-                            0;
+            GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
+
             target->setVertexSourceToBuffer(layout,
                                             fGpu->getUnitSquareVertexBuffer());
             GrDrawTarget::AutoViewMatrixRestore avmr(target);
@@ -997,13 +1018,11 @@
             }
 
             target->preConcatViewMatrix(m);
-
-            if (textured) {
-                target->preConcatSamplerMatrix(0, m);
-            }
+            target->preConcatSamplerMatrices(stageMask, m);
+ 
             target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
         #else
-            target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
+            target->drawSimpleRect(rect, matrix, stageMask);
         #endif
     }
 }
@@ -1014,7 +1033,8 @@
                                const GrMatrix* dstMatrix,
                                const GrMatrix* srcMatrix) {
 
-    if (NULL == paint.getTexture()) {
+    // srcRect refers to paint's first texture
+    if (NULL == paint.getTexture(0)) {
         drawRect(paint, dstRect, -1, dstMatrix);
         return;
     }
@@ -1023,8 +1043,8 @@
 
 #if GR_STATIC_RECT_VB
     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
-
-    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+    
+    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
     GrDrawTarget::AutoViewMatrixRestore avmr(target);
 
     GrMatrix m;
@@ -1037,13 +1057,20 @@
     }
     target->preConcatViewMatrix(m);
 
+    // srcRect refers to first stage
+    int otherStageMask = paint.getActiveStageMask() & 
+                         (~(1 << GrPaint::kFirstTextureStage));
+    if (otherStageMask) {
+        target->preConcatSamplerMatrices(otherStageMask, m);
+    }
+
     m.setAll(srcRect.width(), 0,                srcRect.fLeft,
              0,               srcRect.height(), srcRect.fTop,
              0,               0,                GrMatrix::I()[8]);
     if (NULL != srcMatrix) {
         m.postConcat(*srcMatrix);
     }
-    target->preConcatSamplerMatrix(0, m);
+    target->preConcatSamplerMatrix(GrPaint::kFirstTextureStage, m);
 
     target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
     target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
@@ -1073,26 +1100,22 @@
                              const GrColor colors[],
                              const uint16_t indices[],
                              int indexCount) {
-    GrVertexLayout layout = 0;
-    int vertexSize = sizeof(GrPoint);
 
     GrDrawTarget::AutoReleaseGeometry geo;
 
     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
 
-    if (NULL != paint.getTexture()) {
-        if (NULL == texCoords) {
-            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
-        } else {
-            layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
-            vertexSize += sizeof(GrPoint);
-        }
-    }
+    bool hasTexCoords[GrPaint::kTotalStages] = {
+        NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
+        0                    // remaining stages use positions
+    };
+
+    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
 
     if (NULL != colors) {
         layout |= GrDrawTarget::kColor_VertexLayoutBit;
-        vertexSize += sizeof(GrColor);
     }
+    int vertexSize = GrDrawTarget::VertexSize(layout);
 
     bool doAA = false;
     OffscreenRecord record;
@@ -1105,9 +1128,9 @@
         }
         int texOffsets[GrDrawTarget::kMaxTexCoords];
         int colorOffset;
-        int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
-                                                            texOffsets,
-                                                            &colorOffset);
+        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
+                                                texOffsets,
+                                                &colorOffset);
         void* curVertex = geo.vertices();
 
         for (int i = 0; i < vertexCount; ++i) {
@@ -1119,7 +1142,7 @@
             if (colorOffset > 0) {
                 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
             }
-            curVertex = (void*)((intptr_t)curVertex + vsize);
+            curVertex = (void*)((intptr_t)curVertex + vertexSize);
         }
     } else {
         // we don't do offscreen AA when we have per-vertex tex coords or colors
@@ -1193,10 +1216,7 @@
             return;
         }
     } 
-    GrDrawTarget::StageBitfield enabledStages = 0;
-    if (NULL != paint.getTexture()) {
-        enabledStages |= 1;
-    }
+    GrDrawTarget::StageBitfield enabledStages = paint.getActiveStageMask();
 
     pr->drawPath(target, enabledStages, path, fill, translate);
 }
@@ -1308,8 +1328,21 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
-    target->setTexture(0, paint.getTexture());
-    target->setSamplerState(0, paint.fSampler);
+
+    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
+        int s = i + GrPaint::kFirstTextureStage;
+        target->setTexture(s, paint.getTexture(i));
+        target->setSamplerState(s, *paint.getTextureSampler(i));
+    }
+
+    target->setFirstCoverageStage(GrPaint::kFirstMaskStage);
+
+    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
+        int s = i + GrPaint::kFirstMaskStage;
+        target->setTexture(s, paint.getMask(i));
+        target->setSamplerState(s, *paint.getMaskSampler(i));
+    }
+
     target->setColor(paint.fColor);
 
     if (paint.fDither) {