Add way to determine at link time what path renderer will be used.
Added mechanism for a custom path renderer to punt and fallback to default path renderer



git-svn-id: http://skia.googlecode.com/svn/trunk@1005 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 4058c5b..106ac8a 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -21,13 +21,13 @@
 #include "GrGpu.h"
 #include "GrTextureCache.h"
 #include "GrPaint.h"
+#include "GrPathRenderer.h"
 
 class GrFontCache;
 class GrPathIter;
 class GrVertexBufferAllocPool;
 class GrIndexBufferAllocPool;
 class GrInOrderDrawBuffer;
-class GrPathRenderer;
 
 class GR_API GrContext : public GrRefCnt {
 public:
@@ -479,13 +479,16 @@
     GrGpu*          fGpu;
     GrTextureCache* fTextureCache;
     GrFontCache*    fFontCache;
-    GrPathRenderer* fPathRenderer;
+
+    GrPathRenderer*         fCustomPathRenderer;
+    GrDefaultPathRenderer   fDefaultPathRenderer;
 
     GrVertexBufferAllocPool*    fDrawBufferVBAllocPool;
     GrIndexBufferAllocPool*     fDrawBufferIBAllocPool;
     GrInOrderDrawBuffer*        fDrawBuffer;
 
     GrContext(GrGpu* gpu);
+
     void flushDrawBuffer();
 
     static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
@@ -495,6 +498,11 @@
     GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
 
     void drawClipIntoStencil();
+
+    GrPathRenderer* getPathRenderer(const GrDrawTarget* target,
+                                    GrPathIter* path,
+                                    GrPathFill fill);
+
 };
 
 /**
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index abeec0c..7e12456 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -21,10 +21,10 @@
 #include "GrRefCnt.h"
 #include "GrDrawTarget.h"
 #include "GrTexture.h"
+#include "GrPathRenderer.h"
 
 class GrVertexBufferAllocPool;
 class GrIndexBufferAllocPool;
-class GrPathRenderer;
 
 class GrGpu : public GrDrawTarget {
 
@@ -308,6 +308,14 @@
                                 int vertexCount);
 
     /**
+     * Installs a path renderer that will be used to draw paths that are
+     * part of the clip.
+     */
+    void setClipPathRenderer(GrPathRenderer* pathRenderer) {
+        GrSafeAssign(fClientPathRenderer, pathRenderer);
+    }
+
+    /**
      * Returns an index buffer that can be used to render quads.
      * Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
      * The max number of quads can be queried using GrIndexBuffer::maxQuads().
@@ -495,7 +503,9 @@
     void prepareVertexPool();
     void prepareIndexPool();
 
-    GrPathRenderer* getPathRenderer();
+    // determines the path renderer used to draw a clip path element.
+    GrPathRenderer* getClipPathRenderer(GrPathIter* path,
+                                        GrPathFill fill);
 
     void handleDirtyContext() {
         if (fContextIsDirty) {
@@ -514,7 +524,8 @@
     mutable GrVertexBuffer*     fUnitSquareVertexBuffer; // mutable so it can be
                                                          // created on-demand
 
-    GrPathRenderer*             fPathRenderer;
+    GrDefaultPathRenderer*      fDefaultPathRenderer;
+    GrPathRenderer*             fClientPathRenderer;
 
     bool                        fContextIsDirty;
 
diff --git a/gpu/include/GrPathRenderer.h b/gpu/include/GrPathRenderer.h
new file mode 100644
index 0000000..2d846c8
--- /dev/null
+++ b/gpu/include/GrPathRenderer.h
@@ -0,0 +1,319 @@
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+#ifndef GrPathRenderer_DEFINED
+#define GrPathRenderer_DEFINED
+
+#include "GrDrawTarget.h"
+
+class GrPathIter;
+struct GrPoint;
+
+/**
+ *  Base class for drawing paths into a GrDrawTarget.
+ */
+class GrPathRenderer : public GrRefCnt {
+public:
+    /**
+     * Returns true if this path renderer is able to render the path.
+     * Returning false allows the caller to fallback to another path renderer.
+     *
+     * @param target    The target to draw into
+     * @param path      The path to draw
+     * @param fill      The fill rule to use
+     *
+     * @return  true if the path can be drawn by this object, false otherwise.
+     */
+    virtual bool canDrawPath(const GrDrawTarget* target,
+                             GrPathIter* path,
+                             GrPathFill fill) const = 0;
+
+    /**
+     * Draws a path into the draw target. The target will already have its draw
+     * state configured for the draw.
+     * @param target                the target to draw into.
+     * @param stages                indicates which stages the are already
+     *                              in use. All enabled stages expect positions
+     *                              as texture coordinates. The path renderer
+     *                              use the remaining stages for its path
+     *                              filling algorithm.
+     * @param path                  the path to draw.
+     * @param fill                  the fill rule to apply.
+     * @param translate             optional additional translation to apply to
+     *                              the path. NULL means (0,0).
+     */
+    virtual void drawPath(GrDrawTarget* target,
+                          GrDrawTarget::StageBitfield stages,
+                          GrPathIter* path,
+                          GrPathFill fill,
+                          const GrPoint* translate) = 0;
+
+    /**
+     * For complex clips Gr uses the stencil buffer. The path renderer must be
+     * able to render paths into the stencil buffer. However, the path renderer
+     * itself may require the stencil buffer to resolve the path fill rule. This
+     * function queries whether the path render needs its own stencil
+     * pass. If this returns false then drawPath() should not modify the
+     * the target's stencil settings but use those already set on target.
+     *
+     * @param target target that the path will be rendered to
+     * @param path   the path that will be drawn
+     * @param fill   the fill rule that will be used, will never be an inverse
+     *               rule.
+     *
+     * @return false if this path renderer can generate interior-only fragments
+     *         without changing the stencil settings on the target. If it
+     *         returns true the drawPathToStencil will be used when rendering
+     *         clips.
+     */
+    virtual bool requiresStencilPass(const GrDrawTarget* target,
+                                     GrPathIter* path,
+                                     GrPathFill fill) const { return false; }
+
+    /**
+     * Draws a path to the stencil buffer. Assume the writable stencil bits
+     * are already initialized to zero. Fill will always be either
+     * kWinding_PathFill or kEvenOdd_PathFill.
+     *
+     * Only called if requiresStencilPass returns true for the same combo of
+     * target, path, and fill. Never called with an inverse fill.
+     *
+     * The default implementation assumes the path filling algorithm doesn't
+     * require a separate stencil pass and so crashes.
+     *
+     *
+     * @param target                the target to draw into.
+     * @param path                  the path to draw.
+     * @param fill                  the fill rule to apply.
+     * @param translate             optional additional translation to apply to
+     *                              the path. NULL means (0,0).
+     */
+    virtual void drawPathToStencil(GrDrawTarget* target,
+                                   GrPathIter* path,
+                                   GrPathFill fill,
+                                   const GrPoint* translate) {
+        GrCrash("Unexpected call to drawPathToStencil.");
+    }
+    
+    /**
+     * This is called to install a custom path renderer in every GrContext at
+     * create time. The default implementation in GrCreatePathRenderer_none.cpp
+     * returns NULL. Link against another implementation to install your own.
+     */
+    static GrPathRenderer* CreatePathRenderer();
+
+private:
+
+    typedef GrRefCnt INHERITED;
+};
+
+/**
+ *  Subclass that renders the path using the stencil buffer to resolve fill
+ *  rules (e.g. winding, even-odd)
+ */
+class GrDefaultPathRenderer : public GrPathRenderer {
+public:
+    GrDefaultPathRenderer(bool separateStencilSupport,
+                          bool stencilWrapOpsSupport);
+
+    virtual bool canDrawPath(const GrDrawTarget* target,
+                             GrPathIter* path,
+                             GrPathFill fill) const { return true; }
+
+    virtual void drawPath(GrDrawTarget* target,
+                          GrDrawTarget::StageBitfield stages,
+                          GrPathIter* path,
+                          GrPathFill fill,
+                          const GrPoint* translate);
+    virtual bool requiresStencilPass(const GrDrawTarget* target,
+                                     GrPathIter* path,
+                                     GrPathFill fill) const;
+    virtual void drawPathToStencil(GrDrawTarget* target,
+                                   GrPathIter* path,
+                                   GrPathFill fill,
+                                   const GrPoint* translate);
+private:
+
+    void drawPathHelper(GrDrawTarget* target,
+                        GrDrawTarget::StageBitfield stages,
+                        GrPathIter* path,
+                        GrPathFill fill,
+                        const GrPoint* translate,
+                        bool stencilOnly);
+
+    bool    fSeparateStencil;
+    bool    fStencilWrapOps;
+
+    typedef GrPathRenderer INHERITED;
+};
+
+#endif
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+#ifndef GrPathRenderer_DEFINED
+#define GrPathRenderer_DEFINED
+
+#include "GrDrawTarget.h"
+
+class GrPathIter;
+struct GrPoint;
+
+/**
+ *  Base class for drawing paths into a GrDrawTarget.
+ */
+class GrPathRenderer : public GrRefCnt {
+public:
+    /**
+     * Returns true if this path renderer is able to render the path.
+     * Returning false allows the caller to fallback to another path renderer.
+     *
+     * @param target    The target to draw into
+     * @param path      The path to draw
+     * @param fill      The fill rule to use
+     *
+     * @return  true if the path can be drawn by this object, false otherwise.
+     */
+    virtual bool canDrawPath(const GrDrawTarget* target,
+                             GrPathIter* path,
+                             GrPathFill fill) const = 0;
+
+    /**
+     * Draws a path into the draw target. The target will already have its draw
+     * state configured for the draw.
+     * @param target                the target to draw into.
+     * @param stages                indicates which stages the are already
+     *                              in use. All enabled stages expect positions
+     *                              as texture coordinates. The path renderer
+     *                              use the remaining stages for its path
+     *                              filling algorithm.
+     * @param path                  the path to draw.
+     * @param fill                  the fill rule to apply.
+     * @param translate             optional additional translation to apply to
+     *                              the path. NULL means (0,0).
+     */
+    virtual void drawPath(GrDrawTarget* target,
+                          GrDrawTarget::StageBitfield stages,
+                          GrPathIter* path,
+                          GrPathFill fill,
+                          const GrPoint* translate) = 0;
+
+    /**
+     * For complex clips Gr uses the stencil buffer. The path renderer must be
+     * able to render paths into the stencil buffer. However, the path renderer
+     * itself may require the stencil buffer to resolve the path fill rule. This
+     * function queries whether the path render needs its own stencil
+     * pass. If this returns false then drawPath() should not modify the
+     * the target's stencil settings but use those already set on target.
+     *
+     * @param target target that the path will be rendered to
+     * @param path   the path that will be drawn
+     * @param fill   the fill rule that will be used, will never be an inverse
+     *               rule.
+     *
+     * @return false if this path renderer can generate interior-only fragments
+     *         without changing the stencil settings on the target. If it
+     *         returns true the drawPathToStencil will be used when rendering
+     *         clips.
+     */
+    virtual bool requiresStencilPass(const GrDrawTarget* target,
+                                     GrPathIter* path,
+                                     GrPathFill fill) const { return false; }
+
+    /**
+     * Draws a path to the stencil buffer. Assume the writable stencil bits
+     * are already initialized to zero. Fill will always be either
+     * kWinding_PathFill or kEvenOdd_PathFill.
+     *
+     * Only called if requiresStencilPass returns true for the same combo of
+     * target, path, and fill. Never called with an inverse fill.
+     *
+     * The default implementation assumes the path filling algorithm doesn't
+     * require a separate stencil pass and so crashes.
+     *
+     *
+     * @param target                the target to draw into.
+     * @param path                  the path to draw.
+     * @param fill                  the fill rule to apply.
+     * @param translate             optional additional translation to apply to
+     *                              the path. NULL means (0,0).
+     */
+    virtual void drawPathToStencil(GrDrawTarget* target,
+                                   GrPathIter* path,
+                                   GrPathFill fill,
+                                   const GrPoint* translate) {
+        GrCrash("Unexpected call to drawPathToStencil.");
+    }
+
+private:
+
+    typedef GrRefCnt INHERITED;
+};
+
+/**
+ *  Subclass that renders the path using the stencil buffer to resolve fill
+ *  rules (e.g. winding, even-odd)
+ */
+class GrDefaultPathRenderer : public GrPathRenderer {
+public:
+    GrDefaultPathRenderer(bool separateStencilSupport,
+                          bool stencilWrapOpsSupport);
+
+    virtual bool canDrawPath(const GrDrawTarget* target,
+                             GrPathIter* path,
+                             GrPathFill fill) const { return true; }
+
+    virtual void drawPath(GrDrawTarget* target,
+                          GrDrawTarget::StageBitfield stages,
+                          GrPathIter* path,
+                          GrPathFill fill,
+                          const GrPoint* translate);
+    virtual bool requiresStencilPass(const GrDrawTarget* target,
+                                     GrPathIter* path,
+                                     GrPathFill fill) const;
+    virtual void drawPathToStencil(GrDrawTarget* target,
+                                   GrPathIter* path,
+                                   GrPathFill fill,
+                                   const GrPoint* translate);
+private:
+
+    void drawPathHelper(GrDrawTarget* target,
+                        GrDrawTarget::StageBitfield stages,
+                        GrPathIter* path,
+                        GrPathFill fill,
+                        const GrPoint* translate,
+                        bool stencilOnly);
+
+    bool    fSeparateStencil;
+    bool    fStencilWrapOps;
+
+    typedef GrPathRenderer INHERITED;
+};
+
+#endif
diff --git a/gpu/include/GrRefCnt.h b/gpu/include/GrRefCnt.h
index a466760..c462b2c 100644
--- a/gpu/include/GrRefCnt.h
+++ b/gpu/include/GrRefCnt.h
@@ -93,7 +93,8 @@
  *  Assigns src to dst, checking for NULLs in each, and correctly incrementing
  *  the reference count of src, and decrementing the reference count of dst
  */
-static inline void GrSafeAssign(GrRefCnt*& dst, GrRefCnt* src) {
+template<typename T>
+static inline void GrSafeAssign(T*& dst, T* src) {
     if (src) {
         src->ref();
     }
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index a20c6be..f6009f5 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -63,7 +63,7 @@
     delete fDrawBuffer;
     delete fDrawBufferVBAllocPool;
     delete fDrawBufferIBAllocPool;
-    delete fPathRenderer;
+    GrSafeUnref(fCustomPathRenderer);
 }
 
 void GrContext::abandonAllTextures() {
@@ -546,7 +546,8 @@
     if (NULL != paint.getTexture()) {
         enabledStages |= 1;
     }
-    fPathRenderer->drawPath(target, enabledStages, path, fill, translate);
+    GrPathRenderer* pr = getPathRenderer(target, path, fill);
+    pr->drawPath(target, enabledStages, path, fill, translate);
 }
 
 void GrContext::drawPath(const GrPaint& paint,
@@ -738,9 +739,16 @@
     fGpu->printStats();
 }
 
-GrContext::GrContext(GrGpu* gpu) {
+GrContext::GrContext(GrGpu* gpu) :
+    fDefaultPathRenderer(gpu->supportsTwoSidedStencil(),
+                         gpu->supportsStencilWrapOps()) {
+
     fGpu = gpu;
     fGpu->ref();
+    
+    fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
+    fGpu->setClipPathRenderer(fCustomPathRenderer);
+
     fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
                                        MAX_TEXTURE_CACHE_BYTES);
     fFontCache = new GrFontCache(fGpu);
@@ -768,8 +776,6 @@
 #if BATCH_RECT_TO_RECT
     fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
 #endif
-    fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsTwoSidedStencil(),
-                                              fGpu->supportsStencilWrapOps());
 }
 
 bool GrContext::finalizeTextureKey(GrTextureKey* key,
@@ -808,3 +814,15 @@
 const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
     return fGpu->getQuadIndexBuffer();
 }
+
+GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
+                                           GrPathIter* path,
+                                           GrPathFill fill) {
+    if (NULL != fCustomPathRenderer && 
+        fCustomPathRenderer->canDrawPath(target, path, fill)) {
+        return fCustomPathRenderer;
+    } else {
+        GrAssert(fDefaultPathRenderer.canDrawPath(target, path, fill));
+        return &fDefaultPathRenderer;
+    }
+}
diff --git a/gpu/src/GrCreatePathRenderer_none.cpp b/gpu/src/GrCreatePathRenderer_none.cpp
new file mode 100644
index 0000000..fafecff
--- /dev/null
+++ b/gpu/src/GrCreatePathRenderer_none.cpp
@@ -0,0 +1,20 @@
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+#include "GrPathRenderer.h"
+
+
+GrPathRenderer* GrPathRenderer::CreatePathRenderer() { return NULL; }
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index d60287b..4b52fd8 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -78,7 +78,8 @@
                  fIndexPool(NULL),
                  fQuadIndexBuffer(NULL),
                  fUnitSquareVertexBuffer(NULL),
-                 fPathRenderer(NULL),
+                 fDefaultPathRenderer(NULL),
+                 fClientPathRenderer(NULL),
                  fContextIsDirty(true),
                  fVertexPoolInUse(false),
                  fIndexPoolInUse(false) {
@@ -93,7 +94,8 @@
     GrSafeUnref(fUnitSquareVertexBuffer);
     delete fVertexPool;
     delete fIndexPool;
-    delete fPathRenderer;
+    GrSafeUnref(fClientPathRenderer);
+    GrSafeUnref(fDefaultPathRenderer);
 }
 
 void GrGpu::resetContext() {
@@ -418,15 +420,20 @@
                                                // directly to the stencil buffer
                                                // with a non-inverted fill rule
                                                // without extra passes to
-                                               // resolve in/out status. 
+                                               // resolve in/out status.
+
+                GrPathRenderer* pr = NULL;
+                GrPath::Iter pathIter;
                 if (kRect_ClipType == clip.getElementType(c)) {
                     canRenderDirectToStencil = true;
                     fill = kEvenOdd_PathFill;
                 } else {
                     fill = clip.getPathFill(c);
-                    GrPathRenderer* pr = this->getPathRenderer();
+                    const GrPath& path = clip.getPath(c);
+                    pathIter.reset(path);
+                    pr = this->getClipPathRenderer(&pathIter, NonInvertedFill(fill));
                     canRenderDirectToStencil = 
-                        !pr->requiresStencilPass(this, clip.getPath(c), 
+                        !pr->requiresStencilPass(this, &pathIter,
                                                  NonInvertedFill(fill));
                 }
 
@@ -462,14 +469,14 @@
                     } else {
                         if (canRenderDirectToStencil) {
                             this->setStencil(gDrawToStencil);
-                            getPathRenderer()->drawPath(this, 0, 
-                                                        clip.getPath(c),
-                                                        NonInvertedFill(fill),
-                                                        NULL);
+                            pr->drawPath(this, 0, 
+                                         &pathIter,
+                                         NonInvertedFill(fill),
+                                         NULL);
                         } else {
-                            getPathRenderer()->drawPathToStencil(this, clip.getPath(c),
-                                                                 NonInvertedFill(fill),
-                                                                 NULL);
+                            pr->drawPathToStencil(this, &pathIter,
+                                                  NonInvertedFill(fill),
+                                                  NULL);
                         }
                     }
                 }
@@ -486,9 +493,7 @@
                         } else {
                             SET_RANDOM_COLOR
                             GrAssert(!IsFillInverted(fill));
-                            getPathRenderer()->drawPath(this, 0,
-                                                        clip.getPath(c),
-                                                        fill, NULL);
+                            pr->drawPath(this, 0, &pathIter, fill, NULL);
                         }
                     } else {
                         SET_RANDOM_COLOR
@@ -512,6 +517,23 @@
     return true;
 }
 
+GrPathRenderer* GrGpu::getClipPathRenderer(GrPathIter* path,
+                                           GrPathFill fill) {
+    if (NULL != fClientPathRenderer && 
+        fClientPathRenderer->canDrawPath(this, path, fill)) {
+            return fClientPathRenderer;
+    } else {
+        if (NULL == fDefaultPathRenderer) {
+            fDefaultPathRenderer = 
+                new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
+                                          this->supportsStencilWrapOps());
+        }
+        GrAssert(fDefaultPathRenderer->canDrawPath(this, path, fill));
+        return fDefaultPathRenderer;
+    }
+}
+
+
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrGpu::drawIndexed(GrPrimitiveType type,
@@ -665,16 +687,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrPathRenderer* GrGpu::getPathRenderer() {
-    if (NULL == fPathRenderer) {
-        fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
-                                                  this->supportsStencilWrapOps());
-    }
-    return fPathRenderer;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 const GrGpu::Stats& GrGpu::getStats() const {
     return fStats;
 }
diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h
deleted file mode 100644
index 30bdb5a..0000000
--- a/gpu/src/GrPathRenderer.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-    Copyright 2011 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- */
-
-#ifndef GrPathRenderer_DEFINED
-#define GrPathRenderer_DEFINED
-
-#include "GrDrawTarget.h"
-
-class GrPathIter;
-struct GrPoint;
-
-/**
- *  Base class for drawing paths into a GrDrawTarget.
- */
-class GrPathRenderer {
-public:
-    virtual ~GrPathRenderer() { };
-
-    /**
-     * Draws a path into the draw target. The target will already have its draw
-     * state configured for the draw.
-     * @param target                the target to draw into.
-     * @param stages                indicates which stages the are already
-     *                              in use. All enabled stages expect positions
-     *                              as texture coordinates. The path renderer
-     *                              use the remaining stages for its path
-     *                              filling algorithm.
-     * @param path                  the path to draw.
-     * @param fill                  the fill rule to apply.
-     * @param translate             optional additional translation to apply to
-     *                              the path. NULL means (0,0).
-     */
-    virtual void drawPath(GrDrawTarget* target,
-                          GrDrawTarget::StageBitfield stages,
-                          GrPathIter* path,
-                          GrPathFill fill,
-                          const GrPoint* translate) = 0;
-
-    void drawPath(GrDrawTarget* target,
-                  GrDrawTarget::StageBitfield stages,
-                  const GrPath& path,
-                  GrPathFill fill,
-                  const GrPoint* translate) {
-            GrPath::Iter iter(path);
-            this->drawPath(target, stages, &iter, fill, translate);
-    }
-
-    /**
-     * For complex clips Gr uses the stencil buffer. The path renderer must be
-     * able to render paths into the stencil buffer. However, the path renderer
-     * itself may require the stencil buffer to resolve the path fill rule. This
-     * function queries whether the path render needs its own stencil
-     * pass. If this returns false then drawPath() should not modify the
-     * the target's stencil settings but use those already set on target.
-     *
-     * @param target target that the path will be rendered to
-     * @param path   the path that will be drawn
-     * @param fill   the fill rule that will be used, will never be an inverse
-     *               rule.
-     *
-     * @return false if this path renderer can generate interior-only fragments
-     *         without changing the stencil settings on the target. If it
-     *         returns true the drawPathToStencil will be used when rendering
-     *         clips.
-     */
-    virtual bool requiresStencilPass(const GrDrawTarget* target,
-                                     GrPathIter* path,
-                                     GrPathFill fill) const { return false; }
-
-    bool requiresStencilPass(const GrDrawTarget* target,
-                             const GrPath& path,
-                             GrPathFill fill) const {
-        GrPath::Iter iter(path);
-        return requiresStencilPass(target, &iter, fill);
-    }
-
-    /**
-     * Draws a path to the stencil buffer. Assume the writable stencil bits
-     * are already initialized to zero. Fill will always be either
-     * kWinding_PathFill or kEvenOdd_PathFill.
-     *
-     * Only called if requiresStencilPass returns true for the same combo of
-     * target, path, and fill (or inverse of the fill).
-     *
-     * The default implementation assumes the path filling algorithm doesn't
-     * require a separate stencil pass and so crashes.
-     *
-     *
-     * @param target                the target to draw into.
-     * @param path                  the path to draw.
-     * @param fill                  the fill rule to apply.
-     * @param translate             optional additional translation to apply to
-     *                              the path. NULL means (0,0).
-     */
-    virtual void drawPathToStencil(GrDrawTarget* target,
-                                   GrPathIter* path,
-                                   GrPathFill fill,
-                                   const GrPoint* translate) {
-        GrCrash("Unexpected call to drawPathToStencil.");
-    }
-
-    void drawPathToStencil(GrDrawTarget* target,
-                           const GrPath& path,
-                           GrPathFill fill,
-                           const GrPoint* translate) {
-        GrPath::Iter iter(path);
-        this->drawPathToStencil(target, &iter, fill, translate);
-    }
-};
-
-/**
- *  Subclass that renders the path using the stencil buffer to resolve fill
- *  rules (e.g. winding, even-odd)
- */
-class GrDefaultPathRenderer : public GrPathRenderer {
-public:
-    GrDefaultPathRenderer(bool separateStencilSupport,
-                          bool stencilWrapOpsSupport);
-
-    virtual void drawPath(GrDrawTarget* target,
-                          GrDrawTarget::StageBitfield stages,
-                          GrPathIter* path,
-                          GrPathFill fill,
-                          const GrPoint* translate);
-    virtual bool requiresStencilPass(const GrDrawTarget* target,
-                                     GrPathIter* path,
-                                     GrPathFill fill) const;
-    virtual void drawPathToStencil(GrDrawTarget* target,
-                                   GrPathIter* path,
-                                   GrPathFill fill,
-                                   const GrPoint* translate);
-private:
-
-    void drawPathHelper(GrDrawTarget* target,
-                        GrDrawTarget::StageBitfield stages,
-                        GrPathIter* path,
-                        GrPathFill fill,
-                        const GrPoint* translate,
-                        bool stencilOnly);
-
-    bool    fSeparateStencil;
-    bool    fStencilWrapOps;
-};
-
-#endif
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index 8aeddc9..89ef5f1 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -3,6 +3,7 @@
     GrAtlas.cpp \
     GrClip.cpp \
     GrContext.cpp \
+    GrCreatePathRenderer_none.cpp \
     GrDrawTarget.cpp \
     GrGLIndexBuffer.cpp	\
     GrGLInterface.cpp \
diff --git a/gyp/skia.gyp b/gyp/skia.gyp
index 53ea83b..20b5fae 100644
--- a/gyp/skia.gyp
+++ b/gyp/skia.gyp
@@ -870,6 +870,7 @@
         '../gpu/include/GrPaint.h',
         '../gpu/include/GrPath.h',
         '../gpu/include/GrPathIter.h',
+        '../gpu/include/GrPathRenderer.h',
         '../gpu/include/GrPathSink.h',
         '../gpu/include/GrPlotMgr.h',
         '../gpu/include/GrPoint.h',
@@ -902,6 +903,7 @@
         '../gpu/src/GrBufferAllocPool.h',
         '../gpu/src/GrClip.cpp',
         '../gpu/src/GrContext.cpp',
+        '../gpu/src/GrCreatePathRenderer_none.cpp',
         '../gpu/src/GrDrawTarget.cpp',
         '../gpu/src/GrGLIndexBuffer.cpp',
         '../gpu/src/GrGLInterface.cpp',
@@ -921,7 +923,6 @@
         '../gpu/src/GrMemory.cpp',
         '../gpu/src/GrPath.cpp',
         '../gpu/src/GrPathRenderer.cpp',
-        '../gpu/src/GrPathRenderer.h',
         '../gpu/src/GrPrintf_printf.cpp',
         '../gpu/src/GrRectanizer.cpp',
         '../gpu/src/GrRedBlackTree.h',
diff --git a/vs/SampleApp/SampleApp.vcxproj b/vs/SampleApp/SampleApp.vcxproj
index 9bcce60..016c6ac 100644
--- a/vs/SampleApp/SampleApp.vcxproj
+++ b/vs/SampleApp/SampleApp.vcxproj
@@ -126,6 +126,7 @@
     <ClInclude Include="..\..\gpu\include\GrPaint.h" />

     <ClInclude Include="..\..\gpu\include\GrPath.h" />

     <ClInclude Include="..\..\gpu\include\GrPathIter.h" />

+    <ClInclude Include="..\..\gpu\include\GrPathRenderer.h" />

     <ClInclude Include="..\..\gpu\include\GrPathSink.h" />

     <ClInclude Include="..\..\gpu\include\GrPlotMgr.h" />

     <ClInclude Include="..\..\gpu\include\GrPoint.h" />

@@ -156,7 +157,6 @@
     <ClInclude Include="..\..\gpu\src\GrGpuGL.h" />

     <ClInclude Include="..\..\gpu\src\GrGpuGLFixed.h" />

     <ClInclude Include="..\..\gpu\src\GrGpuGLShaders2.h" />

-    <ClInclude Include="..\..\gpu\src\GrPathRenderer.h" />

     <ClInclude Include="..\..\gpu\src\GrRedBlackTree.h" />

     <ClInclude Include="..\..\gpu\src\GrTextStrike_impl.h" />

     <ClInclude Include="..\..\include\gpu\SkGpuCanvas.h" />

@@ -220,6 +220,7 @@
     <ClCompile Include="..\..\gpu\src\GrBufferAllocPool.cpp" />

     <ClCompile Include="..\..\gpu\src\GrClip.cpp" />

     <ClCompile Include="..\..\gpu\src\GrContext.cpp" />

+    <ClCompile Include="..\..\gpu\src\GrCreatePathRenderer_none.cpp" />

     <ClCompile Include="..\..\gpu\src\GrDrawTarget.cpp" />

     <ClCompile Include="..\..\gpu\src\GrGLIndexBuffer.cpp" />

     <ClCompile Include="..\..\gpu\src\GrGLInterface.cpp" />

diff --git a/vs/SampleApp/SampleApp.vcxproj.filters b/vs/SampleApp/SampleApp.vcxproj.filters
index ba2d106..d8c1914 100644
--- a/vs/SampleApp/SampleApp.vcxproj.filters
+++ b/vs/SampleApp/SampleApp.vcxproj.filters
@@ -460,6 +460,9 @@
     </ClCompile>

     <ClCompile Include="..\..\src\utils\win\skia_win.cpp" />

     <ClCompile Include="..\..\src\views\SkTouchGesture.cpp" />

+    <ClCompile Include="..\..\gpu\src\GrCreatePathRenderer_none.cpp">

+      <Filter>Gr\src</Filter>

+    </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <ClInclude Include="..\..\gpu\include\FlingState.h" />

@@ -692,9 +695,6 @@
     <ClInclude Include="..\..\gpu\src\GrGpuGLShaders2.h">

       <Filter>Gr\src_headers</Filter>

     </ClInclude>

-    <ClInclude Include="..\..\gpu\src\GrPathRenderer.h">

-      <Filter>Gr\src_headers</Filter>

-    </ClInclude>

     <ClInclude Include="..\..\gpu\src\GrTextStrike_impl.h">

       <Filter>Gr\src_headers</Filter>

     </ClInclude>

@@ -728,6 +728,9 @@
     <ClInclude Include="..\..\gpu\include\GrGLDefines.h">

       <Filter>Gr\include</Filter>

     </ClInclude>

+    <ClInclude Include="..\..\gpu\include\GrPathRenderer.h">

+      <Filter>Gr\include</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <None Include="ReadMe.txt" />

diff --git a/xcode/gpu/gpu.xcodeproj/project.pbxproj b/xcode/gpu/gpu.xcodeproj/project.pbxproj
index 155c246..5a44d54 100644
--- a/xcode/gpu/gpu.xcodeproj/project.pbxproj
+++ b/xcode/gpu/gpu.xcodeproj/project.pbxproj
@@ -96,9 +96,10 @@
 		D542EAAD131C87E90065FC9D /* GrStencil.h in Headers */ = {isa = PBXBuildFile; fileRef = D542EAAC131C87E90065FC9D /* GrStencil.h */; };
 		D5558AE3131EB9BB00C71009 /* GrStencil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D5558AE2131EB9BB00C71009 /* GrStencil.cpp */; };
 		D58CAF9A12E7212100CB9277 /* GrGLUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D58CAF9812E7212100CB9277 /* GrGLUtil.cpp */; };
+		D59BD3F4133BBB49003B546A /* GrPathRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = D59BD3F3133BBB49003B546A /* GrPathRenderer.h */; };
+		D59BD413133BD384003B546A /* GrCreatePathRenderer_none.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D59BD412133BD384003B546A /* GrCreatePathRenderer_none.cpp */; };
 		D5ED886F1313F92C00B98D64 /* GrRedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = D5ED886E1313F92C00B98D64 /* GrRedBlackTree.h */; };
 		D5ED88EB13144FD600B98D64 /* GrPathRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D5ED88E913144FD600B98D64 /* GrPathRenderer.cpp */; };
-		D5ED88EC13144FD600B98D64 /* GrPathRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = D5ED88EA13144FD600B98D64 /* GrPathRenderer.h */; };
 		D5FAF20C130726C6001550A4 /* GrGeometryBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = D5FAF20B130726C6001550A4 /* GrGeometryBuffer.h */; };
 		D5FAF22313072C27001550A4 /* GrBufferAllocPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D5FAF22113072C27001550A4 /* GrBufferAllocPool.cpp */; };
 		D5FAF22413072C27001550A4 /* GrBufferAllocPool.h in Headers */ = {isa = PBXBuildFile; fileRef = D5FAF22213072C27001550A4 /* GrBufferAllocPool.h */; };
@@ -195,9 +196,10 @@
 		D542EAAC131C87E90065FC9D /* GrStencil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrStencil.h; path = ../../gpu/include/GrStencil.h; sourceTree = SOURCE_ROOT; };
 		D5558AE2131EB9BB00C71009 /* GrStencil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrStencil.cpp; path = ../../gpu/src/GrStencil.cpp; sourceTree = SOURCE_ROOT; };
 		D58CAF9812E7212100CB9277 /* GrGLUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrGLUtil.cpp; path = ../../gpu/src/GrGLUtil.cpp; sourceTree = SOURCE_ROOT; };
+		D59BD3F3133BBB49003B546A /* GrPathRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrPathRenderer.h; path = ../../gpu/include/GrPathRenderer.h; sourceTree = SOURCE_ROOT; };
+		D59BD412133BD384003B546A /* GrCreatePathRenderer_none.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrCreatePathRenderer_none.cpp; path = ../../gpu/src/GrCreatePathRenderer_none.cpp; sourceTree = SOURCE_ROOT; };
 		D5ED886E1313F92C00B98D64 /* GrRedBlackTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrRedBlackTree.h; path = ../../gpu/src/GrRedBlackTree.h; sourceTree = SOURCE_ROOT; };
 		D5ED88E913144FD600B98D64 /* GrPathRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrPathRenderer.cpp; path = ../../gpu/src/GrPathRenderer.cpp; sourceTree = SOURCE_ROOT; };
-		D5ED88EA13144FD600B98D64 /* GrPathRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrPathRenderer.h; path = ../../gpu/src/GrPathRenderer.h; sourceTree = SOURCE_ROOT; };
 		D5FAF20B130726C6001550A4 /* GrGeometryBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrGeometryBuffer.h; path = ../../gpu/include/GrGeometryBuffer.h; sourceTree = SOURCE_ROOT; };
 		D5FAF22113072C27001550A4 /* GrBufferAllocPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrBufferAllocPool.cpp; path = ../../gpu/src/GrBufferAllocPool.cpp; sourceTree = SOURCE_ROOT; };
 		D5FAF22213072C27001550A4 /* GrBufferAllocPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrBufferAllocPool.h; path = ../../gpu/src/GrBufferAllocPool.h; sourceTree = SOURCE_ROOT; };
@@ -217,6 +219,7 @@
 		00115E3712C116B7008296FE /* include */ = {
 			isa = PBXGroup;
 			children = (
+				D59BD3F3133BBB49003B546A /* GrPathRenderer.h */,
 				7D6EBF5913330E8400AEAADD /* GrGLDefines.h */,
 				7D66934D132ABDA7003AC2F5 /* GrGLPlatformIncludes.h */,
 				7D66934B132ABD8F003AC2F5 /* GrGLInterface.h */,
@@ -294,6 +297,7 @@
 		08FB7795FE84155DC02AAC07 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				D59BD412133BD384003B546A /* GrCreatePathRenderer_none.cpp */,
 				7D669345132ABD5D003AC2F5 /* GrGLInterface.cpp */,
 				D5ED886E1313F92C00B98D64 /* GrRedBlackTree.h */,
 				D539049A12EA01E30025F3D6 /* GrContext_impl.h */,
@@ -320,7 +324,6 @@
 				00115DEE12C1167A008296FE /* GrMatrix.cpp */,
 				00115DEF12C1167A008296FE /* GrMemory.cpp */,
 				00115DF012C1167A008296FE /* GrPath.cpp */,
-				D5ED88EA13144FD600B98D64 /* GrPathRenderer.h */,
 				D5ED88E913144FD600B98D64 /* GrPathRenderer.cpp */,
 				00115DF412C1167A008296FE /* GrRectanizer_fifo.cpp */,
 				00115DF512C1167A008296FE /* GrRectanizer.cpp */,
@@ -418,11 +421,11 @@
 				D5FAF22413072C27001550A4 /* GrBufferAllocPool.h in Headers */,
 				00216E5E130F0B03009A2160 /* GrGLIRect.h in Headers */,
 				D5ED886F1313F92C00B98D64 /* GrRedBlackTree.h in Headers */,
-				D5ED88EC13144FD600B98D64 /* GrPathRenderer.h in Headers */,
 				D542EAAD131C87E90065FC9D /* GrStencil.h in Headers */,
 				7D66934C132ABD8F003AC2F5 /* GrGLInterface.h in Headers */,
 				7D66934E132ABDA7003AC2F5 /* GrGLPlatformIncludes.h in Headers */,
 				7D6EBF5A13330E8400AEAADD /* GrGLDefines.h in Headers */,
+				D59BD3F4133BBB49003B546A /* GrPathRenderer.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -503,6 +506,7 @@
 				D5ED88EB13144FD600B98D64 /* GrPathRenderer.cpp in Sources */,
 				D5558AE3131EB9BB00C71009 /* GrStencil.cpp in Sources */,
 				7D669346132ABD5D003AC2F5 /* GrGLInterface.cpp in Sources */,
+				D59BD413133BD384003B546A /* GrCreatePathRenderer_none.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};