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/GrDrawState.h b/src/gpu/GrDrawState.h
index 2f96c15..d16efa8 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -23,6 +23,11 @@
 #include "SkMatrix.h"
 #include "SkXfermode.h"
 
+/**
+ * Type used to describe how attributes bind to program usage
+ */
+typedef int GrAttribBindings;
+
 class GrDrawState : public GrRefCnt {
 public:
     SK_DECLARE_INST_COUNT(GrDrawState)
@@ -40,8 +45,8 @@
      * coverage rather than as input to the src/dst color blend step.
      *
      * The input color to the first enabled color-stage is either the constant color or interpolated
-     * per-vertex colors. The input to the first coverage stage is either a constant coverage
-     * (usually full-coverage) or interpolated per-vertex coverage.
+     * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is
+     * either a constant coverage (usually full-coverage) or interpolated per-vertex coverage.
      *
      * See the documentation of kCoverageDrawing_StateBit for information about disabling the
      * the color / coverage distinction.
@@ -57,6 +62,9 @@
     };
 
     GrDrawState() {
+#if GR_DEBUG
+        VertexAttributesUnitTest();
+#endif
         this->reset();
     }
 
@@ -107,72 +115,53 @@
     ////
 
     enum {
-        kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+        kVertexAttribCnt = 6,
     };
 
    /**
-     * The format of vertices is represented as an array of GrVertexAttribs, with each representing
-     * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
-     * GrTypesPriv.h).
+     * The format of vertices is represented as an array of vertex attribute
+     * pair, with each pair representing the type of the attribute and the
+     * offset in the vertex structure (see GrVertexAttrib, above).
      *
-     * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
-     * setEffect is called.
+     * This will only set up the vertex geometry. To bind the attributes in
+     * the shaders, attribute indices and attribute bindings need to be set
+     * as well.
      */
 
     /**
      *  Sets vertex attributes for next draw.
      *
      *  @param attribs    the array of vertex attributes to set.
-     *  @param count      the number of attributes being set, limited to kMaxVertexAttribCnt.
+     *  @param count      the number of attributes being set.
+     *                    limited to a count of kVertexAttribCnt.
      */
     void setVertexAttribs(const GrVertexAttrib attribs[], int count);
 
-    const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVertexAttribs.begin(); }
-    int getVertexAttribCount() const { return fCommon.fVertexAttribs.count(); }
+    const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
+    int getVertexAttribCount() const { return fVertexAttribs.count(); }
 
     size_t getVertexSize() const;
 
     /**
-     *  Sets default vertex attributes for next draw. The default is a single attribute:
-     *  {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
+     *  Sets default vertex attributes for next draw.
+     *
+     *  This will also set default vertex attribute indices and bindings
      */
     void setDefaultVertexAttribs();
 
-    /**
-     * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
-     * binding does not appear in the current attribs. These bindings should appear only once in
-     * the attrib array.
-     */
-
-    int positionAttributeIndex() const {
-        return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
-    }
-    int localCoordAttributeIndex() const {
-        return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
-    }
-    int colorVertexAttributeIndex() const {
-        return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
-    }
-    int coverageVertexAttributeIndex() const {
-        return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
-    }
-
-    bool hasLocalCoordAttribute() const {
-        return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
-    }
-    bool hasColorVertexAttribute() const {
-        return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
-    }
-    bool hasCoverageVertexAttribute() const {
-        return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
-    }
-
     bool validateVertexAttribs() const;
 
+    ////////////////////////////////////////////////////////////////////////////
+    // Helpers for picking apart vertex attributes
+
+    // helper array to let us check the expected so we know what bound attrib indices
+    // we care about
+    static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount];
+
     /**
-     * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
-     * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
-     * nicer looking.
+     * Accessing positions, texture coords, or colors, of a vertex within an
+     * array is a hassle involving casts and simple math. These helpers exist
+     * to keep GrDrawTarget clients' code a bit nicer looking.
      */
 
     /**
@@ -229,15 +218,110 @@
 
     /// @}
 
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Attribute Bindings
+    ////
+
+    /**
+     * The vertex data used by the current program is represented as a bitfield
+     * of flags. Programs always use positions and may also use texture
+     * coordinates, per-vertex colors, per-vertex coverage and edge data. The
+     * local coords accessible by effects may either come from positions or
+     * be specified explicitly.
+     */
+
+    /**
+     * Additional Bits that can be specified in GrAttribBindings.
+     */
+    enum AttribBindingsBits {
+        /** explicit local coords are provided (instead of using pre-view-matrix positions) */
+        kLocalCoords_AttribBindingsBit        = 0x1,
+        /* program uses colors (GrColor) */
+        kColor_AttribBindingsBit              = 0x2,
+        /* program uses coverage (GrColor)
+         */
+        kCoverage_AttribBindingsBit           = 0x4,
+        // for below assert
+        kDummyAttribBindingsBit,
+        kHighAttribBindingsBit = kDummyAttribBindingsBit - 1
+    };
+    // make sure we haven't exceeded the number of bits in GrAttribBindings.
+    GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings)));
+
+    enum AttribBindings {
+        kDefault_AttribBindings = 0
+    };
+
+    /**
+     *  Sets attribute bindings for next draw.
+     *
+     *  @param bindings    the attribute bindings to set.
+     */
+    void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; }
+
+    GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Helpers for picking apart attribute bindings
+
     /**
      * Determines whether src alpha is guaranteed to be one for all src pixels
      */
-    bool srcAlphaWillBeOne() const;
+    bool srcAlphaWillBeOne(GrAttribBindings) const;
 
     /**
      * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
      */
-    bool hasSolidCoverage() const;
+    bool hasSolidCoverage(GrAttribBindings) const;
+
+    static void VertexAttributesUnitTest();
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Vertex Attribute Indices
+    ////
+
+    /**
+     * Vertex attribute indices map the data set in the vertex attribute array
+     * to the bindings specified in the attribute bindings. Each binding type
+     * has an associated index in the attribute array. This index is used to
+     * look up the vertex attribute data from the array, and potentially as the
+     * attribute index if we're binding attributes in GL.
+     *
+     * Indices which do not have active attribute bindings will be ignored.
+     */
+
+    enum AttribIndex {
+        kPosition_AttribIndex = 0,
+        kColor_AttribIndex,
+        kCoverage_AttribIndex,
+        kLocalCoords_AttribIndex,
+
+        kLast_AttribIndex = kLocalCoords_AttribIndex
+    };
+    static const int kAttribIndexCount = kLast_AttribIndex + 1;
+
+    // these are used when vertex color and coverage isn't set
+    enum {
+        kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt,
+        kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1,
+    };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Helpers to set attribute indices. These should match the index in the
+    // current attribute index array.
+
+    /**
+     *  Sets index for next draw. This is used to look up the offset
+     *  from the current vertex attribute array and to bind the attributes.
+     *
+     *  @param index      the attribute index we're setting
+     *  @param value      the value of the index
+     */
+    void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; }
+
+    int getAttribIndex(AttribIndex index) const       { return fAttribIndices[index]; }
 
     /// @}
 
@@ -984,6 +1068,15 @@
         if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
             return false;
         }
+        if (fVertexAttribs != s.fVertexAttribs) {
+            return false;
+        }
+        for (int i = 0; i < kAttribIndexCount; ++i) {
+            if ((i == kPosition_AttribIndex || s.fCommon.fAttribBindings & (1 << i)) &&
+                fAttribIndices[i] != s.fAttribIndices[i]) {
+                return false;
+            }
+        }
         for (int i = 0; i < kNumStages; i++) {
             bool enabled = this->isStageEnabled(i);
             if (enabled != s.isStageEnabled(i)) {
@@ -1000,6 +1093,10 @@
     GrDrawState& operator= (const GrDrawState& s) {
         this->setRenderTarget(s.fRenderTarget.get());
         fCommon = s.fCommon;
+        fVertexAttribs = s.fVertexAttribs;
+        for (int i = 0; i < kAttribIndexCount; i++) {
+            fAttribIndices[i] = s.fAttribIndices[i];
+        }
         for (int i = 0; i < kNumStages; i++) {
             if (s.isStageEnabled(i)) {
                 this->fStages[i] = s.fStages[i];
@@ -1013,44 +1110,33 @@
     /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
     struct CommonState {
         // These fields are roughly sorted by decreasing likelihood of being different in op==
-        GrColor                                  fColor;
-        SkMatrix                                 fViewMatrix;
-        GrBlendCoeff                             fSrcBlend;
-        GrBlendCoeff                             fDstBlend;
-        GrColor                                  fBlendConstant;
-        uint32_t                                 fFlagBits;
-        GrVertexAttribArray<kMaxVertexAttribCnt> fVertexAttribs;
-        GrStencilSettings                        fStencilSettings;
-        int                                      fFirstCoverageStage;
-        GrColor                                  fCoverage;
-        SkXfermode::Mode                         fColorFilterMode;
-        GrColor                                  fColorFilterColor;
-        DrawFace                                 fDrawFace;
-
-        // This is simply a different representation of info in fVertexAttribs and thus does
-        // not need to be compared in op==.
-        int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
-
-        GR_STATIC_ASSERT(kGrVertexAttribBindingCnt <= 8*sizeof(uint32_t));
-
+        GrColor                         fColor;
+        GrAttribBindings                fAttribBindings;
+        SkMatrix                        fViewMatrix;
+        GrBlendCoeff                    fSrcBlend;
+        GrBlendCoeff                    fDstBlend;
+        GrColor                         fBlendConstant;
+        uint32_t                        fFlagBits;
+        GrStencilSettings               fStencilSettings;
+        int                             fFirstCoverageStage;
+        GrColor                         fCoverage;
+        SkXfermode::Mode                fColorFilterMode;
+        GrColor                         fColorFilterColor;
+        DrawFace                        fDrawFace;
         bool operator== (const CommonState& other) const {
-            bool result = fColor == other.fColor &&
-                          fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
-                          fSrcBlend == other.fSrcBlend &&
-                          fDstBlend == other.fDstBlend &&
-                          fBlendConstant == other.fBlendConstant &&
-                          fFlagBits == other.fFlagBits &&
-                          fVertexAttribs == other.fVertexAttribs &&
-                          fStencilSettings == other.fStencilSettings &&
-                          fFirstCoverageStage == other.fFirstCoverageStage &&
-                          fCoverage == other.fCoverage &&
-                          fColorFilterMode == other.fColorFilterMode &&
-                          fColorFilterColor == other.fColorFilterColor &&
-                          fDrawFace == other.fDrawFace;
-            GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
-                                            other.fFixedFunctionVertexAttribIndices,
-                                            sizeof(fFixedFunctionVertexAttribIndices)));
-            return result;
+            return fColor == other.fColor &&
+                   fAttribBindings == other.fAttribBindings &&
+                   fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
+                   fSrcBlend == other.fSrcBlend &&
+                   fDstBlend == other.fDstBlend &&
+                   fBlendConstant == other.fBlendConstant &&
+                   fFlagBits == other.fFlagBits &&
+                   fStencilSettings == other.fStencilSettings &&
+                   fFirstCoverageStage == other.fFirstCoverageStage &&
+                   fCoverage == other.fCoverage &&
+                   fColorFilterMode == other.fColorFilterMode &&
+                   fColorFilterColor == other.fColorFilterColor &&
+                   fDrawFace == other.fDrawFace;
         }
         bool operator!= (const CommonState& other) const { return !(*this == other); }
     };
@@ -1083,6 +1169,10 @@
             // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
             fRenderTarget = drawState.fRenderTarget.get();
             SkSafeRef(fRenderTarget);
+            fVertexAttribs = drawState.fVertexAttribs;
+            for (int i = 0; i < kAttribIndexCount; i++) {
+                fAttribIndices[i] = drawState.fAttribIndices[i];
+            }
             // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
             // ref gets fully unref'ed it will cause the underlying effect to unref its resources
             // and recycle them to the cache (if no one else is holding a ref to the resources).
@@ -1096,6 +1186,10 @@
             GrAssert(fInitialized);
             drawState->fCommon = fCommon;
             drawState->setRenderTarget(fRenderTarget);
+            drawState->fVertexAttribs = fVertexAttribs;
+            for (int i = 0; i < kAttribIndexCount; i++) {
+                drawState->fAttribIndices[i] = fAttribIndices[i];
+            }
             for (int i = 0; i < kNumStages; ++i) {
                 fStages[i].restoreTo(&drawState->fStages[i]);
             }
@@ -1105,6 +1199,16 @@
             if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
                 return false;
             }
+            for (int i = 0; i < kAttribIndexCount; ++i) {
+                if ((i == kPosition_AttribIndex ||
+                     state.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
+                    fAttribIndices[i] != state.fAttribIndices[i]) {
+                    return false;
+                }
+            }
+            if (fVertexAttribs != state.fVertexAttribs) {
+                return false;
+            }
             for (int i = 0; i < kNumStages; ++i) {
                 if (!fStages[i].isEqual(state.fStages[i])) {
                     return false;
@@ -1116,15 +1220,22 @@
     private:
         GrRenderTarget*                       fRenderTarget;
         CommonState                           fCommon;
+        int                                   fAttribIndices[kAttribIndexCount];
+        GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
         GrEffectStage::DeferredStage          fStages[kNumStages];
 
         GR_DEBUGCODE(bool fInitialized;)
     };
 
 private:
+    // helper array to let us check the current bindings so we know what bound attrib indices
+    // we care about
+    static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount];
 
     SkAutoTUnref<GrRenderTarget>           fRenderTarget;
     CommonState                            fCommon;
+    int                                    fAttribIndices[kAttribIndexCount];
+    GrVertexAttribArray<kVertexAttribCnt>  fVertexAttribs;
     GrEffectStage                          fStages[kNumStages];
 
     typedef GrRefCnt INHERITED;