From fb495b537f5ddd6966f02cfe38f6b106a4869934 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Mon, 1 Apr 2013 19:12:42 +0000 Subject: [PATCH] Revise attribute binding interface. Replace the old attribute binding and index interface with one where we include the binding as part of the attribute array. Also removed the fixed attribute indices for constant color and coverage attributes, and replaced with dynamic ones based on current attribute set. Removed binding of color and coverage attributes unless they're actually set. Original author: bsalomon@google.com Author: jvanverth@google.com Reviewed By: bsalomon@google.com,robertphillips@google.com Review URL: https://chromiumcodereview.appspot.com/13296005 git-svn-id: http://skia.googlecode.com/svn/trunk@8466 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkTArray.h | 15 ++ include/gpu/GrTypesPriv.h | 132 +++++++++++-- src/gpu/GrAAConvexPathRenderer.cpp | 7 +- src/gpu/GrAAHairLinePathRenderer.cpp | 6 +- src/gpu/GrAARectRenderer.cpp | 52 ++--- src/gpu/GrContext.cpp | 26 +-- src/gpu/GrDrawState.cpp | 218 +++++++-------------- src/gpu/GrDrawState.h | 279 ++++++++------------------- src/gpu/GrDrawTarget.cpp | 9 +- src/gpu/GrInOrderDrawBuffer.cpp | 33 ++-- src/gpu/GrOvalRenderer.cpp | 14 +- src/gpu/GrTextContext.cpp | 7 +- src/gpu/gl/GrGLProgram.cpp | 37 ++-- src/gpu/gl/GrGLProgram.h | 11 +- src/gpu/gl/GrGLProgramDesc.cpp | 80 +++----- src/gpu/gl/GrGLProgramDesc.h | 26 +-- src/gpu/gl/GrGLSL.cpp | 9 - src/gpu/gl/GrGLShaderBuilder.cpp | 2 +- src/gpu/gl/GrGpuGL.cpp | 4 +- src/gpu/gr_unittests.cpp | 1 - tests/GLProgramsTest.cpp | 63 +++--- 21 files changed, 452 insertions(+), 579 deletions(-) diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h index 45808d4b60..bb5e57eada 100644 --- a/include/core/SkTArray.h +++ b/include/core/SkTArray.h @@ -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. */ diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h index ebe28dee09..5a3c386763 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,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; /** - * Types used to describe format of vertices in arrays + * 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. */ 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 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 -class GrVertexAttribArray : public SkSTArray {}; +template class GrVertexAttribArray : public SkSTArray {}; #endif diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 9f24190889..53c237b522 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -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 diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index 0c64a3b3b7..ffc9c50b2a 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}, - {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)) { diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index b4f02ba8cc..0093b08078 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -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()) { diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 32b4d6ae9c..85b2c83384 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -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); diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index f9e12cc207..6d7969f024 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -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(-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; - } + 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; + } - // 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 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; } - - 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(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; } diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index d16efa893c..2f96c15671 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -23,11 +23,6 @@ #include "SkMatrix.h" #include "SkXfermode.h" -/** - * Type used to describe how attributes bind to program usage - */ -typedef int GrAttribBindings; - class GrDrawState : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrDrawState) @@ -45,8 +40,8 @@ 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(); + /** + * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the + * binding does not appear in the current attribs. These bindings should appear only once in + * the attrib array. + */ + + int positionAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]; + } + int localCoordAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + } + int colorVertexAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + } + int coverageVertexAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + } + + bool hasLocalCoordAttribute() const { + return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + } + bool hasColorVertexAttribute() const { + return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + } + bool hasCoverageVertexAttribute() const { + return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + } + bool validateVertexAttribs() const; - //////////////////////////////////////////////////////////////////////////// - // Helpers for picking apart vertex attributes - - // helper array to let us check the expected so we know what bound attrib indices - // we care about - static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount]; - /** - * Accessing positions, texture coords, or colors, of a vertex within an - * array is a hassle involving casts and simple math. These helpers exist - * to keep GrDrawTarget clients' code a bit nicer looking. + * Accessing positions, local coords, or colors, of a vertex within an array is a hassle + * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit + * nicer looking. */ /** @@ -218,110 +229,15 @@ 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 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 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 fRenderTarget; CommonState fCommon; - int fAttribIndices[kAttribIndexCount]; - GrVertexAttribArray fVertexAttribs; GrEffectStage fStages[kNumStages]; typedef GrRefCnt INHERITED; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index bc7d39e573..ea7787153f 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -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"); diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index a090dcf823..8074f26a87 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -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"); diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 8bc0428bdb..2955c75641 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -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; diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index ab2bc424d6..58b3e92c61 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -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); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index cbaa765440..51cae5c8c8 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -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; } } diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 27b6f802f5..4b5dfea69d 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -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; } }; diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 6ed5473a39..73846b8df3 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -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 (requiresCoverageAttrib) { + desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); + } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) { + GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); + desc->fCoverageAttributeIndex = availableAttributeIndex; + } else { + desc->fCoverageAttributeIndex = -1; } - 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 df5729fb18..a77ed71665 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -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). diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp index 570e61e53a..3ec7fc45b2 100644 --- a/src/gpu/gl/GrGLSL.cpp +++ b/src/gpu/gl/GrGLSL.cpp @@ -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)); diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index 86cead41c3..1104cd0cb7 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 (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { + if (-1 != desc.fLocalCoordAttributeIndex) { 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 d03ef781e1..d2996564f3 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -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 diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp index ab5049a36a..618d412bb5 100644 --- a/src/gpu/gr_unittests.cpp +++ b/src/gpu/gr_unittests.cpp @@ -77,5 +77,4 @@ void gr_run_unittests() { GR_DEBUGCODE(test_bsearch();) test_binHashKey(); GrRedBlackTree::UnitTest(); - GrDrawState::VertexAttributesUnitTest(); } diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 512f89ecf2..675d0c1cb4 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -24,18 +24,30 @@ 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];