Take two for r8466:
authorjvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 1 Apr 2013 20:06:51 +0000 (20:06 +0000)
committerjvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 1 Apr 2013 20:06:51 +0000 (20:06 +0000)
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@8468 2bbb7eff-a529-9590-31e7-b0007b416f81

21 files changed:
include/core/SkTArray.h
include/gpu/GrTypesPriv.h
src/gpu/GrAAConvexPathRenderer.cpp
src/gpu/GrAAHairLinePathRenderer.cpp
src/gpu/GrAARectRenderer.cpp
src/gpu/GrContext.cpp
src/gpu/GrDrawState.cpp
src/gpu/GrDrawState.h
src/gpu/GrDrawTarget.cpp
src/gpu/GrInOrderDrawBuffer.cpp
src/gpu/GrOvalRenderer.cpp
src/gpu/GrTextContext.cpp
src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLProgram.h
src/gpu/gl/GrGLProgramDesc.cpp
src/gpu/gl/GrGLProgramDesc.h
src/gpu/gl/GrGLSL.cpp
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGpuGL.cpp
src/gpu/gr_unittests.cpp
tests/GLProgramsTest.cpp

index 45808d4b609fb54f18187ace09d5d65c479853e5..bb5e57eada909ef4fcfeb4a20b3b4461b5bf6487 100644 (file)
@@ -111,6 +111,21 @@ public:
      */
     void reset() { this->pop_back_n(fCount); }
 
+    /**
+     * Resets to a copy of a C array.
+     */
+    void reset(const T* array, int count) {
+        for (int i = 0; i < fCount; ++i) {
+            fItemArray[i].~T();
+        }
+        int delta = count - fCount;
+        this->checkRealloc(delta);
+        fCount = count;
+        for (int i = 0; i < count; ++i) {
+            SkTArrayExt::copy(this, array);
+        }
+    }
+
     /**
      * Number of elements in the array.
      */
index ebe28dee0904dac8dbb6931ec760bb34fde218b8..b2bb765cd01d09a8717b12276643633bb8fc9917 100644 (file)
@@ -8,12 +8,12 @@
 #ifndef GrTypesPriv_DEFINED
 #define GrTypesPriv_DEFINED
 
+#include "GrTypes.h"
 #include "SkTArray.h"
 
 /**
- * Types of shader-language-specific boxed variables we can create.
- * (Currently only GrGLShaderVars, but should be applicable to other shader
- * languages.)
+ * Types of shader-language-specific boxed variables we can create. (Currently only GrGLShaderVars,
+ * but should be applicable to other shader languages.)
  */
 enum GrSLType {
     kVoid_GrSLType,
@@ -23,11 +23,43 @@ enum GrSLType {
     kVec4f_GrSLType,
     kMat33f_GrSLType,
     kMat44f_GrSLType,
-    kSampler2D_GrSLType
+    kSampler2D_GrSLType,
+
+    kLast_GrSLType = kSampler2D_GrSLType
 };
+static const int kGrSLTypeCount = kLast_GrSLType + 1;
+
+/**
+ * Gets the vector size of the SLType. Returns -1 for void, matrices, and samplers.
+ */
+static inline int GrSLTypeVectorCount(GrSLType type) {
+    GrAssert(type >= 0 && type < kGrSLTypeCount);
+    static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1 };
+    return kCounts[type];
+
+    GR_STATIC_ASSERT(0 == kVoid_GrSLType);
+    GR_STATIC_ASSERT(1 == kFloat_GrSLType);
+    GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
+    GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
+    GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
+    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrSLTypeCount);
+}
+
+static inline GrSLType GrSLFloatVectorType(int count) {
+    GrAssert(count > 0 && count <= 4);
+    return (GrSLType)(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);
+}
 
 /**
- * Types used to describe format of vertices in arrays
+ * Types used to describe format of vertices in arrays.
   */
 enum GrVertexAttribType {
     kFloat_GrVertexAttribType = 0,
@@ -40,20 +72,96 @@ enum GrVertexAttribType {
 };
 static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1;
 
+/**
+ * Returns the vector size of the type.
+ */
+static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) {
+    GrAssert(type >= 0 && type < kGrVertexAttribTypeCount);
+    static const int kCounts[] = { 1, 2, 3, 4, 4 };
+    return kCounts[type];
+
+    GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
+    GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
+    GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
+    GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
+    GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+    GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrVertexAttribTypeCount);
+}
+
+/**
+ * Returns the size of the attrib type in bytes.
+ */
+static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
+    GrAssert(type >= 0 && type < kGrVertexAttribTypeCount);
+    static const size_t kSizes[] = {
+        sizeof(float),          // kFloat_GrVertexAttribType
+        2*sizeof(float),        // kVec2f_GrVertexAttribType
+        3*sizeof(float),        // kVec3f_GrVertexAttribType
+        4*sizeof(float),        // kVec4f_GrVertexAttribType
+        4*sizeof(char)          // kVec4ub_GrVertexAttribType
+    };
+    return kSizes[type];
+
+    GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
+    GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
+    GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
+    GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
+    GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+    GR_STATIC_ASSERT(GR_ARRAY_COUNT(kSizes) == kGrVertexAttribTypeCount);
+}
+
+/**
+ * Semantic bindings for vertex attributes. kEffect means that the attribute is input to a GrEffect.
+ * Each binding other than kEffect may not appear more than once in the current set of attributes.
+ * kPosition must be appear for exactly one attribute.
+ */
+enum GrVertexAttribBinding {
+    kPosition_GrVertexAttribBinding,    // required, must have vector count of 2
+    kLocalCoord_GrVertexAttribBinding,  // must have vector count of 2
+    kColor_GrVertexAttribBinding,       // must have vector count of 4
+    kCoverage_GrVertexAttribBinding,    // must have vector count of 4
+
+    kLastFixedFunction_GrVertexAttribBinding = kCoverage_GrVertexAttribBinding,
+
+    kEffect_GrVertexAttribBinding,      // vector length must agree with
+                                        // GrEffect::vertexAttribType() for each effect input to
+                                        // which the attribute is mapped by GrDrawState::setEffect()
+    kLast_GrVertexAttribBinding = kEffect_GrVertexAttribBinding
+};
+
+static const int kGrVertexAttribBindingCnt = kLast_GrVertexAttribBinding + 1;
+static const int kGrFixedFunctionVertexAttribBindingCnt =
+    kLastFixedFunction_GrVertexAttribBinding + 1;
+
+static inline const int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) {
+    GrAssert(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt);
+    static const int kVecCounts[] = { 2, 2, 4, 4 };
+
+    return kVecCounts[binding];
+
+    GR_STATIC_ASSERT(0 == kPosition_GrVertexAttribBinding);
+    GR_STATIC_ASSERT(1 == kLocalCoord_GrVertexAttribBinding);
+    GR_STATIC_ASSERT(2 == kColor_GrVertexAttribBinding);
+    GR_STATIC_ASSERT(3 == kCoverage_GrVertexAttribBinding);
+    GR_STATIC_ASSERT(kGrFixedFunctionVertexAttribBindingCnt == SK_ARRAY_COUNT(kVecCounts));
+}
+
 struct GrVertexAttrib {
-    inline void set(GrVertexAttribType type, size_t offset) {
-        fType = type; fOffset = offset;
+    inline void set(GrVertexAttribType type, size_t offset, GrVertexAttribBinding binding) {
+        fType = type;
+        fOffset = offset;
+        fBinding = binding;
     }
     bool operator==(const GrVertexAttrib& other) const {
-        return fType == other.fType && fOffset == other.fOffset;
+        return fType == other.fType && fOffset == other.fOffset && fBinding == other.fBinding;
     };
     bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); }
 
-    GrVertexAttribType fType;
-    size_t             fOffset;
+    GrVertexAttribType      fType;
+    size_t                  fOffset;
+    GrVertexAttribBinding   fBinding;
 };
 
-template <int N>
-class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
+template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
 
 #endif
index 9f24190889def1b7736fde1eae589c431f2f0fc0..53c237b522b1b34471761c228c681a5e9e93aacd 100644 (file)
@@ -485,13 +485,10 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
 
     // position + edge
     static const GrVertexAttrib kAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
+        {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
+        {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
     };
-
     drawState->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-    drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
 
     enum {
         // the edge effects share this stage with glyph rendering
index 0c64a3b3b7511d27e030e843912fbf39d352448d..ffc9c50b2a3927341ecd9756d7bcb2ac765abc08 100644 (file)
@@ -507,8 +507,8 @@ bool GrAAHairLinePathRenderer::createGeom(
 
     // position + edge
     static const GrVertexAttrib kAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
+        {kVec2f_GrVertexAttribType, 0,                  kPosition_GrVertexAttribBinding},
+        {kVec4f_GrVertexAttribType, sizeof(GrPoint),    kEffect_GrVertexAttribBinding}
     };
     SkMatrix viewM = drawState->getViewMatrix();
 
@@ -522,8 +522,6 @@ bool GrAAHairLinePathRenderer::createGeom(
     int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
 
     target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
-    target->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-    target->drawState()->setAttribBindings(GrDrawState::kDefault_AttribBindings);
     GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
 
     if (!arg->set(target, vertCnt, 0)) {
index b4f02ba8cca7f10c8b6fd5c1f0e362e07c83e679..0093b08078ed472d54a9ed1830928b57c6612e81 100644 (file)
@@ -13,15 +13,17 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer)
 
 namespace {
 
-static void aa_rect_attributes(bool useCoverage, GrAttribBindings* bindings,
-                               GrDrawState::AttribIndex* index) {
-    if (useCoverage) {
-        *bindings = GrDrawState::kCoverage_AttribBindingsBit;
-        *index = GrDrawState::kCoverage_AttribIndex;
-    } else {
-        *bindings = GrDrawState::kColor_AttribBindingsBit;
-        *index = GrDrawState::kColor_AttribIndex;
-    }
+static void aa_rect_attributes(bool useCoverage, const GrVertexAttrib** attribs, int* count) {
+    static const GrVertexAttrib kCoverageAttribs[] = {
+        {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding},
+        {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
+    };
+    static const GrVertexAttrib kColorAttribs[] = {
+        {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding},
+        {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
+    };
+    *attribs = useCoverage ? kCoverageAttribs : kColorAttribs;
+    *count = 2;
 }
 
 static void set_inset_fan(GrPoint* pts, size_t stride,
@@ -128,18 +130,10 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu,
                                   bool useVertexCoverage) {
     GrDrawState* drawState = target->drawState();
 
-    // position + color/coverage
-    static const GrVertexAttrib kVertexAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec4ub_GrVertexAttribType, sizeof(GrPoint)}
-    };
-    GrAttribBindings bindings;
-    GrDrawState::AttribIndex attribIndex;
-    aa_rect_attributes(useVertexCoverage, &bindings, &attribIndex);
-    drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
-    drawState->setAttribBindings(bindings);
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-    drawState->setAttribIndex(attribIndex, 1);
+    const GrVertexAttrib* attribs;
+    int attribCount;
+    aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
+    drawState->setVertexAttribs(attribs, attribCount);
 
     GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
     if (!geo.succeeded()) {
@@ -212,18 +206,10 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
         return;
     }
 
-    // position + color/coverage
-    static const GrVertexAttrib kVertexAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec4ub_GrVertexAttribType, sizeof(GrPoint)}
-    };
-    GrAttribBindings bindings;
-    GrDrawState::AttribIndex attribIndex;
-    aa_rect_attributes(useVertexCoverage, &bindings, &attribIndex);
-    drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
-    drawState->setAttribBindings(bindings);
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-    drawState->setAttribIndex(attribIndex, 1);
+    const GrVertexAttrib* attribs;
+    int attribCount;
+    aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
+    drawState->setVertexAttribs(attribs, attribCount);
 
     GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
     if (!geo.succeeded()) {
index 32b4d6ae9c8cbdd9c6681df277511f2d46387e54..85b2c83384151a2c695e0da4320a09c13994a767 100644 (file)
@@ -358,17 +358,13 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
         GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
         drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
 
-        // position + texture coordinate
+        // position + local coordinate
         static const GrVertexAttrib kVertexAttribs[] = {
-            {kVec2f_GrVertexAttribType, 0},
-            {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
+            {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
+            {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
         };
-
-        static const GrAttribBindings kAttribBindings = GrDrawState::kLocalCoords_AttribBindingsBit;
-        drawState->setAttribBindings(kAttribBindings);
         drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
-        drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-        drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
+
         GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
 
         if (arg.succeeded()) {
@@ -925,19 +921,16 @@ void GrContext::drawVertices(const GrPaint& paint,
     GrVertexAttribArray<3> attribs;
     size_t currentOffset = 0;
     int colorOffset = -1, texOffset = -1;
-    GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings;
 
     // set position attribute
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count());
-    GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset};
+    GrVertexAttrib currAttrib =
+        {kVec2f_GrVertexAttribType, currentOffset, kPosition_GrVertexAttribBinding};
     attribs.push_back(currAttrib);
     currentOffset += sizeof(GrPoint);
 
     // set up optional texture coordinate attributes
     if (NULL != texCoords) {
-        bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
-        drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count());
-        currAttrib.set(kVec2f_GrVertexAttribType, currentOffset);
+        currAttrib.set(kVec2f_GrVertexAttribType, currentOffset, kLocalCoord_GrVertexAttribBinding);
         attribs.push_back(currAttrib);
         texOffset = currentOffset;
         currentOffset += sizeof(GrPoint);
@@ -945,16 +938,13 @@ void GrContext::drawVertices(const GrPaint& paint,
 
     // set up optional color attributes
     if (NULL != colors) {
-        bindings |= GrDrawState::kColor_AttribBindingsBit;
-        drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
-        currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset);
+        currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset, kColor_GrVertexAttribBinding);
         attribs.push_back(currAttrib);
         colorOffset = currentOffset;
         currentOffset += sizeof(GrColor);
     }
 
     drawState->setVertexAttribs(attribs.begin(), attribs.count());
-    drawState->setAttribBindings(bindings);
 
     size_t vertexSize = drawState->getVertexSize();
     GrAssert(vertexSize == currentOffset);
index f9e12cc2077cb54fb95de0ddc315dbeb9ef11e25..6d7969f024797b6a94fce235df4289c84c3e540c 100644 (file)
@@ -46,23 +46,15 @@ void GrDrawState::setFromPaint(const GrPaint& paint) {
 
 ////////////////////////////////////////////////////////////////////////////////
 
-const size_t GrDrawState::kVertexAttribSizes[kGrVertexAttribTypeCount] = {
-    sizeof(float),          // kFloat_GrVertexAttribType
-    2*sizeof(float),        // kVec2_GrVertexAttribType
-    3*sizeof(float),        // kVec3_GrVertexAttribType
-    4*sizeof(float),        // kVec4_GrVertexAttribType
-    4*sizeof(char)          // kCVec4_GrVertexAttribType
-};
-
 static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
     // this works as long as we're 4 byte-aligned
 #if GR_DEBUG
     uint32_t overlapCheck = 0;
 #endif
-    GrAssert(count <= GrDrawState::kVertexAttribCnt);
+    GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
     size_t size = 0;
     for (int index = 0; index < count; ++index) {
-        size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType];
+        size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
         size += attribSize;
 #if GR_DEBUG
         size_t dwordCount = attribSize >> 2;
@@ -76,163 +68,102 @@ static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
 }
 
 size_t GrDrawState::getVertexSize() const {
-    return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count());
+    return vertex_size(fCommon.fVertexAttribs.begin(), fCommon.fVertexAttribs.count());
 }
 
-const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = {
-    0,                            // position is not reflected in the bindings
-    kColor_AttribBindingsBit,
-    kCoverage_AttribBindingsBit,
-    kLocalCoords_AttribBindingsBit,
-};
-
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
-    GrAssert(count <= GrDrawState::kVertexAttribCnt);
-    fVertexAttribs.reset();
-    for (int index = 0; index < count; ++index) {
-        fVertexAttribs.push_back(attribs[index]);
+    GrAssert(count <= kMaxVertexAttribCnt);
+    fCommon.fVertexAttribs.reset(attribs, count);
+
+    // Set all the indices to -1
+    memset(fCommon.fFixedFunctionVertexAttribIndices,
+           0xff,
+           sizeof(fCommon.fFixedFunctionVertexAttribIndices));
+#if GR_DEBUG
+    uint32_t overlapCheck = 0;
+#endif
+    for (int i = 0; i < count; ++i) {
+        if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
+            // The fixed function attribs can only be specified once
+            GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
+            GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
+                     GrVertexAttribTypeVectorCount(attribs[i].fType));
+            fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
+        }
+#if GR_DEBUG
+        size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
+        uint32_t mask = (1 << dwordCount)-1;
+        size_t offsetShift = attribs[i].fOffset >> 2;
+        GrAssert(!(overlapCheck & (mask << offsetShift)));
+        overlapCheck |= (mask << offsetShift);
+#endif
     }
+    // Positions must be specified.
+    GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrDrawState::setDefaultVertexAttribs() {
-    static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0};
-    fVertexAttribs.reset();
-    fVertexAttribs.push_back(kPositionAttrib);
-
-    fCommon.fAttribBindings = kDefault_AttribBindings;
-
-    fAttribIndices[kPosition_AttribIndex] = 0;
+    static const GrVertexAttrib kPositionAttrib =
+        {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
+    fCommon.fVertexAttribs.reset(&kPositionAttrib, 1);
+    // set all the fixed function indices to -1 except position.
+    memset(fCommon.fFixedFunctionVertexAttribIndices,
+           0xff,
+           sizeof(fCommon.fFixedFunctionVertexAttribIndices));
+    fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 bool GrDrawState::validateVertexAttribs() const {
-    // color and coverage can set indices beyond the standard count
-    static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
-    int attributeTypes[kMaxValidAttribIndex];
-    for (int i = 0; i < kMaxValidAttribIndex; ++i) {
-        attributeTypes[i] = -1;
+    // check consistency of effects and attributes
+    GrSLType slTypes[kMaxVertexAttribCnt];
+    for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
+        slTypes[i] = static_cast<GrSLType>(-1);
     }
-
-    // sentinel to make sure effects don't try to use built-in attributes
-    static const int kBuiltInAttributeType = 10000;
-
-    // check our built-in indices
-    if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
-        return false;
-    }
-    attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
-    for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
-        if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
-            int attributeIndex = fAttribIndices[j];
-            if (attributeIndex >= kMaxValidAttribIndex) {
-                return false;
-            }
-            // they should not be shared at all
-            if (attributeTypes[attributeIndex] != -1) {
-                return false;
-            }
-            attributeTypes[attributeIndex] = kBuiltInAttributeType;
-        }
-    }
-    if (fCommon.fAttribBindings & kAttribIndexMasks[kLocalCoords_AttribIndex]) {
-        int attributeIndex = fAttribIndices[kLocalCoords_AttribIndex];
-        if (attributeIndex >= kVertexAttribCnt) {
-            return false;
-        }
-        // they should not be shared at all
-        if (attributeTypes[attributeIndex] != -1) {
-            return false;
-        }
-        attributeTypes[attributeIndex] = kBuiltInAttributeType;
-    }
-
-    // now those set by effects
     for (int s = 0; s < kNumStages; ++s) {
-        const GrEffectStage& stage = fStages[s];
-        const GrEffectRef* effect = stage.getEffect();
-        if (effect == NULL) {
-            continue;
-        }
-
-        // make sure that the count in the stage and the effect matches
-        int numAttributes = stage.getVertexAttribIndexCount();
-        if (numAttributes != effect->get()->numVertexAttribs()) {
-            return false;
-        }
-
-        // make sure that any shared indices have the same type
-        const int* attributeIndices = stage.getVertexAttribIndices();
-        for (int i = 0; i < numAttributes; ++i) {
-            int attributeIndex = attributeIndices[i];
-            if (attributeIndex >= kVertexAttribCnt) {
-                return false;
-            }
-
-            GrSLType attributeType = effect->get()->vertexAttribType(i);
-            if (attributeTypes[attributeIndex] != -1 &&
-                attributeTypes[attributeIndex] != attributeType) {
-                return false;
+        if (this->isStageEnabled(s)) {
+            const GrEffectStage& stage = fStages[s];
+            const GrEffectRef* effect = stage.getEffect();
+            // make sure that any attribute indices have the correct binding type, that the attrib
+            // type and effect's shader lang type are compatible, and that attributes shared by
+            // multiple effects use the same shader lang type.
+            const int* attributeIndices = stage.getVertexAttribIndices();
+            int numAttributes = stage.getVertexAttribIndexCount();
+            for (int i = 0; i < numAttributes; ++i) {
+                int attribIndex = attributeIndices[i];
+                if (attribIndex >= fCommon.fVertexAttribs.count() ||
+                    kEffect_GrVertexAttribBinding != fCommon.fVertexAttribs[attribIndex].fBinding) {
+                    return false;
+                }
+
+                GrSLType effectSLType = (*effect)->vertexAttribType(i);
+                GrVertexAttribType attribType = fCommon.fVertexAttribs[attribIndex].fType;
+                int slVecCount = GrSLTypeVectorCount(effectSLType);
+                int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
+                if (slVecCount != attribVecCount ||
+                    (-1 != slTypes[attribIndex] && slTypes[attribIndex] != effectSLType)) {
+                    return false;
+                }
+                slTypes[attribIndex] = effectSLType;
             }
-            attributeTypes[attributeIndex] = attributeType;
         }
     }
 
     return true;
 }
 
-
-void GrDrawState::VertexAttributesUnitTest() {
-    // not necessarily exhaustive
-    static bool run;
-    if (!run) {
-        run = true;
-
-        GrVertexAttribArray<6> attribs;
-        GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
-
-        GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
-        attribs.push_back(currAttrib);
-        GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
-        attribs[0].fType = kVec2f_GrVertexAttribType;
-        GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
-        attribs[0].fType = kVec3f_GrVertexAttribType;
-        GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
-        attribs[0].fType = kVec4f_GrVertexAttribType;
-        GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
-        attribs[0].fType = kVec4ub_GrVertexAttribType;
-        GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count()));
-
-        currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
-        attribs.push_back(currAttrib);
-        GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
-        currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
-        attribs.push_back(currAttrib);
-        GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
-                 vertex_size(attribs.begin(), attribs.count()));
-        currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
-        attribs.push_back(currAttrib);
-        GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
-                 vertex_size(attribs.begin(), attribs.count()));
-        currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
-        attribs.push_back(currAttrib);
-        GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
-                 vertex_size(attribs.begin(), attribs.count()));
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
-
+bool GrDrawState::srcAlphaWillBeOne() const {
     uint32_t validComponentFlags;
     GrColor color;
     // Check if per-vertex or constant color may have partial alpha
-    if (bindings & kColor_AttribBindingsBit) {
+    if (this->hasColorVertexAttribute()) {
         validComponentFlags = 0;
         color = 0; // not strictly necessary but we get false alarms from tools about uninit.
     } else {
@@ -278,7 +209,7 @@ bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
     return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
 }
 
-bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
+bool GrDrawState::hasSolidCoverage() const {
     // If we're drawing coverage directly then coverage is effectively treated as color.
     if (this->isCoverageDrawing()) {
         return true;
@@ -287,7 +218,7 @@ bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
     GrColor coverage;
     uint32_t validComponentFlags;
     // Initialize to an unknown starting coverage if per-vertex coverage is specified.
-    if (bindings & kCoverage_AttribBindingsBit) {
+    if (this->hasCoverageVertexAttribute()) {
         validComponentFlags = 0;
     } else {
         coverage = fCommon.fCoverage;
@@ -329,7 +260,6 @@ bool GrDrawState::canTweakAlphaForCoverage() const {
 GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
                                                      GrBlendCoeff* srcCoeff,
                                                      GrBlendCoeff* dstCoeff) const {
-    GrAttribBindings bindings = this->getAttribBindings();
 
     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
     if (NULL == srcCoeff) {
@@ -347,14 +277,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
         *dstCoeff = kOne_GrBlendCoeff;
     }
 
-    bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
+    bool srcAIsOne = this->srcAlphaWillBeOne();
     bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
                          (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
 
     bool covIsZero = !this->isCoverageDrawing() &&
-                     !(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
+                     !this->hasCoverageVertexAttribute() &&
                      0 == this->getCoverage();
     // When coeffs are (0,1) there is no reason to draw at all, unless
     // stenciling is enabled. Having color writes disabled is effectively
@@ -371,10 +301,8 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
     // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
     bool hasCoverage = forceCoverage ||
                        0xffffffff != this->getCoverage() ||
-                       (bindings & GrDrawState::kCoverage_AttribBindingsBit);
-    for (int s = this->getFirstCoverageStage();
-         !hasCoverage && s < GrDrawState::kNumStages;
-         ++s) {
+                       this->hasCoverageVertexAttribute();
+    for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
         if (this->isStageEnabled(s)) {
             hasCoverage = true;
         }
index d16efa893c97aa5ed46b5e63b1ac6548799a8b40..2f96c15671eb878ecbf7b4a6a34b8a64aa02ca68 100644 (file)
 #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 @@ public:
      * 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 @@ public:
     };
 
     GrDrawState() {
-#if GR_DEBUG
-        VertexAttributesUnitTest();
-#endif
         this->reset();
     }
 
@@ -115,53 +107,72 @@ public:
     ////
 
     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();
 
-    bool validateVertexAttribs() const;
+    /**
+     * 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.
+     */
 
-    ////////////////////////////////////////////////////////////////////////////
-    // Helpers for picking apart vertex attributes
+    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];
+    }
 
-    // helper array to let us check the expected so we know what bound attrib indices
-    // we care about
-    static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount];
+    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;
 
     /**
-     * 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 @@ public:
 
     /// @}
 
-    ///////////////////////////////////////////////////////////////////////////
-    /// @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 @@ public:
         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 @@ public:
     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 @@ private:
     /** 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 @@ public:
             // 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 @@ public:
             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 @@ public:
             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 @@ public:
     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;
index bc7d39e573a295032b48b7cb4cbd6753bd9510c0..ea7787153f877a10b3d9ac645cd54c1f3013f4f6 100644 (file)
@@ -615,18 +615,15 @@ void GrDrawTarget::drawRect(const GrRect& rect,
                             const SkMatrix* matrix,
                             const GrRect* localRect,
                             const SkMatrix* localMatrix) {
-    GrAttribBindings bindings = 0;
     // position + (optional) texture coord
     static const GrVertexAttrib kAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
+        {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
+        {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
     };
     int attribCount = 1;
 
     if (NULL != localRect) {
-        bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
         attribCount = 2;
-        this->drawState()->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
     }
 
     GrDrawState::AutoViewMatrixRestore avmr;
@@ -635,8 +632,6 @@ void GrDrawTarget::drawRect(const GrRect& rect,
     }
 
     this->drawState()->setVertexAttribs(kAttribs, attribCount);
-    this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-    this->drawState()->setAttribBindings(bindings);
     AutoReleaseGeometry geo(this, 4, 0);
     if (!geo.succeeded()) {
         GrPrintf("Failed to get space for vertices!\n");
index a090dcf823ea8ad78afd5f8ef5327f3972f7cbd3..8074f26a8739155d764b7ed316e1793e7ac1188d 100644 (file)
@@ -77,22 +77,21 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
                                    const SkMatrix* matrix,
                                    const GrRect* localRect,
                                    const SkMatrix* localMatrix) {
-
-    GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings;
     GrDrawState::AutoColorRestore acr;
 
     GrDrawState* drawState = this->drawState();
 
     GrColor color = drawState->getColor();
     GrVertexAttribArray<3> attribs;
-    size_t currentOffset = 0;
-    int colorOffset = -1, localOffset = -1;
 
     // set position attrib
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count());
-    GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset};
-    attribs.push_back(currAttrib);
-    currentOffset += sizeof(GrPoint);
+    static const GrVertexAttrib kPosAttrib =
+        {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
+    attribs.push_back(kPosAttrib);
+
+    size_t currentOffset = sizeof(GrPoint);
+    int colorOffset = -1;
+    int localOffset = -1;
 
     // Using per-vertex colors allows batching across colors. (A lot of rects in a row differing
     // only in color is a common occurrence in tables). However, having per-vertex colors disables
@@ -100,13 +99,11 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
     // optimizations help determine whether coverage and color can be blended correctly when
     // dual-source blending isn't available. This comes into play when there is coverage. If colors
     // were a stage it could take a hint that every vertex's color will be opaque.
-    if (this->caps()->dualSourceBlendingSupport() ||
-        drawState->hasSolidCoverage(drawState->getAttribBindings())) {
-        bindings |= GrDrawState::kColor_AttribBindingsBit;
-        drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
-        currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset);
-        attribs.push_back(currAttrib);
+    if (this->caps()->dualSourceBlendingSupport() || drawState->hasSolidCoverage()) {
         colorOffset = currentOffset;
+        GrVertexAttrib colorAttrib =
+            {kVec4ub_GrVertexAttribType, colorOffset, kColor_GrVertexAttribBinding};
+        attribs.push_back(colorAttrib);
         currentOffset += sizeof(GrColor);
         // We set the draw state's color to white here. This is done so that any batching performed
         // in our subclass's onDraw() won't get a false from GrDrawState::op== due to a color
@@ -116,16 +113,14 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
     }
 
     if (NULL != localRect) {
-        bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
-        drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count());
-        currAttrib.set(kVec2f_GrVertexAttribType, currentOffset);
-        attribs.push_back(currAttrib);
         localOffset = currentOffset;
+        GrVertexAttrib localCoordAttrib =
+            {kVec2f_GrVertexAttribType, localOffset, kLocalCoord_GrVertexAttribBinding};
+        attribs.push_back(localCoordAttrib);
         currentOffset += sizeof(GrPoint);
     }
 
     drawState->setVertexAttribs(attribs.begin(), attribs.count());
-    drawState->setAttribBindings(bindings);
     AutoReleaseGeometry geo(this, 4, 0);
     if (!geo.succeeded()) {
         GrPrintf("Failed to get space for vertices!\n");
index 8bc0428bdb789e04032eab67421af9591541e5c9..2955c756419df6bc730af26299a52aa15d9ededd 100644 (file)
@@ -85,11 +85,10 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
 
     // position + edge
     static const GrVertexAttrib kVertexAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
+        {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+        {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
     };
     drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
     GrAssert(sizeof(CircleVertex) == drawState->getVertexSize());
 
     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@@ -108,7 +107,6 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
         // (kPathMaskStage in GrSWMaskHelper)
         kEdgeEffectStage = GrPaint::kTotalStages,
     };
-    drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
 
     GrEffectRef* effect = GrCircleEdgeEffect::Create(isStroked);
     static const int kCircleEdgeAttrIndex = 1;
@@ -185,12 +183,11 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
 
     // position + edge
     static const GrVertexAttrib kVertexAttribs[] = {
-        {kVec2f_GrVertexAttribType, 0},
-        {kVec2f_GrVertexAttribType, sizeof(GrPoint)},
-        {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint)}
+        {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+        {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding},
+        {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding}
     };
     drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
-    drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
     GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize());
 
     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@@ -209,7 +206,6 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
         // (kPathMaskStage in GrSWMaskHelper)
         kEdgeEffectStage = GrPaint::kTotalStages,
     };
-    drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
 
     GrEffectRef* effect = GrEllipseEdgeEffect::Create(isStroked);
     static const int kEllipseCenterAttrIndex = 1;
index ab2bc424d6cc66e5e9f6f0c4b967c44040d268a5..58b3e92c61661221bf88634db9dfc5ed5526b4de 100644 (file)
@@ -194,10 +194,9 @@ HAS_ATLAS:
     if (NULL == fVertices) {
         // position + texture coord
         static const GrVertexAttrib kVertexAttribs[] = {
-            {kVec2f_GrVertexAttribType, 0},
-            {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
+            {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
+            {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
         };
-        static const GrAttribBindings kAttribBindings = 0;
 
        // If we need to reserve vertices allow the draw target to suggest
         // a number of verts to reserve and whether to perform a flush.
@@ -215,8 +214,6 @@ HAS_ATLAS:
             fDrawTarget = fContext->getTextTarget(fPaint);
             fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
         }
-        fDrawTarget->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
-        fDrawTarget->drawState()->setAttribBindings(kAttribBindings);
         fMaxVertices = kDefaultRequestedVerts;
         // ignore return, no point in flushing again.
         fDrawTarget->geometryHints(&fMaxVertices, NULL);
index cbaa7654408c0df06066924a9937477a2ff229fe..51cae5c8c81fce8804f4e015e3c46523ad7bffe1 100644 (file)
@@ -705,14 +705,17 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
     GL_CALL(BindAttribLocation(fProgramID,
                                fDesc.fPositionAttributeIndex,
                                builder.positionAttribute().c_str()));
-    GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
-    GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
-
-    if (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+    if (-1 != fDesc.fLocalCoordAttributeIndex) {
         GL_CALL(BindAttribLocation(fProgramID,
-                                   fDesc.fLocalCoordsAttributeIndex,
+                                   fDesc.fLocalCoordAttributeIndex,
                                    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();
@@ -826,8 +829,7 @@ void GrGLProgram::setData(GrGpuGL* gpu,
             const GrEffectStage& stage = drawState.getStage(s);
             GrAssert(NULL != stage.getEffect());
 
-            bool explicitLocalCoords =
-                (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit);
+            bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex;
             GrDrawEffect drawEffect(stage, explicitLocalCoords);
             fEffects[s]->setData(fUniformManager, drawEffect);
             int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count();
@@ -847,15 +849,18 @@ void GrGLProgram::setData(GrGpuGL* gpu,
 void GrGLProgram::setColor(const GrDrawState& drawState,
                            GrColor color,
                            SharedGLState* sharedState) {
-    if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) {
+    if (!drawState.hasColorVertexAttribute()) {
         switch (fDesc.fColorInput) {
             case GrGLProgramDesc::kAttribute_ColorInput:
-                if (sharedState->fConstAttribColor != color) {
+                GrAssert(-1 != fDesc.fColorAttributeIndex);
+                if (sharedState->fConstAttribColor != color ||
+                    sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) {
                     // 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:
@@ -868,28 +873,34 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
                     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.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) {
+    if (!drawState.hasCoverageVertexAttribute()) {
         switch (fDesc.fCoverageInput) {
             case GrGLProgramDesc::kAttribute_ColorInput:
-                if (sharedState->fConstAttribCoverage != coverage) {
+                if (sharedState->fConstAttribCoverage != coverage ||
+                    sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) {
                     // 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:
@@ -902,13 +913,17 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
                     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;
     }
 }
 
index 27b6f802f56cdfc9e28a7babf1a7d23926e95b28..4b5dfea69de9c03ecd9c0b69054b6566cf2edab6 100644 (file)
@@ -60,18 +60,23 @@ public:
     GrGLuint programID() const { return fProgramID; }
 
     /**
-     * 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.
+     * 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.
      */
     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;
         }
     };
 
index 6ed5473a39ef6f0161cdddbbf883d2c5708c9e01..73846b8df380371d1c74999fed985ea5e14f407d 100644 (file)
@@ -34,49 +34,42 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
     // 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 requiresAttributeColors =
-        !skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit);
-    bool requiresAttributeCoverage =
-        !skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit);
+    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();
 
     // 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) ||
-                             (!requiresAttributeColors && 0xffffffff == drawState.getColor());
+                             (!requiresColorAttrib && 0xffffffff == drawState.getColor());
     if (colorIsTransBlack) {
         desc->fColorInput = kTransBlack_ColorInput;
     } else if (colorIsSolidWhite) {
         desc->fColorInput = kSolidWhite_ColorInput;
-    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
+    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
         desc->fColorInput = kUniform_ColorInput;
     } else {
         desc->fColorInput = kAttribute_ColorInput;
     }
 
-    bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
+    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
 
     if (skipCoverage) {
         desc->fCoverageInput = kTransBlack_ColorInput;
     } else if (covIsSolidWhite) {
         desc->fCoverageInput = kSolidWhite_ColorInput;
-    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
+    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
         desc->fCoverageInput = kUniform_ColorInput;
     } else {
         desc->fCoverageInput = kAttribute_ColorInput;
@@ -92,9 +85,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
             lastEnabledStage = s;
             const GrEffectRef& effect = *drawState.getStage(s).getEffect();
             const GrBackendEffectFactory& factory = effect->getFactory();
-            bool explicitLocalCoords = (drawState.getAttribBindings() &
-                                        GrDrawState::kLocalCoords_AttribBindingsBit);
-            GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords);
+            GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
             desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
             if (effect->willReadDst()) {
                 readsDst = true;
@@ -139,7 +130,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
             firstCoverageStage = drawState.getFirstCoverageStage();
             hasCoverage = true;
         } else {
-            hasCoverage = requiresAttributeCoverage;
+            hasCoverage = requiresCoverageAttrib;
         }
     }
 
@@ -174,38 +165,27 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
         }
     }
 
-    desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex);
-    if (requiresAttributeColors) {
-        desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex);
+    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++;
     } else {
-        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);
+        desc->fColorAttributeIndex = -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);
+    if (requiresCoverageAttrib) {
+        desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
+    } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
+        GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
+        desc->fCoverageAttributeIndex = availableAttributeIndex;
+    } else {
+        desc->fCoverageAttributeIndex = -1;
     }
-#endif
 }
index df5729fb18bca0e40f48eb72f210ebee893915a0..a77ed716655d099c8779d828d926fb3dd6c709ce 100644 (file)
@@ -39,7 +39,8 @@ public:
     void setRandom(SkMWCRandom*,
                    const GrGpuGL* gpu,
                    const GrTexture* dummyDstTexture,
-                   const GrEffectStage stages[GrDrawState::kNumStages]);
+                   const GrEffectStage stages[GrDrawState::kNumStages],
+                   int currAttribIndex);
 
     /**
      * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
@@ -76,35 +77,34 @@ private:
         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).
index 570e61e53a57e536005bc2943e161a7b64ff56c9..3ec7fc45b215dd70b5ff45baffad2f8bbe780563 100644 (file)
@@ -67,15 +67,6 @@ bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, const char* nameIfDeclared, G
     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));
index 86cead41c35add12d09a94b558e8d87678623e3a..1104cd0cb71721969c5bdfd3352504598cd95407 100644 (file)
@@ -117,7 +117,7 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
 
     fPositionVar = &fVSAttrs.push_back();
     fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
-    if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+    if (-1 != desc.fLocalCoordAttributeIndex) {
         fLocalCoordsVar = &fVSAttrs.push_back();
         fLocalCoordsVar->set(kVec2f_GrSLType,
                              GrGLShaderVar::kAttribute_TypeModifier,
index d03ef781e18fed33f5d427667968d6fae6131561..d2996564f345120d920c7259f50f202c9c787ebd 100644 (file)
@@ -180,9 +180,7 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
 
     fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
 
-    GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
-    GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue);
-    GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue);
+    GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt);
 
     fLastSuccessfulStencilFmtIdx = 0;
     if (false) { // avoid bit rot, suppress warning
index ab5049a36a3281341e8c106c76a0332d9af71b9a..618d412bb5a8ff09606ff024cb13ebe5e96a42a0 100644 (file)
@@ -77,5 +77,4 @@ void gr_run_unittests() {
     GR_DEBUGCODE(test_bsearch();)
     test_binHashKey();
     GrRedBlackTree<int>::UnitTest();
-    GrDrawState::VertexAttributesUnitTest();
 }
index 512f89ecf201c5d4898db23dca6cae0b0340e6c3..675d0c1cb47f4ef023797af2cde04641e1be87c2 100644 (file)
 void GrGLProgramDesc::setRandom(SkMWCRandom* random,
                                 const GrGpuGL* gpu,
                                 const GrTexture* dstTexture,
-                                const GrEffectStage stages[GrDrawState::kNumStages]) {
-    fAttribBindings = 0;
+                                const GrEffectStage stages[GrDrawState::kNumStages],
+                                int currAttribIndex) {
     fEmitsPointSize = random->nextBool();
-    fColorInput = random->nextULessThan(kColorInputCnt);
-    fCoverageInput = random->nextULessThan(kColorInputCnt);
+
+    fPositionAttributeIndex = 0;
+
+    // if the effects have used up all off the available attributes, 
+    // don't try to use color or coverage attributes as input
+    do {
+        fColorInput = random->nextULessThan(kColorInputCnt);
+    } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex && 
+             kAttribute_ColorInput == fColorInput);
+    fColorAttributeIndex = (fColorInput == kAttribute_ColorInput) ? currAttribIndex++ : -1;
+
+    do {
+        fCoverageInput = random->nextULessThan(kColorInputCnt);
+    } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex  &&
+             kAttribute_ColorInput == fCoverageInput);
+    fCoverageAttributeIndex = (fCoverageInput == kAttribute_ColorInput) ? currAttribIndex++ : -1;
 
     fColorFilterXfermode = random->nextULessThan(SkXfermode::kCoeffModesCnt);
 
     fFirstCoverageStage = random->nextULessThan(GrDrawState::kNumStages);
 
-    fAttribBindings |= random->nextBool() ? GrDrawState::kCoverage_AttribBindingsBit : 0;
-
 #if GR_GL_EXPERIMENTAL_GS
     fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
 #endif
@@ -48,18 +60,14 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
         fDualSrcOutput = kNone_DualSrcOutput;
     }
 
-    // use separate tex coords?
-    if (random->nextBool()) {
-        fAttribBindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
-    }
+    bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
+    fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
 
     bool dstRead = false;
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         if (NULL != stages[s].getEffect()) {
             const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory();
-            bool explicitLocalCoords = (fAttribBindings &
-                                        GrDrawState::kLocalCoords_AttribBindingsBit);
-            GrDrawEffect drawEffect(stages[s], explicitLocalCoords);
+            GrDrawEffect drawEffect(stages[s], useLocalCoords);
             fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
             if ((*stages[s].getEffect())->willReadDst()) {
                 dstRead = true;
@@ -70,22 +78,6 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
     if (dstRead) {
         this->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstTexture, gpu->glCaps());
     }
-
-    int attributeIndex = 0;
-    fPositionAttributeIndex = attributeIndex;
-    ++attributeIndex;
-    if (fColorInput || (fAttribBindings & GrDrawState::kColor_AttribBindingsBit)) {
-        fColorAttributeIndex = attributeIndex;
-        ++attributeIndex;
-    }
-    if (fCoverageInput || (fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit)) {
-        fCoverageAttributeIndex = attributeIndex;
-        ++attributeIndex;
-    }
-    if (fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
-        fLocalCoordsAttributeIndex = attributeIndex;
-        ++attributeIndex;
-    }
 }
 
 bool GrGpuGL::programUnitTest(int maxStages) {
@@ -118,7 +110,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
         GrGLProgramDesc pdesc;
         GrEffectStage stages[GrDrawState::kNumStages];
 
-        int currAttribIndex = GrDrawState::kAttribIndexCount;
+        int currAttribIndex = 1;  // we need to always leave room for position
         int attribIndices[2];
         GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
         for (int s = 0; s < maxStages; ++s) {
@@ -131,10 +123,9 @@ bool GrGpuGL::programUnitTest(int maxStages) {
                                                                                 dummyTextures));
                 int numAttribs = (*effect)->numVertexAttribs();
 
-                // If adding this effect would cause to exceed the max attrib count then generate a
-                // new random effect. The explanation for why this check is correct is a bit
-                // convoluted and this code will be removed soon.
-                if (currAttribIndex + numAttribs > GrDrawState::kCoverageOverrideAttribIndexValue) {
+                // If adding this effect would exceed the max attrib count then generate a
+                // new random effect. 
+                if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
                     --s;
                     continue;
                 }
@@ -145,8 +136,8 @@ bool GrGpuGL::programUnitTest(int maxStages) {
             }
         }
         const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
-        pdesc.setRandom(&random, this, dstTexture, stages);
-
+        pdesc.setRandom(&random, this, dstTexture, stages, currAttribIndex);
         const GrEffectStage* stagePtrs[GrDrawState::kNumStages];
         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
             stagePtrs[s] = &stages[s];