Fix some NV path rendering issues with perspective and inverse paths
Review URL: http://codereview.appspot.com/6347050/



git-svn-id: http://skia.googlecode.com/svn/trunk@4403 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 40d998b..81dc1db 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -95,7 +95,10 @@
         GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
             kZero_StencilOp,
             kZero_StencilOp,
-            kEqual_StencilFunc,
+            // We know our rect will hit pixels outside the clip and the user bits will be 0
+            // outside the clip. So we can't just fill where the user bits are 0. We also need to
+            // check that the clip bit is set.
+            kEqualIfInClip_StencilFunc,
             0xffff,
             0x0000,
             0xffff);
@@ -106,7 +109,8 @@
         // 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.
+            // theoretically could set bloat = 0, instead leave it because of matrix inversion
+            // precision.
         } else {
             if (stageMask) {
                 if (!drawState->getViewInverse(&vmi)) {
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 48ccd5d..e49c664 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -514,6 +514,11 @@
     fHWBoundRenderTarget = NULL;
 
     fHWPathMatrixState.invalidate();
+    if (fCaps.fPathStencilingSupport) {
+        // we don't use the model view matrix.
+        GL_CALL(MatrixMode(GR_GL_MODELVIEW));
+        GL_CALL(LoadIdentity());
+    }
 
     // we assume these values
     if (this->glCaps().unpackRowLengthSupport()) {
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index e33f469..d506c6c 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -113,57 +113,45 @@
     const GrMatrix& vm = this->getDrawState().getViewMatrix();
 
     if (kStencilPath_DrawType == type) {
-        if (fHWPathMatrixState.fViewMatrix != vm) {
-            // We use the GL model view matrix to hold the draw state's view
-            // matrix and the GL projection matrix to convert to normalized y-up
-            // coords.
+        if (fHWPathMatrixState.fViewMatrix != vm ||
+            fHWPathMatrixState.fRTSize != viewportSize) {
+            // rescale the coords from skia's "device" coords to GL's normalized coords,
+            // and perform a y-flip.
+            GrMatrix m;
+            m.setScale(GrIntToScalar(2) / rt->width(), GrIntToScalar(-2) / rt->height());
+            m.postTranslate(-1.f , 1.f);
+            m.preConcat(vm);
+
+            // GL wants a column-major 4x4.
             GrGLfloat mv[]  = {
                 // col 0
-                GrScalarToFloat(vm[GrMatrix::kMScaleX]),
-                GrScalarToFloat(vm[GrMatrix::kMSkewY]),
+                GrScalarToFloat(m[GrMatrix::kMScaleX]),
+                GrScalarToFloat(m[GrMatrix::kMSkewY]),
                 0,
-                GrScalarToFloat(vm[GrMatrix::kMPersp0]),
+                GrScalarToFloat(m[GrMatrix::kMPersp0]),
 
                 // col 1
-                GrScalarToFloat(vm[GrMatrix::kMSkewX]),
-                GrScalarToFloat(vm[GrMatrix::kMScaleY]),
+                GrScalarToFloat(m[GrMatrix::kMSkewX]),
+                GrScalarToFloat(m[GrMatrix::kMScaleY]),
                 0,
-                GrScalarToFloat(vm[GrMatrix::kMPersp1]),
+                GrScalarToFloat(m[GrMatrix::kMPersp1]),
 
                 // col 2
                 0, 0, 0, 0,
 
                 // col3
-                GrScalarToFloat(vm[GrMatrix::kMTransX]),
-                GrScalarToFloat(vm[GrMatrix::kMTransY]),
-                0.5f,
-                GrScalarToFloat(vm[GrMatrix::kMPersp2])
-            };
-            GL_CALL(MatrixMode(GR_GL_MODELVIEW));
-            GL_CALL(LoadMatrixf(mv));
-            fHWPathMatrixState.fViewMatrix = vm;
-        }
-        if (fHWPathMatrixState.fRTSize != viewportSize) {
-            GrGLfloat p[] = {
-                // col 0
-                2.f / rt->width(), 0, 0, 0,
-
-                // col 1
-                0, -2.f / rt->height(), 0, 0,
-
-                // col 2
-                0, 0, 1.f, 0,
-
-                // col 3
-                -1.f, 1.f, 0, 1.f,
+                GrScalarToFloat(m[GrMatrix::kMTransX]),
+                GrScalarToFloat(m[GrMatrix::kMTransY]),
+                0.0f,
+                GrScalarToFloat(m[GrMatrix::kMPersp2])
             };
             GL_CALL(MatrixMode(GR_GL_PROJECTION));
-            GL_CALL(LoadMatrixf(p));
+            GL_CALL(LoadMatrixf(mv));
+            fHWPathMatrixState.fViewMatrix = vm;
             fHWPathMatrixState.fRTSize = viewportSize;
         }
     } else if (!fProgramData->fViewMatrix.cheapEqualTo(vm) ||
-        fProgramData->fViewportSize != viewportSize) {
-
+               fProgramData->fViewportSize != viewportSize) {
         GrMatrix m;
         m.setAll(
             GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1,