Batch consecutive draw rects.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@800 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 5cfc6f4..06e5ab8b 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -17,6 +17,7 @@
 
 #include "GrDrawTarget.h"
 #include "GrGpuVertex.h"
+#include "GrTexture.h"
 
 // recursive helper for creating mask with all the tex coord bits set for
 // one stage
@@ -291,7 +292,7 @@
 }
 
 void GrDrawTarget::setClip(const GrClip& clip) {
-    clipWillChange(clip);
+    clipWillBeSet(clip);
     fClip = clip;
 }
 
@@ -484,7 +485,127 @@
     fGeometrySrc.fIndexBuffer  = buffer;
 }
 
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+bool GrDrawTarget::canDisableBlend() const {
+    if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
+        (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
+            return true;
+    }
+
+    // If we have vertex color without alpha then we can't force blend off
+    if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
+         0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
+        return false;
+    }
+
+    // If the src coef will always be 1...
+    if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
+        kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
+        return false;
+    }
+
+    // ...and the dst coef is always 0...
+    if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
+        kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
+        return false;
+    }
+
+    // ...and there isn't a texture with an alpha channel...
+    for (int s = 0; s < kNumStages; ++s) {
+        if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
+            GrAssert(NULL != fCurrDrawState.fTextures[s]);
+            GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config();
+
+            if (GrTexture::kRGB_565_PixelConfig != config &&
+                GrTexture::kRGBX_8888_PixelConfig != config) {
+                return false;
+            }
+        }
+    }
+
+    // ...then we disable blend.
+    return true;
+}
+///////////////////////////////////////////////////////////////////////////////
+void GrDrawTarget::drawRect(const GrRect& rect, 
+                            const GrMatrix* matrix,
+                            int stageEnableMask,
+                            const GrRect* srcRects[],
+                            const GrMatrix* srcMatrices[]) {
+    GR_STATIC_ASSERT(8*sizeof(int) >= kNumStages);
+
+    GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects);
+
+    AutoReleaseGeometry geo(this, layout, 4, 0);
+
+    SetRectVertices(rect, matrix, srcRects, 
+                    srcMatrices, layout, geo.vertices());
+
+    drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
+}
+
+GrVertexLayout GrDrawTarget::GetRectVertexLayout(int stageEnableMask, 
+                                                 const GrRect* srcRects[]) {
+    GrVertexLayout layout = 0;
+
+    for (int i = 0; i < kNumStages; ++i) {
+        int numTC = 0;
+        if (stageEnableMask & (1 << i)) {
+            if (NULL != srcRects && NULL != srcRects[i]) {
+                layout |= StageTexCoordVertexLayoutBit(i, numTC);
+                ++numTC;
+            } else {
+                layout |= StagePosAsTexCoordVertexLayoutBit(i);
+            }
+        }
+    }
+    return layout;
+}
+void GrDrawTarget::SetRectVertices(const GrRect& rect,
+                                   const GrMatrix* matrix, 
+                                   const GrRect* srcRects[], 
+                                   const GrMatrix* srcMatrices[],
+                                   GrVertexLayout layout, 
+                                   void* vertices) {
+#if GR_DEBUG
+    // check that the layout and srcRects agree
+    for (int i = 0; i < kNumStages; ++i) {
+        if (VertexTexCoordsForStage(i, layout) >= 0) {
+            GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
+        } else {
+            GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
+        }
+    }
+#endif
+
+    int stageOffsets[kNumStages];
+    int colorOffset;
+    int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset);
+    GrAssert(-1 == colorOffset);
+
+    GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop, 
+                                            rect.fRight, rect.fBottom,
+                                            vsize);
+    if (NULL != matrix) {
+        matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
+    }
+
+    for (int i = 0; i < kNumStages; ++i) {
+        if (stageOffsets[i] > 0) {
+            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) + 
+                                                stageOffsets[i]);
+            coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
+                               srcRects[i]->fRight, srcRects[i]->fBottom, 
+                               vsize);
+            if (NULL != srcMatrices && NULL != srcMatrices[i]) {
+                srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
+            }
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
     fDrawTarget = target;