Add immediate mode option for gpu configs in dm

Review URL: https://codereview.chromium.org/1421853002
diff --git a/dm/DMGpuSupport.h b/dm/DMGpuSupport.h
index 9e10231..b170a36 100644
--- a/dm/DMGpuSupport.h
+++ b/dm/DMGpuSupport.h
@@ -55,7 +55,9 @@
     void dumpGpuStats(SkString*) const {}
 };
 
-struct GrContextOptions {};
+struct GrContextOptions {
+    bool fImmediateMode;
+};
 
 class GrContextFactory {
 public:
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 9a61b02..cf9a6a2 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -917,8 +917,13 @@
 
 void PreAbandonGpuContextErrorHandler(SkError, void*) {}
 
+DEFINE_bool(imm, false, "Run gpu configs in immediate mode.");
+
 Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
     GrContextOptions options;
+    if (FLAGS_imm) {
+        options.fImmediateMode = true;
+    }
     src.modifyGrContextOptions(&options);
 
     GrContextFactory factory(options);
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 7136ce4..1a2d9e6 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -413,7 +413,7 @@
     bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
 
     void initMockContext();
-    void initCommon();
+    void initCommon(const GrContextOptions& options);
 
     /**
      * These functions create premul <-> unpremul effects if it is possible to generate a pair
diff --git a/include/gpu/GrContextOptions.h b/include/gpu/GrContextOptions.h
index 7c723a8..6b93927 100644
--- a/include/gpu/GrContextOptions.h
+++ b/include/gpu/GrContextOptions.h
@@ -18,7 +18,8 @@
         , fMinTextureSizeOverride(0)
         , fSuppressDualSourceBlending(false)
         , fGeometryBufferMapThreshold(-1)
-        , fUseDrawInsteadOfPartialRenderTargetWrite(false) {}
+        , fUseDrawInsteadOfPartialRenderTargetWrite(false)
+        , fImmediateMode(false) {}
 
     // EXPERIMENTAL
     // May be removed in the future, or may become standard depending
@@ -43,6 +44,10 @@
 
     /** some gpus have problems with partial writes of the rendertarget */
     bool fUseDrawInsteadOfPartialRenderTargetWrite;
+
+    /** The GrContext operates in immedidate mode. It will issue all draws to the backend API
+        immediately. Intended to ease debugging. */
+    bool fImmediateMode;
 };
 
 #endif
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 2ca3461..fee92fe 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -74,11 +74,11 @@
     if (!fGpu) {
         return false;
     }
-    this->initCommon();
+    this->initCommon(options);
     return true;
 }
 
-void GrContext::initCommon() {
+void GrContext::initCommon(const GrContextOptions& options) {
     fCaps = SkRef(fGpu->caps());
     fResourceCache = new GrResourceCache(fCaps);
     fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
@@ -88,7 +88,9 @@
 
     fDidTestPMConversions = false;
 
-    fDrawingManager.reset(new GrDrawingManager(this));
+    GrDrawTarget::Options dtOptions;
+    dtOptions.fImmediateMode = options.fImmediateMode;
+    fDrawingManager.reset(new GrDrawingManager(this, dtOptions));
 
     // GrBatchFontCache will eventually replace GrFontCache
     fBatchFontCache = new GrBatchFontCache(this);
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index f42ee11..1dc26bc 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -32,13 +32,15 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider)
+GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider,
+                           const Options& options)
     : fGpu(SkRef(gpu))
     , fResourceProvider(resourceProvider)
     , fFlushState(fGpu, fResourceProvider, 0)
     , fFlushing(false)
     , fFirstUnpreparedBatch(0)
-    , fFlags(0) {
+    , fFlags(0)
+    , fOptions(options) {
     // TODO: Stop extracting the context (currently needed by GrClipMaskManager)
     fContext = fGpu->getContext();
     fClipMaskManager.reset(new GrClipMaskManager(this));
@@ -472,6 +474,8 @@
 void GrDrawTarget::recordBatch(GrBatch* batch) {
     // A closed drawTarget should never receive new/more batches
     SkASSERT(!this->isClosed());
+    // Should never have batches queued up when in immediate mode.
+    SkASSERT(!fOptions.fImmediateMode || !fBatches.count());
 
     // Check if there is a Batch Draw we can batch with by linearly searching back until we either
     // 1) check every draw
@@ -524,6 +528,9 @@
         SkASSERT(fBatches.count() - kMaxLookback - fFirstUnpreparedBatch == 1);
         fBatches[fFirstUnpreparedBatch++]->prepare(&fFlushState);
     }
+    if (fOptions.fImmediateMode) {
+        this->flush();
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index ec94da1..a487785 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -43,9 +43,13 @@
 
 class GrDrawTarget final : public SkRefCnt {
 public:
+    struct Options {
+        bool fImmediateMode;
+    };
+
     // The context may not be fully constructed and should not be used during GrDrawTarget
     // construction.
-    GrDrawTarget(GrGpu* gpu, GrResourceProvider*);
+    GrDrawTarget(GrGpu* gpu, GrResourceProvider*, const Options& options);
 
     ~GrDrawTarget() override;
 
@@ -221,7 +225,6 @@
 
     const CMMAccess cmmAccess() { return CMMAccess(this); }
 
-
 private:
     friend class GrDrawingManager; // for resetFlag & TopoSortTraits
 
@@ -311,6 +314,7 @@
 
     SkDEBUGCODE(int                             fDebugID;)
     uint32_t                                    fFlags;
+    Options                                     fOptions;
 
     // 'this' drawTarget relies on the output of the drawTargets in 'fDependencies'
     SkTDArray<GrDrawTarget*>                    fDependencies;
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 682b155..0dbd476 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -105,7 +105,8 @@
     }
 #endif
 
-    GrDrawTarget* dt = new GrDrawTarget(fContext->getGpu(), fContext->resourceProvider());
+    GrDrawTarget* dt = new GrDrawTarget(fContext->getGpu(), fContext->resourceProvider(),
+                                        fOptions);
 
     *fDrawTargets.append() = dt;
 
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index d799493..be21d68 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -8,6 +8,7 @@
 #ifndef GrDrawingManager_DEFINED
 #define GrDrawingManager_DEFINED
 
+#include "GrDrawTarget.h"
 #include "SkTDArray.h"
 
 class GrContext;
@@ -40,9 +41,10 @@
     GrContext* getContext() { return fContext; }
 
 private:
-    GrDrawingManager(GrContext* context)
+    GrDrawingManager(GrContext* context, GrDrawTarget::Options options)
         : fContext(context)
         , fAbandoned(false)
+        , fOptions(options)
         , fNVPRTextContext(nullptr) {
         sk_bzero(fTextContexts, sizeof(fTextContexts));
     }
@@ -57,13 +59,14 @@
     static const int kNumPixelGeometries = 5; // The different pixel geometries
     static const int kNumDFTOptions = 2;      // DFT or no DFT
 
-    GrContext*        fContext;
+    GrContext*                  fContext;
 
-    bool              fAbandoned;
-    SkTDArray<GrDrawTarget*> fDrawTargets;
+    bool                        fAbandoned;
+    SkTDArray<GrDrawTarget*>    fDrawTargets;
+    GrDrawTarget::Options       fOptions;
 
-    GrTextContext*    fNVPRTextContext;
-    GrTextContext*    fTextContexts[kNumPixelGeometries][kNumDFTOptions];
+    GrTextContext*              fNVPRTextContext;
+    GrTextContext*              fTextContexts[kNumPixelGeometries][kNumDFTOptions];
 };
 
 #endif
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index aafb0b9..4adc3f7 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -288,7 +288,7 @@
     SkASSERT(nullptr == fGpu);
     fGpu = new MockGpu(this, options);
     SkASSERT(fGpu);
-    this->initCommon();
+    this->initCommon(options);
 
     // We delete these because we want to test the cache starting with zero resources. Also, none of
     // these objects are required for any of tests that use this context. TODO: make stop allocating