Split drawing functionality out of GrContext and into new GrDrawContext

This is mainly a mechanical CL. There were some fiddly bits in GrContext.cpp where it no longer had access to the GrDrawTarget (and had to use the new GrDrawContext).

I've converted GrAARectRenderer & GrOvalRenderer into static classes so I could stop allocating them.

Review URL: https://codereview.chromium.org/1151283004
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 3ed0b6b..550d7ff 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -17,6 +17,7 @@
 #include "GrCaps.h"
 #include "GrContextOptions.h"
 #include "GrDefaultGeoProcFactory.h"
+#include "GrDrawContext.h"
 #include "GrGpuResource.h"
 #include "GrGpuResourcePriv.h"
 #include "GrGpu.h"
@@ -53,23 +54,61 @@
 #include "effects/GrSingleTextureEffect.h"
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
-#define RETURN_IF_ABANDONED if (!fDrawBuffer) { return; }
-#define RETURN_FALSE_IF_ABANDONED if (!fDrawBuffer) { return false; }
-#define RETURN_NULL_IF_ABANDONED if (!fDrawBuffer) { return NULL; }
+#define RETURN_IF_ABANDONED if (fDrawingMgr.abandoned()) { return; }
+#define RETURN_FALSE_IF_ABANDONED if (fDrawingMgr.abandoned()) { return false; }
+#define RETURN_NULL_IF_ABANDONED if (fDrawingMgr.abandoned()) { return NULL; }
 
-class GrContext::AutoCheckFlush {
-public:
-    AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
 
-    ~AutoCheckFlush() {
-        if (fContext->fFlushToReduceCacheSize) {
-            fContext->flush();
-        }
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::DrawingMgr::init(GrContext* context) {
+#ifdef IMMEDIATE_MODE
+    fDrawTarget = SkNEW_ARGS(GrImmediateDrawTarget, (context));
+#else
+    fDrawTarget = SkNEW_ARGS(GrInOrderDrawBuffer, (context));
+#endif    
+
+    fDrawContext = SkNEW_ARGS(GrDrawContext, (context, fDrawTarget));
+}
+
+GrContext::DrawingMgr::~DrawingMgr() {
+    SkSafeUnref(fDrawTarget);
+    SkSafeUnref(fDrawContext);
+}
+
+void GrContext::DrawingMgr::abandon() {
+    SkSafeSetNull(fDrawTarget);
+    fDrawContext->fDrawTarget.reset(NULL);
+    SkSafeSetNull(fDrawContext);
+}
+
+void GrContext::DrawingMgr::purgeResources() {
+    if (fDrawTarget) {
+        fDrawTarget->purgeResources();
     }
+}
 
-private:
-    GrContext* fContext;
-};
+void GrContext::DrawingMgr::reset() {
+    if (fDrawTarget) {
+        fDrawTarget->reset();
+    }
+}
+
+void GrContext::DrawingMgr::flush() {
+    if (fDrawTarget) {
+        fDrawTarget->flush();
+    }
+}
+
+GrDrawContext* GrContext::DrawingMgr::drawContext() { 
+    if (this->abandoned()) {
+        return NULL;
+    }
+    return fDrawContext; 
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 
 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
     GrContextOptions defaultOptions;
@@ -104,19 +143,16 @@
     fPathRendererChain = NULL;
     fSoftwarePathRenderer = NULL;
     fBatchFontCache = NULL;
-    fDrawBuffer = NULL;
     fFlushToReduceCacheSize = false;
-    fAARectRenderer = NULL;
-    fOvalRenderer = NULL;
     fMaxTextureSizeOverride = 1 << 20;
 }
 
 bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
                      const GrContextOptions& options) {
-    SkASSERT(NULL == fGpu);
+    SkASSERT(!fGpu);
 
     fGpu = GrGpu::Create(backend, backendContext, options, this);
-    if (NULL == fGpu) {
+    if (!fGpu) {
         return false;
     }
     this->initCommon();
@@ -130,16 +166,9 @@
 
     fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
 
-    fAARectRenderer = SkNEW(GrAARectRenderer);
-    fOvalRenderer = SkNEW(GrOvalRenderer);
-
     fDidTestPMConversions = false;
 
-#ifdef IMMEDIATE_MODE
-    fDrawBuffer = SkNEW_ARGS(GrImmediateDrawTarget, (this));
-#else
-    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (this));
-#endif
+    fDrawingMgr.init(this);
 
     // GrBatchFontCache will eventually replace GrFontCache
     fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
@@ -148,7 +177,7 @@
 }
 
 GrContext::~GrContext() {
-    if (NULL == fGpu) {
+    if (!fGpu) {
         return;
     }
 
@@ -161,10 +190,6 @@
     SkDELETE(fResourceProvider);
     SkDELETE(fResourceCache);
     SkDELETE(fBatchFontCache);
-    SkDELETE(fDrawBuffer);
-
-    fAARectRenderer->unref();
-    fOvalRenderer->unref();
 
     fGpu->unref();
     SkSafeUnref(fPathRendererChain);
@@ -184,8 +209,7 @@
     SkSafeSetNull(fPathRendererChain);
     SkSafeSetNull(fSoftwarePathRenderer);
 
-    SkDELETE(fDrawBuffer);
-    fDrawBuffer = NULL;
+    fDrawingMgr.abandon();
 
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
@@ -199,9 +223,7 @@
 void GrContext::freeGpuResources() {
     this->flush();
 
-    if (fDrawBuffer) {
-        fDrawBuffer->purgeResources();
-    }
+    fDrawingMgr.purgeResources();
 
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
@@ -238,6 +260,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+bool GrContext::shaderDerivativeSupport() const {
+    return fGpu->caps()->shaderCaps()->shaderDerivativeSupport();
+}
+
 bool GrContext::isConfigTexturable(GrPixelConfig config) const {
     return fGpu->caps()->isConfigTexturable(config);
 }
@@ -278,1093 +304,15 @@
     return fGpu->caps()->maxSampleCount();
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-void GrContext::clear(const SkIRect* rect,
-                      const GrColor color,
-                      bool canIgnoreRect,
-                      GrRenderTarget* renderTarget) {
-    RETURN_IF_ABANDONED
-    ASSERT_OWNED_RESOURCE(renderTarget);
-    SkASSERT(renderTarget);
-
-    AutoCheckFlush acf(this);
-    GR_CREATE_TRACE_MARKER_CONTEXT("GrContext::clear", this);
-    GrDrawTarget* target = this->prepareToDraw();
-    if (NULL == target) {
-        return;
-    }
-    target->clear(rect, color, canIgnoreRect, renderTarget);
-}
-
-void GrContext::drawPaint(GrRenderTarget* rt,
-                          const GrClip& clip,
-                          const GrPaint& origPaint,
-                          const SkMatrix& viewMatrix) {
-    RETURN_IF_ABANDONED
-    // set rect to be big enough to fill the space, but not super-huge, so we
-    // don't overflow fixed-point implementations
-    SkRect r;
-    r.setLTRB(0, 0,
-              SkIntToScalar(rt->width()),
-              SkIntToScalar(rt->height()));
-    SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
-
-    // by definition this fills the entire clip, no need for AA
-    if (paint->isAntiAlias()) {
-        paint.writable()->setAntiAlias(false);
-    }
-
-    bool isPerspective = viewMatrix.hasPerspective();
-
-    // We attempt to map r by the inverse matrix and draw that. mapRect will
-    // map the four corners and bound them with a new rect. This will not
-    // produce a correct result for some perspective matrices.
-    if (!isPerspective) {
-        SkMatrix inverse;
-        if (!viewMatrix.invert(&inverse)) {
-            SkDebugf("Could not invert matrix\n");
-            return;
-        }
-        inverse.mapRect(&r);
-        this->drawRect(rt, clip, *paint, viewMatrix, r);
-    } else {
-        SkMatrix localMatrix;
-        if (!viewMatrix.invert(&localMatrix)) {
-            SkDebugf("Could not invert matrix\n");
-            return;
-        }
-
-        AutoCheckFlush acf(this);
-        GrPipelineBuilder pipelineBuilder;
-        GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, paint, &acf);
-        if (NULL == target) {
-            return;
-        }
-
-        GR_CREATE_TRACE_MARKER("GrContext::drawPaintWithPerspective", target);
-        target->drawRect(&pipelineBuilder,
-                         paint->getColor(),
-                         SkMatrix::I(),
-                         r,
-                         NULL,
-                         &localMatrix);
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-static inline bool is_irect(const SkRect& r) {
-  return SkScalarIsInt(r.fLeft)  && SkScalarIsInt(r.fTop) &&
-         SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
-}
-
-static bool apply_aa_to_rect(GrDrawTarget* target,
-                             GrPipelineBuilder* pipelineBuilder,
-                             SkRect* devBoundRect,
-                             const SkRect& rect,
-                             SkScalar strokeWidth,
-                             const SkMatrix& combinedMatrix,
-                             GrColor color) {
-    if (pipelineBuilder->getRenderTarget()->isMultisampled()) {
-        return false;
-    }
-
-#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
-    if (strokeWidth >= 0) {
-#endif
-        if (!combinedMatrix.preservesAxisAlignment()) {
-            return false;
-        }
-
-#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
-    } else {
-        if (!combinedMatrix.preservesRightAngles()) {
-            return false;
-        }
-    }
-#endif
-
-    combinedMatrix.mapRect(devBoundRect, rect);
-    if (!combinedMatrix.rectStaysRect()) {
-        return true;
-    }
-
-    if (strokeWidth < 0) {
-        return !is_irect(*devBoundRect);
-    }
-
-    return true;
-}
-
-static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
-    return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
-           point.fY >= rect.fTop && point.fY <= rect.fBottom;
-}
-
-class StrokeRectBatch : public GrBatch {
-public:
-    struct Geometry {
-        GrColor fColor;
-        SkMatrix fViewMatrix;
-        SkRect fRect;
-        SkScalar fStrokeWidth;
-    };
-
-    static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) {
-        return SkNEW_ARGS(StrokeRectBatch, (geometry, snapToPixelCenters));
-    }
-
-    const char* name() const override { return "StrokeRectBatch"; }
-
-    void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
-        // When this is called on a batch, there is only one geometry bundle
-        out->setKnownFourComponents(fGeoData[0].fColor);
-    }
-
-    void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
-        out->setKnownSingleComponent(0xff);
-    }
-
-    void initBatchTracker(const GrPipelineInfo& init) override {
-        // Handle any color overrides
-        if (init.fColorIgnored) {
-            fGeoData[0].fColor = GrColor_ILLEGAL;
-        } else if (GrColor_ILLEGAL != init.fOverrideColor) {
-            fGeoData[0].fColor = init.fOverrideColor;
-        }
-
-        // setup batch properties
-        fBatch.fColorIgnored = init.fColorIgnored;
-        fBatch.fColor = fGeoData[0].fColor;
-        fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
-        fBatch.fCoverageIgnored = init.fCoverageIgnored;
-    }
-
-    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
-        SkAutoTUnref<const GrGeometryProcessor> gp(
-                GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType,
-                                                this->color(),
-                                                this->usesLocalCoords(),
-                                                this->coverageIgnored(),
-                                                this->viewMatrix(),
-                                                SkMatrix::I()));
-
-        batchTarget->initDraw(gp, pipeline);
-
-        size_t vertexStride = gp->getVertexStride();
-
-        SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr));
-
-        Geometry& args = fGeoData[0];
-
-        int vertexCount = kVertsPerHairlineRect;
-        if (args.fStrokeWidth > 0) {
-            vertexCount = kVertsPerStrokeRect;
-        }
-
-        const GrVertexBuffer* vertexBuffer;
-        int firstVertex;
-
-        void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount,
-                                                 &vertexBuffer, &firstVertex);
-
-        if (!verts) {
-            SkDebugf("Could not allocate vertices\n");
-            return;
-        }
-
-        SkPoint* vertex = reinterpret_cast<SkPoint*>(verts);
-
-        GrPrimitiveType primType;
-
-        if (args.fStrokeWidth > 0) {;
-            primType = kTriangleStrip_GrPrimitiveType;
-            args.fRect.sort();
-            this->setStrokeRectStrip(vertex, args.fRect, args.fStrokeWidth);
-        } else {
-            // hairline
-            primType = kLineStrip_GrPrimitiveType;
-            vertex[0].set(args.fRect.fLeft, args.fRect.fTop);
-            vertex[1].set(args.fRect.fRight, args.fRect.fTop);
-            vertex[2].set(args.fRect.fRight, args.fRect.fBottom);
-            vertex[3].set(args.fRect.fLeft, args.fRect.fBottom);
-            vertex[4].set(args.fRect.fLeft, args.fRect.fTop);
-        }
-
-        GrVertices vertices;
-        vertices.init(primType, vertexBuffer, firstVertex, vertexCount);
-        batchTarget->draw(vertices);
-    }
-
-    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
-
-private:
-    StrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) {
-        this->initClassID<StrokeRectBatch>();
-
-        fBatch.fHairline = geometry.fStrokeWidth == 0;
-
-        fGeoData.push_back(geometry);
-
-        // setup bounds
-        fBounds = geometry.fRect;
-        SkScalar rad = SkScalarHalf(geometry.fStrokeWidth);
-        fBounds.outset(rad, rad);
-        geometry.fViewMatrix.mapRect(&fBounds);
-
-        // If our caller snaps to pixel centers then we have to round out the bounds
-        if (snapToPixelCenters) {
-            fBounds.roundOut();
-        }
-    }
-
-    /*  create a triangle strip that strokes the specified rect. There are 8
-     unique vertices, but we repeat the last 2 to close up. Alternatively we
-     could use an indices array, and then only send 8 verts, but not sure that
-     would be faster.
-     */
-    void setStrokeRectStrip(SkPoint verts[10], const SkRect& rect, SkScalar width) {
-        const SkScalar rad = SkScalarHalf(width);
-        // TODO we should be able to enable this assert, but we'd have to filter these draws
-        // this is a bug
-        //SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2);
-
-        verts[0].set(rect.fLeft + rad, rect.fTop + rad);
-        verts[1].set(rect.fLeft - rad, rect.fTop - rad);
-        verts[2].set(rect.fRight - rad, rect.fTop + rad);
-        verts[3].set(rect.fRight + rad, rect.fTop - rad);
-        verts[4].set(rect.fRight - rad, rect.fBottom - rad);
-        verts[5].set(rect.fRight + rad, rect.fBottom + rad);
-        verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
-        verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
-        verts[8] = verts[0];
-        verts[9] = verts[1];
-    }
-
-
-    GrColor color() const { return fBatch.fColor; }
-    bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
-    bool colorIgnored() const { return fBatch.fColorIgnored; }
-    const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
-    bool hairline() const { return fBatch.fHairline; }
-    bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
-
-    bool onCombineIfPossible(GrBatch* t) override {
-        // StrokeRectBatch* that = t->cast<StrokeRectBatch>();
-
-        // NonAA stroke rects cannot batch right now
-        // TODO make these batchable
-        return false;
-    }
-
-    struct BatchTracker {
-        GrColor fColor;
-        bool fUsesLocalCoords;
-        bool fColorIgnored;
-        bool fCoverageIgnored;
-        bool fHairline;
-    };
-
-    const static int kVertsPerHairlineRect = 5;
-    const static int kVertsPerStrokeRect = 10;
-
-    BatchTracker fBatch;
-    SkSTArray<1, Geometry, true> fGeoData;
-};
-
-void GrContext::drawRect(GrRenderTarget* rt,
-                         const GrClip& clip,
-                         const GrPaint& paint,
-                         const SkMatrix& viewMatrix,
-                         const SkRect& rect,
-                         const GrStrokeInfo* strokeInfo) {
-    RETURN_IF_ABANDONED
-    if (strokeInfo && strokeInfo->isDashed()) {
-        SkPath path;
-        path.setIsVolatile(true);
-        path.addRect(rect);
-        this->drawPath(rt, clip, paint, viewMatrix, path, *strokeInfo);
-        return;
-    }
-
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-    if (NULL == target) {
-        return;
-    }
-
-    GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
-    SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getWidth();
-
-    // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
-    // cases where the RT is fully inside a stroke.
-    if (width < 0) {
-        SkRect rtRect;
-        pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect);
-        SkRect clipSpaceRTRect = rtRect;
-        bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
-        if (checkClip) {
-            clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
-                                   SkIntToScalar(clip.origin().fY));
-        }
-        // Does the clip contain the entire RT?
-        if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
-            SkMatrix invM;
-            if (!viewMatrix.invert(&invM)) {
-                return;
-            }
-            // Does the rect bound the RT?
-            SkPoint srcSpaceRTQuad[4];
-            invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
-            if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
-                rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
-                rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
-                rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
-                // Will it blend?
-                GrColor clearColor;
-                if (paint.isOpaqueAndConstantColor(&clearColor)) {
-                    target->clear(NULL, clearColor, true, rt);
-                    return;
-                }
-            }
-        }
-    }
-
-    GrColor color = paint.getColor();
-    SkRect devBoundRect;
-    bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isMultisampled();
-    bool doAA = needAA && apply_aa_to_rect(target, &pipelineBuilder, &devBoundRect, rect, width,
-                                           viewMatrix, color);
-
-    if (doAA) {
-        if (width >= 0) {
-            fAARectRenderer->strokeAARect(target,
-                                          &pipelineBuilder,
-                                          color,
-                                          viewMatrix,
-                                          rect,
-                                          devBoundRect,
-                                          *strokeInfo);
-        } else {
-            // filled AA rect
-            fAARectRenderer->fillAARect(target,
-                                        &pipelineBuilder,
-                                        color,
-                                        viewMatrix,
-                                        rect,
-                                        devBoundRect);
-        }
-        return;
-    }
-
-    if (width >= 0) {
-        StrokeRectBatch::Geometry geometry;
-        geometry.fViewMatrix = viewMatrix;
-        geometry.fColor = color;
-        geometry.fRect = rect;
-        geometry.fStrokeWidth = width;
-
-        // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
-        bool snapToPixelCenters = (0 == width && !rt->isMultisampled());
-        SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixelCenters));
-
-        // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
-        // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA
-        // is enabled because it can cause ugly artifacts.
-        pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
-                                 snapToPixelCenters);
-        target->drawBatch(&pipelineBuilder, batch);
-    } else {
-        // filled BW rect
-        target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect);
-    }
-}
-
-void GrContext::drawNonAARectToRect(GrRenderTarget* rt,
-                                    const GrClip& clip,
-                                    const GrPaint& paint,
-                                    const SkMatrix& viewMatrix,
-                                    const SkRect& rectToDraw,
-                                    const SkRect& localRect,
-                                    const SkMatrix* localMatrix) {
-    RETURN_IF_ABANDONED
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-    if (NULL == target) {
-        return;
-    }
-
-    GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target);
-
-    target->drawRect(&pipelineBuilder,
-                     paint.getColor(),
-                     viewMatrix,
-                     rectToDraw,
-                     &localRect,
-                     localMatrix);
-}
-
-static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords,
-                                                        bool hasColors,
-                                                        int* colorOffset,
-                                                        int* texOffset,
-                                                        GrColor color,
-                                                        const SkMatrix& viewMatrix,
-                                                        bool coverageIgnored) {
-    *texOffset = -1;
-    *colorOffset = -1;
-    uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
-    if (hasLocalCoords && hasColors) {
-        *colorOffset = sizeof(SkPoint);
-        *texOffset = sizeof(SkPoint) + sizeof(GrColor);
-        flags |= GrDefaultGeoProcFactory::kColor_GPType |
-                 GrDefaultGeoProcFactory::kLocalCoord_GPType;
-    } else if (hasLocalCoords) {
-        *texOffset = sizeof(SkPoint);
-        flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType;
-    } else if (hasColors) {
-        *colorOffset = sizeof(SkPoint);
-        flags |= GrDefaultGeoProcFactory::kColor_GPType;
-    }
-    return GrDefaultGeoProcFactory::Create(flags, color, hasLocalCoords, coverageIgnored,
-                                           viewMatrix, SkMatrix::I());
-}
-
-class DrawVerticesBatch : public GrBatch {
-public:
-    struct Geometry {
-        GrColor fColor;
-        SkTDArray<SkPoint> fPositions;
-        SkTDArray<uint16_t> fIndices;
-        SkTDArray<GrColor> fColors;
-        SkTDArray<SkPoint> fLocalCoords;
-    };
-
-    static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveType,
-                           const SkMatrix& viewMatrix,
-                           const SkPoint* positions, int vertexCount,
-                           const uint16_t* indices, int indexCount,
-                           const GrColor* colors, const SkPoint* localCoords,
-                           const SkRect& bounds) {
-        return SkNEW_ARGS(DrawVerticesBatch, (geometry, primitiveType, viewMatrix, positions,
-                                              vertexCount, indices, indexCount, colors,
-                                              localCoords, bounds));
-    }
-
-    const char* name() const override { return "DrawVerticesBatch"; }
-
-    void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
-        // When this is called on a batch, there is only one geometry bundle
-        if (this->hasColors()) {
-            out->setUnknownFourComponents();
-        } else {
-            out->setKnownFourComponents(fGeoData[0].fColor);
-        }
-    }
-
-    void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
-        out->setKnownSingleComponent(0xff);
-    }
-
-    void initBatchTracker(const GrPipelineInfo& init) override {
-        // Handle any color overrides
-        if (init.fColorIgnored) {
-            fGeoData[0].fColor = GrColor_ILLEGAL;
-        } else if (GrColor_ILLEGAL != init.fOverrideColor) {
-            fGeoData[0].fColor = init.fOverrideColor;
-        }
-
-        // setup batch properties
-        fBatch.fColorIgnored = init.fColorIgnored;
-        fBatch.fColor = fGeoData[0].fColor;
-        fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
-        fBatch.fCoverageIgnored = init.fCoverageIgnored;
-    }
-
-    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
-        int colorOffset = -1, texOffset = -1;
-        SkAutoTUnref<const GrGeometryProcessor> gp(
-                set_vertex_attributes(this->hasLocalCoords(), this->hasColors(), &colorOffset,
-                                      &texOffset, this->color(), this->viewMatrix(),
-                                      this->coverageIgnored()));
-
-        batchTarget->initDraw(gp, pipeline);
-
-        size_t vertexStride = gp->getVertexStride();
-
-        SkASSERT(vertexStride == sizeof(SkPoint) + (this->hasLocalCoords() ? sizeof(SkPoint) : 0)
-                                                 + (this->hasColors() ? sizeof(GrColor) : 0));
-
-        int instanceCount = fGeoData.count();
-
-        const GrVertexBuffer* vertexBuffer;
-        int firstVertex;
-
-        void* verts = batchTarget->makeVertSpace(vertexStride, this->vertexCount(),
-                                                 &vertexBuffer, &firstVertex);
-
-        if (!verts) {
-            SkDebugf("Could not allocate vertices\n");
-            return;
-        }
-
-        const GrIndexBuffer* indexBuffer = NULL;
-        int firstIndex = 0;
-
-        uint16_t* indices = NULL;
-        if (this->hasIndices()) {
-            indices = batchTarget->makeIndexSpace(this->indexCount(), &indexBuffer, &firstIndex);
-
-            if (!indices) {
-                SkDebugf("Could not allocate indices\n");
-                return;
-            }
-        }
-
-        int indexOffset = 0;
-        int vertexOffset = 0;
-        for (int i = 0; i < instanceCount; i++) {
-            const Geometry& args = fGeoData[i];
-
-            // TODO we can actually cache this interleaved and then just memcopy
-            if (this->hasIndices()) {
-                for (int j = 0; j < args.fIndices.count(); ++j, ++indexOffset) {
-                    *(indices + indexOffset) = args.fIndices[j] + vertexOffset;
-                }
-            }
-
-            for (int j = 0; j < args.fPositions.count(); ++j) {
-                *((SkPoint*)verts) = args.fPositions[j];
-                if (this->hasColors()) {
-                    *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j];
-                }
-                if (this->hasLocalCoords()) {
-                    *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j];
-                }
-                verts = (void*)((intptr_t)verts + vertexStride);
-                vertexOffset++;
-            }
-        }
-
-        GrVertices vertices;
-        if (this->hasIndices()) {
-            vertices.initIndexed(this->primitiveType(), vertexBuffer, indexBuffer, firstVertex,
-                                 firstIndex, this->vertexCount(), this->indexCount());
-
-        } else {
-            vertices.init(this->primitiveType(), vertexBuffer, firstVertex, this->vertexCount());
-        }
-        batchTarget->draw(vertices);
-    }
-
-    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
-
-private:
-    DrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType,
-                      const SkMatrix& viewMatrix,
-                      const SkPoint* positions, int vertexCount,
-                      const uint16_t* indices, int indexCount,
-                      const GrColor* colors, const SkPoint* localCoords, const SkRect& bounds) {
-        this->initClassID<DrawVerticesBatch>();
-        SkASSERT(positions);
-
-        fBatch.fViewMatrix = viewMatrix;
-        Geometry& installedGeo = fGeoData.push_back(geometry);
-
-        installedGeo.fPositions.append(vertexCount, positions);
-        if (indices) {
-            installedGeo.fIndices.append(indexCount, indices);
-            fBatch.fHasIndices = true;
-        } else {
-            fBatch.fHasIndices = false;
-        }
-
-        if (colors) {
-            installedGeo.fColors.append(vertexCount, colors);
-            fBatch.fHasColors = true;
-        } else {
-            fBatch.fHasColors = false;
-        }
-
-        if (localCoords) {
-            installedGeo.fLocalCoords.append(vertexCount, localCoords);
-            fBatch.fHasLocalCoords = true;
-        } else {
-            fBatch.fHasLocalCoords = false;
-        }
-        fBatch.fVertexCount = vertexCount;
-        fBatch.fIndexCount = indexCount;
-        fBatch.fPrimitiveType = primitiveType;
-
-        this->setBounds(bounds);
-    }
-
-    GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; }
-    bool batchablePrimitiveType() const {
-        return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType ||
-               kLines_GrPrimitiveType == fBatch.fPrimitiveType ||
-               kPoints_GrPrimitiveType == fBatch.fPrimitiveType;
-    }
-    GrColor color() const { return fBatch.fColor; }
-    bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
-    bool colorIgnored() const { return fBatch.fColorIgnored; }
-    const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
-    bool hasColors() const { return fBatch.fHasColors; }
-    bool hasIndices() const { return fBatch.fHasIndices; }
-    bool hasLocalCoords() const { return fBatch.fHasLocalCoords; }
-    int vertexCount() const { return fBatch.fVertexCount; }
-    int indexCount() const { return fBatch.fIndexCount; }
-    bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
-
-    bool onCombineIfPossible(GrBatch* t) override {
-        DrawVerticesBatch* that = t->cast<DrawVerticesBatch>();
-
-        if (!this->batchablePrimitiveType() || this->primitiveType() != that->primitiveType()) {
-            return false;
-        }
-
-        SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
-
-        // We currently use a uniform viewmatrix for this batch
-        if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
-            return false;
-        }
-
-        if (this->hasColors() != that->hasColors()) {
-            return false;
-        }
-
-        if (this->hasIndices() != that->hasIndices()) {
-            return false;
-        }
-
-        if (this->hasLocalCoords() != that->hasLocalCoords()) {
-            return false;
-        }
-
-        if (!this->hasColors() && this->color() != that->color()) {
-            return false;
-        }
-
-        if (this->color() != that->color()) {
-            fBatch.fColor = GrColor_ILLEGAL;
-        }
-        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
-        fBatch.fVertexCount += that->vertexCount();
-        fBatch.fIndexCount += that->indexCount();
-
-        this->joinBounds(that->bounds());
-        return true;
-    }
-
-    struct BatchTracker {
-        GrPrimitiveType fPrimitiveType;
-        SkMatrix fViewMatrix;
-        GrColor fColor;
-        bool fUsesLocalCoords;
-        bool fColorIgnored;
-        bool fCoverageIgnored;
-        bool fHasColors;
-        bool fHasIndices;
-        bool fHasLocalCoords;
-        int fVertexCount;
-        int fIndexCount;
-    };
-
-    BatchTracker fBatch;
-    SkSTArray<1, Geometry, true> fGeoData;
-};
-
-void GrContext::drawVertices(GrRenderTarget* rt,
-                             const GrClip& clip,
-                             const GrPaint& paint,
-                             const SkMatrix& viewMatrix,
-                             GrPrimitiveType primitiveType,
-                             int vertexCount,
-                             const SkPoint positions[],
-                             const SkPoint texCoords[],
-                             const GrColor colors[],
-                             const uint16_t indices[],
-                             int indexCount) {
-    RETURN_IF_ABANDONED
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-    if (NULL == target) {
-        return;
-    }
-
-    GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
-
-    // TODO clients should give us bounds
-    SkRect bounds;
-    if (!bounds.setBoundsCheck(positions, vertexCount)) {
-        SkDebugf("drawVertices call empty bounds\n");
-        return;
-    }
-
-    viewMatrix.mapRect(&bounds);
-
-    // If we don't have AA then we outset for a half pixel in each direction to account for
-    // snapping
-    if (!paint.isAntiAlias()) {
-        bounds.outset(0.5f, 0.5f);
-    }
-
-    DrawVerticesBatch::Geometry geometry;
-    geometry.fColor = paint.getColor();
-    SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
-                                                          positions, vertexCount, indices,
-                                                          indexCount, colors, texCoords,
-                                                          bounds));
-
-    target->drawBatch(&pipelineBuilder, batch);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrContext::drawRRect(GrRenderTarget*rt,
-                          const GrClip& clip,
-                          const GrPaint& paint,
-                          const SkMatrix& viewMatrix,
-                          const SkRRect& rrect,
-                          const GrStrokeInfo& strokeInfo) {
-    RETURN_IF_ABANDONED
-    if (rrect.isEmpty()) {
-       return;
-    }
-
-    if (strokeInfo.isDashed()) {
-        SkPath path;
-        path.setIsVolatile(true);
-        path.addRRect(rrect);
-        this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
-        return;
-    }
-
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-    if (NULL == target) {
-        return;
-    }
-
-    GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
-
-    GrColor color = paint.getColor();
-    if (!fOvalRenderer->drawRRect(target,
-                                  &pipelineBuilder,
-                                  color,
-                                  viewMatrix,
-                                  paint.isAntiAlias(),
-                                  rrect,
-                                  strokeInfo)) {
-        SkPath path;
-        path.setIsVolatile(true);
-        path.addRRect(rrect);
-        this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
-                               path, strokeInfo);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrContext::drawDRRect(GrRenderTarget* rt,
-                           const GrClip& clip,
-                           const GrPaint& paint,
-                           const SkMatrix& viewMatrix,
-                           const SkRRect& outer,
-                           const SkRRect& inner) {
-    RETURN_IF_ABANDONED
-    if (outer.isEmpty()) {
-       return;
-    }
-
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-
-    GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
-
-    GrColor color = paint.getColor();
-    if (!fOvalRenderer->drawDRRect(target,
-                                   &pipelineBuilder,
-                                   color,
-                                   viewMatrix,
-                                   paint.isAntiAlias(),
-                                   outer,
-                                   inner)) {
-        SkPath path;
-        path.setIsVolatile(true);
-        path.addRRect(inner);
-        path.addRRect(outer);
-        path.setFillType(SkPath::kEvenOdd_FillType);
-        GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
-        this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
-                               path, fillRec);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrContext::drawOval(GrRenderTarget* rt,
-                         const GrClip& clip,
-                         const GrPaint& paint,
-                         const SkMatrix& viewMatrix,
-                         const SkRect& oval,
-                         const GrStrokeInfo& strokeInfo) {
-    RETURN_IF_ABANDONED
-    if (oval.isEmpty()) {
-       return;
-    }
-
-    if (strokeInfo.isDashed()) {
-        SkPath path;
-        path.setIsVolatile(true);
-        path.addOval(oval);
-        this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
-        return;
-    }
-
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-    if (NULL == target) {
-        return;
-    }
-
-    GR_CREATE_TRACE_MARKER("GrContext::drawOval", target);
-
-    GrColor color = paint.getColor();
-    if (!fOvalRenderer->drawOval(target,
-                                 &pipelineBuilder,
-                                 color,
-                                 viewMatrix,
-                                 paint.isAntiAlias(),
-                                 oval,
-                                 strokeInfo)) {
-        SkPath path;
-        path.setIsVolatile(true);
-        path.addOval(oval);
-        this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
-                               path, strokeInfo);
-    }
-}
-
-// Can 'path' be drawn as a pair of filled nested rectangles?
-static bool is_nested_rects(GrDrawTarget* target,
-                            GrPipelineBuilder* pipelineBuilder,
-                            GrColor color,
-                            const SkMatrix& viewMatrix,
-                            const SkPath& path,
-                            const SkStrokeRec& stroke,
-                            SkRect rects[2]) {
-    SkASSERT(stroke.isFillStyle());
-
-    if (path.isInverseFillType()) {
-        return false;
-    }
-
-    // TODO: this restriction could be lifted if we were willing to apply
-    // the matrix to all the points individually rather than just to the rect
-    if (!viewMatrix.preservesAxisAlignment()) {
-        return false;
-    }
-
-    SkPath::Direction dirs[2];
-    if (!path.isNestedFillRects(rects, dirs)) {
-        return false;
-    }
-
-    if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
-        // The two rects need to be wound opposite to each other
-        return false;
-    }
-
-    // Right now, nested rects where the margin is not the same width
-    // all around do not render correctly
-    const SkScalar* outer = rects[0].asScalars();
-    const SkScalar* inner = rects[1].asScalars();
-
-    bool allEq = true;
-
-    SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
-    bool allGoE1 = margin >= SK_Scalar1;
-
-    for (int i = 1; i < 4; ++i) {
-        SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
-        if (temp < SK_Scalar1) {
-            allGoE1 = false;
-        }
-        if (!SkScalarNearlyEqual(margin, temp)) {
-            allEq = false;
-        }
-    }
-
-    return allEq || allGoE1;
-}
-
-void GrContext::drawPath(GrRenderTarget* rt,
-                         const GrClip& clip,
-                         const GrPaint& paint,
-                         const SkMatrix& viewMatrix,
-                         const SkPath& path,
-                         const GrStrokeInfo& strokeInfo) {
-    RETURN_IF_ABANDONED
-    if (path.isEmpty()) {
-       if (path.isInverseFillType()) {
-           this->drawPaint(rt, clip, paint, viewMatrix);
-       }
-       return;
-    }
-
-    GrColor color = paint.getColor();
-
-    // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
-    // Scratch textures can be recycled after they are returned to the texture
-    // cache. This presents a potential hazard for buffered drawing. However,
-    // the writePixels that uploads to the scratch will perform a flush so we're
-    // OK.
-    AutoCheckFlush acf(this);
-    GrPipelineBuilder pipelineBuilder;
-    GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-    if (NULL == target) {
-        return;
-    }
-
-    GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex());
-
-    if (!strokeInfo.isDashed()) {
-        bool useCoverageAA = paint.isAntiAlias() &&
-                !pipelineBuilder.getRenderTarget()->isMultisampled();
-
-        if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
-            // Concave AA paths are expensive - try to avoid them for special cases
-            SkRect rects[2];
-
-            if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeInfo,
-                                rects)) {
-                fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix,
-                                                   rects);
-                return;
-            }
-        }
-        SkRect ovalRect;
-        bool isOval = path.isOval(&ovalRect);
-
-        if (isOval && !path.isInverseFillType()) {
-            if (fOvalRenderer->drawOval(target,
-                                        &pipelineBuilder,
-                                        color,
-                                        viewMatrix,
-                                        paint.isAntiAlias(),
-                                        ovalRect,
-                                        strokeInfo)) {
-                return;
-            }
-        }
-    }
-    this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
-                           path, strokeInfo);
-}
-
-void GrContext::internalDrawPath(GrDrawTarget* target,
-                                 GrPipelineBuilder* pipelineBuilder,
-                                 const SkMatrix& viewMatrix,
-                                 GrColor color,
-                                 bool useAA,
-                                 const SkPath& path,
-                                 const GrStrokeInfo& strokeInfo) {
-    RETURN_IF_ABANDONED
-    SkASSERT(!path.isEmpty());
-
-    GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target);
-
-
-    // An Assumption here is that path renderer would use some form of tweaking
-    // the src color (either the input alpha or in the frag shader) to implement
-    // aa. If we have some future driver-mojo path AA that can do the right
-    // thing WRT to the blend then we'll need some query on the PR.
-    bool useCoverageAA = useAA &&
-        !pipelineBuilder->getRenderTarget()->isMultisampled();
-
-
-    GrPathRendererChain::DrawType type =
-        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
-                        GrPathRendererChain::kColor_DrawType;
-
-    const SkPath* pathPtr = &path;
-    SkTLazy<SkPath> tmpPath;
-    const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
-
-    // Try a 1st time without stroking the path and without allowing the SW renderer
-    GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr,
-                                               *strokeInfoPtr, false, type);
-
-    GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
-    if (NULL == pr && strokeInfo.isDashed()) {
-        // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
-        if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
-            return;
-        }
-        pathPtr = tmpPath.get();
-        if (pathPtr->isEmpty()) {
-            return;
-        }
-        strokeInfoPtr = &dashlessStrokeInfo;
-        pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
-                                   false, type);
-    }
-
-    if (NULL == pr) {
-        if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, NULL) &&
-            !strokeInfoPtr->isFillStyle()) {
-            // It didn't work above, so try again with stroke converted to a fill.
-            if (!tmpPath.isValid()) {
-                tmpPath.init();
-            }
-            dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
-            if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
-                return;
-            }
-            pathPtr = tmpPath.get();
-            if (pathPtr->isEmpty()) {
-                return;
-            }
-            dashlessStrokeInfo.setFillStyle();
-            strokeInfoPtr = &dashlessStrokeInfo;
-        }
-
-        // This time, allow SW renderer
-        pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
-                                   true, type);
-    }
-
-    if (NULL == pr) {
-#ifdef SK_DEBUG
-        SkDebugf("Unable to find path renderer compatible with path.\n");
-#endif
-        return;
-    }
-
-    pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::flush(int flagsBitfield) {
-    if (NULL == fDrawBuffer) {
-        return;
-    }
+    RETURN_IF_ABANDONED
 
     if (kDiscard_FlushBit & flagsBitfield) {
-        fDrawBuffer->reset();
+        fDrawingMgr.reset();
     } else {
-        fDrawBuffer->flush();
+        fDrawingMgr.flush();
     }
     fResourceCache->notifyFlushOccurred();
     fFlushToReduceCacheSize = false;
@@ -1412,7 +360,7 @@
 
     // If we didn't do a direct texture write then we upload the pixels to a texture and draw.
     GrRenderTarget* renderTarget = surface->asRenderTarget();
-    if (NULL == renderTarget) {
+    if (!renderTarget) {
         return false;
     }
 
@@ -1451,7 +399,7 @@
         }
         fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
         // handle the unpremul step on the CPU if we couldn't create an effect to do it.
-        if (NULL == fp) {
+        if (!fp) {
             size_t tmpRowBytes = 4 * width;
             tmpPixels.reset(width * height);
             if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
@@ -1462,7 +410,7 @@
             buffer = tmpPixels.get();
         }
     }
-    if (NULL == fp) {
+    if (!fp) {
         fp.reset(GrConfigConversionEffect::Create(texture,
                                                   swapRAndB,
                                                   GrConfigConversionEffect::kNone_PMConversion,
@@ -1483,25 +431,18 @@
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
 
-    // This function can be called in the midst of drawing another object (e.g., when uploading a
-    // SW-rasterized clip while issuing a draw). So we push the current geometry state before
-    // drawing a rect to the render target.
-    // The bracket ensures we pop the stack if we wind up flushing below.
-    {
-        GrDrawTarget* drawTarget = this->prepareToDraw();
-        if (!drawTarget) {
-            return false;
-        }
-
-        GrPipelineBuilder pipelineBuilder;
-        pipelineBuilder.addColorProcessor(fp);
-        pipelineBuilder.setRenderTarget(renderTarget);
-        drawTarget->drawSimpleRect(&pipelineBuilder,
-                                   GrColor_WHITE,
-                                   matrix,
-                                   SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)));
+    GrDrawContext* drawContext = this->drawContext();
+    if (!drawContext) {
+        return false;
     }
 
+    GrPaint paint;
+    paint.addColorProcessor(fp);
+
+    SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+
+    drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
+
     if (kFlushWrites_PixelOp & pixelOpsFlags) {
         this->flushSurfaceWrites(surface);
     }
@@ -1614,16 +555,19 @@
                 // clear to the caller that a draw operation (i.e., drawSimpleRect)
                 // can be invoked in this method
                 {
-                    GrPipelineBuilder pipelineBuilder;
-                    SkASSERT(fp);
-                    pipelineBuilder.addColorProcessor(fp);
+                    GrDrawContext* drawContext = this->drawContext();
+                    if (!drawContext) {
+                        return false;
+                    }
 
-                    pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget());
+                    GrPaint paint;
+                    paint.addColorProcessor(fp);
+
                     SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
-                    fDrawBuffer->drawSimpleRect(&pipelineBuilder,
-                                                GrColor_WHITE,
-                                                SkMatrix::I(),
-                                                rect);
+
+                    drawContext->drawRect(tempTexture->asRenderTarget(), GrClip::WideOpen(), paint,
+                                          SkMatrix::I(), rect, NULL);                    
+
                     // we want to read back from the scratch's origin
                     left = 0;
                     top = 0;
@@ -1673,22 +617,10 @@
     }
 }
 
-void GrContext::discardRenderTarget(GrRenderTarget* renderTarget) {
-    RETURN_IF_ABANDONED
-    SkASSERT(renderTarget);
-    ASSERT_OWNED_RESOURCE(renderTarget);
-    AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw();
-    if (NULL == target) {
-        return;
-    }
-    target->discard(renderTarget);
-}
-
 void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
                             const SkIPoint& dstPoint, uint32_t pixelOpsFlags) {
     RETURN_IF_ABANDONED
-    if (NULL == src || NULL == dst) {
+    if (!src || !dst) {
         return;
     }
     ASSERT_OWNED_RESOURCE(src);
@@ -1696,12 +628,16 @@
 
     // Since we're going to the draw target and not GPU, no need to check kNoFlush
     // here.
-
-    GrDrawTarget* target = this->prepareToDraw();
-    if (NULL == target) {
+    if (!dst->asRenderTarget()) {
         return;
     }
-    target->copySurface(dst, src, srcRect, dstPoint);
+
+    GrDrawContext* drawContext = this->drawContext();
+    if (!drawContext) {
+        return;
+    }
+
+    drawContext->copySurface(dst->asRenderTarget(), src, srcRect, dstPoint);
 
     if (kFlushWrites_PixelOp & pixelOpsFlags) {
         this->flush();
@@ -1715,28 +651,6 @@
     }
 }
 
-GrDrawTarget* GrContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder,
-                                       GrRenderTarget* rt,
-                                       const GrClip& clip,
-                                       const GrPaint* paint,
-                                       const AutoCheckFlush* acf) {
-    if (NULL == fGpu || NULL == fDrawBuffer) {
-        return NULL;
-    }
-
-    ASSERT_OWNED_RESOURCE(rt);
-    SkASSERT(rt && paint && acf);
-    pipelineBuilder->setFromPaint(*paint, rt, clip);
-    return fDrawBuffer;
-}
-
-GrDrawTarget* GrContext::prepareToDraw() {
-    if (NULL == fGpu) {
-        return NULL;
-    }
-    return fDrawBuffer;
-}
-
 /*
  * This method finds a path renderer that can draw the specified path on
  * the provided target.
@@ -1752,7 +666,7 @@
                                            GrPathRendererChain::DrawType drawType,
                                            GrPathRendererChain::StencilSupport* stencilSupport) {
 
-    if (NULL == fPathRendererChain) {
+    if (!fPathRendererChain) {
         fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
     }
 
@@ -1764,8 +678,8 @@
                                                              drawType,
                                                              stencilSupport);
 
-    if (NULL == pr && allowSW) {
-        if (NULL == fSoftwarePathRenderer) {
+    if (!pr && allowSW) {
+        if (!fSoftwarePathRenderer) {
             fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
         }
         pr = fSoftwarePathRenderer;
@@ -1796,10 +710,6 @@
         chosenSampleCount : 0;
 }
 
-GrDrawTarget* GrContext::getTextTarget() {
-    return this->prepareToDraw();
-}
-
 namespace {
 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
     GrConfigConversionEffect::PMConversion pmToUPM;
@@ -1861,141 +771,9 @@
 
 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
     fGpu->addGpuTraceMarker(marker);
-    if (fDrawBuffer) {
-        fDrawBuffer->addGpuTraceMarker(marker);
-    }
 }
 
 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
     fGpu->removeGpuTraceMarker(marker);
-    if (fDrawBuffer) {
-        fDrawBuffer->removeGpuTraceMarker(marker);
-    }
 }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef GR_TEST_UTILS
-
-BATCH_TEST_DEFINE(StrokeRectBatch) {
-    StrokeRectBatch::Geometry geometry;
-    geometry.fViewMatrix = GrTest::TestMatrix(random);
-    geometry.fColor = GrRandomColor(random);
-    geometry.fRect = GrTest::TestRect(random);
-    geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f;
-
-    return StrokeRectBatch::Create(geometry, random->nextBool());
-}
-
-static uint32_t seed_vertices(GrPrimitiveType type) {
-    switch (type) {
-        case kTriangles_GrPrimitiveType:
-        case kTriangleStrip_GrPrimitiveType:
-        case kTriangleFan_GrPrimitiveType:
-            return 3;
-        case kPoints_GrPrimitiveType:
-            return 1;
-        case kLines_GrPrimitiveType:
-        case kLineStrip_GrPrimitiveType:
-            return 2;
-    }
-    SkFAIL("Incomplete switch\n");
-    return 0;
-}
-
-static uint32_t primitive_vertices(GrPrimitiveType type) {
-    switch (type) {
-        case kTriangles_GrPrimitiveType:
-            return 3;
-        case kLines_GrPrimitiveType:
-            return 2;
-        case kTriangleStrip_GrPrimitiveType:
-        case kTriangleFan_GrPrimitiveType:
-        case kPoints_GrPrimitiveType:
-        case kLineStrip_GrPrimitiveType:
-            return 1;
-    }
-    SkFAIL("Incomplete switch\n");
-    return 0;
-}
-
-static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) {
-    SkPoint p;
-    p.fX = random->nextRangeScalar(min, max);
-    p.fY = random->nextRangeScalar(min, max);
-    return p;
-}
-
-static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max,
-                             SkRandom* random,
-                             SkTArray<SkPoint>* positions,
-                             SkTArray<SkPoint>* texCoords, bool hasTexCoords,
-                             SkTArray<GrColor>* colors, bool hasColors,
-                             SkTArray<uint16_t>* indices, bool hasIndices) {
-    for (uint32_t v = 0; v < count; v++) {
-        positions->push_back(random_point(random, min, max));
-        if (hasTexCoords) {
-            texCoords->push_back(random_point(random, min, max));
-        }
-        if (hasColors) {
-            colors->push_back(GrRandomColor(random));
-        }
-        if (hasIndices) {
-            SkASSERT(maxVertex <= SK_MaxU16);
-            indices->push_back(random->nextULessThan((uint16_t)maxVertex));
-        }
-    }
-}
-
-BATCH_TEST_DEFINE(VerticesBatch) {
-    GrPrimitiveType type = GrPrimitiveType(random->nextULessThan(kLast_GrPrimitiveType + 1));
-    uint32_t primitiveCount = random->nextRangeU(1, 100);
-
-    // TODO make 'sensible' indexbuffers
-    SkTArray<SkPoint> positions;
-    SkTArray<SkPoint> texCoords;
-    SkTArray<GrColor> colors;
-    SkTArray<uint16_t> indices;
-
-    bool hasTexCoords = random->nextBool();
-    bool hasIndices = random->nextBool();
-    bool hasColors = random->nextBool();
-
-    uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitive_vertices(type);
-
-    static const SkScalar kMinVertExtent = -100.f;
-    static const SkScalar kMaxVertExtent = 100.f;
-    randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
-                     random,
-                     &positions,
-                     &texCoords, hasTexCoords,
-                     &colors, hasColors,
-                     &indices, hasIndices);
-
-    for (uint32_t i = 1; i < primitiveCount; i++) {
-        randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
-                         random,
-                         &positions,
-                         &texCoords, hasTexCoords,
-                         &colors, hasColors,
-                         &indices, hasIndices);
-    }
-
-    SkMatrix viewMatrix = GrTest::TestMatrix(random);
-    SkRect bounds;
-    SkDEBUGCODE(bool result = ) bounds.setBoundsCheck(positions.begin(), vertexCount);
-    SkASSERT(result);
-
-    viewMatrix.mapRect(&bounds);
-
-    DrawVerticesBatch::Geometry geometry;
-    geometry.fColor = GrRandomColor(random);
-    return DrawVerticesBatch::Create(geometry, type, viewMatrix,
-                                     positions.begin(), vertexCount,
-                                     indices.begin(), hasIndices ? vertexCount : 0,
-                                     colors.begin(),
-                                     texCoords.begin(),
-                                     bounds);
-}
-
-#endif