Add GrOpList and rename GrDrawTarget to GrRenderTargetOpList

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3910

Change-Id: I026aa26ecc61a0d002e98892dca728536259e8b1
Reviewed-on: https://skia-review.googlesource.com/3910
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 3a2ad20..315de8b 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -101,8 +101,6 @@
       '<(skia_src_path)/gpu/GrPathRenderingDrawContext.h',
       '<(skia_src_path)/gpu/GrDrawingManager.cpp',
       '<(skia_src_path)/gpu/GrDrawingManager.h',
-      '<(skia_src_path)/gpu/GrDrawTarget.cpp',
-      '<(skia_src_path)/gpu/GrDrawTarget.h',
       '<(skia_src_path)/gpu/GrFixedClip.cpp',
       '<(skia_src_path)/gpu/GrFixedClip.h',
       '<(skia_src_path)/gpu/GrFragmentProcessor.cpp',
@@ -124,6 +122,8 @@
       '<(skia_src_path)/gpu/GrMemoryPool.h',
       '<(skia_src_path)/gpu/GrMesh.h',
       '<(skia_src_path)/gpu/GrNonAtomicRef.h',
+      '<(skia_src_path)/gpu/GrOpList.cpp',
+      '<(skia_src_path)/gpu/GrOpList.h',
       '<(skia_src_path)/gpu/GrOvalRenderer.cpp',
       '<(skia_src_path)/gpu/GrOvalRenderer.h',
       '<(skia_src_path)/gpu/GrPaint.cpp',
@@ -168,6 +168,8 @@
       '<(skia_src_path)/gpu/GrRenderTargetProxy.cpp',
       '<(skia_src_path)/gpu/GrReducedClip.cpp',
       '<(skia_src_path)/gpu/GrReducedClip.h',
+      '<(skia_src_path)/gpu/GrRenderTargetOpList.cpp',
+      '<(skia_src_path)/gpu/GrRenderTargetOpList.h',
       '<(skia_src_path)/gpu/GrResourceCache.cpp',
       '<(skia_src_path)/gpu/GrResourceCache.h',
       '<(skia_src_path)/gpu/GrResourceHandle.h',
diff --git a/include/gpu/GrDrawContext.h b/include/gpu/GrDrawContext.h
index 72de15d..6e9056d 100644
--- a/include/gpu/GrDrawContext.h
+++ b/include/gpu/GrDrawContext.h
@@ -24,12 +24,12 @@
 class GrDrawContextPriv;
 class GrDrawPathBatchBase;
 class GrDrawingManager;
-class GrDrawTarget;
 class GrFixedClip;
 class GrPaint;
 class GrPathProcessor;
 class GrPipelineBuilder;
 class GrRenderTarget;
+class GrRenderTargetOpList;
 class GrStyle;
 class GrSurface;
 struct GrUserStencilSettings;
@@ -366,7 +366,7 @@
 
     friend class GrDrawingManager; // for ctor
     friend class GrDrawContextPriv;
-    friend class GrTestTarget;  // for access to getDrawTarget
+    friend class GrTestTarget;  // for access to getOpList
     friend class GrSWMaskHelper;                 // for access to drawBatch
 
     // All the path renderers currently make their own batches
@@ -412,17 +412,17 @@
                           const GrStyle& style);
 
     // This entry point allows the GrTextContext-derived classes to add their batches to
-    // the drawTarget.
+    // the GrOpList.
     void drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip&, GrDrawBatch* batch);
 
-    GrDrawTarget* getDrawTarget();
+    GrRenderTargetOpList* getOpList();
 
     GrDrawingManager*                 fDrawingManager;
     sk_sp<GrRenderTarget>             fRenderTarget;
 
-    // In MDB-mode the drawTarget can be closed by some other drawContext that has picked
-    // it up. For this reason, the drawTarget should only ever be accessed via 'getDrawTarget'.
-    GrDrawTarget*                     fDrawTarget;
+    // In MDB-mode the GrOpList can be closed by some other drawContext that has picked
+    // it up. For this reason, the GrOpList should only ever be accessed via 'getOpList'.
+    GrRenderTargetOpList*             fOpList;
     GrContext*                        fContext;
     GrInstancedPipelineInfo           fInstancedPipelineInfo;
 
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 364a886..d3cfa86 100644
--- a/include/gpu/GrGpuResource.h
+++ b/include/gpu/GrGpuResource.h
@@ -23,7 +23,7 @@
  *
  * Gpu resources can have three types of refs:
  *   1) Normal ref (+ by ref(), - by unref()): These are used by code that is issuing draw calls
- *      that read and write the resource via GrDrawTarget and by any object that must own a
+ *      that read and write the resource via GrOpList and by any object that must own a
  *      GrGpuResource and is itself owned (directly or indirectly) by Skia-client code.
  *   2) Pending read (+ by addPendingRead(), - by completedRead()): GrContext has scheduled a read
  *      of the resource by the GPU as a result of a skia API call but hasn't executed it yet.
diff --git a/include/gpu/GrGpuResourceRef.h b/include/gpu/GrGpuResourceRef.h
index 4511adc..13adbee 100644
--- a/include/gpu/GrGpuResourceRef.h
+++ b/include/gpu/GrGpuResourceRef.h
@@ -63,7 +63,7 @@
         execution. It can only be called once. */
     void markPendingIO() const;
 
-    /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code.
+    /** Called when the program element/draw state is no longer owned by GrOpList-client code.
         This lets the cache know that the drawing code will no longer schedule additional reads or
         writes to the resource using the program element or draw state. It can only be called once.
       */
diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h
index 1f87787..445846f 100644
--- a/include/gpu/GrRenderTarget.h
+++ b/include/gpu/GrRenderTarget.h
@@ -12,9 +12,9 @@
 #include "SkRect.h"
 
 class GrCaps;
-class GrDrawTarget;
-class GrStencilAttachment;
+class GrRenderTargetOpList;
 class GrRenderTargetPriv;
+class GrStencilAttachment;
 
 /**
  * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.
@@ -115,8 +115,9 @@
     GrRenderTargetPriv renderTargetPriv();
     const GrRenderTargetPriv renderTargetPriv() const;
 
-    void setLastDrawTarget(GrDrawTarget* dt);
-    GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
+    GrRenderTargetOpList* getLastRenderTargetOpList() {
+        return (GrRenderTargetOpList*) this->getLastOpList();
+    }
 
 protected:
     enum class Flags {
@@ -129,7 +130,6 @@
 
     GrRenderTarget(GrGpu*, const GrSurfaceDesc&, Flags = Flags::kNone,
                    GrStencilAttachment* = nullptr);
-    ~GrRenderTarget() override;
 
     // override of GrResource
     void onAbandon() override;
@@ -150,14 +150,6 @@
 
     SkIRect               fResolveRect;
 
-    // The last drawTarget that wrote to or is currently going to write to this renderTarget
-    // The drawTarget can be closed (e.g., no draw context is currently bound
-    // to this renderTarget).
-    // This back-pointer is required so that we can add a dependancy between
-    // the drawTarget used to create the current contents of this renderTarget
-    // and the drawTarget of a destination renderTarget to which this one is being drawn.
-    GrDrawTarget* fLastDrawTarget;
-
     typedef GrSurface INHERITED;
 };
 
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index ac5c5fa..0ac4bf3 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -14,6 +14,7 @@
 #include "SkImageInfo.h"
 #include "SkRect.h"
 
+class GrOpList;
 class GrRenderTarget;
 class GrSurfacePriv;
 class GrTexture;
@@ -127,6 +128,9 @@
 
     static size_t WorstCaseSize(const GrSurfaceDesc& desc);
 
+    void setLastOpList(GrOpList* opList);
+    GrOpList* getLastOpList() { return fLastOpList; }
+
 protected:
     // Methods made available via GrSurfacePriv
     bool savePixels(const char* filename);
@@ -142,12 +146,9 @@
         , fDesc(desc)
         , fReleaseProc(NULL)
         , fReleaseCtx(NULL)
-    {}
-
-    ~GrSurface() override {
-        // check that invokeReleaseProc has been called (if needed)
-        SkASSERT(NULL == fReleaseProc);
+        , fLastOpList(nullptr) {
     }
+    ~GrSurface() override;
 
     GrSurfaceDesc fDesc;
 
@@ -165,6 +166,14 @@
     ReleaseProc fReleaseProc;
     ReleaseCtx  fReleaseCtx;
 
+    // The last opList that wrote to or is currently going to write to this surface
+    // The opList can be closed (e.g., no draw or copy context is currently bound
+    // to this renderTarget or texture).
+    // This back-pointer is required so that we can add a dependancy between
+    // the opList used to create the current contents of this surface
+    // and the opList of a destination surface to which this one is being drawn or copied.
+    GrOpList* fLastOpList;
+
     typedef GrGpuResource INHERITED;
 };
 
diff --git a/include/private/GrRenderTargetProxy.h b/include/private/GrRenderTargetProxy.h
index e4bc70f..59fed59 100644
--- a/include/private/GrRenderTargetProxy.h
+++ b/include/private/GrRenderTargetProxy.h
@@ -28,8 +28,6 @@
                                            SkBackingFit, SkBudgeted);
     static sk_sp<GrRenderTargetProxy> Make(const GrCaps&, sk_sp<GrRenderTarget>);
 
-    ~GrRenderTargetProxy() override;
-
     // TODO: add asTextureProxy variants
     GrRenderTargetProxy* asRenderTargetProxy() override { return this; }
     const GrRenderTargetProxy* asRenderTargetProxy() const override { return this; }
@@ -60,9 +58,6 @@
      */
     int numColorSamples() const { return this->isMixedSampled() ? 0 : fDesc.fSampleCnt; }
 
-    void setLastDrawTarget(GrDrawTarget* dt);
-    GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
-
     GrRenderTargetPriv::Flags testingOnly_getFlags() const;
 
 private:
@@ -83,14 +78,6 @@
     // rendertarget's info here.
     GrRenderTargetPriv::Flags   fFlags;
 
-    // The last drawTarget that wrote to or is currently going to write to this renderTarget
-    // The drawTarget can be closed (e.g., no draw context is currently bound
-    // to this renderTarget).
-    // This back-pointer is required so that we can add a dependancy between
-    // the drawTarget used to create the current contents of this renderTarget
-    // and the drawTarget of a destination renderTarget to which this one is being drawn.
-    GrDrawTarget* fLastDrawTarget;
-
     typedef GrSurfaceProxy INHERITED;
 };
 
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 69656fe..4e2ad3b 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -11,6 +11,7 @@
 #include "GrGpuResource.h"
 #include "SkRect.h"
 
+class GrOpList;
 class GrTextureProxy;
 class GrRenderTargetProxy;
 
@@ -51,13 +52,17 @@
      */
     SkBudgeted isBudgeted() const { return fBudgeted; }
 
+    void setLastOpList(GrOpList* opList);
+    GrOpList* getLastOpList() { return fLastOpList; }
+
 protected:
     // Deferred version
     GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted)
         : fDesc(desc)
         , fFit(fit)
         , fBudgeted(budgeted)
-        , fUniqueID(GrGpuResource::CreateUniqueID()) {
+        , fUniqueID(GrGpuResource::CreateUniqueID())
+        , fLastOpList(nullptr) {
     }
 
     // Wrapped version
@@ -66,10 +71,12 @@
         : fDesc(desc)
         , fFit(fit)
         , fBudgeted(budgeted)
-        , fUniqueID(uniqueID) {
+        , fUniqueID(uniqueID)
+        , fLastOpList(nullptr) {
     }
 
-    virtual ~GrSurfaceProxy() {}
+    virtual ~GrSurfaceProxy();
+
 
     // For wrapped resources, 'fDesc' will always be filled in from the wrapped resource.
     const GrSurfaceDesc fDesc;
@@ -83,6 +90,14 @@
     void notifyAllCntsAreZero(CntType) const { delete this; }
     bool notifyRefCountIsZero() const { return true; }
 
+    // The last opList that wrote to or is currently going to write to this surface
+    // The opList can be closed (e.g., no draw context is currently bound
+    // to this renderTarget).
+    // This back-pointer is required so that we can add a dependancy between
+    // the opList used to create the current contents of this surface
+    // and the opList of a destination surface to which this one is being drawn or copied.
+    GrOpList* fLastOpList;
+
     typedef GrIORef<GrSurfaceProxy> INHERITED;
 
     // to access notifyAllCntsAreZero and notifyRefCntIsZero.
diff --git a/src/core/SkTTopoSort.h b/src/core/SkTTopoSort.h
index 35b85ee..21c8069 100644
--- a/src/core/SkTTopoSort.h
+++ b/src/core/SkTTopoSort.h
@@ -76,7 +76,7 @@
 //
 // TODO: potentially add a version that takes a seed node and just outputs that
 // node and all the nodes on which it depends. This could be used to partially
-// flush a drawTarget DAG.
+// flush a GrOpList DAG.
 template <typename T, typename Traits = T>
 bool SkTTopoSort(SkTDArray<T*>* graph) {
     SkTDArray<T*> result;
diff --git a/src/gpu/GrBatchFlushState.h b/src/gpu/GrBatchFlushState.h
index 89c5292..794bc60 100644
--- a/src/gpu/GrBatchFlushState.h
+++ b/src/gpu/GrBatchFlushState.h
@@ -15,7 +15,7 @@
 class GrGpuCommandBuffer;
 class GrResourceProvider;
 
-/** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
+/** Tracks the state across all the GrBatches in a GrOpList flush. */
 class GrBatchFlushState {
 public:
     GrBatchFlushState(GrGpu*, GrResourceProvider*);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 176d5da..a0884f9 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -90,17 +90,17 @@
 
     fDidTestPMConversions = false;
 
-    GrDrawTarget::Options dtOptions;
-    dtOptions.fClipBatchToBounds = options.fClipBatchToBounds;
-    dtOptions.fDrawBatchBounds = options.fDrawBatchBounds;
-    dtOptions.fMaxBatchLookback = options.fMaxBatchLookback;
-    dtOptions.fMaxBatchLookahead = options.fMaxBatchLookahead;
+    GrRenderTargetOpList::Options rtOpListOptions;
+    rtOpListOptions.fClipBatchToBounds = options.fClipBatchToBounds;
+    rtOpListOptions.fDrawBatchBounds = options.fDrawBatchBounds;
+    rtOpListOptions.fMaxBatchLookback = options.fMaxBatchLookback;
+    rtOpListOptions.fMaxBatchLookahead = options.fMaxBatchLookahead;
     GrPathRendererChain::Options prcOptions;
     prcOptions.fDisableDistanceFieldRenderer = options.fDisableDistanceFieldPaths;
     prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
     prcOptions.fDisableAllPathRenderers = options.fForceSWPathMasks;
-    fDrawingManager.reset(new GrDrawingManager(this, dtOptions, prcOptions, options.fImmediateMode,
-                                               &fSingleOwner));
+    fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions,
+                                               options.fImmediateMode, &fSingleOwner));
 
     // GrBatchFontCache will eventually replace GrFontCache
     fBatchFontCache = new GrBatchFontCache(this);
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 3060062..54de4f0 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -69,10 +69,10 @@
     return fDrawingManager->wasAbandoned();
 }
 
-// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
-// drawTargets to be picked up and added to by drawContexts lower in the call
-// stack. When this occurs with a closed drawTarget, a new one will be allocated
-// when the drawContext attempts to use it (via getDrawTarget).
+// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
+// GrOpLists to be picked up and added to by drawContexts lower in the call
+// stack. When this occurs with a closed GrOpList, a new one will be allocated
+// when the drawContext attempts to use it (via getOpList).
 GrDrawContext::GrDrawContext(GrContext* context,
                              GrDrawingManager* drawingMgr,
                              sk_sp<GrRenderTarget> rt,
@@ -82,7 +82,7 @@
                              GrSingleOwner* singleOwner)
     : fDrawingManager(drawingMgr)
     , fRenderTarget(std::move(rt))
-    , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
+    , fOpList(SkSafeRef(fRenderTarget->getLastRenderTargetOpList()))
     , fContext(context)
     , fInstancedPipelineInfo(fRenderTarget.get())
     , fColorSpace(std::move(colorSpace))
@@ -106,26 +106,26 @@
     SkASSERT(fRenderTarget);
     ASSERT_OWNED_RESOURCE(fRenderTarget);
 
-    if (fDrawTarget && !fDrawTarget->isClosed()) {
-        SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
+    if (fOpList && !fOpList->isClosed()) {
+        SkASSERT(fRenderTarget->getLastOpList() == fOpList);
     }
 }
 #endif
 
 GrDrawContext::~GrDrawContext() {
     ASSERT_SINGLE_OWNER
-    SkSafeUnref(fDrawTarget);
+    SkSafeUnref(fOpList);
 }
 
-GrDrawTarget* GrDrawContext::getDrawTarget() {
+GrRenderTargetOpList* GrDrawContext::getOpList() {
     ASSERT_SINGLE_OWNER
     SkDEBUGCODE(this->validate();)
 
-    if (!fDrawTarget || fDrawTarget->isClosed()) {
-        fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
+    if (!fOpList || fOpList->isClosed()) {
+        fOpList = fDrawingManager->newOpList(fRenderTarget.get());
     }
 
-    return fDrawTarget;
+    return fOpList;
 }
 
 bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
@@ -134,7 +134,7 @@
     SkDEBUGCODE(this->validate();)
     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
 
-    return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
+    return this->getOpList()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
 }
 
 void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
@@ -191,7 +191,7 @@
     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
 
     AutoCheckFlush acf(fDrawingManager);
-    this->getDrawTarget()->discard(fRenderTarget.get());
+    this->getOpList()->discard(fRenderTarget.get());
 }
 
 void GrDrawContext::clear(const SkIRect* rect,
@@ -245,13 +245,13 @@
 
         this->drawRect(clip, paint, SkMatrix::I(), clearRect);
     } else if (isFull) {
-        this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
+        this->getOpList()->fullClear(this->accessRenderTarget(), color);
     } else {
         sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget()));
         if (!batch) {
             return;
         }
-        this->getDrawTarget()->addBatch(std::move(batch));
+        this->getOpList()->addBatch(std::move(batch));
     }
 }
 
@@ -396,7 +396,7 @@
     bool useHWAA;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
-        InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
+        InstancedRendering* ir = this->getOpList()->instancedRendering();
         batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
                                    paint.isAntiAlias(), fInstancedPipelineInfo,
                                    &useHWAA));
@@ -405,7 +405,7 @@
             if (ss) {
                 pipelineBuilder.setUserStencil(ss);
             }
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return true;
         }
     }
@@ -423,7 +423,7 @@
                 if (ss) {
                     pipelineBuilder.setUserStencil(ss);
                 }
-                this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+                this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
                 return true;
             }
         }
@@ -549,7 +549,7 @@
                                          snapToPixelCenters);
             }
 
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return;
         }
     }
@@ -567,15 +567,15 @@
     GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
 
     AutoCheckFlush acf(fDrawContext->fDrawingManager);
-    fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask,
-                                                    fDrawContext->accessRenderTarget());
+    fDrawContext->getOpList()->clearStencilClip(clip, insideStencilMask,
+                                                fDrawContext->accessRenderTarget());
 }
 
 void GrDrawContextPriv::stencilPath(const GrClip& clip, 
                                     bool useHWAA,
                                     const SkMatrix& viewMatrix,
                                     const GrPath* path) {
-    fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
+    fDrawContext->getOpList()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
 }
 
 void GrDrawContextPriv::stencilRect(const GrClip& clip,
@@ -646,13 +646,13 @@
     bool useHWAA;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
-        InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
+        InstancedRendering* ir = this->getOpList()->instancedRendering();
         SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
                                                        croppedLocalRect, paint.isAntiAlias(),
                                                        fInstancedPipelineInfo, &useHWAA));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return;
         }
     }
@@ -705,13 +705,13 @@
     bool useHWAA;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
-        InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
+        InstancedRendering* ir = this->getOpList()->instancedRendering();
         SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
                                                        localMatrix, paint.isAntiAlias(),
                                                        fInstancedPipelineInfo, &useHWAA));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return;
         }
     }
@@ -726,7 +726,7 @@
         SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix,
                                                                   localMatrix, croppedRect));
         GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-        this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+        this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
         return;
     }
 
@@ -776,7 +776,7 @@
                                                             colors, texCoords, bounds));
 
     GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
-    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -799,7 +799,7 @@
                                                          xform, texRect, colors));
 
     GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
-    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -838,13 +838,13 @@
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
         stroke.isFillStyle()) {
-        InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
+        InstancedRendering* ir = this->getOpList()->instancedRendering();
         SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
                                                         paint.isAntiAlias(), fInstancedPipelineInfo,
                                                         &useHWAA));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, *clip, batch);
             return;
         }
     }
@@ -860,7 +860,7 @@
                                                                 shaderCaps));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, *clip, batch);
             return;
         }
     }
@@ -881,13 +881,13 @@
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
         bool useHWAA;
-        InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
+        InstancedRendering* ir = this->getOpList()->instancedRendering();
         SkAutoTUnref<GrDrawBatch> batch(ir->recordDRRect(origOuter, origInner, viewMatrix,
                                                          paintIn.getColor(), paintIn.isAntiAlias(),
                                                          fInstancedPipelineInfo, &useHWAA));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paintIn, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return true;
         }
     }
@@ -997,7 +997,7 @@
 
     SkAutoTUnref<GrDrawBatch> batch(GrRegionBatch::Create(paint.getColor(), viewMatrix, region));
     GrPipelineBuilder pipelineBuilder(paint, false);
-    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
 }
 
 void GrDrawContext::drawOval(const GrClip& clip,
@@ -1022,13 +1022,13 @@
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
         stroke.isFillStyle()) {
-        InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
+        InstancedRendering* ir = this->getOpList()->instancedRendering();
         SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
                                                        paint.isAntiAlias(), fInstancedPipelineInfo,
                                                        &useHWAA));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return;
         }
     }
@@ -1042,7 +1042,7 @@
                                                                         shaderCaps));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return;
         }
     }
@@ -1074,7 +1074,7 @@
                                                                        shaderCaps));
         if (batch) {
             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-            this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+            this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
             return;
         }
     }
@@ -1104,7 +1104,7 @@
                                                              std::move(iter), dst));
 
     GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
-    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
 }
 
 void GrDrawContext::prepareForExternalIO() {
@@ -1134,7 +1134,7 @@
     if (ss) {
         pipelineBuilder.setUserStencil(ss);
     }
-    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
 }
 
 bool GrDrawContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer, size_t dstRowBytes,
@@ -1246,7 +1246,7 @@
                     paint.getColor(), viewMatrix, rects));
                 if (batch) {
                     GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-                    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+                    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
                 }
                 return;
             }
@@ -1263,7 +1263,7 @@
                                                                             shaderCaps));
             if (batch) {
                 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
-                this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+                this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
                 return;
             }
         }
@@ -1433,5 +1433,5 @@
     SkDEBUGCODE(this->validate();)
     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
 
-    this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
+    this->getOpList()->drawBatch(pipelineBuilder, this, clip, batch);
 }
diff --git a/src/gpu/GrDrawContextPriv.h b/src/gpu/GrDrawContextPriv.h
index 63eae12..a48e468 100644
--- a/src/gpu/GrDrawContextPriv.h
+++ b/src/gpu/GrDrawContextPriv.h
@@ -9,7 +9,7 @@
 #define GrDrawContextPriv_DEFINED
 
 #include "GrDrawContext.h"
-#include "GrDrawTarget.h"
+#include "GrRenderTargetOpList.h"
 #include "GrPathRendering.h"
 
 class GrFixedClip;
@@ -22,7 +22,7 @@
 class GrDrawContextPriv {
 public:
     gr_instanced::InstancedRendering* accessInstancedRendering() const {
-        return fDrawContext->getDrawTarget()->instancedRendering();
+        return fDrawContext->getOpList()->instancedRendering();
     }
 
     void clear(const GrFixedClip&, const GrColor, bool canIgnoreClip);
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 5e9b68d..0fe173d 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -9,7 +9,6 @@
 
 #include "GrContext.h"
 #include "GrDrawContext.h"
-#include "GrDrawTarget.h"
 #include "GrPathRenderingDrawContext.h"
 #include "GrResourceProvider.h"
 #include "GrSoftwarePathRenderer.h"
@@ -17,25 +16,21 @@
 #include "SkSurface_Gpu.h"
 #include "SkTTopoSort.h"
 
-#include "instanced/InstancedRendering.h"
-
 #include "text/GrAtlasTextContext.h"
 #include "text/GrStencilAndCoverTextContext.h"
 
-using gr_instanced::InstancedRendering;
-
 void GrDrawingManager::cleanup() {
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        fDrawTargets[i]->makeClosed();  // no drawTarget should receive a new command after this
-        fDrawTargets[i]->clearRT();
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        fOpLists[i]->makeClosed();  // no opList should receive a new command after this
+        fOpLists[i]->clearTarget();
 
-        // We shouldn't need to do this, but it turns out some clients still hold onto drawtargets
+        // We shouldn't need to do this, but it turns out some clients still hold onto opLists
         // after a cleanup
-        fDrawTargets[i]->reset();
-        fDrawTargets[i]->unref();
+        fOpLists[i]->reset();
+        fOpLists[i]->unref();
     }
 
-    fDrawTargets.reset();
+    fOpLists.reset();
 
     delete fPathRendererChain;
     fPathRendererChain = nullptr;
@@ -48,11 +43,8 @@
 
 void GrDrawingManager::abandon() {
     fAbandoned = true;
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
-            InstancedRendering* ir = fDrawTargets[i]->instancedRendering();
-            ir->resetGpuResources(InstancedRendering::ResetType::kAbandon);
-        }
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        fOpLists[i]->abandonGpuResources();
     }
     this->cleanup();
 }
@@ -62,17 +54,14 @@
     delete fPathRendererChain;
     fPathRendererChain = nullptr;
     SkSafeSetNull(fSoftwarePathRenderer);
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
-            InstancedRendering* ir = fDrawTargets[i]->instancedRendering();
-            ir->resetGpuResources(InstancedRendering::ResetType::kDestroy);
-        }
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        fOpLists[i]->freeGpuResources();
     }
 }
 
 void GrDrawingManager::reset() {
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        fDrawTargets[i]->reset();
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        fOpLists[i]->reset();
     }
     fFlushState.reset();
 }
@@ -84,48 +73,48 @@
     fFlushing = true;
     bool flushed = false;
     SkDEBUGCODE(bool result =)
-                        SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
+                        SkTTopoSort<GrOpList, GrOpList::TopoSortTraits>(&fOpLists);
     SkASSERT(result);
 
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        fDrawTargets[i]->prepareBatches(&fFlushState);
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        fOpLists[i]->prepareBatches(&fFlushState);
     }
 
     // Enable this to print out verbose batching information
 #if 0
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        SkDEBUGCODE(fDrawTargets[i]->dump();)
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        SkDEBUGCODE(fOpLists[i]->dump();)
     }
 #endif
 
     // Upload all data to the GPU
     fFlushState.preIssueDraws();
 
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        if (fDrawTargets[i]->drawBatches(&fFlushState)) {
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        if (fOpLists[i]->drawBatches(&fFlushState)) {
             flushed = true;
         }
     }
 
     SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());
 
-    for (int i = 0; i < fDrawTargets.count(); ++i) {
-        fDrawTargets[i]->reset();
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        fOpLists[i]->reset();
 #ifdef ENABLE_MDB
-        fDrawTargets[i]->unref();
+        fOpLists[i]->unref();
 #endif
     }
 
 #ifndef ENABLE_MDB
-    // When MDB is disabled we keep reusing the same drawTarget
-    if (fDrawTargets.count()) {
-        SkASSERT(fDrawTargets.count() == 1);
+    // When MDB is disabled we keep reusing the same GrOpList
+    if (fOpLists.count()) {
+        SkASSERT(fOpLists.count() == 1);
         // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
         // won't bark
-        fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
+        fOpLists[0]->resetFlag(GrOpList::kWasOutput_Flag);
     }
 #else
-    fDrawTargets.reset();
+    fOpLists.reset();
 #endif
 
     fFlushState.reset();
@@ -153,28 +142,33 @@
     }
 }
 
-GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
+GrRenderTargetOpList* GrDrawingManager::newOpList(GrRenderTarget* rt) {
     SkASSERT(fContext);
 
 #ifndef ENABLE_MDB
-    // When MDB is disabled we always just return the single drawTarget
-    if (fDrawTargets.count()) {
-        SkASSERT(fDrawTargets.count() == 1);
-        // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
+    // When MDB is disabled we always just return the single GrOpList
+    if (fOpLists.count()) {
+        SkASSERT(fOpLists.count() == 1);
+        // In the non-MDB-world the same GrOpList gets reused for multiple render targets.
         // Update this pointer so all the asserts are happy
-        rt->setLastDrawTarget(fDrawTargets[0]);
+        rt->setLastOpList(fOpLists[0]);
         // DrawingManager gets the creation ref - this ref is for the caller
-        return SkRef(fDrawTargets[0]);
+
+        // TODO: although this is true right now it isn't cool
+        return SkRef((GrRenderTargetOpList*) fOpLists[0]);
     }
 #endif
 
-    GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
-                                        fContext->getAuditTrail(), fOptionsForDrawTargets);
+    GrRenderTargetOpList* opList = new GrRenderTargetOpList(rt,
+                                                            fContext->getGpu(),
+                                                            fContext->resourceProvider(),
+                                                            fContext->getAuditTrail(),
+                                                            fOptionsForOpLists);
 
-    *fDrawTargets.append() = dt;
+    *fOpLists.append() = opList;
 
     // DrawingManager gets the creation ref - this ref is for the caller
-    return SkRef(dt);
+    return SkRef(opList);
 }
 
 GrAtlasTextContext* GrDrawingManager::getAtlasTextContext() {
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 9fced38..838bb9b 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -9,23 +9,24 @@
 #define GrDrawingManager_DEFINED
 
 #include "text/GrAtlasTextContext.h"
-#include "GrDrawTarget.h"
 #include "GrBatchFlushState.h"
 #include "GrPathRendererChain.h"
 #include "GrPathRenderer.h"
+#include "GrRenderTargetOpList.h"
 #include "GrResourceCache.h"
 #include "SkTDArray.h"
 
+
 class GrContext;
 class GrDrawContext;
 class GrSingleOWner;
 class GrSoftwarePathRenderer;
 
 // The GrDrawingManager allocates a new GrDrawContext for each GrRenderTarget
-// but all of them still land in the same GrDrawTarget!
+// but all of them still land in the same GrOpList!
 //
 // In the future this class will allocate a new GrDrawContext for
-// each GrRenderTarget/GrDrawTarget and manage the DAG.
+// each GrRenderTarget/GrOpList and manage the DAG.
 class GrDrawingManager {
 public:
     ~GrDrawingManager();
@@ -37,9 +38,9 @@
                                          sk_sp<SkColorSpace>,
                                          const SkSurfaceProps*);
 
-    // The caller automatically gets a ref on the returned drawTarget. It must
+    // The caller automatically gets a ref on the returned opList. It must
     // be balanced by an unref call.
-    GrDrawTarget* newDrawTarget(GrRenderTarget* rt);
+    GrRenderTargetOpList* newOpList(GrRenderTarget* rt);
 
     GrContext* getContext() { return fContext; }
 
@@ -63,11 +64,12 @@
     void prepareSurfaceForExternalIO(GrSurface*);
 
 private:
-    GrDrawingManager(GrContext* context, const GrDrawTarget::Options& optionsForDrawTargets,
+    GrDrawingManager(GrContext* context,
+                     const GrRenderTargetOpList::Options& optionsForOpLists,
                      const GrPathRendererChain::Options& optionsForPathRendererChain,
                      bool isImmediateMode, GrSingleOwner* singleOwner)
         : fContext(context)
-        , fOptionsForDrawTargets(optionsForDrawTargets)
+        , fOptionsForOpLists(optionsForOpLists)
         , fOptionsForPathRendererChain(optionsForPathRendererChain)
         , fSingleOwner(singleOwner)
         , fAbandoned(false)
@@ -91,14 +93,14 @@
     static const int kNumDFTOptions = 2;      // DFT or no DFT
 
     GrContext*                        fContext;
-    GrDrawTarget::Options             fOptionsForDrawTargets;
+    GrRenderTargetOpList::Options     fOptionsForOpLists;
     GrPathRendererChain::Options      fOptionsForPathRendererChain;
 
     // In debug builds we guard against improper thread handling
     GrSingleOwner*                    fSingleOwner;
 
     bool                              fAbandoned;
-    SkTDArray<GrDrawTarget*>          fDrawTargets;
+    SkTDArray<GrOpList*>              fOpLists;
 
     SkAutoTDelete<GrAtlasTextContext> fAtlasTextContext;
 
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index b8703dc..ba7ed6f 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -331,7 +331,7 @@
     ResetTimestamp getResetTimestamp() const { return fResetTimestamp; }
 
     // Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst
-    // take place at the GrDrawTarget level and this function implement faster copy paths. The rect
+    // take place at the GrOpList level and this function implement faster copy paths. The rect
     // and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the
     // src/dst bounds and non-empty.
     bool copySurface(GrSurface* dst,
@@ -360,16 +360,16 @@
     // multisample information itself.
     const MultisampleSpecs& getMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&);
 
-    // Creates a GrGpuCommandBuffer in which the GrDrawTarget can send draw commands to instead of
+    // Creates a GrGpuCommandBuffer in which the GrOpList can send draw commands to instead of
     // directly to the Gpu object.
     virtual GrGpuCommandBuffer* createCommandBuffer(
             GrRenderTarget* target,
             const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
             const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) = 0;
 
-    // Called by drawtarget when flushing.
+    // Called by GrOpList when flushing.
     // Provides a hook for post-flush actions (e.g. PLS reset and Vulkan command buffer submits).
-    virtual void finishDrawTarget() {}
+    virtual void finishOpList() {}
 
     virtual GrFence SK_WARN_UNUSED_RESULT insertFence() const = 0;
     virtual bool waitFence(GrFence, uint64_t timeout = 1000) const = 0;
diff --git a/src/gpu/GrOpList.cpp b/src/gpu/GrOpList.cpp
new file mode 100644
index 0000000..ac7f1b2
--- /dev/null
+++ b/src/gpu/GrOpList.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrOpList.h"
+
+#include "GrRenderTarget.h"
+#include "GrRenderTargetOpList.h"
+#include "GrSurface.h"
+
+GrOpList::GrOpList(GrSurface* surface) 
+    : fFlags(0)
+    , fTarget(surface) {
+
+    surface->setLastOpList(this);
+
+#ifdef SK_DEBUG
+    static int debugID = 0;
+    fDebugID = debugID++;
+#endif
+}
+
+GrOpList::~GrOpList() {
+    if (fTarget && this == fTarget->getLastOpList()) {
+        fTarget->setLastOpList(nullptr);
+    }
+}
+
+// Add a GrOpList-based dependency
+void GrOpList::addDependency(GrOpList* dependedOn) {
+    SkASSERT(!dependedOn->dependsOn(this));  // loops are bad
+
+    if (this->dependsOn(dependedOn)) {
+        return;  // don't add duplicate dependencies
+    }
+
+    *fDependencies.push() = dependedOn;
+}
+
+// Convert from a GrSurface-based dependency to a GrOpList one
+void GrOpList::addDependency(GrSurface* dependedOn) {
+    if (dependedOn->getLastOpList()) {
+        // If it is still receiving dependencies, this GrOpList shouldn't be closed
+        SkASSERT(!this->isClosed());
+
+        GrOpList* opList = dependedOn->getLastOpList();
+        if (opList == this) {
+            // self-read - presumably for dst reads
+        } else {
+            this->addDependency(opList);
+
+            // Can't make it closed in the self-read case
+            opList->makeClosed();
+        }
+    }
+}
+
+#ifdef SK_DEBUG
+void GrOpList::dump() const {
+    SkDebugf("--------------------------------------------------------------\n");
+    SkDebugf("node: %d -> RT: %d\n", fDebugID, fTarget ? fTarget->uniqueID() : -1);
+    SkDebugf("relies On (%d): ", fDependencies.count());
+    for (int i = 0; i < fDependencies.count(); ++i) {
+        SkDebugf("%d, ", fDependencies[i]->fDebugID);
+    }
+    SkDebugf("\n");
+}
+#endif
diff --git a/src/gpu/GrOpList.h b/src/gpu/GrOpList.h
new file mode 100644
index 0000000..4af8512
--- /dev/null
+++ b/src/gpu/GrOpList.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrOpList_DEFINED
+#define GrOpList_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTDArray.h"
+
+//#define ENABLE_MDB 1
+
+class GrBatchFlushState;
+class GrSurface;
+
+class GrOpList : public SkRefCnt {
+public:
+    GrOpList(GrSurface* surface);
+    ~GrOpList() override;
+
+    virtual void prepareBatches(GrBatchFlushState* flushState) = 0;
+    virtual bool drawBatches(GrBatchFlushState* flushState) = 0;
+
+    virtual void makeClosed() {
+        // We only close GrOpLists when MDB is enabled. When MDB is disabled there is only
+        // ever one GrOpLists and all calls will be funnelled into it.
+#ifdef ENABLE_MDB
+        this->setFlag(kClosed_Flag);
+#endif    
+    }
+
+    // TODO: it seems a bit odd that GrOpList has nothing to clear on reset
+    virtual void reset() = 0;
+
+    // TODO: in an MDB world, where the OpLists don't allocate GPU resources, it seems like
+    // these could go away
+    virtual void abandonGpuResources() = 0;
+    virtual void freeGpuResources() = 0;
+
+    // TODO: this entry point is only needed in the non-MDB world. Remove when
+    // we make the switch to MDB
+    void clearTarget() { fTarget = nullptr; }
+
+    bool isClosed() const { return this->isSetFlag(kClosed_Flag); }
+
+    /*
+     * Notify this GrOpList that it relies on the contents of 'dependedOn'
+     */
+    void addDependency(GrSurface* dependedOn);
+
+    /*
+     * Does this opList depend on 'dependedOn'?
+     */
+    bool dependsOn(GrOpList* dependedOn) const {
+        return fDependencies.find(dependedOn) >= 0;
+    }
+
+    /*
+     * Dump out the GrOpList dependency DAG
+     */
+    SkDEBUGCODE(virtual void dump() const;)
+
+private:
+    friend class GrDrawingManager; // for resetFlag & TopoSortTraits
+
+    enum Flags {
+        kClosed_Flag    = 0x01,   //!< This GrOpList can't accept any more batches
+
+        kWasOutput_Flag = 0x02,   //!< Flag for topological sorting
+        kTempMark_Flag  = 0x04,   //!< Flag for topological sorting
+    };
+
+    void setFlag(uint32_t flag) {
+        fFlags |= flag;
+    }
+
+    void resetFlag(uint32_t flag) {
+        fFlags &= ~flag;
+    }
+
+    bool isSetFlag(uint32_t flag) const {
+        return SkToBool(fFlags & flag);
+    }
+
+    struct TopoSortTraits {
+        static void Output(GrOpList* dt, int /* index */) {
+            dt->setFlag(GrOpList::kWasOutput_Flag);
+        }
+        static bool WasOutput(const GrOpList* dt) {
+            return dt->isSetFlag(GrOpList::kWasOutput_Flag);
+        }
+        static void SetTempMark(GrOpList* dt) {
+            dt->setFlag(GrOpList::kTempMark_Flag);
+        }
+        static void ResetTempMark(GrOpList* dt) {
+            dt->resetFlag(GrOpList::kTempMark_Flag);
+        }
+        static bool IsTempMarked(const GrOpList* dt) {
+            return dt->isSetFlag(GrOpList::kTempMark_Flag);
+        }
+        static int NumDependencies(const GrOpList* dt) {
+            return dt->fDependencies.count();
+        }
+        static GrOpList* Dependency(GrOpList* dt, int index) {
+            return dt->fDependencies[index];
+        }
+    };
+
+    void addDependency(GrOpList* dependedOn);
+
+    SkDEBUGCODE(int                                 fDebugID;)
+    uint32_t                                        fFlags;
+    GrSurface*                                      fTarget;
+
+    // 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'
+    SkTDArray<GrOpList*>                            fDependencies;
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h
index 37cc3f9..3ac1814 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -22,7 +22,7 @@
 struct GrPoint;
 
 /**
- *  Base class for drawing paths into a GrDrawTarget.
+ *  Base class for drawing paths into a GrOpList.
  *
  *  Derived classes can use stages GrPaint::kTotalStages through GrPipelineBuilder::kNumStages-1.
  *  The stages before GrPaint::kTotalStages are reserved for setting up the draw (i.e., textures and
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index d9ebcf8..5e658fc 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -9,10 +9,10 @@
 
 #include "GrCaps.h"
 #include "GrDrawContext.h"
-#include "GrDrawTarget.h"
 #include "GrGpu.h"
 #include "GrPipelineBuilder.h"
 #include "GrProcOptInfo.h"
+#include "GrRenderTargetOpList.h"
 #include "GrRenderTargetPriv.h"
 #include "GrXferProcessor.h"
 
@@ -178,8 +178,8 @@
 static void add_dependencies_for_processor(const GrFragmentProcessor* proc, GrRenderTarget* rt) {
     GrFragmentProcessor::TextureAccessIter iter(proc);
     while (const GrTextureAccess* access = iter.next()) {
-        SkASSERT(rt->getLastDrawTarget());
-        rt->getLastDrawTarget()->addDependency(access->getTexture());
+        SkASSERT(rt->getLastOpList());
+        rt->getLastOpList()->addDependency(access->getTexture());
     }
 }
 
@@ -192,8 +192,8 @@
 
     for (int i = 0; i < xfer.numTextures(); ++i) {
         GrTexture* texture = xfer.textureAccess(i).getTexture();
-        SkASSERT(rt->getLastDrawTarget());
-        rt->getLastDrawTarget()->addDependency(texture);
+        SkASSERT(rt->getLastOpList());
+        rt->getLastOpList()->addDependency(texture);
     }
 }
 
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 845044f..6330de1 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -105,8 +105,8 @@
     ///////////////////////////////////////////////////////////////////////////
     /// @name GrFragmentProcessors
 
-    // Make the renderTarget's drawTarget (if it exists) be dependent on any
-    // drawTargets in this pipeline
+    // Make the renderTarget's GrOpList (if it exists) be dependent on any
+    // GrOpLists in this pipeline
     void addDependenciesTo(GrRenderTarget* rt) const;
 
     int numColorFragmentProcessors() const { return fNumColorProcessors; }
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 0c33eb3..cb69756 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -311,7 +311,10 @@
     FragmentProcessorArray                  fCoverageFragmentProcessors;
 
     friend class GrPipeline;
-    friend class GrDrawTarget;
+    // This gives the GrRenderTargetOpList raw access to fColorFragmentProcessors &
+    // fCoverageFragmentProcessors
+    // TODO: that access seems a little dodgy
+    friend class GrRenderTargetOpList;
 };
 
 #endif
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index 00b4df0..561f54b 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -171,7 +171,7 @@
     const Attribute& getAttrib(int index) const { return fAttribs[index]; }
 
     // Returns the vertex stride of the GP.  A common use case is to request geometry from a
-    // drawtarget based off of the stride, and to populate this memory using an implicit array of
+    // GrOpList based off of the stride, and to populate this memory using an implicit array of
     // structs.  In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
     size_t getVertexStride() const { return fVertexStride; }
 
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index 2053a16..d28b2b4 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -11,8 +11,8 @@
 #include "GrContext.h"
 #include "GrContextPriv.h"
 #include "GrDrawContext.h"
-#include "GrDrawTarget.h"
 #include "GrGpu.h"
+#include "GrRenderTargetOpList.h"
 #include "GrRenderTargetPriv.h"
 #include "GrStencilAttachment.h"
 
@@ -21,20 +21,12 @@
     : INHERITED(gpu, desc)
     , fStencilAttachment(stencil)
     , fMultisampleSpecsID(0)
-    , fFlags(flags)
-    , fLastDrawTarget(nullptr) {
+    , fFlags(flags) {
     SkASSERT(!(fFlags & Flags::kMixedSampled) || fDesc.fSampleCnt > 0);
     SkASSERT(!(fFlags & Flags::kWindowRectsSupport) || gpu->caps()->maxWindowRectangles() > 0);
     fResolveRect.setLargestInverted();
 }
 
-GrRenderTarget::~GrRenderTarget() {
-    if (fLastDrawTarget) {
-        fLastDrawTarget->clearRT();
-    }
-    SkSafeUnref(fLastDrawTarget);
-}
-
 void GrRenderTarget::discard() {
     // go through context so that all necessary flushing occurs
     GrContext* context = this->getContext();
@@ -85,24 +77,12 @@
     SkSafeSetNull(fStencilAttachment);
 
     // The contents of this renderTarget are gone/invalid. It isn't useful to point back
-    // the creating drawTarget.
-    this->setLastDrawTarget(nullptr);
+    // the creating opList.
+    this->setLastOpList(nullptr);
 
     INHERITED::onAbandon();
 }
 
-void GrRenderTarget::setLastDrawTarget(GrDrawTarget* dt) {
-    if (fLastDrawTarget) {
-        // The non-MDB world never closes so we can't check this condition
-#ifdef ENABLE_MDB
-        SkASSERT(fLastDrawTarget->isClosed());
-#endif
-        fLastDrawTarget->clearRT();
-    }
-
-    SkRefCnt_SafeAssign(fLastDrawTarget, dt);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 bool GrRenderTargetPriv::attachStencilAttachment(GrStencilAttachment* stencil) {
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrRenderTargetOpList.cpp
similarity index 82%
rename from src/gpu/GrDrawTarget.cpp
rename to src/gpu/GrRenderTargetOpList.cpp
index 5b2530f..0dbb777 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "GrDrawTarget.h"
+#include "GrRenderTargetOpList.h"
 
 #include "GrAppliedClip.h"
 #include "GrAuditTrail.h"
@@ -38,20 +38,22 @@
 
 #include "instanced/InstancedRendering.h"
 
+using gr_instanced::InstancedRendering;
+
 ////////////////////////////////////////////////////////////////////////////////
 
 // Experimentally we have found that most batching occurs within the first 10 comparisons.
 static const int kDefaultMaxBatchLookback  = 10;
 static const int kDefaultMaxBatchLookahead = 10;
 
-GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider,
-                           GrAuditTrail* auditTrail, const Options& options)
-    : fLastFullClearBatch(nullptr)
+GrRenderTargetOpList::GrRenderTargetOpList(GrRenderTarget* rt, GrGpu* gpu,
+                                           GrResourceProvider* resourceProvider,
+                                           GrAuditTrail* auditTrail, const Options& options)
+    : INHERITED(rt)
+    , fLastFullClearBatch(nullptr)
     , fGpu(SkRef(gpu))
     , fResourceProvider(resourceProvider)
-    , fAuditTrail(auditTrail)
-    , fFlags(0)
-    , fRenderTarget(rt) {
+    , fAuditTrail(auditTrail) {
     // TODO: Stop extracting the context (currently needed by GrClip)
     fContext = fGpu->getContext();
 
@@ -65,63 +67,18 @@
     if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
         fInstancedRendering.reset(fGpu->createInstancedRendering());
     }
-
-    rt->setLastDrawTarget(this);
-
-#ifdef SK_DEBUG
-    static int debugID = 0;
-    fDebugID = debugID++;
-#endif
 }
 
-GrDrawTarget::~GrDrawTarget() {
-    if (fRenderTarget && this == fRenderTarget->getLastDrawTarget()) {
-        fRenderTarget->setLastDrawTarget(nullptr);
-    }
-
+GrRenderTargetOpList::~GrRenderTargetOpList() {
     fGpu->unref();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
-// Add a GrDrawTarget-based dependency
-void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) {
-    SkASSERT(!dependedOn->dependsOn(this));  // loops are bad
-
-    if (this->dependsOn(dependedOn)) {
-        return;  // don't add duplicate dependencies
-    }
-
-    *fDependencies.push() = dependedOn;
-}
-
-// Convert from a GrSurface-based dependency to a GrDrawTarget one
-void GrDrawTarget::addDependency(GrSurface* dependedOn) {
-    if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) {
-        // If it is still receiving dependencies, this DT shouldn't be closed
-        SkASSERT(!this->isClosed());
-
-        GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget();
-        if (dt == this) {
-            // self-read - presumably for dst reads
-        } else {
-            this->addDependency(dt);
-
-            // Can't make it closed in the self-read case
-            dt->makeClosed();
-        }
-    }
-}
-
 #ifdef SK_DEBUG
-void GrDrawTarget::dump() const {
-    SkDebugf("--------------------------------------------------------------\n");
-    SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->uniqueID() : -1);
-    SkDebugf("relies On (%d): ", fDependencies.count());
-    for (int i = 0; i < fDependencies.count(); ++i) {
-        SkDebugf("%d, ", fDependencies[i]->fDebugID);
-    }
-    SkDebugf("\n");
+void GrRenderTargetOpList::dump() const {
+    INHERITED::dump();
+
     SkDebugf("batches (%d):\n", fRecordedBatches.count());
     for (int i = 0; i < fRecordedBatches.count(); ++i) {
         SkDebugf("*******************************\n");
@@ -140,12 +97,12 @@
 }
 #endif
 
-bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
-                                           GrRenderTarget* rt,
-                                           const GrClip& clip,
-                                           const GrPipelineOptimizations& optimizations,
-                                           GrXferProcessor::DstTexture* dstTexture,
-                                           const SkRect& batchBounds) {
+bool GrRenderTargetOpList::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
+                                                   GrRenderTarget* rt,
+                                                   const GrClip& clip,
+                                                   const GrPipelineOptimizations& optimizations,
+                                                   GrXferProcessor::DstTexture* dstTexture,
+                                                   const SkRect& batchBounds) {
     SkRect bounds = batchBounds;
     bounds.outset(0.5f, 0.5f);
 
@@ -202,11 +159,11 @@
     return true;
 }
 
-void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) {
-    // Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh
-    // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed
-    // but need to be flushed anyway. Closing such drawTargets here will mean new
-    // drawTargets will be created to replace them if the SkGpuDevice(s) write to them again.
+void GrRenderTargetOpList::prepareBatches(GrBatchFlushState* flushState) {
+    // Semi-usually the GrOpLists are already closed at this point, but sometimes Ganesh
+    // needs to flush mid-draw. In that case, the SkGpuDevice's GrOpLists won't be closed
+    // but need to be flushed anyway. Closing such GrOpLists here will mean new
+    // GrOpLists will be created to replace them if the SkGpuDevice(s) write to them again.
     this->makeClosed();
 
     // Loop over the batches that haven't yet generated their geometry
@@ -221,7 +178,7 @@
     }
 }
 
-bool GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
+bool GrRenderTargetOpList::drawBatches(GrBatchFlushState* flushState) {
     if (0 == fRecordedBatches.count()) {
         return false;
     }
@@ -268,11 +225,11 @@
         flushState->setCommandBuffer(nullptr);
     }
 
-    fGpu->finishDrawTarget();
+    fGpu->finishOpList();
     return true;
 }
 
-void GrDrawTarget::reset() {
+void GrRenderTargetOpList::reset() {
     fLastFullClearBatch = nullptr;
     fRecordedBatches.reset();
     if (fInstancedRendering) {
@@ -280,6 +237,20 @@
     }
 }
 
+void GrRenderTargetOpList::abandonGpuResources() {
+    if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
+        InstancedRendering* ir = this->instancedRendering();
+        ir->resetGpuResources(InstancedRendering::ResetType::kAbandon);
+    }
+}
+
+void GrRenderTargetOpList::freeGpuResources() {
+    if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
+        InstancedRendering* ir = this->instancedRendering();
+        ir->resetGpuResources(InstancedRendering::ResetType::kDestroy);
+    }
+}
+
 static void batch_bounds(SkRect* bounds, const GrBatch* batch) {
     *bounds = batch->bounds();
     if (batch->hasZeroArea()) {
@@ -306,10 +277,10 @@
     }
 }
 
-void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
-                             GrDrawContext* drawContext,
-                             const GrClip& clip,
-                             GrDrawBatch* batch) {
+void GrRenderTargetOpList::drawBatch(const GrPipelineBuilder& pipelineBuilder,
+                                     GrDrawContext* drawContext,
+                                     const GrClip& clip,
+                                     GrDrawBatch* batch) {
     // Setup clip
     SkRect bounds;
     batch_bounds(&bounds, batch);
@@ -377,17 +348,17 @@
     }
 
 #ifdef ENABLE_MDB
-    SkASSERT(fRenderTarget);
-    batch->pipeline()->addDependenciesTo(fRenderTarget);
+    SkASSERT(fSurface);
+    batch->pipeline()->addDependenciesTo(fSurface);
 #endif
     this->recordBatch(batch, appliedClip.clippedDrawBounds());
 }
 
-void GrDrawTarget::stencilPath(GrDrawContext* drawContext,
-                               const GrClip& clip,
-                               bool useHWAA,
-                               const SkMatrix& viewMatrix,
-                               const GrPath* path) {
+void GrRenderTargetOpList::stencilPath(GrDrawContext* drawContext,
+                                       const GrClip& clip,
+                                       bool useHWAA,
+                                       const SkMatrix& viewMatrix,
+                                       const GrPath* path) {
     // TODO: extract portions of checkDraw that are relevant to path stenciling.
     SkASSERT(path);
     SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
@@ -426,11 +397,11 @@
     batch->unref();
 }
 
-void GrDrawTarget::addBatch(sk_sp<GrBatch> batch) {
+void GrRenderTargetOpList::addBatch(sk_sp<GrBatch> batch) {
     this->recordBatch(batch.get(), batch->bounds());
 }
 
-void GrDrawTarget::fullClear(GrRenderTarget* renderTarget, GrColor color) {
+void GrRenderTargetOpList::fullClear(GrRenderTarget* renderTarget, GrColor color) {
     // Currently this just inserts or updates the last clear batch. However, once in MDB this can
     // remove all the previously recorded batches and change the load op to clear with supplied
     // color.
@@ -448,7 +419,7 @@
     }
 }
 
-void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
+void GrRenderTargetOpList::discard(GrRenderTarget* renderTarget) {
     // Currently this just inserts a discard batch. However, once in MDB this can remove all the
     // previously recorded batches and change the load op to discard.
     if (this->caps()->discardRenderTargetSupport()) {
@@ -460,10 +431,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrDrawTarget::copySurface(GrSurface* dst,
-                               GrSurface* src,
-                               const SkIRect& srcRect,
-                               const SkIPoint& dstPoint) {
+bool GrRenderTargetOpList::copySurface(GrSurface* dst,
+                                       GrSurface* src,
+                                       const SkIRect& srcRect,
+                                       const SkIPoint& dstPoint) {
     GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
     if (!batch) {
         return false;
@@ -491,8 +462,8 @@
     out->fBottom = SkTMax(a.fBottom, b.fBottom);
 }
 
-GrBatch* GrDrawTarget::recordBatch(GrBatch* batch, const SkRect& clippedBounds) {
-    // A closed drawTarget should never receive new/more batches
+GrBatch* GrRenderTargetOpList::recordBatch(GrBatch* batch, const SkRect& clippedBounds) {
+    // A closed GrOpList should never receive new/more batches
     SkASSERT(!this->isClosed());
 
     // Check if there is a Batch Draw we can batch with by linearly searching back until we either
@@ -552,7 +523,7 @@
     return batch;
 }
 
-void GrDrawTarget::forwardCombine() {
+void GrRenderTargetOpList::forwardCombine() {
     if (fMaxBatchLookahead <= 0) {
         return;
     }
@@ -600,9 +571,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrDrawTarget::clearStencilClip(const GrFixedClip& clip,
-                                    bool insideStencilMask,
-                                    GrRenderTarget* rt) {
+void GrRenderTargetOpList::clearStencilClip(const GrFixedClip& clip,
+                                            bool insideStencilMask,
+                                            GrRenderTarget* rt) {
     GrBatch* batch = new GrClearStencilClipBatch(clip, insideStencilMask, rt);
     this->recordBatch(batch, batch->bounds());
     batch->unref();
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrRenderTargetOpList.h
similarity index 62%
rename from src/gpu/GrDrawTarget.h
rename to src/gpu/GrRenderTargetOpList.h
index 35de239..080ff69 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -5,11 +5,12 @@
  * found in the LICENSE file.
  */
 
-#ifndef GrDrawTarget_DEFINED
-#define GrDrawTarget_DEFINED
+#ifndef GrRenderTargetOpList_DEFINED
+#define GrRenderTargetOpList_DEFINED
 
 #include "GrClip.h"
 #include "GrContext.h"
+#include "GrOpList.h"
 #include "GrPathProcessor.h"
 #include "GrPrimitiveProcessor.h"
 #include "GrPathRendering.h"
@@ -27,8 +28,6 @@
 #include "SkTypes.h"
 #include "SkXfermode.h"
 
-//#define ENABLE_MDB 1
-
 class GrAuditTrail;
 class GrBatch;
 class GrClearBatch;
@@ -38,9 +37,9 @@
 class GrDrawPathBatchBase;
 class GrPipelineBuilder;
 
-class GrDrawTarget final : public SkRefCnt {
+class GrRenderTargetOpList final : public GrOpList {
 public:
-    /** Options for GrDrawTarget behavior. */
+    /** Options for GrRenderTargetOpList behavior. */
     struct Options {
         Options ()
             : fClipBatchToBounds(false)
@@ -53,54 +52,32 @@
         int  fMaxBatchLookahead;
     };
 
-    GrDrawTarget(GrRenderTarget*, GrGpu*, GrResourceProvider*, GrAuditTrail*, const Options&);
+    GrRenderTargetOpList(GrRenderTarget*, GrGpu*, GrResourceProvider*,
+                         GrAuditTrail*, const Options&);
 
-    ~GrDrawTarget() override;
+    ~GrRenderTargetOpList() override;
 
-    void makeClosed() {
+    void makeClosed() override {
+        INHERITED::makeClosed();
+
         fLastFullClearBatch = nullptr;
-        // We only close drawTargets When MDB is enabled. When MDB is disabled there is only
-        // ever one drawTarget and all calls will be funnelled into it.
-#ifdef ENABLE_MDB
-        this->setFlag(kClosed_Flag);
-#endif
         this->forwardCombine();
     }
 
-    bool isClosed() const { return this->isSetFlag(kClosed_Flag); }
-
-    // TODO: this entry point is only needed in the non-MDB world. Remove when
-    // we make the switch to MDB
-    void clearRT() { fRenderTarget = nullptr; }
-
-    /*
-     * Notify this drawTarget that it relies on the contents of 'dependedOn'
-     */
-    void addDependency(GrSurface* dependedOn);
-
-    /*
-     * Does this drawTarget depend on 'dependedOn'?
-     */
-    bool dependsOn(GrDrawTarget* dependedOn) const {
-        return fDependencies.find(dependedOn) >= 0;
-    }
-
-    /*
-     * Dump out the drawTarget dependency DAG
-     */
-    SkDEBUGCODE(void dump() const;)
-
     /**
      * Empties the draw buffer of any queued up draws.
      */
-    void reset();
+    void reset() override;
+
+    void abandonGpuResources() override;
+    void freeGpuResources() override;
 
     /**
      * Together these two functions flush all queued up draws to GrCommandBuffer. The return value
      * of drawBatches() indicates whether any commands were actually issued to the GPU.
      */
-    void prepareBatches(GrBatchFlushState* flushState);
-    bool drawBatches(GrBatchFlushState* flushState);
+    void prepareBatches(GrBatchFlushState* flushState) override;
+    bool drawBatches(GrBatchFlushState* flushState) override;
 
     /**
      * Gets the capabilities of the draw target.
@@ -150,53 +127,11 @@
         return fInstancedRendering;
     }
 
+    SkDEBUGCODE(void dump() const override;)
+
 private:
-    friend class GrDrawingManager; // for resetFlag & TopoSortTraits
     friend class GrDrawContextPriv; // for clearStencilClip
 
-    enum Flags {
-        kClosed_Flag    = 0x01,   //!< This drawTarget can't accept any more batches
-
-        kWasOutput_Flag = 0x02,   //!< Flag for topological sorting
-        kTempMark_Flag  = 0x04,   //!< Flag for topological sorting
-    };
-
-    void setFlag(uint32_t flag) {
-        fFlags |= flag;
-    }
-
-    void resetFlag(uint32_t flag) {
-        fFlags &= ~flag;
-    }
-
-    bool isSetFlag(uint32_t flag) const {
-        return SkToBool(fFlags & flag);
-    }
-
-    struct TopoSortTraits {
-        static void Output(GrDrawTarget* dt, int /* index */) {
-            dt->setFlag(GrDrawTarget::kWasOutput_Flag);
-        }
-        static bool WasOutput(const GrDrawTarget* dt) {
-            return dt->isSetFlag(GrDrawTarget::kWasOutput_Flag);
-        }
-        static void SetTempMark(GrDrawTarget* dt) {
-            dt->setFlag(GrDrawTarget::kTempMark_Flag);
-        }
-        static void ResetTempMark(GrDrawTarget* dt) {
-            dt->resetFlag(GrDrawTarget::kTempMark_Flag);
-        }
-        static bool IsTempMarked(const GrDrawTarget* dt) {
-            return dt->isSetFlag(GrDrawTarget::kTempMark_Flag);
-        }
-        static int NumDependencies(const GrDrawTarget* dt) {
-            return dt->fDependencies.count();
-        }
-        static GrDrawTarget* Dependency(GrDrawTarget* dt, int index) {
-            return dt->fDependencies[index];
-        }
-    };
-
     // Returns the batch that the input batch was combined with or the input batch if it wasn't
     // combined.
     GrBatch* recordBatch(GrBatch*, const SkRect& clippedBounds);
@@ -212,8 +147,6 @@
                                  GrXferProcessor::DstTexture*,
                                  const SkRect& batchBounds);
 
-    void addDependency(GrDrawTarget* dependedOn);
-
     // Used only by drawContextPriv.
     void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
 
@@ -229,13 +162,6 @@
     GrResourceProvider*                             fResourceProvider;
     GrAuditTrail*                                   fAuditTrail;
 
-    SkDEBUGCODE(int                                 fDebugID;)
-    uint32_t                                        fFlags;
-
-    // 'this' drawTarget relies on the output of the drawTargets in 'fDependencies'
-    SkTDArray<GrDrawTarget*>                        fDependencies;
-    GrRenderTarget*                                 fRenderTarget;
-
     bool                                            fClipBatchToBounds;
     bool                                            fDrawBatchBounds;
     int                                             fMaxBatchLookback;
@@ -243,7 +169,7 @@
 
     SkAutoTDelete<gr_instanced::InstancedRendering> fInstancedRendering;
 
-    typedef SkRefCnt INHERITED;
+    typedef GrOpList INHERITED;
 };
 
 #endif
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index fa6bd26..5ea43d6 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -8,8 +8,9 @@
 #include "GrRenderTargetProxy.h"
 
 #include "GrCaps.h"
-#include "GrDrawTarget.h"
 #include "GrGpuResourcePriv.h"
+#include "GrRenderTargetOpList.h"
+#include "GrTextureProvider.h"
 
 // Deferred version
 // TODO: we can probably munge the 'desc' in both the wrapped and deferred
@@ -18,8 +19,7 @@
                                          SkBackingFit fit, SkBudgeted budgeted)
     : INHERITED(desc, fit, budgeted)
     , fTarget(nullptr)
-    , fFlags(GrRenderTargetPriv::Flags::kNone)
-    , fLastDrawTarget(nullptr) {
+    , fFlags(GrRenderTargetPriv::Flags::kNone) {
     // Since we know the newly created render target will be internal, we are able to precompute
     // what the flags will ultimately end up being.
     if (caps.usesMixedSamples() && fDesc.fSampleCnt > 0) {
@@ -35,15 +35,7 @@
     : INHERITED(rt->desc(), SkBackingFit::kExact,
                 rt->resourcePriv().isBudgeted(), rt->uniqueID())
     , fTarget(std::move(rt))
-    , fFlags(fTarget->renderTargetPriv().flags())
-    , fLastDrawTarget(nullptr) {
-}
-
-GrRenderTargetProxy::~GrRenderTargetProxy() {
-    if (fLastDrawTarget) {
-        fLastDrawTarget->clearRT();
-    }
-    SkSafeUnref(fLastDrawTarget);
+    , fFlags(fTarget->renderTargetPriv().flags()) {
 }
 
 GrRenderTarget* GrRenderTargetProxy::instantiate(GrTextureProvider* texProvider) {
@@ -73,18 +65,6 @@
     return fTarget.get();
 }
 
-void GrRenderTargetProxy::setLastDrawTarget(GrDrawTarget* dt) {
-    if (fLastDrawTarget) {
-        // The non-MDB world never closes so we can't check this condition
-#ifdef ENABLE_MDB
-        SkASSERT(fLastDrawTarget->isClosed());
-#endif
-        fLastDrawTarget->clearRT();
-    }
-
-    SkRefCnt_SafeAssign(fLastDrawTarget, dt);
-}
-
 sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(const GrCaps& caps,
                                                      const GrSurfaceDesc& desc,
                                                      SkBackingFit fit,
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index b4d72d5..4c90cdd 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -96,7 +96,7 @@
 
     enum Flags {
         /** If the caller intends to do direct reads/writes to/from the CPU then this flag must be
-         *  set when accessing resources during a GrDrawTarget flush. This includes the execution of
+         *  set when accessing resources during a GrOpList flush. This includes the execution of
          *  GrBatch objects. The reason is that these memory operations are done immediately and
          *  will occur out of order WRT the operations being flushed.
          *  Make this automatic: https://bug.skia.org/4156
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index 3c9368e..9fe00de 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -7,6 +7,7 @@
 
 #include "GrSurface.h"
 #include "GrContext.h"
+#include "GrOpList.h"
 #include "GrSurfacePriv.h"
 
 #include "SkBitmap.h"
@@ -14,6 +15,16 @@
 #include "SkImageEncoder.h"
 #include <stdio.h>
 
+GrSurface::~GrSurface() {
+    if (fLastOpList) {
+        fLastOpList->clearTarget();
+    }
+    SkSafeUnref(fLastOpList);
+
+    // check that invokeReleaseProc has been called (if needed)
+    SkASSERT(NULL == fReleaseProc);
+}
+
 size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) {
     size_t size;
 
@@ -195,3 +206,15 @@
     this->invokeReleaseProc();
     this->INHERITED::onAbandon();
 }
+
+void GrSurface::setLastOpList(GrOpList* opList) {
+    if (fLastOpList) {
+        // The non-MDB world never closes so we can't check this condition
+#ifdef ENABLE_MDB
+        SkASSERT(fLastOpList->isClosed());
+#endif
+        fLastOpList->clearTarget();
+    }
+
+    SkRefCnt_SafeAssign(fLastOpList, opList);
+}
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index f5c401f..9cd84ed 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -7,3 +7,23 @@
 
 #include "GrSurfaceProxy.h"
 
+#include "GrOpList.h"
+
+GrSurfaceProxy::~GrSurfaceProxy() {
+    if (fLastOpList) {
+        fLastOpList->clearTarget();
+    }
+    SkSafeUnref(fLastOpList);
+}
+
+void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
+    if (fLastOpList) {
+        // The non-MDB world never closes so we can't check this condition
+#ifdef ENABLE_MDB
+        SkASSERT(fLastOpList->isClosed());
+#endif
+        fLastOpList->clearTarget();
+    }
+
+    SkRefCnt_SafeAssign(fLastOpList, opList);
+}
diff --git a/src/gpu/GrTracing.h b/src/gpu/GrTracing.h
index 273aa65..1f2a04a 100644
--- a/src/gpu/GrTracing.h
+++ b/src/gpu/GrTracing.h
@@ -57,7 +57,7 @@
 /**
  * GR_CREATE_TRACE_MARKER will place begin and end trace markers for both
  * cpu and gpu (if gpu tracing enabled) for the current scope.
- * name is of type const char* and target is of type GrDrawTarget*
+ * name is of type const char* and target is of type GrOpList*
  */
 #define GR_CREATE_TRACE_MARKER(name, target)                                                       \
     /* Chromium tracing */                                                                         \
diff --git a/src/gpu/GrUserStencilSettings.h b/src/gpu/GrUserStencilSettings.h
index 32fb139..1800259 100644
--- a/src/gpu/GrUserStencilSettings.h
+++ b/src/gpu/GrUserStencilSettings.h
@@ -13,12 +13,12 @@
 
 /**
  * Gr uses the stencil buffer to implement complex clipping inside the
- * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
+ * GrOpList class. The GrOpList makes a subset of the stencil buffer
  * bits available for other uses by external code (user bits). Client code can
- * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
+ * modify these bits. GrOpList will ignore ref, mask, and writemask bits
  * provided by clients that fall outside the user range.
  *
- * When code outside the GrDrawTarget class uses the stencil buffer the contract
+ * When code outside the GrOpList class uses the stencil buffer the contract
  * is as follows:
  *
  * > Normal stencil funcs allow the client to pass / fail regardless of the
diff --git a/src/gpu/batches/GrDrawBatch.h b/src/gpu/batches/GrDrawBatch.h
index 5f37b7b..e675f5f 100644
--- a/src/gpu/batches/GrDrawBatch.h
+++ b/src/gpu/batches/GrDrawBatch.h
@@ -42,7 +42,7 @@
 };
 
 /**
- * Base class for GrBatches that draw. These batches have a GrPipeline installed by GrDrawTarget.
+ * Base class for GrBatches that draw. These batches have a GrPipeline installed by GrOpList.
  */
 class GrDrawBatch : public GrBatch {
 public:
diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp
index 57eac3c..cb4f2c7 100644
--- a/src/gpu/batches/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp
@@ -12,7 +12,6 @@
 #include "GrBatchTest.h"
 #include "GrClip.h"
 #include "GrDefaultGeoProcFactory.h"
-#include "GrDrawTarget.h"
 #include "GrMesh.h"
 #include "GrPathUtils.h"
 #include "GrPipelineBuilder.h"
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 1e80497..3a32e2b 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2238,7 +2238,7 @@
 #else
     // we could just clear the clip bit but when we go through
     // ANGLE a partial stencil mask will cause clears to be
-    // turned into draws. Our contract on GrDrawTarget says that
+    // turned into draws. Our contract on GrOpList says that
     // changing the clip between stencil passes may or may not
     // zero the client's clip bits. So we just clear the whole thing.
     static const GrGLint clipStencilMask  = ~0;
@@ -2616,7 +2616,7 @@
     return new GrGLGpuCommandBuffer(this, static_cast<GrGLRenderTarget*>(target));
 }
 
-void GrGLGpu::finishDrawTarget() {
+void GrGLGpu::finishOpList() {
     if (fPLSHasBeenUsed) {
         /* There is an ARM driver bug where if we use PLS, and then draw a frame which does not
          * use PLS, it leaves garbage all over the place. As a workaround, we use PLS in a
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 7ba79b2..0160835 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -142,7 +142,7 @@
 
     void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override;
 
-    void finishDrawTarget() override;
+    void finishOpList() override;
 
     GrFence SK_WARN_UNUSED_RESULT insertFence() const override;
     bool waitFence(GrFence, uint64_t timeout) const override;
diff --git a/src/gpu/text/GrStencilAndCoverTextContext.h b/src/gpu/text/GrStencilAndCoverTextContext.h
index 0f6735e..c87041a 100644
--- a/src/gpu/text/GrStencilAndCoverTextContext.h
+++ b/src/gpu/text/GrStencilAndCoverTextContext.h
@@ -25,7 +25,7 @@
 
 /*
  * This class implements text rendering using stencil and cover path rendering
- * (by the means of GrDrawTarget::drawPath).
+ * (by the means of GrOpList::drawPath).
  */
 class GrStencilAndCoverTextContext {
 public:
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 0eb8241..b13e162 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1323,7 +1323,7 @@
                                        barrier);
 }
 
-void GrVkGpu::finishDrawTarget() {
+void GrVkGpu::finishOpList() {
     // Submit the current command buffer to the Queue
     this->submitCommandBuffer(kSkip_SyncQueue);
 }
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 273f28c..77eb242 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -139,7 +139,7 @@
                                       GrVkRenderTarget*,
                                       const SkIRect& bounds);
 
-    void finishDrawTarget() override;
+    void finishOpList() override;
 
     GrFence SK_WARN_UNUSED_RESULT insertFence() const override;
     bool waitFence(GrFence, uint64_t timeout) const override;
diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp
index 2e17902..60c10e8 100644
--- a/tools/gpu/GrTest.cpp
+++ b/tools/gpu/GrTest.cpp
@@ -65,9 +65,9 @@
 void GrContext::getTestTarget(GrTestTarget* tar, sk_sp<GrDrawContext> drawContext) {
     this->flush();
     SkASSERT(drawContext);
-    // We could create a proxy GrDrawTarget that passes through to fGpu until ~GrTextTarget() and
+    // We could create a proxy GrOpList that passes through to fGpu until ~GrTextTarget() and
     // then disconnects. This would help prevent test writers from mixing using the returned
-    // GrDrawTarget and regular drawing. We could also assert or fail in GrContext drawing methods
+    // GrOpList and regular drawing. We could also assert or fail in GrContext drawing methods
     // until ~GrTestTarget().
     tar->init(this, std::move(drawContext));
 }
@@ -252,7 +252,7 @@
         pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag, true);
     }
 
-    fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, fDrawContext, GrNoClip(), batch);
+    fDrawContext->getOpList()->drawBatch(pipelineBuilder, fDrawContext, GrNoClip(), batch);
 }
 
 #undef ASSERT_SINGLE_OWNER
diff --git a/tools/gpu/GrTest.h b/tools/gpu/GrTest.h
index 7b05a05..86333b4 100644
--- a/tools/gpu/GrTest.h
+++ b/tools/gpu/GrTest.h
@@ -20,8 +20,8 @@
 };
 
 /** TODO Please do not use this if you can avoid it.  We are in the process of deleting it.
-    Allows a test to temporarily draw to a GrDrawTarget owned by a GrContext. Tests that use this
-    should be careful not to mix using the GrDrawTarget directly and drawing via SkCanvas or
+    Allows a test to temporarily draw to a GrOpList owned by a GrContext. Tests that use this
+    should be careful not to mix using the GrOpList directly and drawing via SkCanvas or
     GrContext. In the future this object may provide some guards to prevent this. */
 class GrTestTarget {
 public: