diff options
author | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-01 19:29:32 +0000 |
---|---|---|
committer | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-01 19:29:32 +0000 |
commit | c7bf2963f00a29bd28e5e2a446da79f93c1d9383 (patch) | |
tree | 065de5e21129c28201547891d806bff2f60bb646 | |
parent | fb495b537f5ddd6966f02cfe38f6b106a4869934 (diff) |
Rolling back r8466.
Not reviewed.
git-svn-id: http://skia.googlecode.com/svn/trunk@8467 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkTArray.h | 15 | ||||
-rw-r--r-- | include/gpu/GrTypesPriv.h | 132 | ||||
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.cpp | 6 | ||||
-rw-r--r-- | src/gpu/GrAARectRenderer.cpp | 52 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 26 | ||||
-rw-r--r-- | src/gpu/GrDrawState.cpp | 220 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 277 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 9 | ||||
-rw-r--r-- | src/gpu/GrInOrderDrawBuffer.cpp | 33 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 14 | ||||
-rw-r--r-- | src/gpu/GrTextContext.cpp | 7 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 37 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDesc.cpp | 80 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDesc.h | 26 | ||||
-rw-r--r-- | src/gpu/gl/GrGLSL.cpp | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gr_unittests.cpp | 1 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 63 |
21 files changed, 579 insertions, 452 deletions
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h index bb5e57eada..45808d4b60 100644 --- a/include/core/SkTArray.h +++ b/include/core/SkTArray.h @@ -112,21 +112,6 @@ 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. */ int count() const { return fCount; } diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h index 5a3c386763..ebe28dee09 100644 --- a/include/gpu/GrTypesPriv.h +++ b/include/gpu/GrTypesPriv.h @@ -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,43 +23,11 @@ enum GrSLType { kVec4f_GrSLType, kMat33f_GrSLType, kMat44f_GrSLType, - kSampler2D_GrSLType, - - kLast_GrSLType = kSampler2D_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, @@ -72,96 +40,20 @@ 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 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, GrVertexAttribBinding binding) { - fType = type; - fOffset = offset; - fBinding = binding; + inline void set(GrVertexAttribType type, size_t offset) { + fType = type; fOffset = offset; } bool operator==(const GrVertexAttrib& other) const { - return fType == other.fType && fOffset == other.fOffset && fBinding == other.fBinding; + return fType == other.fType && fOffset == other.fOffset; }; bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); } - GrVertexAttribType fType; - size_t fOffset; - GrVertexAttribBinding fBinding; + GrVertexAttribType fType; + size_t fOffset; }; -template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {}; +template <int N> +class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {}; #endif diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 53c237b522..9f24190889 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -485,10 +485,13 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, // position + edge static const GrVertexAttrib kAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec4f_GrVertexAttribType, sizeof(GrPoint)} }; + 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 diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index ffc9c50b2a..0c64a3b3b7 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -507,8 +507,8 @@ bool GrAAHairLinePathRenderer::createGeom( // position + edge static const GrVertexAttrib kAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec4f_GrVertexAttribType, sizeof(GrPoint)} }; SkMatrix viewM = drawState->getViewMatrix(); @@ -522,6 +522,8 @@ 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)) { diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index 0093b08078..b4f02ba8cc 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -13,17 +13,15 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer) namespace { -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 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 set_inset_fan(GrPoint* pts, size_t stride, @@ -130,10 +128,18 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu, bool useVertexCoverage) { GrDrawState* drawState = target->drawState(); - const GrVertexAttrib* attribs; - int attribCount; - aa_rect_attributes(useVertexCoverage, &attribs, &attribCount); - drawState->setVertexAttribs(attribs, attribCount); + // 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); GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0); if (!geo.succeeded()) { @@ -206,10 +212,18 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu, return; } - const GrVertexAttrib* attribs; - int attribCount; - aa_rect_attributes(useVertexCoverage, &attribs, &attribCount); - drawState->setVertexAttribs(attribs, attribCount); + // 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); GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); if (!geo.succeeded()) { diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 85b2c83384..32b4d6ae9c 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -358,13 +358,17 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc, GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering); drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params); - // position + local coordinate + // position + texture coordinate static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec2f_GrVertexAttribType, sizeof(GrPoint)} }; - drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + 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()) { @@ -921,16 +925,19 @@ 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 - GrVertexAttrib currAttrib = - {kVec2f_GrVertexAttribType, currentOffset, kPosition_GrVertexAttribBinding}; + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count()); + GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset}; attribs.push_back(currAttrib); currentOffset += sizeof(GrPoint); // set up optional texture coordinate attributes if (NULL != texCoords) { - currAttrib.set(kVec2f_GrVertexAttribType, currentOffset, kLocalCoord_GrVertexAttribBinding); + bindings |= GrDrawState::kLocalCoords_AttribBindingsBit; + drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count()); + currAttrib.set(kVec2f_GrVertexAttribType, currentOffset); attribs.push_back(currAttrib); texOffset = currentOffset; currentOffset += sizeof(GrPoint); @@ -938,13 +945,16 @@ void GrContext::drawVertices(const GrPaint& paint, // set up optional color attributes if (NULL != colors) { - currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset, kColor_GrVertexAttribBinding); + bindings |= GrDrawState::kColor_AttribBindingsBit; + drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count()); + currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset); 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); diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 6d7969f024..f9e12cc207 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -46,15 +46,23 @@ 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::kMaxVertexAttribCnt); + GrAssert(count <= GrDrawState::kVertexAttribCnt); size_t size = 0; for (int index = 0; index < count; ++index) { - size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType); + size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType]; size += attribSize; #if GR_DEBUG size_t dwordCount = attribSize >> 2; @@ -68,102 +76,163 @@ static size_t vertex_size(const GrVertexAttrib* attribs, int count) { } size_t GrDrawState::getVertexSize() const { - return vertex_size(fCommon.fVertexAttribs.begin(), fCommon.fVertexAttribs.count()); + return vertex_size(fVertexAttribs.begin(), 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 <= 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 + GrAssert(count <= GrDrawState::kVertexAttribCnt); + fVertexAttribs.reset(); + for (int index = 0; index < count; ++index) { + fVertexAttribs.push_back(attribs[index]); } - // Positions must be specified. - GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]); } //////////////////////////////////////////////////////////////////////////////// void GrDrawState::setDefaultVertexAttribs() { - 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; + static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0}; + fVertexAttribs.reset(); + fVertexAttribs.push_back(kPositionAttrib); + + fCommon.fAttribBindings = kDefault_AttribBindings; + + fAttribIndices[kPosition_AttribIndex] = 0; } //////////////////////////////////////////////////////////////////////////////// bool GrDrawState::validateVertexAttribs() const { - // check consistency of effects and attributes - GrSLType slTypes[kMaxVertexAttribCnt]; - for (int i = 0; i < kMaxVertexAttribCnt; ++i) { - slTypes[i] = static_cast<GrSLType>(-1); + // 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; } + + // 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) { - 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; + 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; } + 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() const { +bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const { + uint32_t validComponentFlags; GrColor color; // Check if per-vertex or constant color may have partial alpha - if (this->hasColorVertexAttribute()) { + if (bindings & kColor_AttribBindingsBit) { validComponentFlags = 0; color = 0; // not strictly necessary but we get false alarms from tools about uninit. } else { @@ -209,7 +278,7 @@ bool GrDrawState::srcAlphaWillBeOne() const { return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color); } -bool GrDrawState::hasSolidCoverage() const { +bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const { // If we're drawing coverage directly then coverage is effectively treated as color. if (this->isCoverageDrawing()) { return true; @@ -218,7 +287,7 @@ bool GrDrawState::hasSolidCoverage() const { GrColor coverage; uint32_t validComponentFlags; // Initialize to an unknown starting coverage if per-vertex coverage is specified. - if (this->hasCoverageVertexAttribute()) { + if (bindings & kCoverage_AttribBindingsBit) { validComponentFlags = 0; } else { coverage = fCommon.fCoverage; @@ -260,6 +329,7 @@ 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) { @@ -277,14 +347,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, *dstCoeff = kOne_GrBlendCoeff; } - bool srcAIsOne = this->srcAlphaWillBeOne(); + bool srcAIsOne = this->srcAlphaWillBeOne(bindings); bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool covIsZero = !this->isCoverageDrawing() && - !this->hasCoverageVertexAttribute() && + !(bindings & GrDrawState::kCoverage_AttribBindingsBit) && 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 @@ -301,8 +371,10 @@ 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() || - this->hasCoverageVertexAttribute(); - for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) { + (bindings & GrDrawState::kCoverage_AttribBindingsBit); + for (int s = this->getFirstCoverageStage(); + !hasCoverage && s < GrDrawState::kNumStages; + ++s) { if (this->isStageEnabled(s)) { hasCoverage = true; } diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 2f96c15671..d16efa893c 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -23,6 +23,11 @@ #include "SkMatrix.h" #include "SkXfermode.h" +/** + * Type used to describe how attributes bind to program usage + */ +typedef int GrAttribBindings; + class GrDrawState : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrDrawState) @@ -40,8 +45,8 @@ 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. The input to the first coverage stage is either a constant coverage - * (usually full-coverage) or interpolated per-vertex coverage. + * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is + * either a constant coverage (usually full-coverage) or interpolated per-vertex coverage. * * See the documentation of kCoverageDrawing_StateBit for information about disabling the * the color / coverage distinction. @@ -57,6 +62,9 @@ public: }; GrDrawState() { +#if GR_DEBUG + VertexAttributesUnitTest(); +#endif this->reset(); } @@ -107,72 +115,53 @@ public: //// enum { - kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4, + kVertexAttribCnt = 6, }; /** - * The format of vertices is represented as an array of GrVertexAttribs, with each representing - * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in - * GrTypesPriv.h). + * The format of vertices is represented as an array of vertex attribute + * pair, with each pair representing the type of the attribute and the + * offset in the vertex structure (see GrVertexAttrib, above). * - * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when - * setEffect is called. + * This will only set up the vertex geometry. To bind the attributes in + * the shaders, attribute indices and attribute bindings need to be set + * as well. */ /** * Sets vertex attributes for next draw. * * @param attribs the array of vertex attributes to set. - * @param count the number of attributes being set, limited to kMaxVertexAttribCnt. + * @param count the number of attributes being set. + * limited to a count of kVertexAttribCnt. */ void setVertexAttribs(const GrVertexAttrib attribs[], int count); - const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVertexAttribs.begin(); } - int getVertexAttribCount() const { return fCommon.fVertexAttribs.count(); } + const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); } + int getVertexAttribCount() const { return fVertexAttribs.count(); } size_t getVertexSize() const; /** - * Sets default vertex attributes for next draw. The default is a single attribute: - * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType} + * Sets default vertex attributes for next draw. + * + * This will also set default vertex attribute indices and bindings */ void setDefaultVertexAttribs(); - /** - * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the - * binding does not appear in the current attribs. These bindings should appear only once in - * the attrib array. - */ - - int positionAttributeIndex() const { - return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]; - } - int localCoordAttributeIndex() const { - return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; - } - int colorVertexAttributeIndex() const { - return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; - } - int coverageVertexAttributeIndex() const { - return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; - } + bool validateVertexAttribs() const; - 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]; - } + //////////////////////////////////////////////////////////////////////////// + // Helpers for picking apart vertex attributes - bool validateVertexAttribs() const; + // helper array to let us check the expected so we know what bound attrib indices + // we care about + static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount]; /** - * Accessing positions, local coords, or colors, of a vertex within an array is a hassle - * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit - * nicer looking. + * Accessing positions, texture coords, or colors, of a vertex within an + * array is a hassle involving casts and simple math. These helpers exist + * to keep GrDrawTarget clients' code a bit nicer looking. */ /** @@ -229,15 +218,110 @@ 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() const; + bool srcAlphaWillBeOne(GrAttribBindings) const; /** * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw. */ - bool hasSolidCoverage() const; + bool hasSolidCoverage(GrAttribBindings) const; + + static void VertexAttributesUnitTest(); + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Vertex Attribute Indices + //// + + /** + * Vertex attribute indices map the data set in the vertex attribute array + * to the bindings specified in the attribute bindings. Each binding type + * has an associated index in the attribute array. This index is used to + * look up the vertex attribute data from the array, and potentially as the + * attribute index if we're binding attributes in GL. + * + * Indices which do not have active attribute bindings will be ignored. + */ + + enum AttribIndex { + kPosition_AttribIndex = 0, + kColor_AttribIndex, + kCoverage_AttribIndex, + kLocalCoords_AttribIndex, + + kLast_AttribIndex = kLocalCoords_AttribIndex + }; + static const int kAttribIndexCount = kLast_AttribIndex + 1; + + // these are used when vertex color and coverage isn't set + enum { + kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt, + kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1, + }; + + //////////////////////////////////////////////////////////////////////////// + // Helpers to set attribute indices. These should match the index in the + // current attribute index array. + + /** + * Sets index for next draw. This is used to look up the offset + * from the current vertex attribute array and to bind the attributes. + * + * @param index the attribute index we're setting + * @param value the value of the index + */ + void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; } + + int getAttribIndex(AttribIndex index) const { return fAttribIndices[index]; } /// @} @@ -984,6 +1068,15 @@ 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)) { @@ -1000,6 +1093,10 @@ 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]; @@ -1013,44 +1110,33 @@ 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; - SkMatrix fViewMatrix; - GrBlendCoeff fSrcBlend; - GrBlendCoeff fDstBlend; - GrColor fBlendConstant; - uint32_t fFlagBits; - GrVertexAttribArray<kMaxVertexAttribCnt> fVertexAttribs; - GrStencilSettings fStencilSettings; - int fFirstCoverageStage; - GrColor fCoverage; - SkXfermode::Mode fColorFilterMode; - GrColor fColorFilterColor; - DrawFace fDrawFace; - - // This is simply a different representation of info in fVertexAttribs and thus does - // not need to be compared in op==. - int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; - - GR_STATIC_ASSERT(kGrVertexAttribBindingCnt <= 8*sizeof(uint32_t)); - + GrColor fColor; + GrAttribBindings fAttribBindings; + SkMatrix fViewMatrix; + GrBlendCoeff fSrcBlend; + GrBlendCoeff fDstBlend; + GrColor fBlendConstant; + uint32_t fFlagBits; + GrStencilSettings fStencilSettings; + int fFirstCoverageStage; + GrColor fCoverage; + SkXfermode::Mode fColorFilterMode; + GrColor fColorFilterColor; + DrawFace fDrawFace; bool operator== (const CommonState& other) const { - bool result = fColor == other.fColor && - fViewMatrix.cheapEqualTo(other.fViewMatrix) && - fSrcBlend == other.fSrcBlend && - fDstBlend == other.fDstBlend && - fBlendConstant == other.fBlendConstant && - fFlagBits == other.fFlagBits && - fVertexAttribs == other.fVertexAttribs && - fStencilSettings == other.fStencilSettings && - fFirstCoverageStage == other.fFirstCoverageStage && - fCoverage == other.fCoverage && - fColorFilterMode == other.fColorFilterMode && - fColorFilterColor == other.fColorFilterColor && - fDrawFace == other.fDrawFace; - GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices, - other.fFixedFunctionVertexAttribIndices, - sizeof(fFixedFunctionVertexAttribIndices))); - return result; + return fColor == other.fColor && + fAttribBindings == other.fAttribBindings && + fViewMatrix.cheapEqualTo(other.fViewMatrix) && + fSrcBlend == other.fSrcBlend && + fDstBlend == other.fDstBlend && + fBlendConstant == other.fBlendConstant && + fFlagBits == other.fFlagBits && + fStencilSettings == other.fStencilSettings && + fFirstCoverageStage == other.fFirstCoverageStage && + fCoverage == other.fCoverage && + fColorFilterMode == other.fColorFilterMode && + fColorFilterColor == other.fColorFilterColor && + fDrawFace == other.fDrawFace; } bool operator!= (const CommonState& other) const { return !(*this == other); } }; @@ -1083,6 +1169,10 @@ 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). @@ -1096,6 +1186,10 @@ 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]); } @@ -1105,6 +1199,16 @@ 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; @@ -1116,15 +1220,22 @@ 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; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index ea7787153f..bc7d39e573 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -615,15 +615,18 @@ 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, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec2f_GrVertexAttribType, sizeof(GrPoint)} }; int attribCount = 1; if (NULL != localRect) { + bindings |= GrDrawState::kLocalCoords_AttribBindingsBit; attribCount = 2; + this->drawState()->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1); } GrDrawState::AutoViewMatrixRestore avmr; @@ -632,6 +635,8 @@ 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"); diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 8074f26a87..a090dcf823 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -77,21 +77,22 @@ 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 - static const GrVertexAttrib kPosAttrib = - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}; - attribs.push_back(kPosAttrib); - - size_t currentOffset = sizeof(GrPoint); - int colorOffset = -1; - int localOffset = -1; + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count()); + GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset}; + attribs.push_back(currAttrib); + currentOffset += sizeof(GrPoint); // 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 @@ -99,11 +100,13 @@ 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()) { + 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); 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 @@ -113,14 +116,16 @@ 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"); diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 2955c75641..8bc0428bdb 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -85,10 +85,11 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, // position + edge static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec4f_GrVertexAttribType, sizeof(GrPoint)} }; drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); GrAssert(sizeof(CircleVertex) == drawState->getVertexSize()); GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); @@ -107,6 +108,7 @@ 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; @@ -183,11 +185,12 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target, // position + edge static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec2f_GrVertexAttribType, sizeof(GrPoint)}, + {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint)} }; drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize()); GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); @@ -206,6 +209,7 @@ 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; diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index 58b3e92c61..ab2bc424d6 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -194,9 +194,10 @@ HAS_ATLAS: if (NULL == fVertices) { // position + texture coord static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} + {kVec2f_GrVertexAttribType, 0}, + {kVec2f_GrVertexAttribType, sizeof(GrPoint)} }; + 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. @@ -214,6 +215,8 @@ 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); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 51cae5c8c8..cbaa765440 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -705,17 +705,14 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil GL_CALL(BindAttribLocation(fProgramID, fDesc.fPositionAttributeIndex, builder.positionAttribute().c_str())); - if (-1 != fDesc.fLocalCoordAttributeIndex) { + GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME)); + GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME)); + + if (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { GL_CALL(BindAttribLocation(fProgramID, - fDesc.fLocalCoordAttributeIndex, + fDesc.fLocalCoordsAttributeIndex, builder.localCoordsAttribute().c_str())); } - if (-1 != fDesc.fColorAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME)); - } - if (-1 != fDesc.fCoverageAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME)); - } const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end(); for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin(); @@ -829,7 +826,8 @@ void GrGLProgram::setData(GrGpuGL* gpu, const GrEffectStage& stage = drawState.getStage(s); GrAssert(NULL != stage.getEffect()); - bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex; + bool explicitLocalCoords = + (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit); GrDrawEffect drawEffect(stage, explicitLocalCoords); fEffects[s]->setData(fUniformManager, drawEffect); int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count(); @@ -849,18 +847,15 @@ void GrGLProgram::setData(GrGpuGL* gpu, void GrGLProgram::setColor(const GrDrawState& drawState, GrColor color, SharedGLState* sharedState) { - if (!drawState.hasColorVertexAttribute()) { + if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) { switch (fDesc.fColorInput) { case GrGLProgramDesc::kAttribute_ColorInput: - GrAssert(-1 != fDesc.fColorAttributeIndex); - if (sharedState->fConstAttribColor != color || - sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) { + if (sharedState->fConstAttribColor != color) { // OpenGL ES only supports the float varieties of glVertexAttrib GrGLfloat c[4]; GrColorToRGBAFloat(color, c); GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c)); sharedState->fConstAttribColor = color; - sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex; } break; case GrGLProgramDesc::kUniform_ColorInput: @@ -873,34 +868,28 @@ 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.hasCoverageVertexAttribute()) { + if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) { switch (fDesc.fCoverageInput) { case GrGLProgramDesc::kAttribute_ColorInput: - if (sharedState->fConstAttribCoverage != coverage || - sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) { + if (sharedState->fConstAttribCoverage != coverage) { // OpenGL ES only supports the float varieties of glVertexAttrib GrGLfloat c[4]; GrColorToRGBAFloat(coverage, c); GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c)); sharedState->fConstAttribCoverage = coverage; - sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex; } break; case GrGLProgramDesc::kUniform_ColorInput: @@ -913,17 +902,13 @@ 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; } } diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 4b5dfea69d..27b6f802f5 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -60,23 +60,18 @@ public: GrGLuint programID() const { return fProgramID; } /** - * Some GL state that is relevant to programs is not stored per-program. In particular color - * and coverage attributes can be global state. This struct is read and updated by - * GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state - * redundantly. + * Some GL state that is relevant to programs is not stored per-program. In particular vertex + * attributes are global state. This struct is read and updated by GrGLProgram::setData to + * allow us to avoid setting this state redundantly. */ struct SharedGLState { GrColor fConstAttribColor; - int fConstAttribColorIndex; GrColor fConstAttribCoverage; - int fConstAttribCoverageIndex; SharedGLState() { this->invalidate(); } void invalidate() { fConstAttribColor = GrColor_ILLEGAL; - fConstAttribColorIndex = -1; fConstAttribCoverage = GrColor_ILLEGAL; - fConstAttribCoverageIndex = -1; } }; diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 73846b8df3..6ed5473a39 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -34,42 +34,49 @@ 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 requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute(); - bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute(); - // we only need the local coords if we're actually going to generate effect code - bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) && - drawState.hasLocalCoordAttribute(); + bool requiresAttributeColors = + !skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit); + bool requiresAttributeCoverage = + !skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit); // fColorInput/fCoverageInput records how colors are specified for the program so we strip the // bits from the bindings to avoid false negatives when searching for an existing program in the // cache. + desc->fAttribBindings &= + ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit); desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode(); + // no reason to do edge aa or look at per-vertex coverage if coverage is ignored + if (skipCoverage) { + desc->fAttribBindings &= ~(GrDrawState::kCoverage_AttribBindingsBit); + } bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) || - (!requiresColorAttrib && 0xffffffff == drawState.getColor()); + (!requiresAttributeColors && 0xffffffff == drawState.getColor()); if (colorIsTransBlack) { desc->fColorInput = kTransBlack_ColorInput; } else if (colorIsSolidWhite) { desc->fColorInput = kSolidWhite_ColorInput; - } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) { + } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { desc->fColorInput = kUniform_ColorInput; } else { desc->fColorInput = kAttribute_ColorInput; } - bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage(); + bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage(); if (skipCoverage) { desc->fCoverageInput = kTransBlack_ColorInput; } else if (covIsSolidWhite) { desc->fCoverageInput = kSolidWhite_ColorInput; - } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) { + } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { desc->fCoverageInput = kUniform_ColorInput; } else { desc->fCoverageInput = kAttribute_ColorInput; @@ -85,7 +92,9 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, lastEnabledStage = s; const GrEffectRef& effect = *drawState.getStage(s).getEffect(); const GrBackendEffectFactory& factory = effect->getFactory(); - GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib); + bool explicitLocalCoords = (drawState.getAttribBindings() & + GrDrawState::kLocalCoords_AttribBindingsBit); + GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords); desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps()); if (effect->willReadDst()) { readsDst = true; @@ -130,7 +139,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, firstCoverageStage = drawState.getFirstCoverageStage(); hasCoverage = true; } else { - hasCoverage = requiresCoverageAttrib; + hasCoverage = requiresAttributeCoverage; } } @@ -165,27 +174,38 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, } } - desc->fPositionAttributeIndex = drawState.positionAttributeIndex(); - desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); - - // For constant color and coverage we need an attribute with an index beyond those already set - int availableAttributeIndex = drawState.getVertexAttribCount(); - if (requiresColorAttrib) { - desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); - } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) { - GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); - desc->fColorAttributeIndex = availableAttributeIndex; - availableAttributeIndex++; + desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex); + if (requiresAttributeColors) { + desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex); } else { - desc->fColorAttributeIndex = -1; + desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue; } - - if (requiresCoverageAttrib) { - desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); - } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) { - GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); - desc->fCoverageAttributeIndex = availableAttributeIndex; + if (requiresAttributeCoverage) { + desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex); } else { - desc->fCoverageAttributeIndex = -1; + desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue; } + if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { + desc->fLocalCoordsAttributeIndex = drawState.getAttribIndex(GrDrawState::kLocalCoords_AttribIndex); + } + +#if GR_DEBUG + // Verify valid vertex attribute state. These assertions should probably be done somewhere + // higher up the callstack + const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs(); + GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fPositionAttributeIndex].fType).fCount == 2); + if (requiresAttributeColors) { + GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fColorAttributeIndex].fType).fCount == 4); + } + if (requiresAttributeCoverage) { + GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4); + } + if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { + GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2); + } +#endif } diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index a77ed71665..df5729fb18 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -39,8 +39,7 @@ public: void setRandom(SkMWCRandom*, const GrGpuGL* gpu, const GrTexture* dummyDstTexture, - const GrEffectStage stages[GrDrawState::kNumStages], - int currAttribIndex); + const GrEffectStage stages[GrDrawState::kNumStages]); /** * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the @@ -77,34 +76,35 @@ 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). diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp index 3ec7fc45b2..570e61e53a 100644 --- a/src/gpu/gl/GrGLSL.cpp +++ b/src/gpu/gl/GrGLSL.cpp @@ -67,6 +67,15 @@ 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)); diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index 1104cd0cb7..86cead41c3 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -117,7 +117,7 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, fPositionVar = &fVSAttrs.push_back(); fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); - if (-1 != desc.fLocalCoordAttributeIndex) { + if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { fLocalCoordsVar = &fVSAttrs.push_back(); fLocalCoordsVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index d2996564f3..d03ef781e1 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -180,7 +180,9 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context) fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext())); - GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt); + GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt); + GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue); + GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue); fLastSuccessfulStencilFmtIdx = 0; if (false) { // avoid bit rot, suppress warning diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp index 618d412bb5..ab5049a36a 100644 --- a/src/gpu/gr_unittests.cpp +++ b/src/gpu/gr_unittests.cpp @@ -77,4 +77,5 @@ void gr_run_unittests() { GR_DEBUGCODE(test_bsearch();) test_binHashKey(); GrRedBlackTree<int>::UnitTest(); + GrDrawState::VertexAttributesUnitTest(); } diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 675d0c1cb4..512f89ecf2 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -24,30 +24,18 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random, const GrGpuGL* gpu, const GrTexture* dstTexture, - const GrEffectStage stages[GrDrawState::kNumStages], - int currAttribIndex) { + const GrEffectStage stages[GrDrawState::kNumStages]) { + fAttribBindings = 0; fEmitsPointSize = random->nextBool(); - - 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; + fColorInput = random->nextULessThan(kColorInputCnt); + fCoverageInput = random->nextULessThan(kColorInputCnt); 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 @@ -60,14 +48,18 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random, fDualSrcOutput = kNone_DualSrcOutput; } - bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt; - fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1; + // use separate tex coords? + if (random->nextBool()) { + fAttribBindings |= GrDrawState::kLocalCoords_AttribBindingsBit; + } bool dstRead = false; for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (NULL != stages[s].getEffect()) { const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory(); - GrDrawEffect drawEffect(stages[s], useLocalCoords); + bool explicitLocalCoords = (fAttribBindings & + GrDrawState::kLocalCoords_AttribBindingsBit); + GrDrawEffect drawEffect(stages[s], explicitLocalCoords); fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps()); if ((*stages[s].getEffect())->willReadDst()) { dstRead = true; @@ -78,6 +70,22 @@ 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) { @@ -110,7 +118,7 @@ bool GrGpuGL::programUnitTest(int maxStages) { GrGLProgramDesc pdesc; GrEffectStage stages[GrDrawState::kNumStages]; - int currAttribIndex = 1; // we need to always leave room for position + int currAttribIndex = GrDrawState::kAttribIndexCount; int attribIndices[2]; GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; for (int s = 0; s < maxStages; ++s) { @@ -123,9 +131,10 @@ bool GrGpuGL::programUnitTest(int maxStages) { dummyTextures)); int numAttribs = (*effect)->numVertexAttribs(); - // If adding this effect would exceed the max attrib count then generate a - // new random effect. - if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) { + // 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) { --s; continue; } @@ -136,8 +145,8 @@ bool GrGpuGL::programUnitTest(int maxStages) { } } const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1]; - pdesc.setRandom(&random, this, dstTexture, stages, currAttribIndex); - + pdesc.setRandom(&random, this, dstTexture, stages); + const GrEffectStage* stagePtrs[GrDrawState::kNumStages]; for (int s = 0; s < GrDrawState::kNumStages; ++s) { stagePtrs[s] = &stages[s]; |