Revise attribute binding interface.

Replace the old attribute binding and index interface with one where we include the binding as part of the attribute array. Also removed the fixed attribute indices for constant color and coverage attributes, and replaced with dynamic ones based on current attribute set. Removed binding of color and coverage attributes unless they're actually set.

Original author: bsalomon@google.com

Author: jvanverth@google.com

Reviewed By: bsalomon@google.com,robertphillips@google.com

Review URL: https://chromiumcodereview.appspot.com/13296005

git-svn-id: http://skia.googlecode.com/svn/trunk@8466 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index d16efa8..2f96c15 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -23,11 +23,6 @@
 #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)
@@ -45,8 +40,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, depending upon GrAttribBindings. The input to the first coverage stage is
-     * either a constant coverage (usually full-coverage) or interpolated per-vertex coverage.
+     * per-vertex colors. 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.
@@ -62,9 +57,6 @@
     };
 
     GrDrawState() {
-#if GR_DEBUG
-        VertexAttributesUnitTest();
-#endif
         this->reset();
     }
 
@@ -115,53 +107,72 @@
     ////
 
     enum {
-        kVertexAttribCnt = 6,
+        kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
     };
 
    /**
-     * 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 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).
      *
-     * 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.
+     * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
+     * setEffect is called.
      */
 
     /**
      *  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 a count of kVertexAttribCnt.
+     *  @param count      the number of attributes being set, limited to kMaxVertexAttribCnt.
      */
     void setVertexAttribs(const GrVertexAttrib attribs[], int count);
 
-    const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
-    int getVertexAttribCount() const { return fVertexAttribs.count(); }
+    const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVertexAttribs.begin(); }
+    int getVertexAttribCount() const { return fCommon.fVertexAttribs.count(); }
 
     size_t getVertexSize() const;
 
     /**
-     *  Sets default vertex attributes for next draw.
-     *
-     *  This will also set default vertex attribute indices and bindings
+     *  Sets default vertex attributes for next draw. The default is a single attribute:
+     *  {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
      */
     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, 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.
+     * 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.
      */
 
     /**
@@ -218,110 +229,15 @@
 
     /// @}
 
-    ///////////////////////////////////////////////////////////////////////////
-    /// @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(GrAttribBindings) const;
+    bool srcAlphaWillBeOne() const;
 
     /**
      * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
      */
-    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]; }
+    bool hasSolidCoverage() const;
 
     /// @}
 
@@ -1068,15 +984,6 @@
         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)) {
@@ -1093,10 +1000,6 @@
     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];
@@ -1110,33 +1013,44 @@
     /** 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;
-        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;
+        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));
+
         bool operator== (const CommonState& other) const {
-            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 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;
         }
         bool operator!= (const CommonState& other) const { return !(*this == other); }
     };
@@ -1169,10 +1083,6 @@
             // 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).
@@ -1186,10 +1096,6 @@
             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]);
             }
@@ -1199,16 +1105,6 @@
             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;
@@ -1220,22 +1116,15 @@
     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;