Ensure all vertex attributes (except zero that we always use) are disabled after a resetContext.

Review URL: http://codereview.appspot.com/5309043/


git-svn-id: http://skia.googlecode.com/svn/trunk@2494 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGLProgram.h b/src/gpu/GrGLProgram.h
index dafa79d..783ebf6 100644
--- a/src/gpu/GrGLProgram.h
+++ b/src/gpu/GrGLProgram.h
@@ -61,7 +61,7 @@
      void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
 
     /**
-     * Attribute indices
+     * Attribute indices. These should not overlap. Matrices consume 3 slots.
      */
     static int PositionAttributeIdx() { return 0; }
     static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
@@ -72,10 +72,10 @@
     static int EdgeAttributeIdx() { return 3 + GrDrawTarget::kMaxTexCoords; }
 
     static int ViewMatrixAttributeIdx() {
-        return 2 + GrDrawTarget::kMaxTexCoords;
+        return 4 + GrDrawTarget::kMaxTexCoords;
     }
     static int TextureMatrixAttributeIdx(int stage) {
-        return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage;
+        return 7 + GrDrawTarget::kMaxTexCoords + 3 * stage;
     }
 
 private:
diff --git a/src/gpu/GrGpuGLShaders.cpp b/src/gpu/GrGpuGLShaders.cpp
index feb6a1f..71444da 100644
--- a/src/gpu/GrGpuGLShaders.cpp
+++ b/src/gpu/GrGpuGLShaders.cpp
@@ -325,6 +325,8 @@
                             this->hasExtension("GL_OES_standard_derivatives");
     }
 
+    GR_GL_GetIntegerv(gl, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttribs);
+
     fProgramData = NULL;
     fProgramCache = new ProgramCache(gl, glslVersion);
 
@@ -361,14 +363,27 @@
 void GrGpuGLShaders::resetContext() {
     INHERITED::resetContext();
 
-    fHWGeometryState.fVertexLayout = 0;
     fHWGeometryState.fVertexOffset = ~0;
-    GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
-    GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx()));
-    for (int t = 0; t < kMaxTexCoords; ++t) {
-        GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
+
+    // Third party GL code may have left vertex attributes enabled. Some GL
+    // implementations (osmesa) may read vetex attributes that are not required
+    // by the current shader. Therefore, we have to ensure that only the
+    // attributes we require for the current draw are enabled or we may cause an
+    // invalid read.
+
+    // Disable all vertex layout bits so that next flush will assume all
+    // optional vertex attributes are disabled.
+    fHWGeometryState.fVertexLayout = 0;
+
+    // We always use the this attribute and assume it is always enabled.
+    int posAttrIdx = GrGLProgram::PositionAttributeIdx();
+    GL_CALL(EnableVertexAttribArray(posAttrIdx));
+    // Disable all other vertex attributes.
+    for  (int va = 0; va < fMaxVertexAttribs; ++va) {
+        if (va != posAttrIdx) {
+            GL_CALL(DisableVertexAttribArray(va));
+        }
     }
-    GL_CALL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx()));
 
     fHWProgramID = 0;
 }
diff --git a/src/gpu/GrGpuGLShaders.h b/src/gpu/GrGpuGLShaders.h
index 0c8322b..fc5215f 100644
--- a/src/gpu/GrGpuGLShaders.h
+++ b/src/gpu/GrGpuGLShaders.h
@@ -85,6 +85,9 @@
     CachedData*                 fProgramData;
     GrGLuint                    fHWProgramID;
     GrGLProgram                 fCurrentProgram;
+    // If we get rid of fixed function subclass this should move
+    // to the GLCaps struct in parent class
+    GrGLint                     fMaxVertexAttribs;
 
     typedef GrGpuGL INHERITED;
 };