Implement filling a path with nv_path_rendering cover

Implement filling a path with nv_path_rendering cover functionality.

The nv_path_rendering cover can be used if the fill is non-inverted
and the draw operation does not require use of vertex shaders.

Moves code for the inverted fill from GrStencilAndCoverPathRenderer
down to GrGpuGL.

R=bsalomon@google.com, markkilgard@gmail.com, cdalton@nvidia.com

Author: kkinnunen@nvidia.com

Review URL: https://codereview.chromium.org/22686002

git-svn-id: http://skia.googlecode.com/svn/trunk@11667 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index f7330a8..ef3b953 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -17,7 +17,7 @@
 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
     SkASSERT(NULL != context);
     SkASSERT(NULL != context->getGpu());
-    if (context->getGpu()->caps()->pathStencilingSupport()) {
+    if (context->getGpu()->caps()->pathRenderingSupport()) {
         return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu()));
     } else {
         return NULL;
@@ -25,7 +25,7 @@
 }
 
 GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) {
-    SkASSERT(gpu->caps()->pathStencilingSupport());
+    SkASSERT(gpu->caps()->pathRenderingSupport());
     fGpu = gpu;
     gpu->ref();
 }
@@ -40,6 +40,7 @@
                                                 bool antiAlias) const {
     return stroke.isFillStyle() &&
            !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
+           NULL != target->getDrawState().getRenderTarget()->getStencilBuffer() &&
            target->getDrawState().getStencil().isDisabled();
 }
 
@@ -70,27 +71,7 @@
 
     SkAutoTUnref<GrPath> p(fGpu->createPath(path));
 
-    SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(path.getFillType());
-    target->stencilPath(p, stroke, nonInvertedFill);
-
-    // TODO: Use built in cover operation rather than a rect draw. This will require making our
-    // fragment shaders be able to eat varyings generated by a matrix.
-
-    // fill the path, zero out the stencil
-    SkRect bounds = p->getBounds();
-    SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf;
-    GrDrawState::AutoViewMatrixRestore avmr;
-
-    if (nonInvertedFill == path.getFillType()) {
-        GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
-            kZero_StencilOp,
-            kZero_StencilOp,
-            kNotEqual_StencilFunc,
-            0xffff,
-            0x0000,
-            0xffff);
-        *drawState->stencil() = kStencilPass;
-    } else {
+    if (path.isInverseFillType()) {
         GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
             kZero_StencilOp,
             kZero_StencilOp,
@@ -101,23 +82,22 @@
             0xffff,
             0x0000,
             0xffff);
-        SkMatrix vmi;
-        bounds.setLTRB(0, 0,
-                       SkIntToScalar(drawState->getRenderTarget()->width()),
-                       SkIntToScalar(drawState->getRenderTarget()->height()));
-        // 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.
-        } else {
-            avmr.setIdentity(drawState);
-            bloat = 0;
-        }
+
         *drawState->stencil() = kInvertedStencilPass;
+    } else {
+        GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
+            kZero_StencilOp,
+            kZero_StencilOp,
+            kNotEqual_StencilFunc,
+            0xffff,
+            0x0000,
+            0xffff);
+
+        *drawState->stencil() = kStencilPass;
     }
-    bounds.outset(bloat, bloat);
-    target->drawSimpleRect(bounds, NULL);
+
+    target->fillPath(p, stroke, path.getFillType());
+
     target->drawState()->stencil()->setDisabled();
     return true;
 }