Remove GrPipelineBuilder from getPathRenderer call

Logically this CL:

Moves the PathRendererChain from GrContext to GrDrawManager
   - this was needed to untangled the Path-Chain/Renderer header mess
   - this entailed adding getDrawingMgr so the CMM could access the PathRenderingChain
   - this also entailed re-adding freeGpuResources to the GrDrawingMgr
Moves the CanDrawArgs struct up stack
Removes the GrPipelineBuilder from the CanDrawArgs struct

Review URL: https://codereview.chromium.org/1407883004
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 445c6db..9617e0d 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -7,6 +7,7 @@
 
 #include "GrClipMaskManager.h"
 #include "GrCaps.h"
+#include "GrDrawingManager.h"
 #include "GrDrawContext.h"
 #include "GrDrawTarget.h"
 #include "GrGpuResourcePriv.h"
@@ -49,12 +50,13 @@
 // Does the path in 'element' require SW rendering? If so, return true (and,
 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set
 // 'prOut' to the non-SW path renderer that will do the job).
-static bool path_needs_SW_renderer(GrContext* context,
-                                   const GrPipelineBuilder& pipelineBuilder,
-                                   const SkMatrix& viewMatrix,
-                                   const Element* element,
-                                   GrPathRenderer** prOut,
-                                   bool needsStencil) {
+bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context,
+                                            bool isStencilDisabled,
+                                            const GrRenderTarget* rt,
+                                            const SkMatrix& viewMatrix,
+                                            const Element* element,
+                                            GrPathRenderer** prOut,
+                                            bool needsStencil) {
     if (Element::kRect_Type == element->getType()) {
         // rects can always be drawn directly w/o using the software path
         // TODO: skip rrects once we're drawing them directly.
@@ -86,9 +88,17 @@
                             : GrPathRendererChain::kColor_DrawType;    
         }
     
+        GrPathRenderer::CanDrawPathArgs canDrawArgs;
+        canDrawArgs.fShaderCaps = context->caps()->shaderCaps();
+        canDrawArgs.fViewMatrix = &viewMatrix;
+        canDrawArgs.fPath = &path;
+        canDrawArgs.fStroke = &stroke;
+        canDrawArgs.fAntiAlias = element->isAA();
+        canDrawArgs.fIsStencilDisabled = isStencilDisabled;
+        canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
+
         // the 'false' parameter disallows use of the SW path renderer
-        GrPathRenderer* pr = context->getPathRenderer(pipelineBuilder, viewMatrix, path,
-                                                      stroke, false, type);
+        GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawArgs, false, type);
         if (prOut) {
             *prOut = pr;
         }
@@ -99,13 +109,20 @@
 // Determines whether it is possible to draw the element to both the stencil buffer and the
 // alpha mask simultaneously. If so and the element is a path a compatible path renderer is
 // also returned.
-static GrPathRenderer* get_path_renderer(GrContext* context,
-                                         GrPipelineBuilder* pipelineBuilder,
-                                         const SkMatrix& viewMatrix,
-                                         const SkClipStack::Element* element) {
+GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context,
+                                                   GrTexture* texture,
+                                                   const SkMatrix& viewMatrix,
+                                                   const SkClipStack::Element* element) {
     GrPathRenderer* pr;
     static const bool kNeedsStencil = true;
-    path_needs_SW_renderer(context, *pipelineBuilder, viewMatrix, element, &pr, kNeedsStencil);
+    static const bool kStencilIsDisabled = true;
+    PathNeedsSWRenderer(context,
+                        kStencilIsDisabled,
+                        texture->asRenderTarget(),
+                        viewMatrix,
+                        element,
+                        &pr,
+                        kNeedsStencil);
     return pr;
 }
 
@@ -131,6 +148,7 @@
  * entire clip should be rendered in SW and then uploaded en masse to the gpu.
  */
 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder,
+                                      const GrRenderTarget* rt,
                                       const SkVector& clipToMaskOffset,
                                       const GrReducedClip::ElementList& elements) {
     // TODO: generalize this function so that when
@@ -149,8 +167,8 @@
         bool needsStencil = invert || 
                             SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op;
 
-        if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translate,
-                                   element, nullptr, needsStencil)) {
+        if (PathNeedsSWRenderer(this->getContext(), pipelineBuilder.getStencil().isDisabled(),
+                                rt, translate, element, nullptr, needsStencil)) {
             return true;
         }
     }
@@ -360,7 +378,7 @@
             SkIntToScalar(-clipSpaceIBounds.fTop)
         };
 
-        if (this->useSWOnlyPath(pipelineBuilder, clipToMaskOffset, elements)) {
+        if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)) {
             // The clip geometry is complex enough that it will be more efficient to create it
             // entirely in software
             result.reset(this->createSoftwareClipMask(genID,
@@ -426,7 +444,8 @@
                                     const SkClipStack::Element* element,
                                     GrPathRenderer* pr) {
 
-    pipelineBuilder->setRenderTarget(target->asRenderTarget());
+    GrRenderTarget* rt = target->asRenderTarget();
+    pipelineBuilder->setRenderTarget(rt);
 
     // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP
     // which ignores color.
@@ -462,8 +481,17 @@
                 GrPathRendererChain::DrawType type;
                 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
                                          GrPathRendererChain::kColor_DrawType;
-                pr = this->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix,
-                                                         path, stroke, false, type);
+
+                GrPathRenderer::CanDrawPathArgs canDrawArgs;
+                canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps();
+                canDrawArgs.fViewMatrix = &viewMatrix;
+                canDrawArgs.fPath = &path;
+                canDrawArgs.fStroke = &stroke;
+                canDrawArgs.fAntiAlias = element->isAA();;
+                canDrawArgs.fIsStencilDisabled = pipelineBuilder->getStencil().isDisabled();
+                canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
+
+                pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false, type);
             }
             if (nullptr == pr) {
                 return false;
@@ -566,8 +594,9 @@
             pipelineBuilder.setClip(clip);
             pipelineBuilder.setRenderTarget(texture->asRenderTarget());
 
-            GrPathRenderer* pr = get_path_renderer(this->getContext(), &pipelineBuilder,
-                                                   translate, element);
+            SkASSERT(pipelineBuilder.getStencil().isDisabled());
+            GrPathRenderer* pr = GetPathRenderer(this->getContext(),
+                                                 texture, translate, element);
             if (Element::kRect_Type != element->getType() && !pr) {
                 // useSWOnlyPath should now filter out all cases where gpu-side mask merging would
                 // be performed (i.e., pr would be NULL for a non-rect path). See skbug.com/4519
@@ -701,13 +730,21 @@
                 if (fillInverted) {
                     clipPath.toggleInverseFillType();
                 }
-                pr = this->getContext()->getPathRenderer(pipelineBuilder,
-                                                         viewMatrix,
-                                                         clipPath,
-                                                         stroke,
-                                                         false,
-                                                         GrPathRendererChain::kStencilOnly_DrawType,
-                                                         &stencilSupport);
+
+                SkASSERT(pipelineBuilder.getStencil().isDisabled());
+
+                GrPathRenderer::CanDrawPathArgs canDrawArgs;
+                canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps();
+                canDrawArgs.fViewMatrix = &viewMatrix;
+                canDrawArgs.fPath = &clipPath;
+                canDrawArgs.fStroke = &stroke;
+                canDrawArgs.fAntiAlias = false;
+                canDrawArgs.fIsStencilDisabled = pipelineBuilder.getStencil().isDisabled();
+                canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
+
+                pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false,
+                                                                           GrPathRendererChain::kStencilOnly_DrawType,
+                                                                           &stencilSupport);
                 if (nullptr == pr) {
                     return false;
                 }
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 2d9816c..98fd3af 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -76,6 +76,18 @@
     inline const GrCaps* caps() const;
     inline GrResourceProvider* resourceProvider();
 
+    static bool PathNeedsSWRenderer(GrContext* context,
+                                    bool isStencilDisabled,
+                                    const GrRenderTarget* rt,
+                                    const SkMatrix& viewMatrix,
+                                    const SkClipStack::Element* element,
+                                    GrPathRenderer** prOut,
+                                    bool needsStencil);
+    static GrPathRenderer* GetPathRenderer(GrContext* context,
+                                           GrTexture* texture,
+                                           const SkMatrix& viewMatrix,
+                                           const SkClipStack::Element* element);
+
     /**
      * Informs the helper function adjustStencilParams() about how the stencil
      * buffer clip is being used.
@@ -125,8 +137,9 @@
                                       const SkIRect& clipSpaceIBounds);
 
    bool useSWOnlyPath(const GrPipelineBuilder&,
-                       const SkVector& clipToMaskOffset,
-                       const GrReducedClip::ElementList& elements);
+                      const GrRenderTarget* rt,
+                      const SkVector& clipToMaskOffset,
+                      const GrReducedClip::ElementList& elements);
 
     // Draws a clip element into the target alpha mask. The caller should have already setup the
     // desired blend operation. Optionally if the caller already selected a path renderer it can
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 04e1b8d..755b0f2 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -60,8 +60,6 @@
     fCaps = nullptr;
     fResourceCache = nullptr;
     fResourceProvider = nullptr;
-    fPathRendererChain = nullptr;
-    fSoftwarePathRenderer = nullptr;
     fBatchFontCache = nullptr;
     fFlushToReduceCacheSize = false;
 }
@@ -118,8 +116,6 @@
 
     fGpu->unref();
     fCaps->unref();
-    SkSafeUnref(fPathRendererChain);
-    SkSafeUnref(fSoftwarePathRenderer);
 }
 
 void GrContext::abandonContext() {
@@ -130,11 +126,6 @@
 
     fGpu->contextAbandoned();
 
-    // a path renderer may be holding onto resources that
-    // are now unusable
-    SkSafeSetNull(fPathRendererChain);
-    SkSafeSetNull(fSoftwarePathRenderer);
-
     fDrawingManager->abandon();
 
     fBatchFontCache->freeAll();
@@ -151,9 +142,8 @@
 
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
-    // a path renderer may be holding onto resources
-    SkSafeSetNull(fPathRendererChain);
-    SkSafeSetNull(fSoftwarePathRenderer);
+
+    fDrawingManager->freeGpuResources();
 
     fResourceCache->purgeAllUnlocked();
 }
@@ -535,42 +525,6 @@
     }
 }
 
-/*
- * This method finds a path renderer that can draw the specified path on
- * the provided target.
- * Due to its expense, the software path renderer has split out so it can
- * can be individually allowed/disallowed via the "allowSW" boolean.
- */
-GrPathRenderer* GrContext::getPathRenderer(const GrPipelineBuilder& pipelineBuilder,
-                                           const SkMatrix& viewMatrix,
-                                           const SkPath& path,
-                                           const GrStrokeInfo& stroke,
-                                           bool allowSW,
-                                           GrPathRendererChain::DrawType drawType,
-                                           GrPathRendererChain::StencilSupport* stencilSupport) {
-
-    if (!fPathRendererChain) {
-        fPathRendererChain = new GrPathRendererChain(this);
-    }
-
-    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(this->caps()->shaderCaps(),
-                                                             pipelineBuilder,
-                                                             viewMatrix,
-                                                             path,
-                                                             stroke,
-                                                             drawType,
-                                                             stencilSupport);
-
-    if (!pr && allowSW) {
-        if (!fSoftwarePathRenderer) {
-            fSoftwarePathRenderer = new GrSoftwarePathRenderer(this);
-        }
-        pr = fSoftwarePathRenderer;
-    }
-
-    return pr;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 int GrContext::getRecommendedSampleCount(GrPixelConfig config,
                                          SkScalar dpi) const {
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index d64273a..82e1057 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -680,21 +680,28 @@
     // thing WRT to the blend then we'll need some query on the PR.
     bool useCoverageAA = useAA &&
         !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
+    bool isStencilDisabled = pipelineBuilder->getStencil().isDisabled();
+    bool isStencilBufferMSAA = pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
 
-
-    GrPathRendererChain::DrawType type =
-        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
-                        GrPathRendererChain::kColor_DrawType;
+    const GrPathRendererChain::DrawType type =
+        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
+                      : GrPathRendererChain::kColor_DrawType;
 
     const SkPath* pathPtr = &path;
     SkTLazy<SkPath> tmpPath;
     const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
 
+    GrPathRenderer::CanDrawPathArgs canDrawArgs;
+    canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
+    canDrawArgs.fViewMatrix = &viewMatrix;
+    canDrawArgs.fPath = pathPtr;
+    canDrawArgs.fStroke = strokeInfoPtr;
+    canDrawArgs.fAntiAlias = useCoverageAA;
+    canDrawArgs.fIsStencilDisabled = isStencilDisabled;
+    canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
+
     // Try a 1st time without stroking the path and without allowing the SW renderer
-    GrPathRenderer* pr = fDrawingManager->getContext()->getPathRenderer(*pipelineBuilder,
-                                                                        viewMatrix, *pathPtr,
-                                                                        *strokeInfoPtr, false,
-                                                                        type);
+    GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
 
     GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
     if (nullptr == pr && strokeInfo.isDashed()) {
@@ -707,9 +714,11 @@
             return;
         }
         strokeInfoPtr = &dashlessStrokeInfo;
-        pr = fDrawingManager->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix,
-                                                            *pathPtr, *strokeInfoPtr,
-                                                            false, type);
+
+        canDrawArgs.fPath = pathPtr;
+        canDrawArgs.fStroke = strokeInfoPtr;
+
+        pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
     }
 
     if (nullptr == pr) {
@@ -731,10 +740,11 @@
             strokeInfoPtr = &dashlessStrokeInfo;
         }
 
+        canDrawArgs.fPath = pathPtr;
+        canDrawArgs.fStroke = strokeInfoPtr;
+
         // This time, allow SW renderer
-        pr = fDrawingManager->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix,
-                                                            *pathPtr, *strokeInfoPtr,
-                                                            true, type);
+        pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
     }
 
     if (nullptr == pr) {
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 0dbd476..0a487da 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -10,6 +10,7 @@
 #include "GrDrawingManager.h"
 #include "GrDrawTarget.h"
 #include "GrResourceProvider.h"
+#include "GrSoftwarePathRenderer.h"
 #include "GrStencilAndCoverTextContext.h"
 #include "SkTTopoSort.h"
 
@@ -29,6 +30,9 @@
         delete fTextContexts[i][1];
         fTextContexts[i][1] = nullptr;
     }
+
+    SkSafeSetNull(fPathRendererChain);
+    SkSafeSetNull(fSoftwarePathRenderer);
 }
 
 GrDrawingManager::~GrDrawingManager() {
@@ -40,6 +44,12 @@
     this->cleanup();
 }
 
+void GrDrawingManager::freeGpuResources() {
+    // a path renderer may be holding onto resources
+    SkSafeSetNull(fPathRendererChain);
+    SkSafeSetNull(fSoftwarePathRenderer);
+}
+
 void GrDrawingManager::reset() {
     for (int i = 0; i < fDrawTargets.count(); ++i) {
         fDrawTargets[i]->reset();
@@ -114,7 +124,33 @@
     return SkRef(dt);
 }
 
-GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt, 
+/*
+ * This method finds a path renderer that can draw the specified path on
+ * the provided target.
+ * Due to its expense, the software path renderer has split out so it can
+ * can be individually allowed/disallowed via the "allowSW" boolean.
+ */
+GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
+                                                  bool allowSW,
+                                                  GrPathRendererChain::DrawType drawType,
+                                                  GrPathRenderer::StencilSupport* stencilSupport) {
+
+    if (!fPathRendererChain) {
+        fPathRendererChain = new GrPathRendererChain(fContext);
+    }
+
+    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
+    if (!pr && allowSW) {
+        if (!fSoftwarePathRenderer) {
+            fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext);
+        }
+        pr = fSoftwarePathRenderer;
+    }
+
+    return pr;
+}
+
+GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt,
                                              const SkSurfaceProps* surfaceProps) {
     if (this->abandoned()) {
         return nullptr;
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index be21d68..c8b9a9b 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -9,10 +9,13 @@
 #define GrDrawingManager_DEFINED
 
 #include "GrDrawTarget.h"
+#include "GrPathRendererChain.h"
+#include "GrPathRenderer.h"
 #include "SkTDArray.h"
 
 class GrContext;
 class GrDrawContext;
+class GrSoftwarePathRenderer;
 class GrTextContext;
 
 // Currently the DrawingManager creates a separate GrTextContext for each
@@ -29,6 +32,7 @@
     ~GrDrawingManager();
 
     bool abandoned() const { return fAbandoned; }
+    void freeGpuResources();
 
     GrDrawContext* drawContext(GrRenderTarget* rt, const SkSurfaceProps* surfaceProps);
 
@@ -40,12 +44,19 @@
 
     GrContext* getContext() { return fContext; }
 
+    GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
+                                    bool allowSW,
+                                    GrPathRendererChain::DrawType drawType,
+                                    GrPathRenderer::StencilSupport* stencilSupport = NULL);
+
 private:
     GrDrawingManager(GrContext* context, GrDrawTarget::Options options)
         : fContext(context)
         , fAbandoned(false)
         , fOptions(options)
-        , fNVPRTextContext(nullptr) {
+        , fNVPRTextContext(nullptr)
+        , fPathRendererChain(nullptr)
+        , fSoftwarePathRenderer(nullptr) {
         sk_bzero(fTextContexts, sizeof(fTextContexts));
     }
 
@@ -67,6 +78,9 @@
 
     GrTextContext*              fNVPRTextContext;
     GrTextContext*              fTextContexts[kNumPixelGeometries][kNumDFTOptions];
+
+    GrPathRendererChain*        fPathRendererChain;
+    GrSoftwarePathRenderer*     fSoftwarePathRenderer;
 };
 
 #endif
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h
index 2390ba0..25a2a68 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -10,7 +10,6 @@
 #define GrPathRenderer_DEFINED
 
 #include "GrDrawTarget.h"
-#include "GrPathRendererChain.h"
 #include "GrStencil.h"
 #include "GrStrokeInfo.h"
 
@@ -51,13 +50,11 @@
      *                  covered by the path.
      * 3) kNoSupport: This path renderer cannot be used to stencil the path.
      */
-    typedef GrPathRendererChain::StencilSupport StencilSupport;
-    static const StencilSupport kNoSupport_StencilSupport =
-        GrPathRendererChain::kNoSupport_StencilSupport;
-    static const StencilSupport kStencilOnly_StencilSupport =
-        GrPathRendererChain::kStencilOnly_StencilSupport;
-    static const StencilSupport kNoRestriction_StencilSupport =
-        GrPathRendererChain::kNoRestriction_StencilSupport;
+    enum StencilSupport {
+        kNoSupport_StencilSupport,
+        kStencilOnly_StencilSupport,
+        kNoRestriction_StencilSupport,
+    };
 
     /**
      * This function is to get the stencil support for a particular path. The path's fill must
@@ -82,15 +79,17 @@
      */
     struct CanDrawPathArgs {
         const GrShaderCaps*         fShaderCaps;
-        const GrPipelineBuilder*    fPipelineBuilder;// only used by GrStencilAndCoverPathRenderer
         const SkMatrix*             fViewMatrix;
         const SkPath*               fPath;
         const GrStrokeInfo*         fStroke;
         bool                        fAntiAlias;
 
+        // These next two are only used by GrStencilAndCoverPathRenderer
+        bool                        fIsStencilDisabled;
+        bool                        fIsStencilBufferMSAA;
+
         void validate() const {
             SkASSERT(fShaderCaps);
-            SkASSERT(fPipelineBuilder);
             SkASSERT(fViewMatrix);
             SkASSERT(fPath);
             SkASSERT(fStroke);
@@ -151,11 +150,14 @@
 #ifdef SK_DEBUG
         CanDrawPathArgs canArgs;
         canArgs.fShaderCaps = args.fTarget->caps()->shaderCaps();
-        canArgs.fPipelineBuilder = args.fPipelineBuilder;
         canArgs.fViewMatrix = args.fViewMatrix;
         canArgs.fPath = args.fPath;
         canArgs.fStroke = args.fStroke;
         canArgs.fAntiAlias = args.fAntiAlias;
+
+        canArgs.fIsStencilDisabled = args.fPipelineBuilder->getStencil().isDisabled();
+        canArgs.fIsStencilBufferMSAA = 
+                          args.fPipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
         SkASSERT(this->canDrawPath(canArgs));
         SkASSERT(args.fPipelineBuilder->getStencil().isDisabled() ||
                  kNoRestriction_StencilSupport == this->getStencilSupport(*args.fPath,
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index c6bc4c0..63195c6 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -39,18 +39,12 @@
     return pr;
 }
 
-GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrShaderCaps* shaderCaps,
-                                                     const GrPipelineBuilder& pipelineBuilder,
-                                                     const SkMatrix& viewMatrix,
-                                                     const SkPath& path,
-                                                     const GrStrokeInfo& stroke,
+GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
                                                      DrawType drawType,
-                                                     StencilSupport* stencilSupport) {
+                                                     GrPathRenderer::StencilSupport* stencilSupport) {
     if (!fInit) {
         this->init();
     }
-    bool antiAlias = (kColorAntiAlias_DrawType == drawType ||
-                      kStencilAndColorAntiAlias_DrawType == drawType);
 
     GR_STATIC_ASSERT(GrPathRenderer::kNoSupport_StencilSupport <
                      GrPathRenderer::kStencilOnly_StencilSupport);
@@ -68,17 +62,10 @@
 
 
     for (int i = 0; i < fChain.count(); ++i) {
-        GrPathRenderer::CanDrawPathArgs args;
-        args.fShaderCaps = shaderCaps;
-        args.fPipelineBuilder = &pipelineBuilder;
-        args.fViewMatrix = &viewMatrix;
-        args.fPath = &path;
-        args.fStroke = &stroke;
-        args.fAntiAlias = antiAlias;
         if (fChain[i]->canDrawPath(args)) {
             if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) {
                 GrPathRenderer::StencilSupport support =
-                                                       fChain[i]->getStencilSupport(path, stroke);
+                                        fChain[i]->getStencilSupport(*args.fPath, *args.fStroke);
                 if (support < minStencilSupport) {
                     continue;
                 } else if (stencilSupport) {
diff --git a/src/gpu/GrPathRendererChain.h b/src/gpu/GrPathRendererChain.h
new file mode 100644
index 0000000..e0e7d46
--- /dev/null
+++ b/src/gpu/GrPathRendererChain.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrPathRendererChain_DEFINED
+#define GrPathRendererChain_DEFINED
+
+#include "GrPathRenderer.h"
+
+#include "SkRefCnt.h"
+#include "SkTArray.h"
+
+class GrContext;
+class GrPipelineBuilder;
+class GrShaderCaps;
+class GrStrokeInfo;
+class SkMatrix;
+class SkPath;
+
+/**
+ * Keeps track of an ordered list of path renderers. When a path needs to be
+ * drawn this list is scanned to find the most preferred renderer. To add your
+ * path renderer to the list implement the GrPathRenderer::AddPathRenderers
+ * function.
+ */
+class GrPathRendererChain : public SkRefCnt {
+public:
+    GrPathRendererChain(GrContext* context);
+
+    ~GrPathRendererChain();
+
+    /** Documents how the caller plans to use a GrPathRenderer to draw a path. It affects the PR
+        returned by getPathRenderer */
+    enum DrawType {
+        kColor_DrawType,                    // draw to the color buffer, no AA
+        kColorAntiAlias_DrawType,           // draw to color buffer, with partial coverage AA
+        kStencilOnly_DrawType,              // draw just to the stencil buffer
+        kStencilAndColor_DrawType,          // draw the stencil and color buffer, no AA
+        kStencilAndColorAntiAlias_DrawType  // draw the stencil and color buffer, with partial
+                                            // coverage AA.
+    };
+
+    /** Returns a GrPathRenderer compatible with the request if one is available. If the caller
+        is drawing the path to the stencil buffer then stencilSupport can be used to determine
+        whether the path can be rendered with arbitrary stencil rules or not. See comments on
+        StencilSupport in GrPathRenderer.h. */
+    GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
+                                    DrawType drawType,
+                                    GrPathRenderer::StencilSupport* stencilSupport);
+
+private:
+    GrPathRendererChain();
+
+    // takes a ref and unrefs in destructor
+    GrPathRenderer* addPathRenderer(GrPathRenderer* pr);
+
+    void init();
+
+    enum {
+        kPreAllocCount = 8,
+    };
+    bool fInit;
+    GrContext*                                          fOwner;
+    SkSTArray<kPreAllocCount, GrPathRenderer*, true>    fChain;
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index e329bc5..2bafd9a 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -229,11 +229,6 @@
      */
     void setStencil(const GrStencilSettings& settings) { fStencilSettings = settings; }
 
-    /**
-     * Shortcut to disable stencil testing and ops.
-     */
-    void disableStencil() { fStencilSettings.setDisabled(); }
-
     GrStencilSettings* stencil() { return &fStencilSettings; }
 
     /**
diff --git a/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp b/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp
index 720c1c3..c96e207 100644
--- a/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp
@@ -49,11 +49,11 @@
     if (args.fStroke->isHairlineStyle()) {
         return false;
     }
-    if (!args.fPipelineBuilder->getStencil().isDisabled()) {
+    if (!args.fIsStencilDisabled) {
         return false;
     }
     if (args.fAntiAlias) {
-        return args.fPipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
+        return args.fIsStencilBufferMSAA;
     } else {
         return true; // doesn't do per-path AA, relies on the target having MSAA
     }