Beginning to refactor nvpr code

BUG=skia:

Review URL: https://codereview.chromium.org/687563008
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 11abb57..2f25272 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -527,28 +527,20 @@
     }
 }
 
-void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
+void GrDrawTarget::stencilPath(const GrPath* path, GrPathRendering::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path stenciling.
     SkASSERT(path);
     SkASSERT(this->caps()->pathRenderingSupport());
-    SkASSERT(!SkPath::IsInverseFillType(fill));
     this->onStencilPath(path, fill);
 }
 
-void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
+void GrDrawTarget::drawPath(const GrPath* path, GrPathRendering::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path rendering.
     SkASSERT(path);
     SkASSERT(this->caps()->pathRenderingSupport());
-    const GrDrawState* drawState = &getDrawState();
 
-    SkRect devBounds;
-    if (SkPath::IsInverseFillType(fill)) {
-        devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
-                                   SkIntToScalar(drawState->getRenderTarget()->height()));
-    } else {
-        devBounds = path->getBounds();
-    }
-    SkMatrix viewM = drawState->getViewMatrix();
+    SkRect devBounds = path->getBounds();
+    SkMatrix viewM = this->drawState()->getViewMatrix();
     viewM.mapRect(&devBounds);
 
     GrDeviceCoordTexture dstCopy;
@@ -562,7 +554,7 @@
 void GrDrawTarget::drawPaths(const GrPathRange* pathRange,
                              const uint32_t indices[], int count,
                              const float transforms[], PathTransformType transformsType,
-                             SkPath::FillType fill) {
+                             GrPathRendering::FillType fill) {
     SkASSERT(this->caps()->pathRenderingSupport());
     SkASSERT(pathRange);
     SkASSERT(indices);
@@ -724,43 +716,6 @@
 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
 }
 
-static const GrStencilSettings& winding_path_stencil_settings() {
-    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
-        kIncClamp_StencilOp,
-        kIncClamp_StencilOp,
-        kAlwaysIfInClip_StencilFunc,
-        0xFFFF, 0xFFFF, 0xFFFF);
-    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
-}
-
-static const GrStencilSettings& even_odd_path_stencil_settings() {
-    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
-        kInvert_StencilOp,
-        kInvert_StencilOp,
-        kAlwaysIfInClip_StencilFunc,
-        0xFFFF, 0xFFFF, 0xFFFF);
-    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
-}
-
-void GrDrawTarget::getPathStencilSettingsForFillType(SkPath::FillType fill,
-                                                     GrStencilSettings* outStencilSettings) {
-
-    switch (fill) {
-        default:
-            SkFAIL("Unexpected path fill.");
-            /* fallthrough */;
-        case SkPath::kWinding_FillType:
-        case SkPath::kInverseWinding_FillType:
-            *outStencilSettings = winding_path_stencil_settings();
-            break;
-        case SkPath::kEvenOdd_FillType:
-        case SkPath::kInverseEvenOdd_FillType:
-            *outStencilSettings = even_odd_path_stencil_settings();
-            break;
-    }
-    this->getClipMaskManager()->adjustPathStencilParams(outStencilSettings);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 7d8a03c..4545f74 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -315,15 +315,16 @@
     /**
      * Draws path into the stencil buffer. The fill must be either even/odd or
      * winding (not inverse or hairline). It will respect the HW antialias flag
-     * on the draw state (if possible in the 3D API).
+     * on the draw state (if possible in the 3D API).  Note, we will never have an inverse fill
+     * with stencil path
      */
-    void stencilPath(const GrPath*, SkPath::FillType fill);
+    void stencilPath(const GrPath*, GrPathRendering::FillType fill);
 
     /**
      * Draws a path. Fill must not be a hairline. It will respect the HW
      * antialias flag on the draw state (if possible in the 3D API).
      */
-    void drawPath(const GrPath*, SkPath::FillType fill);
+    void drawPath(const GrPath*, GrPathRendering::FillType fill);
 
     /**
      * Draws many paths. It will respect the HW
@@ -340,7 +341,7 @@
     void drawPaths(const GrPathRange* pathRange,
                    const uint32_t indices[], int count,
                    const float transforms[], PathTransformType transformsType,
-                   SkPath::FillType fill);
+                   GrPathRendering::FillType fill);
 
     /**
      * Helper function for drawing rects. It performs a geometry src push and pop
@@ -490,7 +491,7 @@
     /**
      * For subclass internal use to invoke a call to onDrawPath().
      */
-    void executeDrawPath(const GrPath* path, SkPath::FillType fill,
+    void executeDrawPath(const GrPath* path, GrPathRendering::FillType fill,
                          const GrDeviceCoordTexture* dstCopy) {
         this->onDrawPath(path, fill, dstCopy);
     }
@@ -501,13 +502,11 @@
     void executeDrawPaths(const GrPathRange* pathRange,
                           const uint32_t indices[], int count,
                           const float transforms[], PathTransformType transformsType,
-                          SkPath::FillType fill,
+                          GrPathRendering::FillType fill,
                           const GrDeviceCoordTexture* dstCopy) {
         this->onDrawPaths(pathRange, indices, count, transforms, transformsType, fill, dstCopy);
     }
 
-    void getPathStencilSettingsForFillType(SkPath::FillType, GrStencilSettings*);
-
     ////////////////////////////////////////////////////////////////////////////
 
     /**
@@ -898,13 +897,13 @@
                             const SkRect* localRect,
                             const SkMatrix* localMatrix);
 
-    virtual void onStencilPath(const GrPath*, SkPath::FillType) = 0;
-    virtual void onDrawPath(const GrPath*, SkPath::FillType,
+    virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) = 0;
+    virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
                             const GrDeviceCoordTexture* dstCopy) = 0;
     virtual void onDrawPaths(const GrPathRange*,
                              const uint32_t indices[], int count,
                              const float transforms[], PathTransformType,
-                             SkPath::FillType, const GrDeviceCoordTexture*) = 0;
+                             GrPathRendering::FillType, const GrDeviceCoordTexture*) = 0;
 
     virtual void didAddGpuTraceMarker() = 0;
     virtual void didRemoveGpuTraceMarker() = 0;
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 4b1c35a..2f4f0a6 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -275,13 +275,13 @@
 bool GrGpu::setupClipAndFlushState(DrawType type,
                                    const GrDeviceCoordTexture* dstCopy,
                                    const SkRect* devBounds,
-                                   GrDrawState::AutoRestoreEffects* are) {
+                                   GrDrawState::AutoRestoreEffects* are,
+                                   GrDrawState::AutoRestoreStencil* ars) {
     GrClipMaskManager::ScissorState scissorState;
-    GrDrawState::AutoRestoreStencil ars;
     if (!fClipMaskManager.setupClipping(this->getClip(),
                                         devBounds,
                                         are,
-                                        &ars,
+                                        ars,
                                         &scissorState)) {
         return false;
     }
@@ -325,56 +325,109 @@
 void GrGpu::onDraw(const DrawInfo& info) {
     this->handleDirtyContext();
     GrDrawState::AutoRestoreEffects are;
+    GrDrawState::AutoRestoreStencil ars;
     if (!this->setupClipAndFlushState(PrimTypeToDrawType(info.primitiveType()),
                                       info.getDstCopy(),
                                       info.getDevBounds(),
-                                      &are)) {
+                                      &are,
+                                      &ars)) {
         return;
     }
     this->onGpuDraw(info);
 }
 
-void GrGpu::onStencilPath(const GrPath* path, SkPath::FillType fill) {
+
+// TODO hack
+static const GrStencilSettings& winding_path_stencil_settings() {
+    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
+        kIncClamp_StencilOp,
+        kIncClamp_StencilOp,
+        kAlwaysIfInClip_StencilFunc,
+        0xFFFF, 0xFFFF, 0xFFFF);
+    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
+}
+
+static const GrStencilSettings& even_odd_path_stencil_settings() {
+    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
+        kInvert_StencilOp,
+        kInvert_StencilOp,
+        kAlwaysIfInClip_StencilFunc,
+        0xFFFF, 0xFFFF, 0xFFFF);
+    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
+}
+
+static void get_path_stencil_settings_for_filltype(GrPathRendering::FillType fill,
+                                                   GrStencilSettings* outStencilSettings) {
+
+    switch (fill) {
+        default:
+            SkFAIL("Unexpected path fill.");
+        case GrPathRendering::kWinding_FillType:
+            *outStencilSettings = winding_path_stencil_settings();
+            break;
+        case GrPathRendering::kEvenOdd_FillType:
+            *outStencilSettings = even_odd_path_stencil_settings();
+            break;
+    }
+}
+
+void GrGpu::onStencilPath(const GrPath* path, GrPathRendering::FillType fill) {
     this->handleDirtyContext();
 
     GrDrawState::AutoRestoreEffects are;
-    if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, NULL, &are)) {
+    GrDrawState::AutoRestoreStencil ars;
+    if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, NULL, &are, &ars)) {
         return;
     }
 
-    this->pathRendering()->stencilPath(path, fill);
+    GrStencilSettings stencilSettings;
+    get_path_stencil_settings_for_filltype(fill, &stencilSettings);
+    fClipMaskManager.adjustPathStencilParams(&stencilSettings);
+
+    this->pathRendering()->stencilPath(path, stencilSettings);
 }
 
 
-void GrGpu::onDrawPath(const GrPath* path, SkPath::FillType fill,
+void GrGpu::onDrawPath(const GrPath* path, GrPathRendering::FillType fill,
                        const GrDeviceCoordTexture* dstCopy) {
     this->handleDirtyContext();
 
     drawState()->setDefaultVertexAttribs();
 
     GrDrawState::AutoRestoreEffects are;
-    if (!this->setupClipAndFlushState(kDrawPath_DrawType, dstCopy, NULL, &are)) {
+    GrDrawState::AutoRestoreStencil ars;
+    if (!this->setupClipAndFlushState(kDrawPath_DrawType, dstCopy, NULL, &are, &ars)) {
         return;
     }
 
-    this->pathRendering()->drawPath(path, fill);
+    GrStencilSettings stencilSettings;
+    get_path_stencil_settings_for_filltype(fill, &stencilSettings);
+    fClipMaskManager.adjustPathStencilParams(&stencilSettings);
+
+    this->pathRendering()->drawPath(path, stencilSettings);
 }
 
 void GrGpu::onDrawPaths(const GrPathRange* pathRange,
                         const uint32_t indices[], int count,
                         const float transforms[], PathTransformType transformsType,
-                        SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
+                        GrPathRendering::FillType fill, const GrDeviceCoordTexture* dstCopy) {
     this->handleDirtyContext();
 
     drawState()->setDefaultVertexAttribs();
 
     GrDrawState::AutoRestoreEffects are;
-    if (!this->setupClipAndFlushState(kDrawPaths_DrawType, dstCopy, NULL, &are)) {
+    GrDrawState::AutoRestoreStencil ars;
+    if (!this->setupClipAndFlushState(kDrawPaths_DrawType, dstCopy, NULL, &are, &ars)) {
         return;
     }
 
+    GrStencilSettings stencilSettings;
+    get_path_stencil_settings_for_filltype(fill, &stencilSettings);
+    fClipMaskManager.adjustPathStencilParams(&stencilSettings);
+
     pathRange->willDrawPaths(indices, count);
-    this->pathRendering()->drawPaths(pathRange, indices, count, transforms, transformsType, fill);
+    this->pathRendering()->drawPaths(pathRange, indices, count, transforms, transformsType,
+                                     stencilSettings);
 }
 
 void GrGpu::finalizeReservedVertices() {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 7c90ee4..0e2ec88 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -335,7 +335,8 @@
     bool setupClipAndFlushState(DrawType,
                                 const GrDeviceCoordTexture* dstCopy,
                                 const SkRect* devBounds,
-                                GrDrawState::AutoRestoreEffects*);
+                                GrDrawState::AutoRestoreEffects*,
+                                GrDrawState::AutoRestoreStencil*);
 
     // Functions used to map clip-respecting stencil tests into normal
     // stencil funcs supported by GPUs.
@@ -452,13 +453,13 @@
 
     // GrDrawTarget overrides
     virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
-    virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
-    virtual void onDrawPath(const GrPath*, SkPath::FillType,
+    virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) SK_OVERRIDE;
+    virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
                             const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
     virtual void onDrawPaths(const GrPathRange*,
                              const uint32_t indices[], int count,
                              const float transforms[], PathTransformType,
-                             SkPath::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
+                             GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
 
     // readies the pools to provide vertex/index data.
     void prepareVertexPool();
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index e7d0f83..61c3e0c 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -361,7 +361,7 @@
     }
 }
 
-void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
+void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, GrPathRendering::FillType fill) {
     this->recordClipIfNecessary();
     // Only compare the subset of GrDrawState relevant to path stenciling?
     this->recordStateIfNecessary();
@@ -371,7 +371,8 @@
 }
 
 void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
-                                     SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
+                                     GrPathRendering::FillType fill,
+                                     const GrDeviceCoordTexture* dstCopy) {
     this->recordClipIfNecessary();
     // TODO: Only compare the subset of GrDrawState relevant to path covering?
     this->recordStateIfNecessary();
@@ -386,7 +387,8 @@
 void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
                                       const uint32_t indices[], int count,
                                       const float transforms[], PathTransformType transformsType,
-                                      SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
+                                      GrPathRendering::FillType fill,
+                                      const GrDeviceCoordTexture* dstCopy) {
     SkASSERT(pathRange);
     SkASSERT(indices);
     SkASSERT(transforms);
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 7b9a926..e6971a9 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -139,7 +139,7 @@
 
         virtual void execute(GrClipTarget*);
 
-        SkPath::FillType fFill;
+        GrPathRendering::FillType fFill;
 
     private:
         GrPendingIOResource<const GrPath, kRead_GrIOType>   fPath;
@@ -152,8 +152,8 @@
 
         virtual void execute(GrClipTarget*);
 
-        SkPath::FillType        fFill;
-        GrDeviceCoordTexture    fDstCopy;
+        GrPathRendering::FillType fFill;
+        GrDeviceCoordTexture      fDstCopy;
 
     private:
         GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
@@ -168,10 +168,10 @@
 
         virtual void execute(GrClipTarget*);
 
-        size_t                  fCount;
-        PathTransformType       fTransformsType;
-        SkPath::FillType        fFill;
-        GrDeviceCoordTexture    fDstCopy;
+        size_t                    fCount;
+        PathTransformType         fTransformsType;
+        GrPathRendering::FillType fFill;
+        GrDeviceCoordTexture      fDstCopy;
 
     private:
         GrPendingIOResource<const GrPathRange, kRead_GrIOType> fPathRange;
@@ -257,13 +257,13 @@
                             const SkRect* localRect,
                             const SkMatrix* localMatrix) SK_OVERRIDE;
 
-    virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
-    virtual void onDrawPath(const GrPath*, SkPath::FillType,
+    virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) SK_OVERRIDE;
+    virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
                             const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
     virtual void onDrawPaths(const GrPathRange*,
                              const uint32_t indices[], int count,
                              const float transforms[], PathTransformType,
-                             SkPath::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
+                             GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
 
     virtual bool onReserveVertexSpace(size_t vertexSize,
                                       int vertexCount,
diff --git a/src/gpu/GrPathRendering.h b/src/gpu/GrPathRendering.h
index 26cfa11..cd42206 100644
--- a/src/gpu/GrPathRendering.h
+++ b/src/gpu/GrPathRendering.h
@@ -16,6 +16,7 @@
 class SkTypeface;
 class GrPath;
 class GrGpu;
+class GrStencilSettings;
 
 /**
  * Abstract class wrapping HW path rendering API.
@@ -33,6 +34,18 @@
 public:
     virtual ~GrPathRendering() { }
 
+    // No native support for inverse at this time
+    enum FillType {
+        /** Specifies that "inside" is computed by a non-zero sum of signed
+            edge crossings
+        */
+        kWinding_FillType,
+        /** Specifies that "inside" is computed by an odd number of edge
+            crossings
+        */
+        kEvenOdd_FillType,
+    };
+
     enum PathTransformType {
         kNone_PathTransformType,        //!< []
         kTranslateX_PathTransformType,  //!< [kMTransX]
@@ -111,10 +124,11 @@
      */
     virtual GrPathRange* createGlyphs(const SkTypeface*, const SkDescriptor*, const SkStrokeRec&) = 0;
 
-    virtual void stencilPath(const GrPath*, SkPath::FillType) = 0;
-    virtual void drawPath(const GrPath*, SkPath::FillType) = 0;
+    virtual void stencilPath(const GrPath*, const GrStencilSettings&) = 0;
+    virtual void drawPath(const GrPath*, const GrStencilSettings&) = 0;
     virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
-                           const float transforms[], PathTransformType, SkPath::FillType) = 0;
+                           const float transforms[], PathTransformType,
+                           const GrStencilSettings&) = 0;
 protected:
     GrPathRendering() { }
 
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 5f55c1a..6ed4b9e 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -14,6 +14,22 @@
 #include "GrPath.h"
 #include "SkStrokeRec.h"
 
+/*
+ * For now paths only natively support winding and even odd fill types
+ */
+static GrPathRendering::FillType convert_skpath_filltype(SkPath::FillType fill) {
+    switch (fill) {
+        default:
+            SkFAIL("Incomplete Switch\n");
+        case SkPath::kWinding_FillType:
+        case SkPath::kInverseWinding_FillType:
+            return GrPathRendering::kWinding_FillType;
+        case SkPath::kEvenOdd_FillType:
+        case SkPath::kInverseEvenOdd_FillType:
+            return GrPathRendering::kEvenOdd_FillType;
+    }
+}
+
 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
     SkASSERT(context);
     SkASSERT(context->getGpu());
@@ -44,10 +60,10 @@
            target->getDrawState().getStencil().isDisabled();
 }
 
-GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport(
-                                                        const SkPath&,
-                                                        const SkStrokeRec& ,
-                                                        const GrDrawTarget*) const {
+GrPathRenderer::StencilSupport
+GrStencilAndCoverPathRenderer::onGetStencilSupport(const SkPath&,
+                                                   const SkStrokeRec& ,
+                                                   const GrDrawTarget*) const {
     return GrPathRenderer::kStencilOnly_StencilSupport;
 }
 
@@ -67,7 +83,7 @@
                                                   GrDrawTarget* target) {
     SkASSERT(!path.isInverseFillType());
     SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
-    target->stencilPath(p, path.getFillType());
+    target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
 }
 
 bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
@@ -94,7 +110,27 @@
             0x0000,
             0xffff);
 
-        *drawState->stencil() = kInvertedStencilPass;
+        drawState->setStencil(kInvertedStencilPass);
+
+        // fake inverse with a stencil and cover
+        target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
+
+        GrDrawState::AutoViewMatrixRestore avmr;
+        SkRect bounds = SkRect::MakeLTRB(0, 0,
+                                         SkIntToScalar(drawState->getRenderTarget()->width()),
+                                         SkIntToScalar(drawState->getRenderTarget()->height()));
+        SkMatrix vmi;
+        // mapRect through persp matrix may not be correct
+        if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
+            vmi.mapRect(&bounds);
+            // theoretically could set bloat = 0, instead leave it because of matrix inversion
+            // precision.
+            SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
+            bounds.outset(bloat, bloat);
+        } else {
+            avmr.setIdentity(drawState);
+        }
+        target->drawSimpleRect(bounds);
     } else {
         GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
             kZero_StencilOp,
@@ -104,11 +140,10 @@
             0x0000,
             0xffff);
 
-        *drawState->stencil() = kStencilPass;
+        drawState->setStencil(kStencilPass);
+        target->drawPath(p, convert_skpath_filltype(path.getFillType()));
     }
 
-    target->drawPath(p, path.getFillType());
-
     target->drawState()->stencil()->setDisabled();
     return true;
 }
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index b53ff79..94a6c2e 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -413,7 +413,7 @@
     }
 
     fDrawTarget->drawPaths(fGlyphs, fIndexBuffer, fPendingGlyphCount,
-                           fTransformBuffer, fTransformType, SkPath::kWinding_FillType);
+                           fTransformBuffer, fTransformType, GrPathRendering::kWinding_FillType);
 
     fPendingGlyphCount = 0;
 }
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 26584bc..66b129e 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -152,147 +152,88 @@
     return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke));
 }
 
-void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) {
+void GrGLPathRendering::stencilPath(const GrPath* path, const GrStencilSettings& stencilSettings) {
     GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
     SkASSERT(fGpu->drawState()->getRenderTarget());
     SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
 
-    this->flushPathStencilSettings(fill);
-    SkASSERT(!fHWPathStencilSettings.isTwoSided());
-
-    GrGLenum fillMode =
-        gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
-    GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
-    GL_CALL(StencilFillPath(id, fillMode, writeMask));
-}
-
-void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) {
-    GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
-    SkASSERT(fGpu->drawState()->getRenderTarget());
-    SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
-
-    this->flushPathStencilSettings(fill);
+    this->flushPathStencilSettings(stencilSettings);
     SkASSERT(!fHWPathStencilSettings.isTwoSided());
 
     const SkStrokeRec& stroke = path->getStroke();
 
-    SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
+    GrGLenum fillMode =
+        gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+    GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+
+    if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+        GL_CALL(StencilFillPath(id, fillMode, writeMask));
+    }
+    if (stroke.needToApply()) {
+        GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
+    }
+}
+
+void GrGLPathRendering::drawPath(const GrPath* path, const GrStencilSettings& stencilSettings) {
+    GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
+    SkASSERT(fGpu->drawState()->getRenderTarget());
+    SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
+
+    this->flushPathStencilSettings(stencilSettings);
+    SkASSERT(!fHWPathStencilSettings.isTwoSided());
+
+    const SkStrokeRec& stroke = path->getStroke();
 
     GrGLenum fillMode =
         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
     GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
 
-    if (nonInvertedFill == fill) {
-        if (stroke.needToApply()) {
-            if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
-                GL_CALL(StencilFillPath(id, fillMode, writeMask));
-            }
-            this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
-        } else {
-            this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
-        }
-    } else {
-        if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+    if (stroke.needToApply()) {
+        if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
             GL_CALL(StencilFillPath(id, fillMode, writeMask));
         }
-        if (stroke.needToApply()) {
-            GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
-        }
-
-        GrDrawState* drawState = fGpu->drawState();
-        GrDrawState::AutoViewMatrixRestore avmr;
-        SkRect bounds = SkRect::MakeLTRB(0, 0,
-                                         SkIntToScalar(drawState->getRenderTarget()->width()),
-                                         SkIntToScalar(drawState->getRenderTarget()->height()));
-        SkMatrix vmi;
-        // mapRect through persp matrix may not be correct
-        if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
-            vmi.mapRect(&bounds);
-            // theoretically could set bloat = 0, instead leave it because of matrix inversion
-            // precision.
-            SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
-            bounds.outset(bloat, bloat);
-        } else {
-            avmr.setIdentity(drawState);
-        }
-
-        fGpu->drawSimpleRect(bounds);
+        this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
+    } else {
+        this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
     }
 }
 
 void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count,
                                   const float transforms[], PathTransformType transformsType,
-                                  SkPath::FillType fill) {
+                                  const GrStencilSettings& stencilSettings) {
     SkASSERT(fGpu->caps()->pathRenderingSupport());
     SkASSERT(fGpu->drawState()->getRenderTarget());
     SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
 
     GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
 
-    this->flushPathStencilSettings(fill);
+    this->flushPathStencilSettings(stencilSettings);
     SkASSERT(!fHWPathStencilSettings.isTwoSided());
 
     const SkStrokeRec& stroke = pathRange->getStroke();
 
-    SkPath::FillType nonInvertedFill =
-        SkPath::ConvertToNonInverseFillType(fill);
-
     GrGLenum fillMode =
         gr_stencil_op_to_gl_path_rendering_fill_mode(
             fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
     GrGLint writeMask =
         fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
 
-    if (nonInvertedFill == fill) {
-        if (stroke.needToApply()) {
-            if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
-                GL_CALL(StencilFillPathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
-                                writeMask, gXformType2GLType[transformsType],
-                                transforms));
-            }
-            this->stencilThenCoverStrokePathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
-                                GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
-                                gXformType2GLType[transformsType], transforms);
-        } else {
-            this->stencilThenCoverFillPathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
-                                GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
-                                gXformType2GLType[transformsType], transforms);
-        }
-    } else {
-        if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+    if (stroke.needToApply()) {
+        if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
             GL_CALL(StencilFillPathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
-                                writeMask, gXformType2GLType[transformsType],
-                                transforms));
+                            count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+                            writeMask, gXformType2GLType[transformsType],
+                            transforms));
         }
-        if (stroke.needToApply()) {
-            GL_CALL(StencilStrokePathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
-                                writeMask, gXformType2GLType[transformsType],
-                                transforms));
-        }
-
-        GrDrawState* drawState = fGpu->drawState();
-        GrDrawState::AutoViewMatrixRestore avmr;
-        SkRect bounds = SkRect::MakeLTRB(0, 0,
-                                         SkIntToScalar(drawState->getRenderTarget()->width()),
-                                         SkIntToScalar(drawState->getRenderTarget()->height()));
-        SkMatrix vmi;
-        // mapRect through persp matrix may not be correct
-        if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
-            vmi.mapRect(&bounds);
-            // theoretically could set bloat = 0, instead leave it because of matrix inversion
-            // precision.
-            SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
-            bounds.outset(bloat, bloat);
-        } else {
-            avmr.setIdentity(drawState);
-        }
-
-        fGpu->drawSimpleRect(bounds);
+        this->stencilThenCoverStrokePathInstanced(
+                            count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
+                            GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+                            gXformType2GLType[transformsType], transforms);
+    } else {
+        this->stencilThenCoverFillPathInstanced(
+                            count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
+                            GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+                            gXformType2GLType[transformsType], transforms);
     }
 }
 
@@ -466,18 +407,16 @@
     fPathNameAllocator->free(path);
 }
 
-void GrGLPathRendering::flushPathStencilSettings(SkPath::FillType fill) {
-    GrStencilSettings pathStencilSettings;
-    fGpu->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
-    if (fHWPathStencilSettings != pathStencilSettings) {
+void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
+    if (fHWPathStencilSettings != stencilSettings) {
         // Just the func, ref, and mask is set here. The op and write mask are params to the call
         // that draws the path to the SB (glStencilFillPath)
         GrGLenum func =
-            GrToGLStencilFunc(pathStencilSettings.func(GrStencilSettings::kFront_Face));
-        GL_CALL(PathStencilFunc(func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
-                                pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
+            GrToGLStencilFunc(stencilSettings.func(GrStencilSettings::kFront_Face));
+        GL_CALL(PathStencilFunc(func, stencilSettings.funcRef(GrStencilSettings::kFront_Face),
+                                stencilSettings.funcMask(GrStencilSettings::kFront_Face)));
 
-        fHWPathStencilSettings = pathStencilSettings;
+        fHWPathStencilSettings = stencilSettings;
     }
 }
 
diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h
index 5133506..f314563 100644
--- a/src/gpu/gl/GrGLPathRendering.h
+++ b/src/gpu/gl/GrGLPathRendering.h
@@ -39,11 +39,11 @@
     virtual GrPathRange* createGlyphs(const SkTypeface*,
                                       const SkDescriptor*,
                                       const SkStrokeRec&) SK_OVERRIDE;
-    virtual void stencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
-    virtual void drawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
+    virtual void stencilPath(const GrPath*, const GrStencilSettings&) SK_OVERRIDE;
+    virtual void drawPath(const GrPath*, const GrStencilSettings&) SK_OVERRIDE;
     virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
                            const float transforms[], PathTransformType,
-                           SkPath::FillType) SK_OVERRIDE;
+                           const GrStencilSettings&) SK_OVERRIDE;
 
     /* Called when the 3D context state is unknown. */
     void resetContext();
@@ -107,7 +107,7 @@
     };
     const Caps& caps() const { return fCaps; }
 
-    void flushPathStencilSettings(SkPath::FillType fill);
+    void flushPathStencilSettings(const GrStencilSettings&);
 
     // NV_path_rendering v1.2
     void stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index a00333d..9d08f64 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1871,6 +1871,7 @@
 }
 
 void GrGpuGL::flushStencil(const GrStencilSettings& stencilSettings, DrawType type) {
+    // TODO figure out why we need to flush stencil settings on path draws at all
     if (kStencilPath_DrawType != type && fHWStencilSettings != stencilSettings) {
         if (stencilSettings.isDisabled()) {
             if (kNo_TriState != fHWStencilTestEnabled) {
@@ -1917,10 +1918,7 @@
     const GrRenderTarget* rt = optState.getRenderTarget();
     if (kGL_GrGLStandard == this->glStandard()) {
         if (RT_HAS_MSAA) {
-            // FIXME: GL_NV_pr doesn't seem to like MSAA disabled. The paths
-            // convex hulls of each segment appear to get filled.
-            bool enableMSAA = kStencilPath_DrawType == type ||
-                              optState.isHWAntialiasState();
+            bool enableMSAA = optState.isHWAntialiasState();
             if (enableMSAA) {
                 if (kYes_TriState != fMSAAEnabled) {
                     GL_CALL(Enable(GR_GL_MULTISAMPLE));