Cleanup GrDrawTarget now that all paths lead to GrBatch

Review URL: https://codereview.chromium.org/1315513008
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 0e7e6bc..7eaa8bc 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -36,7 +36,8 @@
     : fGpu(SkRef(gpu))
     , fCaps(SkRef(gpu->caps()))
     , fResourceProvider(resourceProvider)
-    , fFlushing(false) {
+    , fFlushing(false)
+    , fLastFlushToken(0) {
 }
 
 GrDrawTarget::~GrDrawTarget() {
@@ -119,12 +120,31 @@
     }
     fFlushing = true;
 
-    this->onFlush();
+    GrBatchFlushState flushState(fGpu, fResourceProvider, fLastFlushToken);
+
+    // Loop over all batches and generate geometry
+    for (int i = 0; i < fBatches.count(); ++i) {
+        fBatches[i]->prepare(&flushState);
+    }
+
+    // Upload all data to the GPU
+    flushState.preIssueDraws();
+
+    // Draw all the generated geometry.
+    for (int i = 0; i < fBatches.count(); ++i) {
+        fBatches[i]->draw(&flushState);
+    }
+
+    fLastFlushToken = flushState.lastFlushedToken();
 
     fFlushing = false;
     this->reset();
 }
 
+void GrDrawTarget::reset() {
+    fBatches.reset();
+}
+
 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
     // Setup clip
     GrScissorState scissorState;
@@ -148,7 +168,7 @@
     if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) {
         return;
     }
-    this->onDrawBatch(batch);
+    this->recordBatch(batch);
 }
 
 static const GrStencilSettings& winding_path_stencil_settings() {
@@ -213,7 +233,7 @@
                                                 stencilSettings, scissorState,
                                                 pipelineBuilder.getRenderTarget(),
                                                 path);
-    this->onDrawBatch(batch);
+    this->recordBatch(batch);
     batch->unref();
 }
 
@@ -269,7 +289,7 @@
         return;
     }
 
-    this->onDrawBatch(batch);
+    this->recordBatch(batch);
 }
 
 void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
@@ -344,7 +364,7 @@
         this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect);
     } else {
         GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
-        this->onDrawBatch(batch);
+        this->recordBatch(batch);
         batch->unref();
     }
 }
@@ -352,7 +372,7 @@
 void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
     if (this->caps()->discardRenderTargetSupport()) {
         GrBatch* batch = new GrDiscardBatch(renderTarget);
-        this->onDrawBatch(batch);
+        this->recordBatch(batch);
         batch->unref();
     }
 }
@@ -365,11 +385,67 @@
                                const SkIPoint& dstPoint) {
     GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
     if (batch) {
-        this->onDrawBatch(batch);
+        this->recordBatch(batch);
         batch->unref();
     }
 }
 
+template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
+    SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
+             b.fLeft <= b.fRight && b.fTop <= b.fBottom);
+    return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
+}
+
+void GrDrawTarget::recordBatch(GrBatch* batch) {
+    // Check if there is a Batch Draw we can batch with by linearly searching back until we either
+    // 1) check every draw
+    // 2) intersect with something
+    // 3) find a 'blocker'
+    // Experimentally we have found that most batching occurs within the first 10 comparisons.
+    static const int kMaxLookback = 10;
+
+    GrBATCH_INFO("Re-Recording (%s, B%u)\n"
+        "\tBounds (%f, %f, %f, %f)\n",
+        batch->name(),
+        batch->uniqueID(),
+        batch->bounds().fLeft, batch->bounds().fRight,
+        batch->bounds().fTop, batch->bounds().fBottom);
+    GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
+    GrBATCH_INFO("\tOutcome:\n");    
+    int maxCandidates = SkTMin(kMaxLookback, fBatches.count());
+    if (maxCandidates) {
+        int i = 0;
+        while (true) {
+            GrBatch* candidate = fBatches.fromBack(i);
+            // We cannot continue to search backwards if the render target changes
+            if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
+                GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
+                    candidate->name(), candidate->uniqueID());
+                break;
+            }
+            if (candidate->combineIfPossible(batch, *this->caps())) {
+                GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
+                    candidate->uniqueID());
+                return;
+            }
+            // Stop going backwards if we would cause a painter's order violation.
+            if (intersect(candidate->bounds(), batch->bounds())) {
+                GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
+                    candidate->uniqueID());
+                break;
+            }
+            ++i;
+            if (i == maxCandidates) {
+                GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
+                break;
+            }
+        }
+    } else {
+        GrBATCH_INFO("\t\tFirstBatch\n");
+    }
+    fBatches.push_back().reset(SkRef(batch));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 GrDrawTarget::PipelineInfo::PipelineInfo(const GrPipelineBuilder* pipelineBuilder,
@@ -416,6 +492,6 @@
 
 void GrClipTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
     GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
-    this->onDrawBatch(batch);
+    this->recordBatch(batch);
     batch->unref();
 }