Use vertexless shaders when NVpr is available

Adds support for vertexless shaders and enables them when
NV_path_rendering is available. This takes a
GrGLFragmentOnlyShaderBuilder class, a GrGLTexGenEffectArray class,
support for setting TexGen and the projection matrix in GrGpuGL, and
code for setting the GL fixed function state where necessary.

R=bsalomon@google.com, kkinnunen@nvidia.com

Author: cdalton@nvidia.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@11620 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 50d2a1f..18165d9 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -124,6 +124,7 @@
     fCaps.reset(SkRef(ctx.info().caps()));
 
     fHWBoundTextures.reset(ctx.info().caps()->maxFragmentTextureUnits());
+    fHWTexGenSettings.reset(ctx.info().caps()->maxFixedFunctionTextureCoords());
 
     fillInConfigRenderableTable();
 
@@ -377,7 +378,13 @@
             GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
             GL_CALL(Disable(GR_GL_TEXTURE_GEN_Q));
             GL_CALL(Disable(GR_GL_TEXTURE_GEN_R));
+            if (this->caps()->pathStencilingSupport()) {
+                GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+            }
+            fHWTexGenSettings[i].fMode = GR_GL_NONE;
+            fHWTexGenSettings[i].fNumComponents = 0;
         }
+        fHWActiveTexGenSets = 0;
     }
 
     // we assume these values
@@ -2114,6 +2121,124 @@
     texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
 }
 
+void GrGpuGL::setProjectionMatrix(const SkMatrix& matrix,
+                                  const SkISize& renderTargetSize,
+                                  GrSurfaceOrigin renderTargetOrigin) {
+
+    SkASSERT(this->glCaps().fixedFunctionSupport());
+
+    if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
+        renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
+        matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
+        return;
+    }
+
+    fHWProjectionMatrixState.fViewMatrix = matrix;
+    fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
+    fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
+
+    GrGLfloat glMatrix[4 * 4];
+    fHWProjectionMatrixState.getGLMatrix<4>(glMatrix);
+    GL_CALL(MatrixMode(GR_GL_PROJECTION));
+    GL_CALL(LoadMatrixf(glMatrix));
+}
+
+void GrGpuGL::enableTexGen(int unitIdx,
+                           TexGenComponents components,
+                           const GrGLfloat* coefficients) {
+
+    SkASSERT(this->glCaps().fixedFunctionSupport());
+    SkASSERT(this->caps()->pathStencilingSupport());
+    SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
+
+    if (GR_GL_OBJECT_LINEAR == fHWTexGenSettings[unitIdx].fMode &&
+        components == fHWTexGenSettings[unitIdx].fNumComponents &&
+        !memcmp(coefficients, fHWTexGenSettings[unitIdx].fCoefficients,
+                3 * components * sizeof(GrGLfloat))) {
+        return;
+    }
+
+    this->setTextureUnit(unitIdx);
+
+    if (GR_GL_OBJECT_LINEAR != fHWTexGenSettings[unitIdx].fMode) {
+        for (int i = 0; i < 4; i++) {
+            GL_CALL(TexGeni(GR_GL_S + i, GR_GL_TEXTURE_GEN_MODE, GR_GL_OBJECT_LINEAR));
+        }
+        fHWTexGenSettings[unitIdx].fMode = GR_GL_OBJECT_LINEAR;
+    }
+
+    for (int i = fHWTexGenSettings[unitIdx].fNumComponents; i < components; i++) {
+        GL_CALL(Enable(GR_GL_TEXTURE_GEN_S + i));
+    }
+    for (int i = components; i < fHWTexGenSettings[unitIdx].fNumComponents; i++) {
+        GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + i));
+    }
+    fHWTexGenSettings[unitIdx].fNumComponents = components;
+
+    for (int i = 0; i < components; i++) {
+        GrGLfloat plane[] = {coefficients[0 + 3 * i],
+                             coefficients[1 + 3 * i],
+                             0,
+                             coefficients[2 + 3 * i]};
+        GL_CALL(TexGenfv(GR_GL_S + i, GR_GL_OBJECT_PLANE, plane));
+    }
+
+    GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
+                       GR_GL_OBJECT_LINEAR,
+                       components,
+                       coefficients));
+
+    memcpy(fHWTexGenSettings[unitIdx].fCoefficients, coefficients,
+           3 * components * sizeof(GrGLfloat));
+
+    fHWActiveTexGenSets = SkTMax(fHWActiveTexGenSets, unitIdx);
+}
+
+void GrGpuGL::enableTexGen(int unitIdx, TexGenComponents components, const SkMatrix& matrix) {
+
+    GrGLfloat coefficients[3 * 3];
+    SkASSERT(this->glCaps().fixedFunctionSupport());
+    SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
+
+    coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
+    coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
+    coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
+
+    if (components >= kST_TexGenComponents) {
+        coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
+        coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
+        coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
+    }
+
+    if (components >= kSTR_TexGenComponents) {
+        coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
+        coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
+        coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
+    }
+
+    enableTexGen(unitIdx, components, coefficients);
+}
+
+void GrGpuGL::disableUnusedTexGen(int numUsedTexCoordSets) {
+
+    SkASSERT(this->glCaps().fixedFunctionSupport());
+
+    for (int i = numUsedTexCoordSets; i < fHWActiveTexGenSets; i++) {
+        if (0 == fHWTexGenSettings[i].fNumComponents) {
+            continue;
+        }
+
+        this->setTextureUnit(i);
+        for (int j = 0; j < fHWTexGenSettings[i].fNumComponents; j++) {
+            GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + j));
+        }
+        GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+        fHWTexGenSettings[i].fNumComponents = 0;
+    }
+
+    fHWActiveTexGenSets = SkTMin(fHWActiveTexGenSets, numUsedTexCoordSets);
+}
+
 void GrGpuGL::flushMiscFixedFunctionState() {
 
     const GrDrawState& drawState = this->getDrawState();