Split drawing functionality out of GrContext and into new GrDrawContext
authorrobertphillips <robertphillips@google.com>
Tue, 26 May 2015 18:38:03 +0000 (11:38 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 26 May 2015 18:38:03 +0000 (11:38 -0700)
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

39 files changed:
gm/texdata.cpp
gyp/gpu.gypi
include/gpu/GrContext.h
include/gpu/GrDrawContext.h [new file with mode: 0644]
src/core/SkImageFilter.cpp
src/effects/SkAlphaThresholdFilter.cpp
src/effects/SkBlurMaskFilter.cpp
src/effects/SkDisplacementMapEffect.cpp
src/effects/SkGpuBlurUtils.cpp
src/effects/SkLightingImageFilter.cpp
src/effects/SkMorphologyImageFilter.cpp
src/effects/SkXfermodeImageFilter.cpp
src/gpu/GrAARectRenderer.cpp
src/gpu/GrAARectRenderer.h
src/gpu/GrAtlas.h
src/gpu/GrAtlasTextContext.cpp
src/gpu/GrAtlasTextContext.h
src/gpu/GrBatchFontCache.h
src/gpu/GrClipMaskManager.cpp
src/gpu/GrContext.cpp
src/gpu/GrDefaultPathRenderer.cpp
src/gpu/GrDrawContext.cpp [new file with mode: 0644]
src/gpu/GrDrawTarget.cpp
src/gpu/GrDrawTarget.h
src/gpu/GrLayerCache.cpp
src/gpu/GrOvalRenderer.cpp
src/gpu/GrOvalRenderer.h
src/gpu/GrRenderTarget.cpp
src/gpu/GrSWMaskHelper.cpp
src/gpu/GrSoftwarePathRenderer.cpp
src/gpu/GrStencilAndCoverPathRenderer.cpp
src/gpu/GrStencilAndCoverTextContext.cpp
src/gpu/GrTest.cpp
src/gpu/GrTextContext.cpp
src/gpu/GrTextContext.h
src/gpu/SkGpuDevice.cpp
src/gpu/SkGpuDevice.h
src/gpu/SkGr.cpp
src/gpu/effects/GrConfigConversionEffect.cpp

index dff2944..e7c15b2 100644 (file)
@@ -12,6 +12,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "SkColorPriv.h"
 #include "effects/GrPorterDuffXferProcessor.h"
 #include "effects/GrSimpleTextureEffect.h"
@@ -38,7 +39,8 @@ protected:
     void onDraw(SkCanvas* canvas) override {
         GrRenderTarget* target = canvas->internal_private_accessTopLayerRenderTarget();
         GrContext* ctx = canvas->getGrContext();
-        if (ctx && target) {
+        GrDrawContext* drawContext = ctx ? ctx->drawContext() : NULL;
+        if (drawContext && target) {
             SkAutoTArray<SkPMColor> gTextureData((2 * S) * (2 * S));
             static const int stride = 2 * S;
             static const SkPMColor gray  = SkPackARGB32(0x40, 0x40, 0x40, 0x40);
@@ -111,7 +113,7 @@ protected:
                 tm.postIDiv(2*S, 2*S);
                 paint.addColorTextureProcessor(texture, tm);
 
-                ctx->drawRect(target, clip, paint, vm, SkRect::MakeWH(2*S, 2*S));
+                drawContext->drawRect(target, clip, paint, vm, SkRect::MakeWH(2*S, 2*S));
 
                 // now update the lower right of the texture in first pass
                 // or upper right in second pass
@@ -125,7 +127,7 @@ protected:
                 texture->writePixels(S, (i ? 0 : S), S, S,
                                      texture->config(), gTextureData.get(),
                                      4 * stride);
-                ctx->drawRect(target, clip, paint, vm, SkRect::MakeWH(2*S, 2*S));
+                drawContext->drawRect(target, clip, paint, vm, SkRect::MakeWH(2*S, 2*S));
             }
         } else {
             this->drawGpuOnlyMessage(canvas);
index 01f70f1..15f6647 100644 (file)
@@ -19,6 +19,7 @@
       '<(skia_include_path)/gpu/GrContextOptions.h',
       '<(skia_include_path)/gpu/GrContext.h',
       '<(skia_include_path)/gpu/GrCoordTransform.h',
+      '<(skia_include_path)/gpu/GrDrawContext.h',
       '<(skia_include_path)/gpu/GrFragmentProcessor.h',
       '<(skia_include_path)/gpu/GrFragmentStage.h',
       '<(skia_include_path)/gpu/GrGpuResource.h',
       '<(skia_src_path)/gpu/GrDefaultGeoProcFactory.h',
       '<(skia_src_path)/gpu/GrDefaultPathRenderer.cpp',
       '<(skia_src_path)/gpu/GrDefaultPathRenderer.h',
+      '<(skia_src_path)/gpu/GrDrawContext.cpp',
       '<(skia_src_path)/gpu/GrDrawTarget.cpp',
       '<(skia_src_path)/gpu/GrDrawTarget.h',
       '<(skia_src_path)/gpu/GrFontAtlasSizes.h',
index b6fef3d..2167513 100644 (file)
@@ -21,6 +21,7 @@
 class GrAARectRenderer;
 class GrBatchFontCache;
 struct GrContextOptions;
+class GrDrawContext;
 class GrDrawTarget;
 class GrFragmentProcessor;
 class GrGpu;
@@ -158,6 +159,11 @@ public:
     /// Texture and Render Target Queries
 
     /**
+     * Are shader derivatives supported?
+     */
+    bool shaderDerivativeSupport() const;
+
+    /**
      * Can the provided configuration act as a texture?
      */
     bool isConfigTexturable(GrPixelConfig) const;
@@ -211,167 +217,14 @@ public:
      */
     int getRecommendedSampleCount(GrPixelConfig config, SkScalar dpi) const;
 
-    ///////////////////////////////////////////////////////////////////////////
-    // Draws
-
     /**
-     * Clear the entire or rect of the render target, ignoring any clips.
-     * @param rect  the rect to clear or the whole thing if rect is NULL.
-     * @param color the color to clear to.
-     * @param canIgnoreRect allows partial clears to be converted to whole
-     *                      clears on platforms for which that is cheap
-     * @param target The render target to clear.
-     */
-    void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect, GrRenderTarget* target);
-
-    /**
-     *  Draw everywhere (respecting the clip) with the paint.
-     */
-    void drawPaint(GrRenderTarget*, const GrClip&, const GrPaint&, const SkMatrix& viewMatrix);
-
-    /**
-     *  Draw the rect using a paint.
-     *  @param paint        describes how to color pixels.
-     *  @param viewMatrix   transformation matrix
-     *  @param strokeInfo   the stroke information (width, join, cap), and.
-     *                      the dash information (intervals, count, phase).
-     *                      If strokeInfo == NULL, then the rect is filled.
-     *                      Otherwise, if stroke width == 0, then the stroke
-     *                      is always a single pixel thick, else the rect is
-     *                      mitered/beveled stroked based on stroke width.
-     *  The rects coords are used to access the paint (through texture matrix)
-     */
-    void drawRect(GrRenderTarget*,
-                  const GrClip&,
-                  const GrPaint& paint,
-                  const SkMatrix& viewMatrix,
-                  const SkRect&,
-                  const GrStrokeInfo* strokeInfo = NULL);
-
-    /**
-     * Maps a rectangle of shader coordinates to a rectangle and draws that rectangle
-     *
-     * @param paint         describes how to color pixels.
-     * @param viewMatrix    transformation matrix which applies to rectToDraw
-     * @param rectToDraw    the rectangle to draw
-     * @param localRect     the rectangle of shader coordinates applied to rectToDraw
-     * @param localMatrix   an optional matrix to transform the shader coordinates before applying
-     *                      to rectToDraw
-     */
-    void drawNonAARectToRect(GrRenderTarget*,
-                             const GrClip&,
-                             const GrPaint& paint,
-                             const SkMatrix& viewMatrix,
-                             const SkRect& rectToDraw,
-                             const SkRect& localRect,
-                             const SkMatrix* localMatrix = NULL);
-
-    /**
-     * Draws a non-AA rect with paint and a localMatrix
-     */
-    void drawNonAARectWithLocalMatrix(GrRenderTarget* rt,
-                                      const GrClip& clip,
-                                      const GrPaint& paint,
-                                      const SkMatrix& viewMatrix,
-                                      const SkRect& rect,
-                                      const SkMatrix& localMatrix) {
-        this->drawNonAARectToRect(rt, clip, paint, viewMatrix, rect, rect, &localMatrix);
-    }
-
-    /**
-     *  Draw a roundrect using a paint.
-     *
-     *  @param paint        describes how to color pixels.
-     *  @param viewMatrix   transformation matrix
-     *  @param rrect        the roundrect to draw
-     *  @param strokeInfo   the stroke information (width, join, cap) and
-     *                      the dash information (intervals, count, phase).
-     */
-    void drawRRect(GrRenderTarget*,
-                   const GrClip&,
-                   const GrPaint&,
-                   const SkMatrix& viewMatrix,
-                   const SkRRect& rrect,
-                   const GrStrokeInfo&);
-
-    /**
-     *  Shortcut for drawing an SkPath consisting of nested rrects using a paint.
-     *  Does not support stroking. The result is undefined if outer does not contain
-     *  inner.
+     * Returns a helper object to orchestrate draws. 
      *
-     *  @param paint        describes how to color pixels.
-     *  @param viewMatrix   transformation matrix
-     *  @param outer        the outer roundrect
-     *  @param inner        the inner roundrect
-     */
-    void drawDRRect(GrRenderTarget*,
-                    const GrClip&,
-                    const GrPaint&,
-                    const SkMatrix& viewMatrix,
-                    const SkRRect& outer,
-                    const SkRRect& inner);
-
-
-    /**
-     * Draws a path.
-     *
-     * @param paint         describes how to color pixels.
-     * @param viewMatrix    transformation matrix
-     * @param path          the path to draw
-     * @param strokeInfo    the stroke information (width, join, cap) and
-     *                      the dash information (intervals, count, phase).
+     * @return a draw context
      */
-    void drawPath(GrRenderTarget*,
-                  const GrClip&,
-                  const GrPaint&,
-                  const SkMatrix& viewMatrix,
-                  const SkPath&,
-                  const GrStrokeInfo&);
-
-    /**
-     * Draws vertices with a paint.
-     *
-     * @param   paint           describes how to color pixels.
-     * @param   viewMatrix      transformation matrix
-     * @param   primitiveType   primitives type to draw.
-     * @param   vertexCount     number of vertices.
-     * @param   positions       array of vertex positions, required.
-     * @param   texCoords       optional array of texture coordinates used
-     *                          to access the paint.
-     * @param   colors          optional array of per-vertex colors, supercedes
-     *                          the paint's color field.
-     * @param   indices         optional array of indices. If NULL vertices
-     *                          are drawn non-indexed.
-     * @param   indexCount      if indices is non-null then this is the
-     *                          number of indices.
-     */
-    void drawVertices(GrRenderTarget*,
-                      const GrClip&,
-                      const GrPaint& paint,
-                      const SkMatrix& viewMatrix,
-                      GrPrimitiveType primitiveType,
-                      int vertexCount,
-                      const SkPoint positions[],
-                      const SkPoint texs[],
-                      const GrColor colors[],
-                      const uint16_t indices[],
-                      int indexCount);
-
-    /**
-     * Draws an oval.
-     *
-     * @param paint         describes how to color pixels.
-     * @param viewMatrix    transformation matrix
-     * @param oval          the bounding rect of the oval.
-     * @param strokeInfo    the stroke information (width, join, cap) and
-     *                      the dash information (intervals, count, phase).
-     */
-    void drawOval(GrRenderTarget*,
-                  const GrClip&,
-                  const GrPaint& paint,
-                  const SkMatrix& viewMatrix,
-                  const SkRect& oval,
-                  const GrStrokeInfo& strokeInfo);
+    GrDrawContext* drawContext() {
+        return fDrawingMgr.drawContext();    
+    }
 
     ///////////////////////////////////////////////////////////////////////////
     // Misc.
@@ -397,6 +250,12 @@ public:
      */
     void flush(int flagsBitfield = 0);
 
+    void flushIfNecessary() {
+        if (fFlushToReduceCacheSize) {
+            this->flush();
+        }    
+    }
+
    /**
     * These flags can be used with the read/write pixels functions below.
     */
@@ -500,12 +359,6 @@ public:
     void prepareSurfaceForExternalRead(GrSurface*);
 
     /**
-     * Provides a perfomance hint that the render target's contents are allowed
-     * to become undefined.
-     */
-    void discardRenderTarget(GrRenderTarget*);
-
-    /**
      * An ID associated with this context, guaranteed to be unique.
      */
     uint32_t uniqueID() { return fUniqueID; }
@@ -517,8 +370,7 @@ public:
     GrBatchFontCache* getBatchFontCache() { return fBatchFontCache; }
     GrLayerCache* getLayerCache() { return fLayerCache.get(); }
     GrTextBlobCache* getTextBlobCache() { return fTextBlobCache; }
-    GrDrawTarget* getTextTarget();
-    GrAARectRenderer* getAARectRenderer() { return fAARectRenderer; }
+    bool abandoned() const { return fDrawingMgr.abandoned(); }
     GrResourceProvider* resourceProvider() { return fResourceProvider; }
     const GrResourceProvider* resourceProvider() const { return fResourceProvider; }
     GrResourceCache* getResourceCache() { return fResourceCache; }
@@ -564,13 +416,8 @@ private:
     GrPathRendererChain*            fPathRendererChain;
     GrSoftwarePathRenderer*         fSoftwarePathRenderer;
 
-    GrDrawTarget*                   fDrawBuffer;
-
     // Set by OverbudgetCB() to request that GrContext flush before exiting a draw.
     bool                            fFlushToReduceCacheSize;
-    GrAARectRenderer*               fAARectRenderer;
-    GrOvalRenderer*                 fOvalRenderer;
-
     bool                            fDidTestPMConversions;
     int                             fPMToUPMConversion;
     int                             fUPMToPMConversion;
@@ -588,28 +435,46 @@ private:
 
     GrContext(); // init must be called after the constructor.
     bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
+
+    // Currently the DrawingMgr just wraps the single GrDrawTarget in a single
+    // GrDrawContext and hands it out. In the future this class will allocate
+    // a new GrDrawContext for each GrRenderTarget/GrDrawTarget and manage
+    // the DAG.
+    class DrawingMgr {
+    public:
+        DrawingMgr()
+            : fDrawTarget(NULL)
+            , fDrawContext(NULL) {
+        }
+
+        ~DrawingMgr();
+
+        void init(GrContext* context);
+
+        void abandon();
+        bool abandoned() const { return NULL == fDrawTarget; }
+
+        void purgeResources();
+        void reset();
+        void flush();
+
+        // Callers should take a ref if they rely on the GrDrawContext sticking around.
+        // NULL will be returned if the context has been abandoned.
+        GrDrawContext* drawContext();
+
+    private:
+        friend class GrContext;  // for access to fDrawTarget for testing
+
+        GrDrawTarget*     fDrawTarget;
+
+        GrDrawContext*    fDrawContext;
+    };
+
+    DrawingMgr                      fDrawingMgr;
+
     void initMockContext();
     void initCommon();
 
-    class AutoCheckFlush;
-    // Sets the paint and returns the target to draw into.
-    GrDrawTarget* prepareToDraw(GrPipelineBuilder*,
-                                GrRenderTarget* rt,
-                                const GrClip&,
-                                const GrPaint* paint,
-                                const AutoCheckFlush*);
-
-    // A simpler version of the above which just returns the draw target.  Clip is *NOT* set
-    GrDrawTarget* prepareToDraw();
-
-    void internalDrawPath(GrDrawTarget*,
-                          GrPipelineBuilder*,
-                          const SkMatrix& viewMatrix,
-                          GrColor,
-                          bool useAA,
-                          const SkPath&,
-                          const GrStrokeInfo&);
-
     /**
      * Creates a new text rendering context that is optimal for the
      * render target and the context. Caller assumes the ownership
diff --git a/include/gpu/GrDrawContext.h b/include/gpu/GrDrawContext.h
new file mode 100644 (file)
index 0000000..1ed99c1
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDrawContext_DEFINED
+#define GrDrawContext_DEFINED
+
+#include "GrColor.h"
+#include "SkRefCnt.h"
+
+class GrBatch;
+class GrClip;
+class GrContext;
+class GrDrawTarget;
+class GrPaint;
+class GrPathProcessor;
+class GrPathRange;
+class GrPipelineBuilder;
+class GrRenderTarget;
+class GrStrokeInfo;
+class GrSurface;
+struct SkIPoint;
+struct SkIRect;
+class SkMatrix;
+class SkPath;
+struct SkPoint;
+struct SkRect;
+class SkRRect;
+
+
+/*
+ * A helper object to orchestrate draws
+ */
+class SK_API GrDrawContext : public SkRefCnt {
+public:
+    SK_DECLARE_INST_COUNT(GrDrawContext)
+
+    void copySurface(GrRenderTarget* dst, GrSurface* src,
+                     const SkIRect& srcRect, const SkIPoint& dstPoint);
+
+    // drawText and drawPaths are thanks to the GrAtlasTextContext and the 
+    // GrStencilAndCoverTextContext respectively
+    // TODO: remove these two
+    void drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch);
+
+    void drawPaths(GrPipelineBuilder* pipelineBuilder,
+                   const GrPathProcessor* pathProc,
+                   const GrPathRange* pathRange,
+                   const void* indices,
+                   int /*GrDrawTarget::PathIndexType*/ indexType,
+                   const float transformValues[],
+                   int /*GrDrawTarget::PathTransformType*/ transformType,
+                   int count,
+                   int /*GrPathRendering::FillType*/ fill);
+
+    /**
+     * Provides a perfomance hint that the render target's contents are allowed
+     * to become undefined.
+     */
+    void discard(GrRenderTarget*);
+
+    /**
+     * Clear the entire or rect of the render target, ignoring any clips.
+     * @param target The render target to clear.
+     * @param rect  the rect to clear or the whole thing if rect is NULL.
+     * @param color the color to clear to.
+     * @param canIgnoreRect allows partial clears to be converted to whole
+     *                      clears on platforms for which that is cheap
+     */
+    void clear(GrRenderTarget*, const SkIRect* rect, GrColor color, bool canIgnoreRect);
+
+    /**
+     *  Draw everywhere (respecting the clip) with the paint.
+     */
+    void drawPaint(GrRenderTarget*, const GrClip&, const GrPaint&, const SkMatrix& viewMatrix);
+
+    /**
+     *  Draw the rect using a paint.
+     *  @param paint        describes how to color pixels.
+     *  @param viewMatrix   transformation matrix
+     *  @param strokeInfo   the stroke information (width, join, cap), and.
+     *                      the dash information (intervals, count, phase).
+     *                      If strokeInfo == NULL, then the rect is filled.
+     *                      Otherwise, if stroke width == 0, then the stroke
+     *                      is always a single pixel thick, else the rect is
+     *                      mitered/beveled stroked based on stroke width.
+     *  The rects coords are used to access the paint (through texture matrix)
+     */
+    void drawRect(GrRenderTarget*,
+                  const GrClip&,
+                  const GrPaint& paint,
+                  const SkMatrix& viewMatrix,
+                  const SkRect&,
+                  const GrStrokeInfo* strokeInfo = NULL);
+
+    /**
+     * Maps a rectangle of shader coordinates to a rectangle and draws that rectangle
+     *
+     * @param paint         describes how to color pixels.
+     * @param viewMatrix    transformation matrix which applies to rectToDraw
+     * @param rectToDraw    the rectangle to draw
+     * @param localRect     the rectangle of shader coordinates applied to rectToDraw
+     * @param localMatrix   an optional matrix to transform the shader coordinates before applying
+     *                      to rectToDraw
+     */
+    void drawNonAARectToRect(GrRenderTarget*,
+                             const GrClip&,
+                             const GrPaint& paint,
+                             const SkMatrix& viewMatrix,
+                             const SkRect& rectToDraw,
+                             const SkRect& localRect,
+                             const SkMatrix* localMatrix = NULL);
+
+    /**
+     * Draws a non-AA rect with paint and a localMatrix
+     */
+    void drawNonAARectWithLocalMatrix(GrRenderTarget* rt,
+                                      const GrClip& clip,
+                                      const GrPaint& paint,
+                                      const SkMatrix& viewMatrix,
+                                      const SkRect& rect,
+                                      const SkMatrix& localMatrix) {
+        this->drawNonAARectToRect(rt, clip, paint, viewMatrix, rect, rect, &localMatrix);
+    }
+
+    /**
+     *  Draw a roundrect using a paint.
+     *
+     *  @param paint        describes how to color pixels.
+     *  @param viewMatrix   transformation matrix
+     *  @param rrect        the roundrect to draw
+     *  @param strokeInfo   the stroke information (width, join, cap) and
+     *                      the dash information (intervals, count, phase).
+     */
+    void drawRRect(GrRenderTarget*,
+                   const GrClip&,
+                   const GrPaint&,
+                   const SkMatrix& viewMatrix,
+                   const SkRRect& rrect,
+                   const GrStrokeInfo&);
+
+    /**
+     *  Shortcut for drawing an SkPath consisting of nested rrects using a paint.
+     *  Does not support stroking. The result is undefined if outer does not contain
+     *  inner.
+     *
+     *  @param paint        describes how to color pixels.
+     *  @param viewMatrix   transformation matrix
+     *  @param outer        the outer roundrect
+     *  @param inner        the inner roundrect
+     */
+    void drawDRRect(GrRenderTarget*,
+                    const GrClip&,
+                    const GrPaint&,
+                    const SkMatrix& viewMatrix,
+                    const SkRRect& outer,
+                    const SkRRect& inner);
+
+
+    /**
+     * Draws a path.
+     *
+     * @param paint         describes how to color pixels.
+     * @param viewMatrix    transformation matrix
+     * @param path          the path to draw
+     * @param strokeInfo    the stroke information (width, join, cap) and
+     *                      the dash information (intervals, count, phase).
+     */
+    void drawPath(GrRenderTarget*,
+                  const GrClip&,
+                  const GrPaint&,
+                  const SkMatrix& viewMatrix,
+                  const SkPath&,
+                  const GrStrokeInfo&);
+
+    /**
+     * Draws vertices with a paint.
+     *
+     * @param   paint           describes how to color pixels.
+     * @param   viewMatrix      transformation matrix
+     * @param   primitiveType   primitives type to draw.
+     * @param   vertexCount     number of vertices.
+     * @param   positions       array of vertex positions, required.
+     * @param   texCoords       optional array of texture coordinates used
+     *                          to access the paint.
+     * @param   colors          optional array of per-vertex colors, supercedes
+     *                          the paint's color field.
+     * @param   indices         optional array of indices. If NULL vertices
+     *                          are drawn non-indexed.
+     * @param   indexCount      if indices is non-null then this is the
+     *                          number of indices.
+     */
+    void drawVertices(GrRenderTarget*,
+                      const GrClip&,
+                      const GrPaint& paint,
+                      const SkMatrix& viewMatrix,
+                      GrPrimitiveType primitiveType,
+                      int vertexCount,
+                      const SkPoint positions[],
+                      const SkPoint texs[],
+                      const GrColor colors[],
+                      const uint16_t indices[],
+                      int indexCount);
+
+    /**
+     * Draws an oval.
+     *
+     * @param paint         describes how to color pixels.
+     * @param viewMatrix    transformation matrix
+     * @param oval          the bounding rect of the oval.
+     * @param strokeInfo    the stroke information (width, join, cap) and
+     *                      the dash information (intervals, count, phase).
+     */
+    void drawOval(GrRenderTarget*,
+                  const GrClip&,
+                  const GrPaint& paint,
+                  const SkMatrix& viewMatrix,
+                  const SkRect& oval,
+                  const GrStrokeInfo& strokeInfo);
+
+
+private:
+    friend class GrContext; // for ctor
+
+    GrDrawContext(GrContext* context, GrDrawTarget* drawTarget);
+
+    // Sets the paint. Returns true on success; false on failure.
+    bool prepareToDraw(GrPipelineBuilder*,
+                       GrRenderTarget* rt,
+                       const GrClip&,
+                       const GrPaint* paint);
+
+    // A simpler version of the above which just returns true on success; false on failure.  
+    // Clip is *NOT* set
+    bool prepareToDraw(GrRenderTarget* rt);
+
+    void internalDrawPath(GrDrawTarget*,
+                          GrPipelineBuilder*,
+                          const SkMatrix& viewMatrix,
+                          GrColor,
+                          bool useAA,
+                          const SkPath&,
+                          const GrStrokeInfo&);
+
+    GrContext*                     fContext;     // owning context -> no ref
+    SkAutoTUnref<GrDrawTarget>     fDrawTarget;
+};
+
+#endif
index 0a5e16e..91b3bc3 100644 (file)
@@ -20,6 +20,7 @@
 #include "SkValidationUtils.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "SkGrPixelRef.h"
 #include "SkGr.h"
 #endif
@@ -276,11 +277,15 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont
         SkASSERT(fp);
         GrPaint paint;
         paint.addColorProcessor(fp)->unref();
-        context->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(), dstRect,
-                                     srcRect);
 
-        WrapTexture(dst, bounds.width(), bounds.height(), result);
-        return true;
+        GrDrawContext* drawContext = context->drawContext();
+        if (drawContext) {
+            drawContext->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(),
+                                             dstRect, srcRect);
+
+            WrapTexture(dst, bounds.width(), bounds.height(), result);
+            return true;
+        }
     }
 #endif
     return false;
index d463877..395408c 100644 (file)
@@ -10,6 +10,9 @@
 #include "SkReadBuffer.h"
 #include "SkWriteBuffer.h"
 #include "SkRegion.h"
+#if SK_SUPPORT_GPU
+#include "GrDrawContext.h"
+#endif
 
 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter {
 public:
@@ -284,16 +287,17 @@ bool SkAlphaThresholdFilterImpl::asFragmentProcessor(GrFragmentProcessor** fp,
             return false;
         }
 
-        {
+        GrDrawContext* drawContext = context->drawContext();
+        if (drawContext) {
             GrPaint grPaint;
             grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
             SkRegion::Iterator iter(fRegion);
-            context->clear(NULL, 0x0, true, maskTexture->asRenderTarget());
+            drawContext->clear(maskTexture->asRenderTarget(), NULL, 0x0, true);
 
             while (!iter.done()) {
                 SkRect rect = SkRect::Make(iter.rect());
-                context->drawRect(maskTexture->asRenderTarget(), GrClip::WideOpen(), grPaint,
-                                  in_matrix, rect);
+                drawContext->drawRect(maskTexture->asRenderTarget(), GrClip::WideOpen(), grPaint,
+                                      in_matrix, rect);
                 iter.next();
             }
         }
index 556cb44..22a9ac6 100644 (file)
@@ -19,6 +19,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "GrTexture.h"
 #include "GrFragmentProcessor.h"
 #include "GrInvariantOutput.h"
@@ -870,8 +871,14 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context,
     if (!viewMatrix.invert(&inverse)) {
         return false;
     }
-    context->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), rect, inverse);
-    return true;
+
+    GrDrawContext* drawContext = context->drawContext();
+    if (drawContext) {
+        drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), rect, inverse);
+        return true;
+    }
+
+    return false;
 }
 
 class GrRRectBlurEffect : public GrFragmentProcessor {
@@ -1154,8 +1161,15 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
     if (!viewMatrix.invert(&inverse)) {
         return false;
     }
-    context->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), proxy_rect, inverse);
-    return true;
+
+    GrDrawContext* drawContext = context->drawContext();
+    if (drawContext) {
+        drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(),
+                                                  proxy_rect, inverse);
+        return true;
+    }
+
+    return false;
 }
 
 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
@@ -1236,8 +1250,14 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
             //             = 0 * src + (1 - src) * dst
             paint.setCoverageSetOpXPFactory(SkRegion::kDifference_Op);
         }
-        context->drawRect((*result)->asRenderTarget(), GrClip::WideOpen(), paint, SkMatrix::I(),
-                          clipRect);
+
+        GrDrawContext* drawContext = context->drawContext();
+        if (!drawContext) {
+            return false;
+        }
+
+        drawContext->drawRect((*result)->asRenderTarget(), GrClip::WideOpen(),
+                              paint, SkMatrix::I(), clipRect);
     }
 
     return true;
index 23202e2..d7d92c8 100644 (file)
@@ -12,6 +12,7 @@
 #include "SkColorPriv.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "GrCoordTransform.h"
 #include "GrInvariantOutput.h"
 #include "effects/GrTextureDomain.h"
@@ -457,8 +458,14 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
     SkMatrix matrix;
     matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
                         -SkIntToScalar(colorBounds.y()));
-    context->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, matrix,
-                      SkRect::Make(colorBounds));
+
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return false;
+    }
+
+    drawContext->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, matrix,
+                          SkRect::Make(colorBounds));
     offset->fX = bounds.left();
     offset->fY = bounds.top();
     WrapTexture(dst, bounds.width(), bounds.height(), result);
index 6cb349e..4997afe 100644 (file)
@@ -13,6 +13,7 @@
 #include "effects/GrConvolutionEffect.h"
 #include "effects/GrMatrixConvolutionEffect.h"
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #endif
 
 namespace SkGpuBlurUtils {
@@ -43,7 +44,7 @@ static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int
     return sigma;
 }
 
-static void convolve_gaussian_1d(GrContext* context,
+static void convolve_gaussian_1d(GrDrawContext* drawContext,
                                  GrRenderTarget* rt,
                                  const GrClip& clip,
                                  const SkRect& srcRect,
@@ -58,10 +59,10 @@ static void convolve_gaussian_1d(GrContext* context,
     SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
         texture, direction, radius, sigma, useBounds, bounds));
     paint.addColorProcessor(conv);
-    context->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRect);
+    drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRect);
 }
 
-static void convolve_gaussian_2d(GrContext* context,
+static void convolve_gaussian_2d(GrDrawContext* drawContext,
                                  GrRenderTarget* rt,
                                  const GrClip& clip,
                                  const SkRect& srcRect,
@@ -81,10 +82,10 @@ static void convolve_gaussian_2d(GrContext* context,
             useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_Mode,
             true, sigmaX, sigmaY));
     paint.addColorProcessor(conv);
-    context->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRect);
+    drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRect);
 }
 
-static void convolve_gaussian(GrContext* context,
+static void convolve_gaussian(GrDrawContext* drawContext,
                               GrRenderTarget* rt,
                               const GrClip& clip,
                               const SkRect& srcRect,
@@ -96,7 +97,7 @@ static void convolve_gaussian(GrContext* context,
                               bool cropToSrcRect) {
     float bounds[2] = { 0.0f, 1.0f };
     if (!cropToSrcRect) {
-        convolve_gaussian_1d(context, rt, clip, srcRect, dstRect, texture,
+        convolve_gaussian_1d(drawContext, rt, clip, srcRect, dstRect, texture,
                              direction, radius, sigma, false, bounds);
         return;
     }
@@ -128,15 +129,15 @@ static void convolve_gaussian(GrContext* context,
     }
     if (radius >= size * SK_ScalarHalf) {
         // Blur radius covers srcRect; use bounds over entire draw
-        convolve_gaussian_1d(context, rt, clip, srcRect, dstRect, texture,
+        convolve_gaussian_1d(drawContext, rt, clip, srcRect, dstRect, texture,
                             direction, radius, sigma, true, bounds);
     } else {
         // Draw upper and lower margins with bounds; middle without.
-        convolve_gaussian_1d(context, rt, clip, lowerSrcRect, lowerDstRect, texture,
+        convolve_gaussian_1d(drawContext, rt, clip, lowerSrcRect, lowerDstRect, texture,
                              direction, radius, sigma, true, bounds);
-        convolve_gaussian_1d(context, rt, clip, upperSrcRect, upperDstRect, texture,
+        convolve_gaussian_1d(drawContext, rt, clip, upperSrcRect, upperDstRect, texture,
                              direction, radius, sigma, true, bounds);
-        convolve_gaussian_1d(context, rt, clip, middleSrcRect, middleDstRect, texture,
+        convolve_gaussian_1d(drawContext, rt, clip, middleSrcRect, middleDstRect, texture,
                              direction, radius, sigma, false, bounds);
     }
 }
@@ -195,6 +196,11 @@ GrTexture* GaussianBlur(GrContext* context,
         return NULL;
     }
 
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return NULL;
+    }
+
     for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
         GrPaint paint;
         SkMatrix matrix;
@@ -219,8 +225,8 @@ GrTexture* GaussianBlur(GrContext* context,
         }
         scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
                              i < scaleFactorY ? 0.5f : 1.0f);
-        context->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint, SkMatrix::I(),
-                                     dstRect, srcRect);
+        drawContext->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint, SkMatrix::I(),
+                                         dstRect, srcRect);
         srcRect = dstRect;
         srcTexture = dstTexture;
         SkTSwap(dstTexture, tempTexture);
@@ -235,7 +241,7 @@ GrTexture* GaussianBlur(GrContext* context,
         // We shouldn't be scaling because this is a small size blur
         SkASSERT((scaleFactorX == scaleFactorY) == 1);
         SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
-        convolve_gaussian_2d(context, dstTexture->asRenderTarget(), clip, srcRect, dstRect,
+        convolve_gaussian_2d(drawContext, dstTexture->asRenderTarget(), clip, srcRect, dstRect,
                              srcTexture, radiusX, radiusY, sigmaX, sigmaY, cropToRect, srcIRect);
         srcTexture = dstTexture;
         srcRect = dstRect;
@@ -248,10 +254,10 @@ GrTexture* GaussianBlur(GrContext* context,
                 // X convolution from reading garbage.
                 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                               radiusX, srcIRect.height());
-                context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarget());
+                drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
             }
             SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
-            convolve_gaussian(context, dstTexture->asRenderTarget(), clip, srcRect, dstRect,
+            convolve_gaussian(drawContext, dstTexture->asRenderTarget(), clip, srcRect, dstRect,
                               srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, sigmaX,
                               cropToRect);
             srcTexture = dstTexture;
@@ -265,11 +271,11 @@ GrTexture* GaussianBlur(GrContext* context,
                 // convolution from reading garbage.
                 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                               srcIRect.width(), radiusY);
-                context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarget());
+                drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
             }
 
             SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
-            convolve_gaussian(context, dstTexture->asRenderTarget(), clip, srcRect,
+            convolve_gaussian(drawContext, dstTexture->asRenderTarget(), clip, srcRect,
                               dstRect, srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, sigmaY,
                               cropToRect);
             srcTexture = dstTexture;
@@ -283,10 +289,10 @@ GrTexture* GaussianBlur(GrContext* context,
         // upsampling.
         clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                       srcIRect.width() + 1, 1);
-        context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarget());
+        drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
         clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                       1, srcIRect.height());
-        context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarget());
+        drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
         SkMatrix matrix;
         matrix.setIDiv(srcTexture->width(), srcTexture->height());
 
@@ -297,8 +303,8 @@ GrTexture* GaussianBlur(GrContext* context,
 
         SkRect dstRect(srcRect);
         scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
-        context->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint,
-                                     SkMatrix::I(), dstRect, srcRect);
+        drawContext->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint,
+                                         SkMatrix::I(), dstRect, srcRect);
         srcRect = dstRect;
         srcTexture = dstTexture;
         SkTSwap(dstTexture, tempTexture);
index d281da4..9d7ce95 100644 (file)
@@ -15,6 +15,7 @@
 #include "SkTypes.h"
 
 #if SK_SUPPORT_GPU
+#include "GrDrawContext.h"
 #include "GrFragmentProcessor.h"
 #include "GrInvariantOutput.h"
 #include "effects/GrSingleTextureEffect.h"
@@ -310,7 +311,7 @@ protected:
 #endif
 private:
 #if SK_SUPPORT_GPU
-    void drawRect(GrContext* context,
+    void drawRect(GrDrawContext* drawContext,
                   GrTexture* src,
                   GrTexture* dst,
                   const SkMatrix& matrix,
@@ -323,7 +324,7 @@ private:
 };
 
 #if SK_SUPPORT_GPU
-void SkLightingImageFilterInternal::drawRect(GrContext* context,
+void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext,
                                              GrTexture* src,
                                              GrTexture* dst,
                                              const SkMatrix& matrix,
@@ -335,8 +336,8 @@ void SkLightingImageFilterInternal::drawRect(GrContext* context,
     GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, bounds, boundaryMode);
     GrPaint paint;
     paint.addColorProcessor(fp)->unref();
-    context->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(),
-                                 dstRect, srcRect);
+    drawContext->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(),
+                                     dstRect, srcRect);
 }
 
 bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy,
@@ -388,19 +389,26 @@ bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy,
     SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
     SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
     SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
-    this->drawRect(context, srcTexture, dst, matrix, clip, topLeft, kTopLeft_BoundaryMode, bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, top, kTop_BoundaryMode, bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, topRight, kTopRight_BoundaryMode,
+
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return false;
+    }
+
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, topLeft, kTopLeft_BoundaryMode, 
                    bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, left, kLeft_BoundaryMode, bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, interior, kInterior_BoundaryMode,
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, top, kTop_BoundaryMode, bounds);
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, topRight, kTopRight_BoundaryMode,
                    bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, right, kRight_BoundaryMode, bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode,
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, left, kLeft_BoundaryMode, bounds);
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, interior, kInterior_BoundaryMode,
                    bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, bottom, kBottom_BoundaryMode, bounds);
-    this->drawRect(context, srcTexture, dst, matrix, clip, bottomRight, kBottomRight_BoundaryMode,
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, right, kRight_BoundaryMode, bounds);
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode,
                    bounds);
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, bottom, kBottom_BoundaryMode, bounds);
+    this->drawRect(drawContext, srcTexture, dst, matrix, clip, bottomRight,
+                   kBottomRight_BoundaryMode, bounds);
     WrapTexture(dst, bounds.width(), bounds.height(), result);
     return true;
 }
index f4bcaf4..5eccb0d 100644 (file)
@@ -14,6 +14,7 @@
 #include "SkMorphology_opts.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "GrInvariantOutput.h"
 #include "GrTexture.h"
 #include "effects/Gr1DKernelEffect.h"
@@ -560,7 +561,7 @@ GrFragmentProcessor* GrMorphologyEffect::TestCreate(SkRandom* random,
 namespace {
 
 
-void apply_morphology_rect(GrContext* context,
+void apply_morphology_rect(GrDrawContext* drawContext,
                            GrRenderTarget* rt,
                            const GrClip& clip,
                            GrTexture* texture,
@@ -576,11 +577,11 @@ void apply_morphology_rect(GrContext* context,
                                                        radius,
                                                        morphType,
                                                        bounds))->unref();
-    context->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
-                                 SkRect::Make(srcRect));
+    drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
+                                     SkRect::Make(srcRect));
 }
 
-void apply_morphology_rect_no_bounds(GrContext* context,
+void apply_morphology_rect_no_bounds(GrDrawContext* drawContext,
                                      GrRenderTarget* rt,
                                      const GrClip& clip,
                                      GrTexture* texture,
@@ -594,11 +595,11 @@ void apply_morphology_rect_no_bounds(GrContext* context,
                                                        direction,
                                                        radius,
                                                        morphType))->unref();
-    context->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
-                                 SkRect::Make(srcRect));
+    drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
+                                     SkRect::Make(srcRect));
 }
 
-void apply_morphology_pass(GrContext* context,
+void apply_morphology_pass(GrDrawContext* drawContext,
                            GrRenderTarget* rt,
                            const GrClip& clip,
                            GrTexture* texture,
@@ -632,15 +633,15 @@ void apply_morphology_pass(GrContext* context,
     }
     if (middleSrcRect.fLeft - middleSrcRect.fRight >= 0) {
         // radius covers srcRect; use bounds over entire draw
-        apply_morphology_rect(context, rt, clip, texture, srcRect, dstRect, radius,
+        apply_morphology_rect(drawContext, rt, clip, texture, srcRect, dstRect, radius,
                               morphType, bounds, direction);
     } else {
         // Draw upper and lower margins with bounds; middle without.
-        apply_morphology_rect(context, rt, clip, texture, lowerSrcRect, lowerDstRect, radius,
+        apply_morphology_rect(drawContext, rt, clip, texture, lowerSrcRect, lowerDstRect, radius,
                               morphType, bounds, direction);
-        apply_morphology_rect(context, rt, clip, texture, upperSrcRect, upperDstRect, radius,
+        apply_morphology_rect(drawContext, rt, clip, texture, upperSrcRect, upperDstRect, radius,
                               morphType, bounds, direction);
-        apply_morphology_rect_no_bounds(context, rt, clip, texture, middleSrcRect, middleDstRect,
+        apply_morphology_rect_no_bounds(drawContext, rt, clip, texture, middleSrcRect, middleDstRect,
                                         radius, morphType, direction);
     }
 }
@@ -666,13 +667,18 @@ bool apply_morphology(const SkBitmap& input,
     desc.fConfig = kSkia8888_GrPixelConfig;
     SkIRect srcRect = rect;
 
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return false;
+    }
+
     if (radius.fWidth > 0) {
         GrTexture* texture = context->textureProvider()->refScratchTexture(
             desc, GrTextureProvider::kApprox_ScratchTexMatch);
         if (NULL == texture) {
             return false;
         }
-        apply_morphology_pass(context, texture->asRenderTarget(), clip, srcTexture,
+        apply_morphology_pass(drawContext, texture->asRenderTarget(), clip, srcTexture,
                               srcRect, dstRect, radius.fWidth, morphType,
                               Gr1DKernelEffect::kX_Direction);
         SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
@@ -680,7 +686,7 @@ bool apply_morphology(const SkBitmap& input,
         GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphType ?
                                 SK_ColorWHITE :
                                 SK_ColorTRANSPARENT;
-        context->clear(&clearRect, clearColor, false, texture->asRenderTarget());
+        drawContext->clear(texture->asRenderTarget(), &clearRect, clearColor, false);
         srcTexture.reset(texture);
         srcRect = dstRect;
     }
@@ -690,7 +696,7 @@ bool apply_morphology(const SkBitmap& input,
         if (NULL == texture) {
             return false;
         }
-        apply_morphology_pass(context, texture->asRenderTarget(), clip, srcTexture,
+        apply_morphology_pass(drawContext, texture->asRenderTarget(), clip, srcTexture,
                               srcRect, dstRect, radius.fHeight, morphType,
                               Gr1DKernelEffect::kY_Direction);
         srcTexture.reset(texture);
index 76c4629..f98247a 100644 (file)
@@ -14,6 +14,7 @@
 #include "SkXfermode.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "effects/GrTextureDomain.h"
 #include "SkGr.h"
 #endif
@@ -178,7 +179,14 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
 
     paint.addColorProcessor(foregroundDomain.get());
     paint.addColorProcessor(xferProcessor)->unref();
-    context->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, SkMatrix::I(), srcRect);
+
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return false;
+    }
+
+    drawContext->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, 
+                          SkMatrix::I(), srcRect);
 
     offset->fX = backgroundOffset.fX;
     offset->fY = backgroundOffset.fY;
index 6b8abc3..a52a701 100644 (file)
@@ -313,7 +313,7 @@ enum CoverageAttribType {
 };
 }
 
-void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target,
+void GrAARectRenderer::GeometryFillAARect(GrDrawTarget* target,
                                           GrPipelineBuilder* pipelineBuilder,
                                           GrColor color,
                                           const SkMatrix& viewMatrix,
@@ -330,7 +330,7 @@ void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target,
     target->drawBatch(pipelineBuilder, batch);
 }
 
-void GrAARectRenderer::strokeAARect(GrDrawTarget* target,
+void GrAARectRenderer::StrokeAARect(GrDrawTarget* target,
                                     GrPipelineBuilder* pipelineBuilder,
                                     GrColor color,
                                     const SkMatrix& viewMatrix,
@@ -371,7 +371,7 @@ void GrAARectRenderer::strokeAARect(GrDrawTarget* target,
     }
 
     if (spare <= 0 && miterStroke) {
-        this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, devOutside);
+        FillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, devOutside);
         return;
     }
 
@@ -388,8 +388,8 @@ void GrAARectRenderer::strokeAARect(GrDrawTarget* target,
         devOutsideAssist.outset(0, ry);
     }
 
-    this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
-                               devOutsideAssist, devInside, miterStroke);
+    GeometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
+                         devOutsideAssist, devInside, miterStroke);
 }
 
 GR_DECLARE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
@@ -773,7 +773,7 @@ private:
     SkSTArray<1, Geometry, true> fGeoData;
 };
 
-void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
+void GrAARectRenderer::GeometryStrokeAARect(GrDrawTarget* target,
                                             GrPipelineBuilder* pipelineBuilder,
                                             GrColor color,
                                             const SkMatrix& viewMatrix,
@@ -792,7 +792,7 @@ void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
     target->drawBatch(pipelineBuilder, batch);
 }
 
-void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target,
+void GrAARectRenderer::FillAANestedRects(GrDrawTarget* target,
                                          GrPipelineBuilder* pipelineBuilder,
                                          GrColor color,
                                          const SkMatrix& viewMatrix,
@@ -805,12 +805,12 @@ void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target,
     viewMatrix.mapRect(&devInside, rects[1]);
 
     if (devInside.isEmpty()) {
-        this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, devOutside);
+        FillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, devOutside);
         return;
     }
 
-    this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
-                               devOutside, devInside, true);
+    GeometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
+                         devOutside, devInside, true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
index 023eadc..8f42671 100644 (file)
@@ -11,7 +11,6 @@
 #include "GrColor.h"
 #include "SkMatrix.h"
 #include "SkRect.h"
-#include "SkRefCnt.h"
 #include "SkStrokeRec.h"
 
 class GrClip;
@@ -22,55 +21,53 @@ class GrPipelineBuilder;
 /*
  * This class wraps helper functions that draw AA rects (filled & stroked)
  */
-class GrAARectRenderer : public SkRefCnt {
+class GrAARectRenderer {
 public:
-    SK_DECLARE_INST_COUNT(GrAARectRenderer)
-
     // TODO: potentialy fuse the fill & stroke methods and differentiate
     // between them by passing in stroke (==NULL means fill).
 
-    void fillAARect(GrDrawTarget* target,
-                    GrPipelineBuilder* pipelineBuilder,
-                    GrColor color,
-                    const SkMatrix& viewMatrix,
-                    const SkRect& rect,
-                    const SkRect& devRect) {
-        this->geometryFillAARect(target, pipelineBuilder, color, viewMatrix, rect, devRect);
+    static void FillAARect(GrDrawTarget* target,
+                           GrPipelineBuilder* pipelineBuilder,
+                           GrColor color,
+                           const SkMatrix& viewMatrix,
+                           const SkRect& rect,
+                           const SkRect& devRect) {
+        GeometryFillAARect(target, pipelineBuilder, color, viewMatrix, rect, devRect);
     }
 
-    void strokeAARect(GrDrawTarget*,
-                      GrPipelineBuilder*,
-                      GrColor,
-                      const SkMatrix& viewMatrix,
-                      const SkRect& rect,
-                      const SkRect& devRect,
-                      const SkStrokeRec& stroke);
+    static void StrokeAARect(GrDrawTarget*,
+                             GrPipelineBuilder*,
+                             GrColor,
+                             const SkMatrix& viewMatrix,
+                             const SkRect& rect,
+                             const SkRect& devRect,
+                             const SkStrokeRec& stroke);
 
     // First rect is outer; second rect is inner
-    void fillAANestedRects(GrDrawTarget*,
-                           GrPipelineBuilder*,
-                           GrColor,
-                           const SkMatrix& viewMatrix,
-                           const SkRect rects[2]);
+    static void FillAANestedRects(GrDrawTarget*,
+                                  GrPipelineBuilder*,
+                                  GrColor,
+                                  const SkMatrix& viewMatrix,
+                                  const SkRect rects[2]);
 
 private:
-    void geometryFillAARect(GrDrawTarget*,
-                            GrPipelineBuilder*,
-                            GrColor,
-                            const SkMatrix& viewMatrix,
-                            const SkRect& rect,
-                            const SkRect& devRect);
+    GrAARectRenderer();
 
-    void geometryStrokeAARect(GrDrawTarget*,
-                              GrPipelineBuilder*,
-                              GrColor,
-                              const SkMatrix& viewMatrix,
-                              const SkRect& devOutside,
-                              const SkRect& devOutsideAssist,
-                              const SkRect& devInside,
-                              bool miterStroke);
+    static void GeometryFillAARect(GrDrawTarget*,
+                                   GrPipelineBuilder*,
+                                   GrColor,
+                                   const SkMatrix& viewMatrix,
+                                   const SkRect& rect,
+                                   const SkRect& devRect);
 
-    typedef SkRefCnt INHERITED;
+    static void GeometryStrokeAARect(GrDrawTarget*,
+                                     GrPipelineBuilder*,
+                                     GrColor,
+                                     const SkMatrix& viewMatrix,
+                                     const SkRect& devOutside,
+                                     const SkRect& devOutsideAssist,
+                                     const SkRect& devInside,
+                                     bool miterStroke);
 };
 
 #endif // GrAARectRenderer_DEFINED
index 23cb326..5ef2dab 100644 (file)
@@ -10,8 +10,8 @@
 #define GrAtlas_DEFINED
 
 
+#include "SkTDArray.h"
 #include "GrTexture.h"
-#include "GrDrawTarget.h"
 #include "SkPoint.h"
 #include "SkTInternalLList.h"
 
index f230757..35a9164 100644 (file)
@@ -11,7 +11,7 @@
 #include "GrBatchTarget.h"
 #include "GrBatchTest.h"
 #include "GrDefaultGeoProcFactory.h"
-#include "GrDrawTarget.h"
+#include "GrDrawContext.h"
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
 #include "GrResourceProvider.h"
@@ -350,7 +350,12 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
                                       const SkTextBlob* blob, SkScalar x, SkScalar y,
                                       SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
     // If we have been abandoned, then don't draw
-    if (!fContext->getTextTarget()) {
+    if (fContext->abandoned()) {
+        return;
+    }
+
+    GrDrawContext* drawContext = fContext->drawContext();
+    if (!drawContext) {
         return;
     }
 
@@ -428,7 +433,7 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
     }
 
     cacheBlob->fPaintColor = skPaint.getColor();
-    this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
+    this->flush(drawContext, blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
                 clip, viewMatrix, clipBounds, x, y, transX, transY);
 }
 
@@ -455,7 +460,7 @@ inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint,
     // rasterizers and mask filters modify alpha, which doesn't
     // translate well to distance
     if (skPaint.getRasterizer() || skPaint.getMaskFilter() ||
-        !fContext->getTextTarget()->caps()->shaderCaps()->shaderDerivativeSupport()) {
+        !fContext->shaderDerivativeSupport()) {
         return false;
     }
 
@@ -775,10 +780,13 @@ void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
                                     const SkMatrix& viewMatrix,
                                     const char text[], size_t byteLength,
                                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
-    SkAutoTUnref<BitmapTextBlob> blob(
+    GrDrawContext* drawContext = fContext->drawContext();
+    if (drawContext) {
+        SkAutoTUnref<BitmapTextBlob> blob(
             this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
                                      text, byteLength, x, y, regionClipBounds));
-    this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, regionClipBounds);
+        this->flush(drawContext, blob, rt, skPaint, paint, clip, regionClipBounds);
+    }
 }
 
 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
@@ -787,13 +795,16 @@ void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
                                        const char text[], size_t byteLength,
                                        const SkScalar pos[], int scalarsPerPosition,
                                        const SkPoint& offset, const SkIRect& regionClipBounds) {
-    SkAutoTUnref<BitmapTextBlob> blob(
+    GrDrawContext* drawContext = fContext->drawContext();
+    if (drawContext) {
+        SkAutoTUnref<BitmapTextBlob> blob(
             this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
                                         text, byteLength,
                                         pos, scalarsPerPosition,
                                         offset, regionClipBounds));
 
-    this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, regionClipBounds);
+        this->flush(drawContext, blob, rt, skPaint, paint, clip, regionClipBounds);
+    }
 }
 
 void GrAtlasTextContext::internalDrawBMPText(BitmapTextBlob* blob, int runIndex,
@@ -2109,9 +2120,11 @@ GrAtlasTextContext::createBatch(BitmapTextBlob* cacheBlob, const PerSubRunInfo&
     return batch;
 }
 
-inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder* pipelineBuilder,
+inline void GrAtlasTextContext::flushRun(GrDrawContext* drawContext,
+                                         GrPipelineBuilder* pipelineBuilder,
                                          BitmapTextBlob* cacheBlob, int run, GrColor color,
-                                         SkScalar transX, SkScalar transY, const SkPaint& skPaint) {
+                                         SkScalar transX, SkScalar transY,
+                                         const SkPaint& skPaint) {
     for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); subRun++) {
         const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun];
         int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
@@ -2122,7 +2135,7 @@ inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder
         SkAutoTUnref<BitmapTextBatch> batch(this->createBatch(cacheBlob, info, glyphCount, run,
                                                               subRun, color, transX, transY,
                                                               skPaint));
-        target->drawBatch(pipelineBuilder, batch);
+        drawContext->drawText(pipelineBuilder, batch);
     }
 }
 
@@ -2152,7 +2165,7 @@ inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend
     }
 }
 
-void GrAtlasTextContext::flush(GrDrawTarget* target,
+void GrAtlasTextContext::flush(GrDrawContext* drawContext,
                                const SkTextBlob* blob,
                                BitmapTextBlob* cacheBlob,
                                GrRenderTarget* rt,
@@ -2178,14 +2191,15 @@ void GrAtlasTextContext::flush(GrDrawTarget* target,
             continue;
         }
         cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
-        this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, transX, transY, skPaint);
+        this->flushRun(drawContext, &pipelineBuilder, cacheBlob, run, color,
+                       transX, transY, skPaint);
     }
 
     // Now flush big glyphs
     this->flushBigGlyphs(cacheBlob, rt, skPaint, transX, transY, clipBounds);
 }
 
-void GrAtlasTextContext::flush(GrDrawTarget* target,
+void GrAtlasTextContext::flush(GrDrawContext* drawContext,
                                BitmapTextBlob* cacheBlob,
                                GrRenderTarget* rt,
                                const SkPaint& skPaint,
@@ -2197,7 +2211,7 @@ void GrAtlasTextContext::flush(GrDrawTarget* target,
 
     GrColor color = grPaint.getColor();
     for (int run = 0; run < cacheBlob->fRunCount; run++) {
-        this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint);
+        this->flushRun(drawContext, &pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint);
     }
 
     // Now flush big glyphs
index eb7ba47..ad0f765 100644 (file)
@@ -24,6 +24,7 @@
 #endif
 
 class BitmapTextBatch;
+class GrDrawContext;
 class GrPipelineBuilder;
 class GrTextBlobCache;
 
@@ -278,17 +279,17 @@ private:
                                         int glyphCount, int run, int subRun,
                                         GrColor, SkScalar transX, SkScalar transY,
                                         const SkPaint&);
-    inline void flushRun(GrDrawTarget*, GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
+    inline void flushRun(GrDrawContext*, GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
                          SkScalar transX, SkScalar transY, const SkPaint&);
     inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt,
                                const SkPaint& skPaint,
                                SkScalar transX, SkScalar transY, const SkIRect& clipBounds);
 
     // We have to flush SkTextBlobs differently from drawText / drawPosText
-    void flush(GrDrawTarget*, const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
+    void flush(GrDrawContext*, const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
                const GrPaint&, SkDrawFilter*, const GrClip&, const SkMatrix& viewMatrix,
                const SkIRect& clipBounds, SkScalar x, SkScalar y, SkScalar transX, SkScalar transY);
-    void flush(GrDrawTarget*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
+    void flush(GrDrawContext*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
                const GrPaint&, const GrClip&, const SkIRect& clipBounds);
 
     // A helper for drawing BitmapText in a run of distance fields
index f1c56ac..9804750 100644 (file)
@@ -9,7 +9,6 @@
 #define GrBatchFontCache_DEFINED
 
 #include "GrBatchAtlas.h"
-#include "GrDrawTarget.h"
 #include "GrFontScaler.h"
 #include "GrGlyph.h"
 #include "SkTDynamicHash.h"
index 6850515..9279ba5 100644 (file)
@@ -8,8 +8,9 @@
 #include "GrClipMaskManager.h"
 #include "GrAAConvexPathRenderer.h"
 #include "GrAAHairLinePathRenderer.h"
-#include "GrAARectRenderer.h"
 #include "GrCaps.h"
+#include "GrDrawContext.h"
+#include "GrDrawTarget.h"
 #include "GrPaint.h"
 #include "GrPathRenderer.h"
 #include "GrRenderTarget.h"
@@ -394,14 +395,12 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
             if (element->isAA()) {
                 SkRect devRect = element->getRect();
                 viewMatrix.mapRect(&devRect);
-                this->getContext()->getAARectRenderer()->fillAARect(fClipTarget,
-                                                                    pipelineBuilder,
-                                                                    color,
-                                                                    viewMatrix,
-                                                                    element->getRect(),
-                                                                    devRect);
+
+                fClipTarget->drawAARect(pipelineBuilder, color, viewMatrix,
+                                        element->getRect(), devRect);
             } else {
-                fClipTarget->drawSimpleRect(pipelineBuilder, color, viewMatrix, element->getRect());
+                fClipTarget->drawSimpleRect(pipelineBuilder, color, viewMatrix,
+                                            element->getRect());
             }
             return true;
         default: {
index 3ed0b6b..550d7ff 100755 (executable)
@@ -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"
 #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();
+    }
+}
+
+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; 
+}
+
+////////////////////////////////////////////////////////////////////////////////
 
-private:
-    GrContext* fContext;
-};
 
 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
     GrContextOptions defaultOptions;
@@ -104,19 +143,16 @@ GrContext::GrContext() : fUniqueID(next_id()) {
     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 @@ void GrContext::initCommon() {
 
     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 @@ void GrContext::initCommon() {
 }
 
 GrContext::~GrContext() {
-    if (NULL == fGpu) {
+    if (!fGpu) {
         return;
     }
 
@@ -161,10 +190,6 @@ GrContext::~GrContext() {
     SkDELETE(fResourceProvider);
     SkDELETE(fResourceCache);
     SkDELETE(fBatchFontCache);
-    SkDELETE(fDrawBuffer);
-
-    fAARectRenderer->unref();
-    fOvalRenderer->unref();
 
     fGpu->unref();
     SkSafeUnref(fPathRendererChain);
@@ -184,8 +209,7 @@ void GrContext::abandonContext() {
     SkSafeSetNull(fPathRendererChain);
     SkSafeSetNull(fSoftwarePathRenderer);
 
-    SkDELETE(fDrawBuffer);
-    fDrawBuffer = NULL;
+    fDrawingMgr.abandon();
 
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
@@ -199,9 +223,7 @@ void GrContext::resetContext(uint32_t state) {
 void GrContext::freeGpuResources() {
     this->flush();
 
-    if (fDrawBuffer) {
-        fDrawBuffer->purgeResources();
-    }
+    fDrawingMgr.purgeResources();
 
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
@@ -238,6 +260,10 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
 
 ////////////////////////////////////////////////////////////////////////////////
 
+bool GrContext::shaderDerivativeSupport() const {
+    return fGpu->caps()->shaderCaps()->shaderDerivativeSupport();
+}
+
 bool GrContext::isConfigTexturable(GrPixelConfig config) const {
     return fGpu->caps()->isConfigTexturable(config);
 }
@@ -278,1093 +304,15 @@ int GrContext::getMaxSampleCount() const {
     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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
 
     // 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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
         }
         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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
             buffer = tmpPixels.get();
         }
     }
-    if (NULL == fp) {
+    if (!fp) {
         fp.reset(GrConfigConversionEffect::Create(texture,
                                                   swapRAndB,
                                                   GrConfigConversionEffect::kNone_PMConversion,
@@ -1483,25 +431,18 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
     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 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
                 // 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;
+                    }
+
+                    GrPaint paint;
+                    paint.addColorProcessor(fp);
 
-                    pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget());
                     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::prepareSurfaceForExternalRead(GrSurface* surface) {
     }
 }
 
-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 @@ void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe
 
     // Since we're going to the draw target and not GPU, no need to check kNoFlush
     // here.
+    if (!dst->asRenderTarget()) {
+        return;
+    }
 
-    GrDrawTarget* target = this->prepareToDraw();
-    if (NULL == target) {
+    GrDrawContext* drawContext = this->drawContext();
+    if (!drawContext) {
         return;
     }
-    target->copySurface(dst, src, srcRect, dstPoint);
+
+    drawContext->copySurface(dst->asRenderTarget(), src, srcRect, dstPoint);
 
     if (kFlushWrites_PixelOp & pixelOpsFlags) {
         this->flush();
@@ -1715,28 +651,6 @@ void GrContext::flushSurfaceWrites(GrSurface* surface) {
     }
 }
 
-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 @@ GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
                                            GrPathRendererChain::DrawType drawType,
                                            GrPathRendererChain::StencilSupport* stencilSupport) {
 
-    if (NULL == fPathRendererChain) {
+    if (!fPathRendererChain) {
         fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
     }
 
@@ -1764,8 +678,8 @@ GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
                                                              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 @@ int GrContext::getRecommendedSampleCount(GrPixelConfig config,
         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::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes)
 
 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
index 7659847..f039cee 100644 (file)
@@ -679,7 +679,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target,
             }
             const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() :
                                                                                viewMatrix;
-            target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &localMatrix);
+            target->drawBWRect(pipelineBuilder, color, viewM, bounds, NULL, &localMatrix);
         } else {
             if (passCount > 1) {
                 pipelineBuilder->setDisableColorXPFactory();
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
new file mode 100644 (file)
index 0000000..3fe3f86
--- /dev/null
@@ -0,0 +1,1271 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrAARectRenderer.h"
+#include "GrBatch.h"
+#include "GrBatchTest.h"
+#include "GrDefaultGeoProcFactory.h"
+#include "GrDrawContext.h"
+#include "GrOvalRenderer.h"
+#include "GrPathRenderer.h"
+
+#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext)
+#define RETURN_IF_ABANDONED        if (!fDrawTarget) { return; }
+#define RETURN_FALSE_IF_ABANDONED  if (!fDrawTarget) { return false; }
+#define RETURN_NULL_IF_ABANDONED   if (!fDrawTarget) { return NULL; }
+
+class AutoCheckFlush {
+public:
+    AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
+    ~AutoCheckFlush() { fContext->flushIfNecessary(); }
+
+private:
+    GrContext* fContext;
+};
+
+GrDrawContext::GrDrawContext(GrContext* context, GrDrawTarget* drawTarget)
+    : fContext(context)
+    , fDrawTarget(SkRef(drawTarget)) {
+}
+
+void GrDrawContext::copySurface(GrRenderTarget* dst, GrSurface* src,
+                                const SkIRect& srcRect, const SkIPoint& dstPoint) {
+    if (!this->prepareToDraw(dst)) {
+        return;
+    }
+
+    fDrawTarget->copySurface(dst, src, srcRect, dstPoint);
+}
+
+void GrDrawContext::drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) {
+    fDrawTarget->drawBatch(pipelineBuilder, batch);
+}
+
+void GrDrawContext::drawPaths(GrPipelineBuilder* pipelineBuilder,
+                              const GrPathProcessor* pathProc,
+                              const GrPathRange* pathRange,
+                              const void* indices,
+                              int /*GrDrawTarget::PathIndexType*/ indexType,
+                              const float transformValues[],
+                              int /*GrDrawTarget::PathTransformType*/ transformType,
+                              int count,
+                              int /*GrPathRendering::FillType*/ fill) {
+    fDrawTarget->drawPaths(pipelineBuilder, pathProc, pathRange,
+                           indices, (GrDrawTarget::PathIndexType) indexType,
+                           transformValues,
+                           (GrDrawTarget::PathTransformType) transformType,
+                           count, (GrPathRendering::FillType) fill);
+}
+
+void GrDrawContext::discard(GrRenderTarget* renderTarget) {
+    RETURN_IF_ABANDONED
+    SkASSERT(renderTarget);
+    AutoCheckFlush acf(fContext);
+    if (!this->prepareToDraw(renderTarget)) {
+        return;
+    }
+    fDrawTarget->discard(renderTarget);
+}
+
+void GrDrawContext::clear(GrRenderTarget* renderTarget,
+                          const SkIRect* rect,
+                          const GrColor color,
+                          bool canIgnoreRect) {
+    RETURN_IF_ABANDONED
+    SkASSERT(renderTarget);
+
+    AutoCheckFlush acf(fContext);
+    if (!this->prepareToDraw(renderTarget)) {
+        return;
+    }
+    fDrawTarget->clear(rect, color, canIgnoreRect, renderTarget);
+}
+
+
+void GrDrawContext::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(fContext);
+        GrPipelineBuilder pipelineBuilder;
+        if (!this->prepareToDraw(&pipelineBuilder, rt, clip, paint)) {
+            return;
+        }
+
+        fDrawTarget->drawBWRect(&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 GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    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)) {
+                    fDrawTarget->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(fDrawTarget, &pipelineBuilder, &devBoundRect, rect,
+                                           width, viewMatrix, color);
+
+    if (doAA) {
+        if (width >= 0) {
+            GrAARectRenderer::StrokeAARect(fDrawTarget,
+                                           &pipelineBuilder,
+                                           color,
+                                           viewMatrix,
+                                           rect,
+                                           devBoundRect,
+                                           *strokeInfo);
+        } else {
+            // filled AA rect
+            GrAARectRenderer::FillAARect(fDrawTarget,
+                                         &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);
+        fDrawTarget->drawBatch(&pipelineBuilder, batch);
+    } else {
+        // filled BW rect
+        fDrawTarget->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect);
+    }
+}
+
+void GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    fDrawTarget->drawBWRect(&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 GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    // 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));
+
+    fDrawTarget->drawBatch(&pipelineBuilder, batch);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    GrColor color = paint.getColor();
+    if (!GrOvalRenderer::DrawRRect(fDrawTarget,
+                                   &pipelineBuilder,
+                                   color,
+                                   viewMatrix,
+                                   paint.isAntiAlias(),
+                                   rrect,
+                                   strokeInfo)) {
+        SkPath path;
+        path.setIsVolatile(true);
+        path.addRRect(rrect);
+        this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
+                               paint.isAntiAlias(), path, strokeInfo);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    GrColor color = paint.getColor();
+    if (!GrOvalRenderer::DrawDRRect(fDrawTarget,
+                                    &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(fDrawTarget, &pipelineBuilder, viewMatrix, color,
+                               paint.isAntiAlias(), path, fillRec);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    GrColor color = paint.getColor();
+    if (!GrOvalRenderer::DrawOval(fDrawTarget,
+                                  &pipelineBuilder,
+                                  color,
+                                  viewMatrix,
+                                  paint.isAntiAlias(),
+                                  oval,
+                                  strokeInfo)) {
+        SkPath path;
+        path.setIsVolatile(true);
+        path.addOval(oval);
+        this->internalDrawPath(fDrawTarget, &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 GrDrawContext::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(fContext);
+    GrPipelineBuilder pipelineBuilder;
+    if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
+        return;
+    }
+
+    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(fDrawTarget, &pipelineBuilder, color, viewMatrix, path, strokeInfo,
+                                rects)) {
+                GrAARectRenderer::FillAANestedRects(fDrawTarget, &pipelineBuilder, color,
+                                                    viewMatrix, rects);
+                return;
+            }
+        }
+        SkRect ovalRect;
+        bool isOval = path.isOval(&ovalRect);
+
+        if (isOval && !path.isInverseFillType()) {
+            if (GrOvalRenderer::DrawOval(fDrawTarget,
+                                         &pipelineBuilder,
+                                         color,
+                                         viewMatrix,
+                                         paint.isAntiAlias(),
+                                         ovalRect,
+                                         strokeInfo)) {
+                return;
+            }
+        }
+    }
+    this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
+                           path, strokeInfo);
+}
+
+void GrDrawContext::internalDrawPath(GrDrawTarget* target,
+                                     GrPipelineBuilder* pipelineBuilder,
+                                     const SkMatrix& viewMatrix,
+                                     GrColor color,
+                                     bool useAA,
+                                     const SkPath& path,
+                                     const GrStrokeInfo& strokeInfo) {
+    RETURN_IF_ABANDONED
+    SkASSERT(!path.isEmpty());
+
+
+    // 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 = fContext->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 = fContext->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 = fContext->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);
+}
+
+bool GrDrawContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder,
+                                  GrRenderTarget* rt,
+                                  const GrClip& clip,
+                                  const GrPaint* paint) {
+    RETURN_FALSE_IF_ABANDONED
+
+    ASSERT_OWNED_RESOURCE(rt);
+    SkASSERT(rt && paint);
+    pipelineBuilder->setFromPaint(*paint, rt, clip);
+    return true;
+}
+
+bool GrDrawContext::prepareToDraw(GrRenderTarget* rt) {
+    RETURN_FALSE_IF_ABANDONED
+
+    ASSERT_OWNED_RESOURCE(rt);
+    SkASSERT(rt);
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#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
+
index 644161f..e4c0821 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "GrDrawTarget.h"
 
+#include "GrAARectRenderer.h"
 #include "GrBatch.h"
 #include "GrCaps.h"
 #include "GrContext.h"
@@ -293,7 +294,7 @@ void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
                       transformType, count, stencilSettings, pipelineInfo);
 }
 
-void GrDrawTarget::drawRect(GrPipelineBuilder* pipelineBuilder,
+void GrDrawTarget::drawBWRect(GrPipelineBuilder* pipelineBuilder,
                             GrColor color,
                             const SkMatrix& viewMatrix,
                             const SkRect& rect,
@@ -304,6 +305,14 @@ void GrDrawTarget::drawRect(GrPipelineBuilder* pipelineBuilder,
    this->drawBatch(pipelineBuilder, batch);
 }
 
+void GrDrawTarget::drawAARect(GrPipelineBuilder* pipelineBuilder,
+                              GrColor color,
+                              const SkMatrix& viewMatrix,
+                              const SkRect& rect,
+                              const SkRect& devRect) {
+   GrAARectRenderer::FillAARect(this, pipelineBuilder, color, viewMatrix, rect, devRect);
+}
+
 void GrDrawTarget::clear(const SkIRect* rect,
                          GrColor color,
                          bool canIgnoreRect,
index 9cb91e3..53129ed 100644 (file)
@@ -118,26 +118,31 @@ public:
      *                    that rectangle before it is input to GrCoordTransforms that read local
      *                    coordinates
      */
-    void drawRect(GrPipelineBuilder* pipelineBuilder,
-                  GrColor color,
-                  const SkMatrix& viewMatrix,
-                  const SkRect& rect,
-                  const SkRect* localRect,
-                  const SkMatrix* localMatrix);
+    void drawBWRect(GrPipelineBuilder* pipelineBuilder,
+                    GrColor color,
+                    const SkMatrix& viewMatrix,
+                    const SkRect& rect,
+                    const SkRect* localRect,
+                    const SkMatrix* localMatrix);
 
     /**
      * Helper for drawRect when the caller doesn't need separate local rects or matrices.
      */
     void drawSimpleRect(GrPipelineBuilder* ds, GrColor color, const SkMatrix& viewM,
                         const SkRect& rect) {
-        this->drawRect(ds, color, viewM, rect, NULL, NULL);
+        this->drawBWRect(ds, color, viewM, rect, NULL, NULL);
     }
     void drawSimpleRect(GrPipelineBuilder* ds, GrColor color, const SkMatrix& viewM,
                         const SkIRect& irect) {
         SkRect rect = SkRect::Make(irect);
-        this->drawRect(ds, color, viewM, rect, NULL, NULL);
+        this->drawBWRect(ds, color, viewM, rect, NULL, NULL);
     }
 
+    void drawAARect(GrPipelineBuilder* pipelineBuilder,
+                    GrColor color,
+                    const SkMatrix& viewMatrix,
+                    const SkRect& rect,
+                    const SkRect& devRect);
 
     /**
      * Clear the passed in render target. Ignores the GrPipelineBuilder and clip. Clears the whole
index aea1c9b..a023e65 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "GrAtlas.h"
+#include "GrDrawContext.h"
 #include "GrGpu.h"
 #include "GrLayerCache.h"
 #include "GrSurfacePriv.h"
@@ -465,7 +466,11 @@ void GrLayerCache::purgeAll() {
 
     SkASSERT(0 == fPictureHash.count());
 
-    fContext->discardRenderTarget(fAtlas->getTexture()->asRenderTarget());
+    GrDrawContext* drawContext = fContext->drawContext();
+
+    if (drawContext) {
+        drawContext->discard(fAtlas->getTexture()->asRenderTarget());
+    }
 }
 #endif
 
index 112c344..f98adaa 100644 (file)
@@ -602,7 +602,7 @@ GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(SkRandom* random,
 
 ///////////////////////////////////////////////////////////////////////////////
 
-bool GrOvalRenderer::drawOval(GrDrawTarget* target,
+bool GrOvalRenderer::DrawOval(GrDrawTarget* target,
                               GrPipelineBuilder* pipelineBuilder,
                               GrColor color,
                               const SkMatrix& viewMatrix,
@@ -618,15 +618,15 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target,
 
     // we can draw circles
     if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(viewMatrix)) {
-        this->drawCircle(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval, stroke);
+        DrawCircle(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval, stroke);
     // if we have shader derivative support, render as device-independent
     } else if (target->caps()->shaderCaps()->shaderDerivativeSupport()) {
-        return this->drawDIEllipse(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval,
-                                   stroke);
+        return DrawDIEllipse(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval,
+                             stroke);
     // otherwise axis-aligned ellipses only
     } else if (viewMatrix.rectStaysRect()) {
-        return this->drawEllipse(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval,
-                                 stroke);
+        return DrawEllipse(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval,
+                           stroke);
     } else {
         return false;
     }
@@ -834,7 +834,7 @@ static GrBatch* create_circle_batch(GrColor color,
     return CircleBatch::Create(geometry);
 }
 
-void GrOvalRenderer::drawCircle(GrDrawTarget* target,
+void GrOvalRenderer::DrawCircle(GrDrawTarget* target,
                                 GrPipelineBuilder* pipelineBuilder,
                                 GrColor color,
                                 const SkMatrix& viewMatrix,
@@ -1091,7 +1091,7 @@ static GrBatch* create_ellipse_batch(GrColor color,
     return EllipseBatch::Create(geometry);
 }
 
-bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
+bool GrOvalRenderer::DrawEllipse(GrDrawTarget* target,
                                  GrPipelineBuilder* pipelineBuilder,
                                  GrColor color,
                                  const SkMatrix& viewMatrix,
@@ -1337,7 +1337,7 @@ static GrBatch* create_diellipse_batch(GrColor color,
     return DIEllipseBatch::Create(geometry, devBounds);
 }
 
-bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
+bool GrOvalRenderer::DrawDIEllipse(GrDrawTarget* target,
                                    GrPipelineBuilder* pipelineBuilder,
                                    GrColor color,
                                    const SkMatrix& viewMatrix,
@@ -1396,7 +1396,7 @@ static const GrIndexBuffer* ref_rrect_index_buffer(bool strokeOnly,
     }
 }
 
-bool GrOvalRenderer::drawDRRect(GrDrawTarget* target,
+bool GrOvalRenderer::DrawDRRect(GrDrawTarget* target,
                                 GrPipelineBuilder* pipelineBuilder,
                                 GrColor color,
                                 const SkMatrix& viewMatrix,
@@ -1426,7 +1426,7 @@ bool GrOvalRenderer::drawDRRect(GrDrawTarget* target,
     }
 
     SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
-    if (this->drawRRect(target, pipelineBuilder, color, viewMatrix, useAA, origOuter, fillRec)) {
+    if (DrawRRect(target, pipelineBuilder, color, viewMatrix, useAA, origOuter, fillRec)) {
         return true;
     }
 
@@ -1457,7 +1457,7 @@ bool GrOvalRenderer::drawDRRect(GrDrawTarget* target,
     if (applyAA) {
         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
     }
-    target->drawRect(pipelineBuilder, color, SkMatrix::I(), bounds, NULL, &invert);
+    target->drawBWRect(pipelineBuilder, color, SkMatrix::I(), bounds, NULL, &invert);
     return true;
 }
 
@@ -1966,7 +1966,7 @@ static GrBatch* create_rrect_batch(GrColor color,
     }
 }
 
-bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
+bool GrOvalRenderer::DrawRRect(GrDrawTarget* target,
                                GrPipelineBuilder* pipelineBuilder,
                                GrColor color,
                                const SkMatrix& viewMatrix,
@@ -1974,8 +1974,8 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
                                const SkRRect& rrect,
                                const SkStrokeRec& stroke) {
     if (rrect.isOval()) {
-        return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA, rrect.getBounds(),
-                              stroke);
+        return DrawOval(target, pipelineBuilder, color, viewMatrix, useAA, rrect.getBounds(),
+                        stroke);
     }
 
     bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisampled();
index 57ce2a5..d8d9e0c 100644 (file)
@@ -8,68 +8,64 @@
 #ifndef GrOvalRenderer_DEFINED
 #define GrOvalRenderer_DEFINED
 
-#include "GrContext.h"
 #include "GrPaint.h"
 
-class GrContext;
 class GrDrawTarget;
-class GrPaint;
+class GrPipelineBuilder;
 struct SkRect;
 class SkStrokeRec;
 
 /*
  * This class wraps helper functions that draw ovals and roundrects (filled & stroked)
  */
-class GrOvalRenderer : public SkRefCnt {
+class GrOvalRenderer {
 public:
-    SK_DECLARE_INST_COUNT(GrOvalRenderer)
-
-    bool drawOval(GrDrawTarget*,
-                  GrPipelineBuilder*,
-                  GrColor,
-                  const SkMatrix& viewMatrix,
-                  bool useAA,
-                  const SkRect& oval,
-                  const SkStrokeRec& stroke);
-    bool drawRRect(GrDrawTarget*,
-                   GrPipelineBuilder*,
-                   GrColor,
-                   const SkMatrix& viewMatrix,
-                   bool useAA,
-                   const SkRRect& rrect,
-                   const SkStrokeRec& stroke);
-    bool drawDRRect(GrDrawTarget* target,
-                    GrPipelineBuilder*,
-                    GrColor,
-                    const SkMatrix& viewMatrix,
-                    bool useAA,
-                    const SkRRect& outer,
-                    const SkRRect& inner);
+    static bool DrawOval(GrDrawTarget*,
+                         GrPipelineBuilder*,
+                         GrColor,
+                         const SkMatrix& viewMatrix,
+                         bool useAA,
+                         const SkRect& oval,
+                         const SkStrokeRec& stroke);
+    static bool DrawRRect(GrDrawTarget*,
+                          GrPipelineBuilder*,
+                          GrColor,
+                          const SkMatrix& viewMatrix,
+                          bool useAA,
+                          const SkRRect& rrect,
+                          const SkStrokeRec& stroke);
+    static bool DrawDRRect(GrDrawTarget* target,
+                           GrPipelineBuilder*,
+                           GrColor,
+                           const SkMatrix& viewMatrix,
+                           bool useAA,
+                           const SkRRect& outer,
+                           const SkRRect& inner);
 
 private:
-    bool drawEllipse(GrDrawTarget* target,
-                     GrPipelineBuilder*,
-                     GrColor,
-                     const SkMatrix& viewMatrix,
-                     bool useCoverageAA,
-                     const SkRect& ellipse,
-                     const SkStrokeRec& stroke);
-    bool drawDIEllipse(GrDrawTarget* target,
-                       GrPipelineBuilder*,
-                       GrColor,
-                       const SkMatrix& viewMatrix,
-                       bool useCoverageAA,
-                       const SkRect& ellipse,
-                       const SkStrokeRec& stroke);
-    void drawCircle(GrDrawTarget* target,
-                    GrPipelineBuilder*,
-                    GrColor,
-                    const SkMatrix& viewMatrix,
-                    bool useCoverageAA,
-                    const SkRect& circle,
-                    const SkStrokeRec& stroke);
+    GrOvalRenderer();
 
-    typedef SkRefCnt INHERITED;
+    static bool DrawEllipse(GrDrawTarget* target,
+                            GrPipelineBuilder*,
+                            GrColor,
+                            const SkMatrix& viewMatrix,
+                            bool useCoverageAA,
+                            const SkRect& ellipse,
+                            const SkStrokeRec& stroke);
+    static bool DrawDIEllipse(GrDrawTarget* target,
+                              GrPipelineBuilder*,
+                              GrColor,
+                              const SkMatrix& viewMatrix,
+                              bool useCoverageAA,
+                              const SkRect& ellipse,
+                              const SkStrokeRec& stroke);
+    static void DrawCircle(GrDrawTarget* target,
+                           GrPipelineBuilder*,
+                           GrColor,
+                           const SkMatrix& viewMatrix,
+                           bool useCoverageAA,
+                           const SkRect& circle,
+                           const SkStrokeRec& stroke);
 };
 
 #endif // GrOvalRenderer_DEFINED
index d539c90..59a7ae5 100644 (file)
@@ -10,6 +10,7 @@
 #include "GrRenderTarget.h"
 
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "GrGpu.h"
 #include "GrRenderTargetPriv.h"
 #include "GrStencilAttachment.h"
 void GrRenderTarget::discard() {
     // go through context so that all necessary flushing occurs
     GrContext* context = this->getContext();
-    if (NULL == context) {
+    GrDrawContext* drawContext = context ? context->drawContext() : NULL;
+    if (!drawContext) {
         return;
     }
-    context->discardRenderTarget(this);
+
+    drawContext->discard(this);
 }
 
 void GrRenderTarget::flagAsNeedingResolve(const SkIRect* rect) {
index 2591186..c978866 100644 (file)
@@ -376,5 +376,5 @@ void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
                                                        GrTextureParams::kNone_FilterMode,
                                                        kDevice_GrCoordSet))->unref();
 
-    target->drawRect(pipelineBuilder, color, SkMatrix::I(), dstRect, NULL, &invert);
+    target->drawBWRect(pipelineBuilder, color, SkMatrix::I(), dstRect, NULL, &invert);
 }
index fb060aa..d9b58a8 100644 (file)
@@ -94,22 +94,22 @@ void draw_around_inv_path(GrDrawTarget* target,
     if (devClipBounds.fTop < devPathBounds.fTop) {
         rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
                   devClipBounds.fRight, devPathBounds.fTop);
-        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
+        target->drawBWRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
     }
     if (devClipBounds.fLeft < devPathBounds.fLeft) {
         rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
                   devPathBounds.fLeft, devPathBounds.fBottom);
-        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
+        target->drawBWRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
     }
     if (devClipBounds.fRight > devPathBounds.fRight) {
         rect.iset(devPathBounds.fRight, devPathBounds.fTop,
                   devClipBounds.fRight, devPathBounds.fBottom);
-        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
+        target->drawBWRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
     }
     if (devClipBounds.fBottom > devPathBounds.fBottom) {
         rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
                   devClipBounds.fRight, devClipBounds.fBottom);
-        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
+        target->drawBWRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
     }
 }
 
index a6992df..a082325 100644 (file)
@@ -142,7 +142,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(GrDrawTarget* target,
             }
         }
         const SkMatrix& viewM = viewMatrix.hasPerspective() ? SkMatrix::I() : viewMatrix;
-        target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &invert);
+        target->drawBWRect(pipelineBuilder, color, viewM, bounds, NULL, &invert);
     } else {
         GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
             kZero_StencilOp,
index 63efcfc..539d731 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrStencilAndCoverTextContext.h"
 #include "GrAtlasTextContext.h"
+#include "GrDrawContext.h"
 #include "GrDrawTarget.h"
 #include "GrPath.h"
 #include "GrPathRange.h"
@@ -434,7 +435,13 @@ void GrStencilAndCoverTextContext::flush() {
         SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor(),
                                                                  fViewMatrix,
                                                                  fLocalMatrix));
-        fDrawTarget->drawPaths(&fPipelineBuilder, pp, fGlyphs,
+
+        GrDrawContext* drawContext = fContext->drawContext();
+        if (!drawContext) {
+            return;
+        }
+
+        drawContext->drawPaths(&fPipelineBuilder, pp, fGlyphs,
                                fGlyphIndices, GrPathRange::kU16_PathIndexType,
                                get_xy_scalar_array(fGlyphPositions),
                                GrPathRendering::kTranslate_PathTransformType,
@@ -482,6 +489,5 @@ void GrStencilAndCoverTextContext::finish() {
     fPipelineBuilder.stencil()->setDisabled();
     fStateRestore.set(NULL);
     fViewMatrix = fContextInitialMatrix;
-    GrTextContext::finish();
 }
 
index 8580661..8546cf1 100644 (file)
@@ -27,7 +27,7 @@ void GrContext::getTestTarget(GrTestTarget* tar) {
     // 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
     // until ~GrTestTarget().
-    tar->init(this, fDrawBuffer);
+    tar->init(this, fDrawingMgr.fDrawTarget);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -268,7 +268,5 @@ void GrContext::initMockContext() {
     // We delete these because we want to test the cache starting with zero resources. Also, none of
     // these objects are required for any of tests that use this context. TODO: make stop allocating
     // resources in the buffer pools.
-    SkDELETE(fDrawBuffer);
-    fDrawBuffer = NULL;
-
+    fDrawingMgr.abandon();
 }
index 4c6dabc..4b8bc68 100644 (file)
@@ -24,8 +24,7 @@ GrTextContext::GrTextContext(GrContext* context, SkGpuDevice* gpuDevice,
     : fFallbackTextContext(NULL)
     , fContext(context)
     , fGpuDevice(gpuDevice)
-    , fDeviceProperties(properties)
-    , fDrawTarget(NULL) {
+    , fDeviceProperties(properties) {
 }
 
 GrTextContext::~GrTextContext() {
@@ -41,8 +40,6 @@ void GrTextContext::init(GrRenderTarget* rt, const GrClip& clip, const GrPaint&
     fRegionClipBounds = regionClipBounds;
     fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
 
-    fDrawTarget = fContext->getTextTarget();
-
     fPaint = grPaint;
     fSkPaint = skPaint;
 }
@@ -51,7 +48,7 @@ void GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPai
                              const SkPaint& skPaint, const SkMatrix& viewMatrix,
                              const char text[], size_t byteLength,
                              SkScalar x, SkScalar y, const SkIRect& clipBounds) {
-    if (!fContext->getTextTarget()) {
+    if (fContext->abandoned()) {
         return;
     }
 
@@ -75,7 +72,7 @@ void GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const Gr
                                 const char text[], size_t byteLength,
                                 const SkScalar pos[], int scalarsPerPosition,
                                 const SkPoint& offset, const SkIRect& clipBounds) {
-    if (!fContext->getTextTarget()) {
+    if (fContext->abandoned()) {
         return;
     }
 
index 8529528..242ae3a 100644 (file)
@@ -53,7 +53,6 @@ protected:
 
     SkAutoTUnref<GrRenderTarget>   fRenderTarget;
     GrClip                         fClip;
-    GrDrawTarget*                  fDrawTarget;
     SkIRect                        fClipRect;
     SkIRect                        fRegionClipBounds;
     GrPaint                        fPaint;
@@ -83,7 +82,6 @@ protected:
 
     void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
               const SkIRect& regionClipBounds);
-    void finish() { fDrawTarget = NULL; }
 
     static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
     // sets extent in stopVector and returns glyph count
index ea998b8..94ded8d 100644 (file)
@@ -8,6 +8,7 @@
 #include "SkGpuDevice.h"
 
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "GrGpu.h"
 #include "GrGpuResourcePriv.h"
 #include "GrLayerHoister.h"
@@ -168,6 +169,7 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
     bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
     fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLeakyProperties(),
                                                useDFT);
+    fDrawContext.reset(SkRef(fContext->drawContext()));
 }
 
 GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::Budgeted budgeted,
@@ -226,7 +228,7 @@ SkGpuDevice::~SkGpuDevice() {
         delete fDrawProcs;
     }
 
-    delete fTextContext;
+    SkDELETE(fTextContext);
 
     fRenderTarget->unref();
     fContext->unref();
@@ -310,7 +312,7 @@ void SkGpuDevice::clearAll() {
     GrColor color = 0;
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clearAll", fContext);
     SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
-    fContext->clear(&rect, color, true, fRenderTarget);
+    fDrawContext->clear(fRenderTarget, &rect, color, true);
     fNeedClear = false;
 }
 
@@ -344,6 +346,8 @@ void SkGpuDevice::replaceRenderTarget(bool shouldRetainContent) {
     SkASSERT(fRenderTarget->surfacePriv().info() == fLegacyBitmap.info());
     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fRenderTarget->surfacePriv().info(), fRenderTarget));
     fLegacyBitmap.setPixelRef(pr)->unref();
+
+    fDrawContext.reset(SkRef(fRenderTarget->getContext()->drawContext()));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -357,7 +361,7 @@ void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
         return;
     }
 
-    fContext->drawPaint(fRenderTarget, fClip, grPaint, *draw.fMatrix);
+    fDrawContext->drawPaint(fRenderTarget, fClip, grPaint, *draw.fMatrix);
 }
 
 // must be in SkCanvas::PointMode order
@@ -388,7 +392,7 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
         path.setIsVolatile(true);
         path.moveTo(pts[0]);
         path.lineTo(pts[1]);
-        fContext->drawPath(fRenderTarget, fClip, grPaint, *draw.fMatrix, path, strokeInfo);
+        fDrawContext->drawPath(fRenderTarget, fClip, grPaint, *draw.fMatrix, path, strokeInfo);
         return;
     }
 
@@ -404,17 +408,17 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
         return;
     }
 
-    fContext->drawVertices(fRenderTarget,
-                           fClip,
-                           grPaint,
-                           *draw.fMatrix,
-                           gPointMode2PrimtiveType[mode],
-                           SkToS32(count),
-                           (SkPoint*)pts,
-                           NULL,
-                           NULL,
-                           NULL,
-                           0);
+    fDrawContext->drawVertices(fRenderTarget,
+                               fClip,
+                               grPaint,
+                               *draw.fMatrix,
+                               gPointMode2PrimtiveType[mode],
+                               SkToS32(count),
+                               (SkPoint*)pts,
+                               NULL,
+                               NULL,
+                               NULL,
+                               0);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -478,7 +482,7 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
         return;
     }
 
-    fContext->drawRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, &strokeInfo);
+    fDrawContext->drawRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, &strokeInfo);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -548,7 +552,7 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
         return;
     }
 
-    fContext->drawRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, strokeInfo);
+    fDrawContext->drawRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, strokeInfo);
 }
 
 void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
@@ -566,7 +570,7 @@ void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
         }
 
         if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) {
-            fContext->drawDRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, outer, inner);
+            fDrawContext->drawDRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, outer, inner);
             return;
         }
     }
@@ -615,7 +619,7 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
         return;
     }
 
-    fContext->drawOval(fRenderTarget, fClip, grPaint, *draw.fMatrix, oval, strokeInfo);
+    fDrawContext->drawOval(fRenderTarget, fClip, grPaint, *draw.fMatrix, oval, strokeInfo);
 }
 
 #include "SkMaskFilter.h"
@@ -628,7 +632,7 @@ namespace {
 // Draw a mask using the supplied paint. Since the coverage/geometry
 // is already burnt into the mask this boils down to a rect draw.
 // Return true if the mask was successfully drawn.
-bool draw_mask(GrContext* context,
+bool draw_mask(GrDrawContext* drawContext,
                GrRenderTarget* rt,
                const GrClip& clip,
                const SkMatrix& viewMatrix,
@@ -646,7 +650,7 @@ bool draw_mask(GrContext* context,
     if (!viewMatrix.invert(&inverse)) {
         return false;
     }
-    context->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), maskRect, inverse);
+    drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), maskRect, inverse);
     return true;
 }
 
@@ -654,7 +658,8 @@ static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& r
     return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBounds, rect);
 }
 
-bool draw_with_mask_filter(GrContext* context,
+bool draw_with_mask_filter(GrDrawContext* drawContext,
+                           GrTextureProvider* textureProvider,
                            GrRenderTarget* rt,
                            const GrClip& clipData,
                            const SkMatrix& viewMatrix,
@@ -688,7 +693,7 @@ bool draw_with_mask_filter(GrContext* context,
     desc.fHeight = dstM.fBounds.height();
     desc.fConfig = kAlpha_8_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> texture(context->textureProvider()->refScratchTexture(
+    SkAutoTUnref<GrTexture> texture(textureProvider->refScratchTexture(
         desc, GrTextureProvider::kApprox_ScratchTexMatch));
     if (!texture) {
         return false;
@@ -698,12 +703,11 @@ bool draw_with_mask_filter(GrContext* context,
 
     SkRect maskRect = SkRect::Make(dstM.fBounds);
 
-    return draw_mask(context, rt, clipData, viewMatrix, maskRect, grp, texture);
+    return draw_mask(drawContext, rt, clipData, viewMatrix, maskRect, grp, texture);
 }
 
 // Create a mask of 'devPath' and place the result in 'mask'.
 GrTexture* create_mask_GPU(GrContext* context,
-                           GrRenderTarget* rt,
                            const SkRect& maskRect,
                            const SkPath& devPath,
                            const GrStrokeInfo& strokeInfo,
@@ -731,7 +735,12 @@ GrTexture* create_mask_GPU(GrContext* context,
 
     SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
 
-    context->clear(NULL, 0x0, true, mask->asRenderTarget());
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return NULL;
+    }
+
+    drawContext->clear(mask->asRenderTarget(), NULL, 0x0, true);
 
     GrPaint tempPaint;
     tempPaint.setAntiAlias(doAA);
@@ -743,7 +752,7 @@ GrTexture* create_mask_GPU(GrContext* context,
     // Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
     SkMatrix translate;
     translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
-    context->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
+    drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
     return mask;
 }
 
@@ -871,7 +880,6 @@ void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& pai
 
 
             SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext,
-                                                         fRenderTarget,
                                                          maskRect,
                                                          *devPathPtr,
                                                          strokeInfo,
@@ -883,7 +891,7 @@ void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& pai
                 if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskRect, &filtered, true)) {
                     // filterMaskGPU gives us ownership of a ref to the result
                     SkAutoTUnref<GrTexture> atu(filtered);
-                    if (draw_mask(fContext,
+                    if (draw_mask(fDrawContext,
                                   fRenderTarget,
                                   fClip,
                                   viewMatrix,
@@ -901,12 +909,13 @@ void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& pai
         // GPU path fails
         SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_Style :
                                                               SkPaint::kFill_Style;
-        draw_with_mask_filter(fContext, fRenderTarget, fClip, viewMatrix, *devPathPtr,
+        draw_with_mask_filter(fDrawContext, fContext->textureProvider(), fRenderTarget,
+                              fClip, viewMatrix, *devPathPtr,
                               paint.getMaskFilter(), clipBounds, &grPaint, style);
         return;
     }
 
-    fContext->drawPath(fRenderTarget, fClip, grPaint, viewMatrix, *pathPtr, strokeInfo);
+    fDrawContext->drawPath(fRenderTarget, fClip, grPaint, viewMatrix, *pathPtr, strokeInfo);
 }
 
 static const int kBmpSmallTileSize = 1 << 10;
@@ -1493,8 +1502,8 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
         return;
     }
 
-    fContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, viewMatrix, dstRect,
-                                  paintRect);
+    fDrawContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, viewMatrix, dstRect,
+                                      paintRect);
 }
 
 bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
@@ -1569,18 +1578,18 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
         return;
     }
 
-    fContext->drawNonAARectToRect(fRenderTarget,
-                                  fClip,
-                                  grPaint,
-                                  SkMatrix::I(),
-                                  SkRect::MakeXYWH(SkIntToScalar(left),
-                                                   SkIntToScalar(top),
-                                                   SkIntToScalar(w),
-                                                   SkIntToScalar(h)),
-                                  SkRect::MakeXYWH(0,
-                                                   0,
-                                                   SK_Scalar1 * w / texture->width(),
-                                                   SK_Scalar1 * h / texture->height()));
+    fDrawContext->drawNonAARectToRect(fRenderTarget,
+                                      fClip,
+                                      grPaint,
+                                      SkMatrix::I(),
+                                      SkRect::MakeXYWH(SkIntToScalar(left),
+                                                       SkIntToScalar(top),
+                                                       SkIntToScalar(w),
+                                                       SkIntToScalar(h)),
+                                      SkRect::MakeXYWH(0,
+                                                       0,
+                                                       SK_Scalar1 * w / texture->width(),
+                                                       SK_Scalar1 * h / texture->height()));
 }
 
 void SkGpuDevice::drawBitmapRect(const SkDraw& origDraw, const SkBitmap& bitmap,
@@ -1695,8 +1704,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
     SkRect srcRect = SkRect::MakeWH(SK_Scalar1 * w / devTex->width(),
                                     SK_Scalar1 * h / devTex->height());
 
-    fContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, SkMatrix::I(), dstRect,
-                                  srcRect);
+    fDrawContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, SkMatrix::I(), dstRect,
+                                      srcRect);
 }
 
 bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) {
@@ -1865,17 +1874,17 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
         }
         colors = convertedColors.get();
     }
-    fContext->drawVertices(fRenderTarget,
-                           fClip,
-                           grPaint,
-                           *draw.fMatrix,
-                           primType,
-                           vertexCount,
-                           vertices,
-                           texs,
-                           colors,
-                           outIndices,
-                           indexCount);
+    fDrawContext->drawVertices(fRenderTarget,
+                               fClip,
+                               grPaint,
+                               *draw.fMatrix,
+                               primType,
+                               vertexCount,
+                               vertices,
+                               texs,
+                               colors,
+                               outIndices,
+                               indexCount);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
index c1ea4fe..1356a6f 100644 (file)
@@ -151,6 +151,7 @@ private:
     SkIPoint                        fClipOrigin;
     GrClip                          fClip;
     GrTextContext*                  fTextContext;
+    SkAutoTUnref<GrDrawContext>     fDrawContext;
     SkSurfaceProps                  fSurfaceProps;
     GrRenderTarget*                 fRenderTarget;
     // remove when our clients don't rely on accessBitmap()
index f8c4941..decb358 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "SkGr.h"
 
+#include "GrDrawContext.h"
 #include "GrXferProcessor.h"
 #include "SkColorFilter.h"
 #include "SkConfig8888.h"
@@ -245,8 +246,13 @@ GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch,
     SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
     SkRect localRect = SkRect::MakeWH(1.f, 1.f);
 
-    context->drawNonAARectToRect(stretched->asRenderTarget(), GrClip::WideOpen(), paint,
-                                 SkMatrix::I(), rect, localRect);
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return NULL;
+    }
+
+    drawContext->drawNonAARectToRect(stretched->asRenderTarget(), GrClip::WideOpen(), paint,
+                                     SkMatrix::I(), rect, localRect);
 
     return stretched;
 }
@@ -398,7 +404,12 @@ static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKe
     SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth),
                               SkIntToScalar(yuvInfo.fSize[0].fHeight));
 
-    ctx->drawRect(renderTarget, GrClip::WideOpen(), paint, SkMatrix::I(), r);
+    GrDrawContext* drawContext = ctx->drawContext();
+    if (!drawContext) {
+        return NULL;
+    }
+
+    drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, SkMatrix::I(), r);
 
     return result;
 }
index 9a6f9fc..d5b8a18 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrConfigConversionEffect.h"
 #include "GrContext.h"
+#include "GrDrawContext.h"
 #include "GrInvariantOutput.h"
 #include "GrSimpleTextureEffect.h"
 #include "SkMatrix.h"
@@ -207,6 +208,11 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
 
     bool failed = true;
 
+    GrDrawContext* drawContext = context->drawContext();
+    if (!drawContext) {
+        return;
+    }
+
     for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) {
         *pmToUPMRule = kConversionRules[i][0];
         *upmToPMRule = kConversionRules[i][1];
@@ -229,32 +235,32 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
 
         GrPaint paint1;
         paint1.addColorProcessor(pmToUPM1);
-        context->drawNonAARectToRect(readTex->asRenderTarget(),
-                                     GrClip::WideOpen(),
-                                     paint1,
-                                     SkMatrix::I(),
-                                     kDstRect,
-                                     kSrcRect);
+        drawContext->drawNonAARectToRect(readTex->asRenderTarget(),
+                                         GrClip::WideOpen(),
+                                         paint1,
+                                         SkMatrix::I(),
+                                         kDstRect,
+                                         kSrcRect);
 
         readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead);
 
         GrPaint paint2;
         paint2.addColorProcessor(upmToPM);
-        context->drawNonAARectToRect(tempTex->asRenderTarget(),
-                                     GrClip::WideOpen(),
-                                     paint2,
-                                     SkMatrix::I(),
-                                     kDstRect,
-                                     kSrcRect);
+        drawContext->drawNonAARectToRect(tempTex->asRenderTarget(),
+                                         GrClip::WideOpen(),
+                                         paint2,
+                                         SkMatrix::I(),
+                                         kDstRect,
+                                         kSrcRect);
 
         GrPaint paint3;
         paint3.addColorProcessor(pmToUPM2);
-        context->drawNonAARectToRect(readTex->asRenderTarget(),
-                                     GrClip::WideOpen(),
-                                     paint3,
-                                     SkMatrix::I(),
-                                     kDstRect,
-                                     kSrcRect);
+        drawContext->drawNonAARectToRect(readTex->asRenderTarget(),
+                                         GrClip::WideOpen(),
+                                         paint3,
+                                         SkMatrix::I(),
+                                         kDstRect,
+                                         kSrcRect);
 
         readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, secondRead);