When cache is full delay flush until GrContext draw is finished

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/25673004

git-svn-id: http://skia.googlecode.com/svn/trunk/src@11613 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/GrContext.cpp b/gpu/GrContext.cpp
index 6b1efbe..91e8286 100644
--- a/gpu/GrContext.cpp
+++ b/gpu/GrContext.cpp
@@ -68,6 +68,20 @@
 // Glorified typedef to avoid including GrDrawState.h in GrContext.h
 class GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
 
+class GrContext::AutoCheckFlush {
+public:
+    AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(NULL != context); }
+
+    ~AutoCheckFlush() {
+        if (fContext->fFlushToReduceCacheSize) {
+            fContext->flush();
+        }
+    }
+
+private:
+    GrContext* fContext;
+};
+
 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
     GrContext* context = SkNEW(GrContext);
     if (context->init(backend, backendContext)) {
@@ -101,6 +115,7 @@
     fDrawBuffer = NULL;
     fDrawBufferVBAllocPool = NULL;
     fDrawBufferIBAllocPool = NULL;
+    fFlushToReduceCacheSize = false;
     fAARectRenderer = NULL;
     fOvalRenderer = NULL;
     fViewMatrix.reset();
@@ -533,10 +548,8 @@
     GrContext* context = reinterpret_cast<GrContext*>(data);
 
     // Flush the InOrderDrawBuffer to possibly free up some textures
-    context->flush();
+    context->fFlushToReduceCacheSize = true;
 
-    // TODO: actually track flush's behavior rather than always just
-    // returning true.
     return true;
 }
 
@@ -606,7 +619,8 @@
                       const GrColor color,
                       GrRenderTarget* target) {
     AutoRestoreEffects are;
-    this->prepareToDraw(NULL, BUFFERED_DRAW, &are)->clear(rect, color, target);
+    AutoCheckFlush acf(this);
+    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->clear(rect, color, target);
 }
 
 void GrContext::drawPaint(const GrPaint& origPaint) {
@@ -755,7 +769,8 @@
     SK_TRACE_EVENT0("GrContext::drawRect");
 
     AutoRestoreEffects are;
-    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
+    AutoCheckFlush acf(this);
+    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
     SkMatrix combinedMatrix = target->drawState()->getViewMatrix();
     if (NULL != matrix) {
@@ -874,7 +889,8 @@
                                const SkMatrix* localMatrix) {
     SK_TRACE_EVENT0("GrContext::drawRectToRect");
     AutoRestoreEffects are;
-    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
+    AutoCheckFlush acf(this);
+    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
     target->drawRect(dstRect, dstMatrix, &localRect, localMatrix);
 }
@@ -930,7 +946,8 @@
     GrDrawTarget::AutoReleaseGeometry geo;
 
     AutoRestoreEffects are;
-    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
+    AutoCheckFlush acf(this);
+    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
     GrDrawState* drawState = target->drawState();
 
@@ -982,7 +999,8 @@
     }
 
     AutoRestoreEffects are;
-    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
+    AutoCheckFlush acf(this);
+    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
     bool useAA = paint.isAntiAlias() &&
                  !target->getDrawState().getRenderTarget()->isMultisampled() &&
@@ -1005,7 +1023,8 @@
     }
 
     AutoRestoreEffects are;
-    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
+    AutoCheckFlush acf(this);
+    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
     bool useAA = paint.isAntiAlias() &&
                  !target->getDrawState().getRenderTarget()->isMultisampled() &&
@@ -1088,7 +1107,8 @@
     // the writePixels that uploads to the scratch will perform a flush so we're
     // OK.
     AutoRestoreEffects are;
-    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
+    AutoCheckFlush acf(this);
+    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
     bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled();
     if (useAA && stroke.getWidth() < 0 && !path.isConvex()) {
@@ -1183,6 +1203,7 @@
     } else {
         fDrawBuffer->flush();
     }
+    fFlushToReduceCacheSize = false;
 }
 
 bool GrContext::writeTexturePixels(GrTexture* texture,
@@ -1590,7 +1611,8 @@
 
 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
                                        BufferedDraw buffered,
-                                       AutoRestoreEffects* are) {
+                                       AutoRestoreEffects* are,
+                                       AutoCheckFlush* acf) {
     // All users of this draw state should be freeing up all effects when they're done.
     // Otherwise effects that own resources may keep those resources alive indefinitely.
     SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
@@ -1602,6 +1624,7 @@
     ASSERT_OWNED_RESOURCE(fRenderTarget.get());
     if (NULL != paint) {
         SkASSERT(NULL != are);
+        SkASSERT(NULL != acf);
         are->set(fDrawState);
         fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
 #if GR_DEBUG_PARTIAL_COVERAGE_CHECK
@@ -1701,7 +1724,7 @@
 }
 
 GrDrawTarget* GrContext::getTextTarget() {
-    return this->prepareToDraw(NULL, BUFFERED_DRAW, NULL);
+    return this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL);
 }
 
 const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {