Make Gr clear take a rect for a partial-clear

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



git-svn-id: http://skia.googlecode.com/svn/trunk@1203 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 3112112..214fc05 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -282,9 +282,11 @@
     // Draws
 
     /**
-     *  Clear the entire render target, ignoring any clips
+     * Clear the entire or rect of the render target, ignoring any clips.
+     * @param rect  the rect to clear or the whole thing if rect is NULL.
+     * @param color the color to clear to.
      */
-    void clear(GrColor color);
+    void clear(const GrIRect* rect, GrColor color);
 
     /**
      *  Draw everywhere (respecting the clip) with the paint.
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index cb36d3c..c971e71 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -731,10 +731,11 @@
     }
 
     /**
-     * Clear the entire render target. Ignores the clip an all other draw state
-     * (blend mode, stages, etc).
+     * Clear the render target. Ignores the clip and all other draw state
+     * (blend mode, stages, etc). Clears the whole thing if rect is NULL,
+     * otherwise just the rect.
      */
-    virtual void clear(GrColor color) = 0;
+    virtual void clear(const GrIRect* rect, GrColor color) = 0;
 
     ///////////////////////////////////////////////////////////////////////////
 
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index 19f3746..590712b 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -263,7 +263,7 @@
     virtual void drawNonIndexed(GrPrimitiveType type,
                                 int startVertex,
                                 int vertexCount);
-    virtual void clear(GrColor color);
+    virtual void clear(const GrIRect* rect, GrColor color);
 
     /**
      * Installs a path renderer that will be used to draw paths that are
@@ -444,8 +444,9 @@
     virtual GrIndexBuffer* onCreateIndexBuffer(uint32_t size,
                                                bool dynamic) = 0;
 
-    // overridden by API-specific derivated class to perform the clear.
-    virtual void onClear(GrColor color) = 0;
+    // overridden by API-specific derivated class to perform the clear and 
+    // clearRect. NULL rect means clear whole target.
+    virtual void onClear(const GrIRect* rect, GrColor color) = 0;
 
     // overridden by API-specific derived class to perform the draw call.
     virtual void onDrawIndexed(GrPrimitiveType type,
diff --git a/gpu/include/GrInOrderDrawBuffer.h b/gpu/include/GrInOrderDrawBuffer.h
index 03a2f2d..b26cd72 100644
--- a/gpu/include/GrInOrderDrawBuffer.h
+++ b/gpu/include/GrInOrderDrawBuffer.h
@@ -100,7 +100,7 @@
                                int* vertexCount,
                                int* indexCount) const;
 
-    virtual void clear(GrColor color);
+    virtual void clear(const GrIRect* rect, GrColor color);
 
 private:
 
@@ -119,6 +119,7 @@
 
     struct Clear {
         int fBeforeDrawIdx;
+        GrIRect fRect;
         GrColor fColor;
     };
 
diff --git a/gpu/include/GrRect.h b/gpu/include/GrRect.h
index a9ff6ec..b85574a 100644
--- a/gpu/include/GrRect.h
+++ b/gpu/include/GrRect.h
@@ -76,19 +76,22 @@
 
     /**
      * Sets this rect to the intersection with a clip rect. If there is no
-     * intersection then this rect will be made empty.
+     * intersection then this rect will be made empty and the function will
+     * return false.
      */
-    void intersectWith(const GrIRect& clipRect) {
+    bool intersectWith(const GrIRect& clipRect) {
         if (fRight < clipRect.fLeft ||
             fLeft > clipRect.fRight ||
             fBottom < clipRect.fTop ||
             fTop > clipRect.fBottom) {
             this->setEmpty();
+            return false;
         } else {
             fLeft = GrMax(fLeft, clipRect.fLeft);
             fRight = GrMin(fRight, clipRect.fRight);
             fTop = GrMax(fTop, clipRect.fTop);
             fBottom = GrMin(fBottom, clipRect.fBottom);
+            return true;
         }
     }
 
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 0584e4b..d3904e0 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -391,11 +391,9 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-void GrContext::clear(GrColor color) {
-    // gpu flush call is immediate, must flush. 
-    // (could in theory skip draws to current render target.)
+void GrContext::clear(const GrIRect* rect, const GrColor color) {
     this->flush();
-    fGpu->clear(color);
+    fGpu->clear(rect, color);
 }
 
 void GrContext::drawPaint(const GrPaint& paint) {
@@ -462,7 +460,7 @@
     // clip gets applied in second pass
     target->disableState(GrDrawTarget::kClip_StateBit);
 
-    target->clear(0x0);
+    target->clear(NULL, 0x0);
     return true;
 }
 
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index c05a04a..cb78204 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -173,9 +173,9 @@
     return this->onCreateIndexBuffer(size, dynamic);
 }
 
-void GrGpu::clear(GrColor color) {
+void GrGpu::clear(const GrIRect* rect, GrColor color) {
     this->handleDirtyContext();
-    this->onClear(color);
+    this->onClear(rect, color);
 }
 
 void GrGpu::forceRenderTargetFlush() {
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 4bdf10e..352ad3f 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -1166,15 +1166,25 @@
     }
 }
 
-void GrGpuGL::onClear(GrColor color) {
+void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
     if (NULL == fCurrDrawState.fRenderTarget) {
         return;
     }
-    flushRenderTarget();
-    if (fHWBounds.fScissorEnabled) {
-        GR_GL(Disable(GR_GL_SCISSOR_TEST));
-        fHWBounds.fScissorEnabled = false;
+    GrIRect r;
+    if (NULL != rect) {
+        // flushScissor expects rect to be clipped to the target.
+        r = *rect;
+        GrIRect rtRect(0, 0, 
+                       fCurrDrawState.fRenderTarget->width(),
+                       fCurrDrawState.fRenderTarget->height());
+        if (r.intersectWith(rtRect)) {
+            rect = &r;
+        } else {
+            return;
+        }
     }
+    this->flushRenderTarget();
+    this->flushScissor(rect);
     GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
     fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
     GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 918ab80..bfa7351 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -27,10 +27,11 @@
 
 class GrGpuGL : public GrGpu {
 public:
-            GrGpuGL();
     virtual ~GrGpuGL();
 
 protected:
+    GrGpuGL();
+
     struct {
         size_t                  fVertexOffset;
         GrVertexLayout          fVertexLayout;
@@ -87,7 +88,7 @@
                                                  int width, int height);
     virtual GrRenderTarget* onCreateRenderTargetFrom3DApiState();
 
-    virtual void onClear(GrColor color);
+    virtual void onClear(const GrIRect* rect, GrColor color);
 
     virtual void onForceRenderTargetFlush();
 
@@ -140,6 +141,7 @@
     static bool BlendCoefReferencesConstant(GrBlendCoeff coeff);
 
 private:
+
     // notify callbacks to update state tracking when related
     // objects are bound to GL or deleted outside of the class
     void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 7b769fe..2ea12e1 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -150,7 +150,12 @@
             GrAssert(0 == lastDraw.fIndexCount % 6);
             GrAssert(0 == lastDraw.fStartIndex);
 
-            appendToPreviousDraw = lastDraw.fVertexBuffer == fCurrPoolVertexBuffer &&
+            bool clearSinceLastDraw =
+                            fClears.count() && 
+                            fClears.back().fBeforeDrawIdx == fDraws.count();
+
+            appendToPreviousDraw =  !clearSinceLastDraw &&
+                                    lastDraw.fVertexBuffer == fCurrPoolVertexBuffer &&
                                    (fCurrQuad * 4 + lastDraw.fStartVertex) == fCurrPoolStartVertex;
             if (appendToPreviousDraw) {
                 lastDraw.fVertexCount += 4;
@@ -288,14 +293,21 @@
     draw.fIndexBuffer = NULL;
 }
 
-void GrInOrderDrawBuffer::clear(GrColor color) {
+void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
+    GrIRect r;
+    if (NULL == rect) {
+        // We could do something smart and remove previous draws and clears to
+        // the current render target. If we get that smart we have to make sure
+        // those draws aren't read before this clear (render-to-texture).
+        r.setLTRB(0, 0, 
+                  this->getRenderTarget()->width(), 
+                  this->getRenderTarget()->height());
+        rect = &r;
+    }
     Clear& clr = fClears.push_back();
     clr.fColor = color;
     clr.fBeforeDrawIdx = fDraws.count();
-
-    // We could do something smart and remove previous draws and clears to the
-    // current render target. If we get that smart we have to make sure those
-    // draws aren't read before this clear (render-to-texture).
+    clr.fRect = *rect;
 }
 
 void GrInOrderDrawBuffer::reset() {
@@ -354,7 +366,7 @@
     for (int i = 0; i < numDraws; ++i) {
         while (currClear < fClears.count() && 
                i == fClears[currClear].fBeforeDrawIdx) {
-            target->clear(fClears[currClear].fColor);
+            target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
             ++currClear;
         }
 
@@ -388,7 +400,7 @@
     }
     while (currClear < fClears.count()) {
         GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
-        target->clear(fClears[currClear].fColor);
+        target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
         ++currClear;
     }
 }