Rolling back r8466. 

Not reviewed.


git-svn-id: http://skia.googlecode.com/svn/trunk@8467 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 51cae5c..cbaa765 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -705,17 +705,14 @@
     GL_CALL(BindAttribLocation(fProgramID,
                                fDesc.fPositionAttributeIndex,
                                builder.positionAttribute().c_str()));
-    if (-1 != fDesc.fLocalCoordAttributeIndex) {
+    GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
+    GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
+
+    if (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
         GL_CALL(BindAttribLocation(fProgramID,
-                                   fDesc.fLocalCoordAttributeIndex,
+                                   fDesc.fLocalCoordsAttributeIndex,
                                    builder.localCoordsAttribute().c_str()));
     }
-    if (-1 != fDesc.fColorAttributeIndex) {
-        GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
-    }
-    if (-1 != fDesc.fCoverageAttributeIndex) {
-        GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
-    }
 
     const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end();
     for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin();
@@ -829,7 +826,8 @@
             const GrEffectStage& stage = drawState.getStage(s);
             GrAssert(NULL != stage.getEffect());
 
-            bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex;
+            bool explicitLocalCoords =
+                (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit);
             GrDrawEffect drawEffect(stage, explicitLocalCoords);
             fEffects[s]->setData(fUniformManager, drawEffect);
             int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count();
@@ -849,18 +847,15 @@
 void GrGLProgram::setColor(const GrDrawState& drawState,
                            GrColor color,
                            SharedGLState* sharedState) {
-    if (!drawState.hasColorVertexAttribute()) {
+    if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) {
         switch (fDesc.fColorInput) {
             case GrGLProgramDesc::kAttribute_ColorInput:
-                GrAssert(-1 != fDesc.fColorAttributeIndex);
-                if (sharedState->fConstAttribColor != color ||
-                    sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) {
+                if (sharedState->fConstAttribColor != color) {
                     // OpenGL ES only supports the float varieties of glVertexAttrib
                     GrGLfloat c[4];
                     GrColorToRGBAFloat(color, c);
                     GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c));
                     sharedState->fConstAttribColor = color;
-                    sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex;
                 }
                 break;
             case GrGLProgramDesc::kUniform_ColorInput:
@@ -873,34 +868,28 @@
                     fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
                     fColor = color;
                 }
-                sharedState->fConstAttribColorIndex = -1;
                 break;
             case GrGLProgramDesc::kSolidWhite_ColorInput:
             case GrGLProgramDesc::kTransBlack_ColorInput:
-                sharedState->fConstAttribColorIndex = -1;
                 break;
             default:
                 GrCrash("Unknown color type.");
         }
-    } else {
-        sharedState->fConstAttribColorIndex = -1;
     }
 }
 
 void GrGLProgram::setCoverage(const GrDrawState& drawState,
                               GrColor coverage,
                               SharedGLState* sharedState) {
-    if (!drawState.hasCoverageVertexAttribute()) {
+    if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) {
         switch (fDesc.fCoverageInput) {
             case GrGLProgramDesc::kAttribute_ColorInput:
-                if (sharedState->fConstAttribCoverage != coverage ||
-                    sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) {
+                if (sharedState->fConstAttribCoverage != coverage) {
                     // OpenGL ES only supports the float varieties of  glVertexAttrib
                     GrGLfloat c[4];
                     GrColorToRGBAFloat(coverage, c);
                     GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c));
                     sharedState->fConstAttribCoverage = coverage;
-                    sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex;
                 }
                 break;
             case GrGLProgramDesc::kUniform_ColorInput:
@@ -913,17 +902,13 @@
                     fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
                     fCoverage = coverage;
                 }
-                sharedState->fConstAttribCoverageIndex = -1;
                 break;
             case GrGLProgramDesc::kSolidWhite_ColorInput:
             case GrGLProgramDesc::kTransBlack_ColorInput:
-                sharedState->fConstAttribCoverageIndex = -1;
                 break;
             default:
                 GrCrash("Unknown coverage type.");
         }
-    } else {
-        sharedState->fConstAttribCoverageIndex = -1;
     }
 }
 
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 4b5dfea..27b6f80 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -60,23 +60,18 @@
     GrGLuint programID() const { return fProgramID; }
 
     /**
-     * Some GL state that is relevant to programs is not stored per-program. In particular color
-     * and coverage attributes can be global state. This struct is read and updated by 
-     * GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state 
-     * redundantly.
+     * Some GL state that is relevant to programs is not stored per-program. In particular vertex
+     * attributes are global state. This struct is read and updated by GrGLProgram::setData to
+     * allow us to avoid setting this state redundantly.
      */
     struct SharedGLState {
         GrColor fConstAttribColor;
-        int     fConstAttribColorIndex;
         GrColor fConstAttribCoverage;
-        int     fConstAttribCoverageIndex;
 
         SharedGLState() { this->invalidate(); }
         void invalidate() {
             fConstAttribColor = GrColor_ILLEGAL;
-            fConstAttribColorIndex = -1;
             fConstAttribCoverage = GrColor_ILLEGAL;
-            fConstAttribCoverageIndex = -1;
         }
     };
 
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 73846b8..6ed5473 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -34,42 +34,49 @@
     // bindings in use or other descriptor field settings) it should be set
     // to a canonical value to avoid duplicate programs with different keys.
 
+    // Must initialize all fields or cache will have false negatives!
+    desc->fAttribBindings = drawState.getAttribBindings();
 
     desc->fEmitsPointSize = isPoints;
 
-    bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
-    bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
-    // we only need the local coords if we're actually going to generate effect code
-    bool requiresLocalCoordAttrib = !(skipCoverage  && skipColor) &&
-                                    drawState.hasLocalCoordAttribute();
+    bool requiresAttributeColors =
+        !skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit);
+    bool requiresAttributeCoverage =
+        !skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit);
 
     // fColorInput/fCoverageInput records how colors are specified for the program so we strip the
     // bits from the bindings to avoid false negatives when searching for an existing program in the
     // cache.
+    desc->fAttribBindings &=
+        ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit);
 
     desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
 
+    // no reason to do edge aa or look at per-vertex coverage if coverage is ignored
+    if (skipCoverage) {
+        desc->fAttribBindings &= ~(GrDrawState::kCoverage_AttribBindingsBit);
+    }
 
     bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
     bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
-                             (!requiresColorAttrib && 0xffffffff == drawState.getColor());
+                             (!requiresAttributeColors && 0xffffffff == drawState.getColor());
     if (colorIsTransBlack) {
         desc->fColorInput = kTransBlack_ColorInput;
     } else if (colorIsSolidWhite) {
         desc->fColorInput = kSolidWhite_ColorInput;
-    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
+    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
         desc->fColorInput = kUniform_ColorInput;
     } else {
         desc->fColorInput = kAttribute_ColorInput;
     }
 
-    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
+    bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
 
     if (skipCoverage) {
         desc->fCoverageInput = kTransBlack_ColorInput;
     } else if (covIsSolidWhite) {
         desc->fCoverageInput = kSolidWhite_ColorInput;
-    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
+    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
         desc->fCoverageInput = kUniform_ColorInput;
     } else {
         desc->fCoverageInput = kAttribute_ColorInput;
@@ -85,7 +92,9 @@
             lastEnabledStage = s;
             const GrEffectRef& effect = *drawState.getStage(s).getEffect();
             const GrBackendEffectFactory& factory = effect->getFactory();
-            GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
+            bool explicitLocalCoords = (drawState.getAttribBindings() &
+                                        GrDrawState::kLocalCoords_AttribBindingsBit);
+            GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords);
             desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
             if (effect->willReadDst()) {
                 readsDst = true;
@@ -130,7 +139,7 @@
             firstCoverageStage = drawState.getFirstCoverageStage();
             hasCoverage = true;
         } else {
-            hasCoverage = requiresCoverageAttrib;
+            hasCoverage = requiresAttributeCoverage;
         }
     }
 
@@ -165,27 +174,38 @@
         }
     }
 
-    desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
-    desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
-
-    // For constant color and coverage we need an attribute with an index beyond those already set
-    int availableAttributeIndex = drawState.getVertexAttribCount();
-    if (requiresColorAttrib) {
-        desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
-    } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
-        GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
-        desc->fColorAttributeIndex = availableAttributeIndex;
-        availableAttributeIndex++;
+    desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex);
+    if (requiresAttributeColors) {
+        desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex);
     } else {
-        desc->fColorAttributeIndex = -1;
+        desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue;
+    }
+    if (requiresAttributeCoverage) {
+        desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex);
+    } else {
+        desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue;
+    }
+    if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+        desc->fLocalCoordsAttributeIndex = drawState.getAttribIndex(GrDrawState::kLocalCoords_AttribIndex);
     }
 
-    if (requiresCoverageAttrib) {
-        desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
-    } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
-        GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
-        desc->fCoverageAttributeIndex = availableAttributeIndex;
-    } else {
-        desc->fCoverageAttributeIndex = -1;
+#if GR_DEBUG
+    // Verify valid vertex attribute state. These assertions should probably be done somewhere
+    // higher up the callstack
+    const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs();
+    GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt);
+    GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fPositionAttributeIndex].fType).fCount == 2);
+    if (requiresAttributeColors) {
+        GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt);
+        GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fColorAttributeIndex].fType).fCount == 4);
     }
+    if (requiresAttributeCoverage) {
+        GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt);
+        GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4);
+    }
+    if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+        GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt);
+        GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2);
+    }
+#endif
 }
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index a77ed71..df5729f 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -39,8 +39,7 @@
     void setRandom(SkMWCRandom*,
                    const GrGpuGL* gpu,
                    const GrTexture* dummyDstTexture,
-                   const GrEffectStage stages[GrDrawState::kNumStages],
-                   int currAttribIndex);
+                   const GrEffectStage stages[GrDrawState::kNumStages]);
 
     /**
      * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
@@ -77,34 +76,35 @@
         kDualSrcOutputCnt
     };
 
+    // should the FS discard if the coverage is zero (to avoid stencil manipulation)
+    bool                        fDiscardIfZeroCoverage;
+
+    // stripped of bits that don't affect program generation
+    GrAttribBindings            fAttribBindings;
+
     /** Non-zero if this stage has an effect */
     GrGLEffect::EffectKey       fEffectKeys[GrDrawState::kNumStages];
 
-    // To enable experimental geometry shader code (not for use in	
-    // production)	 
-#if GR_GL_EXPERIMENTAL_GS	
-    bool                     fExperimentalGS;	
-#endif	
-
+    // To enable experimental geometry shader code (not for use in
+    // production)
+#if GR_GL_EXPERIMENTAL_GS
+    bool                        fExperimentalGS;
+#endif
     GrGLShaderBuilder::DstReadKey fDstRead;             // set by GrGLShaderBuilder if there
                                                         // are effects that must read the dst.
                                                         // Otherwise, 0.
 
-    // should the FS discard if the coverage is zero (to avoid stencil manipulation)
-    SkBool8                     fDiscardIfZeroCoverage;
-
     uint8_t                     fColorInput;            // casts to enum ColorInput
     uint8_t                     fCoverageInput;         // casts to enum ColorInput
     uint8_t                     fDualSrcOutput;         // casts to enum DualSrcOutput
-
     int8_t                      fFirstCoverageStage;
     SkBool8                     fEmitsPointSize;
     uint8_t                     fColorFilterXfermode;   // casts to enum SkXfermode::Mode
 
     int8_t                      fPositionAttributeIndex;
-    int8_t                      fLocalCoordAttributeIndex;
     int8_t                      fColorAttributeIndex;
     int8_t                      fCoverageAttributeIndex;
+    int8_t                      fLocalCoordsAttributeIndex;
 
     // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
     // code generation to GrGLShaderBuilder (and maybe add getters rather than friending).
diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp
index 3ec7fc4..570e61e 100644
--- a/src/gpu/gl/GrGLSL.cpp
+++ b/src/gpu/gl/GrGLSL.cpp
@@ -67,6 +67,15 @@
     return declaredOutput;
 }
 
+GrSLType GrSLFloatVectorType (int count) {
+    GR_STATIC_ASSERT(kFloat_GrSLType == 1);
+    GR_STATIC_ASSERT(kVec2f_GrSLType == 2);
+    GR_STATIC_ASSERT(kVec3f_GrSLType == 3);
+    GR_STATIC_ASSERT(kVec4f_GrSLType == 4);
+    GrAssert(count > 0 && count <= 4);
+    return (GrSLType)(count);
+}
+
 const char* GrGLSLVectorHomogCoord(int count) {
     static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 1104cd0..86cead4 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -117,7 +117,7 @@
 
     fPositionVar = &fVSAttrs.push_back();
     fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
-    if (-1 != desc.fLocalCoordAttributeIndex) {
+    if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
         fLocalCoordsVar = &fVSAttrs.push_back();
         fLocalCoordsVar->set(kVec2f_GrSLType,
                              GrGLShaderVar::kAttribute_TypeModifier,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index d299656..d03ef78 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -180,7 +180,9 @@
 
     fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
 
-    GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt);
+    GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
+    GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue);
+    GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue);
 
     fLastSuccessfulStencilFmtIdx = 0;
     if (false) { // avoid bit rot, suppress warning