diff options
-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, 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 @@ -112,6 +112,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. */ int count() const { return fCount; } diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h index ebe28dee09..b2bb765cd0 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; + +/** + * Gets the vector size of the SLType. Returns -1 for void, matrices, and samplers. + */ +static inline int GrSLTypeVectorCount(GrSLType type) { + GrAssert(type >= 0 && type < kGrSLTypeCount); + static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1 }; + return kCounts[type]; + + GR_STATIC_ASSERT(0 == kVoid_GrSLType); + GR_STATIC_ASSERT(1 == kFloat_GrSLType); + GR_STATIC_ASSERT(2 == kVec2f_GrSLType); + GR_STATIC_ASSERT(3 == kVec3f_GrSLType); + GR_STATIC_ASSERT(4 == kVec4f_GrSLType); + GR_STATIC_ASSERT(5 == kMat33f_GrSLType); + GR_STATIC_ASSERT(6 == kMat44f_GrSLType); + GR_STATIC_ASSERT(7 == kSampler2D_GrSLType); + GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrSLTypeCount); +} + +static inline GrSLType GrSLFloatVectorType(int count) { + GrAssert(count > 0 && count <= 4); + return (GrSLType)(count); + + GR_STATIC_ASSERT(kFloat_GrSLType == 1); + GR_STATIC_ASSERT(kVec2f_GrSLType == 2); + GR_STATIC_ASSERT(kVec3f_GrSLType == 3); + GR_STATIC_ASSERT(kVec4f_GrSLType == 4); +} /** - * Types used to describe format of vertices in arrays + * Types used to describe format of vertices in arrays. */ enum GrVertexAttribType { kFloat_GrVertexAttribType = 0, @@ -40,20 +72,96 @@ enum GrVertexAttribType { }; static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1; +/** + * Returns the vector size of the type. + */ +static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) { + GrAssert(type >= 0 && type < kGrVertexAttribTypeCount); + static const int kCounts[] = { 1, 2, 3, 4, 4 }; + return kCounts[type]; + + GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); + GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); + GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); + GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); + GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType); + GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrVertexAttribTypeCount); +} + +/** + * Returns the size of the attrib type in bytes. + */ +static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) { + GrAssert(type >= 0 && type < kGrVertexAttribTypeCount); + static const size_t kSizes[] = { + sizeof(float), // kFloat_GrVertexAttribType + 2*sizeof(float), // kVec2f_GrVertexAttribType + 3*sizeof(float), // kVec3f_GrVertexAttribType + 4*sizeof(float), // kVec4f_GrVertexAttribType + 4*sizeof(char) // kVec4ub_GrVertexAttribType + }; + return kSizes[type]; + + GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); + GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); + GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); + GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); + GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType); + GR_STATIC_ASSERT(GR_ARRAY_COUNT(kSizes) == kGrVertexAttribTypeCount); +} + +/** + * Semantic bindings for vertex attributes. kEffect means that the attribute is input to a GrEffect. + * Each binding other than kEffect may not appear more than once in the current set of attributes. + * kPosition must be appear for exactly one attribute. + */ +enum GrVertexAttribBinding { + kPosition_GrVertexAttribBinding, // required, must have vector count of 2 + kLocalCoord_GrVertexAttribBinding, // must have vector count of 2 + kColor_GrVertexAttribBinding, // must have vector count of 4 + kCoverage_GrVertexAttribBinding, // must have vector count of 4 + + kLastFixedFunction_GrVertexAttribBinding = kCoverage_GrVertexAttribBinding, + + kEffect_GrVertexAttribBinding, // vector length must agree with + // GrEffect::vertexAttribType() for each effect input to + // which the attribute is mapped by GrDrawState::setEffect() + kLast_GrVertexAttribBinding = kEffect_GrVertexAttribBinding +}; + +static const int kGrVertexAttribBindingCnt = kLast_GrVertexAttribBinding + 1; +static const int kGrFixedFunctionVertexAttribBindingCnt = + kLastFixedFunction_GrVertexAttribBinding + 1; + +static inline const int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) { + GrAssert(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt); + static const int kVecCounts[] = { 2, 2, 4, 4 }; + + return kVecCounts[binding]; + + GR_STATIC_ASSERT(0 == kPosition_GrVertexAttribBinding); + GR_STATIC_ASSERT(1 == kLocalCoord_GrVertexAttribBinding); + GR_STATIC_ASSERT(2 == kColor_GrVertexAttribBinding); + GR_STATIC_ASSERT(3 == kCoverage_GrVertexAttribBinding); + GR_STATIC_ASSERT(kGrFixedFunctionVertexAttribBindingCnt == SK_ARRAY_COUNT(kVecCounts)); +} + struct GrVertexAttrib { - inline void set(GrVertexAttribType type, size_t offset) { - fType = type; fOffset = offset; + inline void set(GrVertexAttribType type, size_t offset, GrVertexAttribBinding binding) { + fType = type; + fOffset = offset; + fBinding = binding; } bool operator==(const GrVertexAttrib& other) const { - return fType == other.fType && fOffset == other.fOffset; + return fType == other.fType && fOffset == other.fOffset && fBinding == other.fBinding; }; bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); } - GrVertexAttribType fType; - size_t fOffset; + GrVertexAttribType fType; + size_t fOffset; + GrVertexAttribBinding fBinding; }; -template <int N> -class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {}; +template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {}; #endif 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<GrSLType>(-1); } - - // sentinel to make sure effects don't try to use built-in attributes - static const int kBuiltInAttributeType = 10000; - - // check our built-in indices - if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) { - return false; - } - attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType; - for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) { - if (fCommon.fAttribBindings & kAttribIndexMasks[j]) { - int attributeIndex = fAttribIndices[j]; - if (attributeIndex >= kMaxValidAttribIndex) { - return false; - } - // they should not be shared at all - if (attributeTypes[attributeIndex] != -1) { - return false; - } - attributeTypes[attributeIndex] = kBuiltInAttributeType; - } - } - if (fCommon.fAttribBindings & kAttribIndexMasks[kLocalCoords_AttribIndex]) { - int attributeIndex = fAttribIndices[kLocalCoords_AttribIndex]; - if (attributeIndex >= kVertexAttribCnt) { - return false; - } - // they should not be shared at all - if (attributeTypes[attributeIndex] != -1) { - return false; - } - attributeTypes[attributeIndex] = kBuiltInAttributeType; - } - - // now those set by effects for (int s = 0; s < kNumStages; ++s) { - const GrEffectStage& stage = fStages[s]; - const GrEffectRef* effect = stage.getEffect(); - if (effect == NULL) { - continue; - } - - // make sure that the count in the stage and the effect matches - int numAttributes = stage.getVertexAttribIndexCount(); - if (numAttributes != effect->get()->numVertexAttribs()) { - return false; - } - - // make sure that any shared indices have the same type - const int* attributeIndices = stage.getVertexAttribIndices(); - for (int i = 0; i < numAttributes; ++i) { - int attributeIndex = attributeIndices[i]; - if (attributeIndex >= kVertexAttribCnt) { - return false; - } - - GrSLType attributeType = effect->get()->vertexAttribType(i); - if (attributeTypes[attributeIndex] != -1 && - attributeTypes[attributeIndex] != attributeType) { - return false; + if (this->isStageEnabled(s)) { + const GrEffectStage& stage = fStages[s]; + const GrEffectRef* effect = stage.getEffect(); + // make sure that any attribute indices have the correct binding type, that the attrib + // type and effect's shader lang type are compatible, and that attributes shared by + // multiple effects use the same shader lang type. + const int* attributeIndices = stage.getVertexAttribIndices(); + int numAttributes = stage.getVertexAttribIndexCount(); + for (int i = 0; i < numAttributes; ++i) { + int attribIndex = attributeIndices[i]; + if (attribIndex >= fCommon.fVertexAttribs.count() || + kEffect_GrVertexAttribBinding != fCommon.fVertexAttribs[attribIndex].fBinding) { + return false; + } + + GrSLType effectSLType = (*effect)->vertexAttribType(i); + GrVertexAttribType attribType = fCommon.fVertexAttribs[attribIndex].fType; + int slVecCount = GrSLTypeVectorCount(effectSLType); + int attribVecCount = GrVertexAttribTypeVectorCount(attribType); + if (slVecCount != attribVecCount || + (-1 != slTypes[attribIndex] && slTypes[attribIndex] != effectSLType)) { + return false; + } + slTypes[attribIndex] = effectSLType; } - attributeTypes[attributeIndex] = attributeType; } } return true; } - -void GrDrawState::VertexAttributesUnitTest() { - // not necessarily exhaustive - static bool run; - if (!run) { - run = true; - - GrVertexAttribArray<6> attribs; - GrAssert(0 == vertex_size(attribs.begin(), attribs.count())); - - GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0}; - attribs.push_back(currAttrib); - GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count())); - attribs[0].fType = kVec2f_GrVertexAttribType; - GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); - attribs[0].fType = kVec3f_GrVertexAttribType; - GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); - attribs[0].fType = kVec4f_GrVertexAttribType; - GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); - attribs[0].fType = kVec4ub_GrVertexAttribType; - GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count())); - - currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char)); - attribs.push_back(currAttrib); - GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); - currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float)); - attribs.push_back(currAttrib); - GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) == - vertex_size(attribs.begin(), attribs.count())); - currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float)); - attribs.push_back(currAttrib); - GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) == - vertex_size(attribs.begin(), attribs.count())); - currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float)); - attribs.push_back(currAttrib); - GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) == - vertex_size(attribs.begin(), attribs.count())); - } -} - //////////////////////////////////////////////////////////////////////////////// -bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const { - +bool GrDrawState::srcAlphaWillBeOne() const { uint32_t validComponentFlags; GrColor color; // Check if per-vertex or constant color may have partial alpha - if (bindings & kColor_AttribBindingsBit) { + if (this->hasColorVertexAttribute()) { validComponentFlags = 0; color = 0; // not strictly necessary but we get false alarms from tools about uninit. } else { @@ -278,7 +209,7 @@ bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const { return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color); } -bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const { +bool GrDrawState::hasSolidCoverage() const { // If we're drawing coverage directly then coverage is effectively treated as color. if (this->isCoverageDrawing()) { return true; @@ -287,7 +218,7 @@ bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const { GrColor coverage; uint32_t validComponentFlags; // Initialize to an unknown starting coverage if per-vertex coverage is specified. - if (bindings & kCoverage_AttribBindingsBit) { + if (this->hasCoverageVertexAttribute()) { validComponentFlags = 0; } else { coverage = fCommon.fCoverage; @@ -329,7 +260,6 @@ bool GrDrawState::canTweakAlphaForCoverage() const { GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const { - GrAttribBindings bindings = this->getAttribBindings(); GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; if (NULL == srcCoeff) { @@ -347,14 +277,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, *dstCoeff = kOne_GrBlendCoeff; } - bool srcAIsOne = this->srcAlphaWillBeOne(bindings); + bool srcAIsOne = this->srcAlphaWillBeOne(); bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool covIsZero = !this->isCoverageDrawing() && - !(bindings & GrDrawState::kCoverage_AttribBindingsBit) && + !this->hasCoverageVertexAttribute() && 0 == this->getCoverage(); // When coeffs are (0,1) there is no reason to draw at all, unless // stenciling is enabled. Having color writes disabled is effectively @@ -371,10 +301,8 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, // check for coverage due to constant coverage, per-vertex coverage, or coverage stage bool hasCoverage = forceCoverage || 0xffffffff != this->getCoverage() || - (bindings & GrDrawState::kCoverage_AttribBindingsBit); - for (int s = this->getFirstCoverageStage(); - !hasCoverage && s < GrDrawState::kNumStages; - ++s) { + this->hasCoverageVertexAttribute(); + for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) { if (this->isStageEnabled(s)) { hasCoverage = true; } 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(); - bool validateVertexAttribs() const; + /** + * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the + * binding does not appear in the current attribs. These bindings should appear only once in + * the attrib array. + */ - //////////////////////////////////////////////////////////////////////////// - // Helpers for picking apart vertex attributes + int positionAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]; + } + int localCoordAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + } + int colorVertexAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + } + int coverageVertexAttributeIndex() const { + return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + } - // helper array to let us check the expected so we know what bound attrib indices - // we care about - static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount]; + bool hasLocalCoordAttribute() const { + return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + } + bool hasColorVertexAttribute() const { + return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + } + bool hasCoverageVertexAttribute() const { + return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + } + + bool validateVertexAttribs() const; /** - * Accessing positions, texture coords, or colors, of a vertex within an - * array is a hassle involving casts and simple math. These helpers exist - * to keep GrDrawTarget clients' code a bit nicer looking. + * Accessing positions, local coords, or colors, of a vertex within an array is a hassle + * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit + * nicer looking. */ /** @@ -218,110 +229,15 @@ public: /// @} - /////////////////////////////////////////////////////////////////////////// - /// @name Attribute Bindings - //// - - /** - * The vertex data used by the current program is represented as a bitfield - * of flags. Programs always use positions and may also use texture - * coordinates, per-vertex colors, per-vertex coverage and edge data. The - * local coords accessible by effects may either come from positions or - * be specified explicitly. - */ - - /** - * Additional Bits that can be specified in GrAttribBindings. - */ - enum AttribBindingsBits { - /** explicit local coords are provided (instead of using pre-view-matrix positions) */ - kLocalCoords_AttribBindingsBit = 0x1, - /* program uses colors (GrColor) */ - kColor_AttribBindingsBit = 0x2, - /* program uses coverage (GrColor) - */ - kCoverage_AttribBindingsBit = 0x4, - // for below assert - kDummyAttribBindingsBit, - kHighAttribBindingsBit = kDummyAttribBindingsBit - 1 - }; - // make sure we haven't exceeded the number of bits in GrAttribBindings. - GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings))); - - enum AttribBindings { - kDefault_AttribBindings = 0 - }; - - /** - * Sets attribute bindings for next draw. - * - * @param bindings the attribute bindings to set. - */ - void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; } - - GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; } - - //////////////////////////////////////////////////////////////////////////// - // Helpers for picking apart attribute bindings - /** * Determines whether src alpha is guaranteed to be one for all src pixels */ - bool srcAlphaWillBeOne(GrAttribBindings) const; + bool srcAlphaWillBeOne() const; /** * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw. */ - bool hasSolidCoverage(GrAttribBindings) const; - - static void VertexAttributesUnitTest(); - - /// @} - - /////////////////////////////////////////////////////////////////////////// - /// @name Vertex Attribute Indices - //// - - /** - * Vertex attribute indices map the data set in the vertex attribute array - * to the bindings specified in the attribute bindings. Each binding type - * has an associated index in the attribute array. This index is used to - * look up the vertex attribute data from the array, and potentially as the - * attribute index if we're binding attributes in GL. - * - * Indices which do not have active attribute bindings will be ignored. - */ - - enum AttribIndex { - kPosition_AttribIndex = 0, - kColor_AttribIndex, - kCoverage_AttribIndex, - kLocalCoords_AttribIndex, - - kLast_AttribIndex = kLocalCoords_AttribIndex - }; - static const int kAttribIndexCount = kLast_AttribIndex + 1; - - // these are used when vertex color and coverage isn't set - enum { - kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt, - kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1, - }; - - //////////////////////////////////////////////////////////////////////////// - // Helpers to set attribute indices. These should match the index in the - // current attribute index array. - - /** - * Sets index for next draw. This is used to look up the offset - * from the current vertex attribute array and to bind the attributes. - * - * @param index the attribute index we're setting - * @param value the value of the index - */ - void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; } - - int getAttribIndex(AttribIndex index) const { return fAttribIndices[index]; } + bool hasSolidCoverage() const; /// @} @@ -1068,15 +984,6 @@ public: if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) { return false; } - if (fVertexAttribs != s.fVertexAttribs) { - return false; - } - for (int i = 0; i < kAttribIndexCount; ++i) { - if ((i == kPosition_AttribIndex || s.fCommon.fAttribBindings & (1 << i)) && - fAttribIndices[i] != s.fAttribIndices[i]) { - return false; - } - } for (int i = 0; i < kNumStages; i++) { bool enabled = this->isStageEnabled(i); if (enabled != s.isStageEnabled(i)) { @@ -1093,10 +1000,6 @@ public: GrDrawState& operator= (const GrDrawState& s) { this->setRenderTarget(s.fRenderTarget.get()); fCommon = s.fCommon; - fVertexAttribs = s.fVertexAttribs; - for (int i = 0; i < kAttribIndexCount; i++) { - fAttribIndices[i] = s.fAttribIndices[i]; - } for (int i = 0; i < kNumStages; i++) { if (s.isStageEnabled(i)) { this->fStages[i] = s.fStages[i]; @@ -1110,33 +1013,44 @@ private: /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */ struct CommonState { // These fields are roughly sorted by decreasing likelihood of being different in op== - GrColor fColor; - GrAttribBindings fAttribBindings; - SkMatrix fViewMatrix; - GrBlendCoeff fSrcBlend; - GrBlendCoeff fDstBlend; - GrColor fBlendConstant; - uint32_t fFlagBits; - GrStencilSettings fStencilSettings; - int fFirstCoverageStage; - GrColor fCoverage; - SkXfermode::Mode fColorFilterMode; - GrColor fColorFilterColor; - DrawFace fDrawFace; + GrColor fColor; + SkMatrix fViewMatrix; + GrBlendCoeff fSrcBlend; + GrBlendCoeff fDstBlend; + GrColor fBlendConstant; + uint32_t fFlagBits; + GrVertexAttribArray<kMaxVertexAttribCnt> fVertexAttribs; + GrStencilSettings fStencilSettings; + int fFirstCoverageStage; + GrColor fCoverage; + SkXfermode::Mode fColorFilterMode; + GrColor fColorFilterColor; + DrawFace fDrawFace; + + // This is simply a different representation of info in fVertexAttribs and thus does + // not need to be compared in op==. + int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; + + GR_STATIC_ASSERT(kGrVertexAttribBindingCnt <= 8*sizeof(uint32_t)); + bool operator== (const CommonState& other) const { - return fColor == other.fColor && - fAttribBindings == other.fAttribBindings && - fViewMatrix.cheapEqualTo(other.fViewMatrix) && - fSrcBlend == other.fSrcBlend && - fDstBlend == other.fDstBlend && - fBlendConstant == other.fBlendConstant && - fFlagBits == other.fFlagBits && - fStencilSettings == other.fStencilSettings && - fFirstCoverageStage == other.fFirstCoverageStage && - fCoverage == other.fCoverage && - fColorFilterMode == other.fColorFilterMode && - fColorFilterColor == other.fColorFilterColor && - fDrawFace == other.fDrawFace; + bool result = fColor == other.fColor && + fViewMatrix.cheapEqualTo(other.fViewMatrix) && + fSrcBlend == other.fSrcBlend && + fDstBlend == other.fDstBlend && + fBlendConstant == other.fBlendConstant && + fFlagBits == other.fFlagBits && + fVertexAttribs == other.fVertexAttribs && + fStencilSettings == other.fStencilSettings && + fFirstCoverageStage == other.fFirstCoverageStage && + fCoverage == other.fCoverage && + fColorFilterMode == other.fColorFilterMode && + fColorFilterColor == other.fColorFilterColor && + fDrawFace == other.fDrawFace; + GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices, + other.fFixedFunctionVertexAttribIndices, + sizeof(fFixedFunctionVertexAttribIndices))); + return result; } bool operator!= (const CommonState& other) const { return !(*this == other); } }; @@ -1169,10 +1083,6 @@ public: // TODO: Here we will copy the GrRenderTarget pointer without taking a ref. fRenderTarget = drawState.fRenderTarget.get(); SkSafeRef(fRenderTarget); - fVertexAttribs = drawState.fVertexAttribs; - for (int i = 0; i < kAttribIndexCount; i++) { - fAttribIndices[i] = drawState.fAttribIndices[i]; - } // Here we ref the effects directly rather than the effect-refs. TODO: When the effect- // ref gets fully unref'ed it will cause the underlying effect to unref its resources // and recycle them to the cache (if no one else is holding a ref to the resources). @@ -1186,10 +1096,6 @@ public: GrAssert(fInitialized); drawState->fCommon = fCommon; drawState->setRenderTarget(fRenderTarget); - drawState->fVertexAttribs = fVertexAttribs; - for (int i = 0; i < kAttribIndexCount; i++) { - drawState->fAttribIndices[i] = fAttribIndices[i]; - } for (int i = 0; i < kNumStages; ++i) { fStages[i].restoreTo(&drawState->fStages[i]); } @@ -1199,16 +1105,6 @@ public: if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) { return false; } - for (int i = 0; i < kAttribIndexCount; ++i) { - if ((i == kPosition_AttribIndex || - state.fCommon.fAttribBindings & kAttribIndexMasks[i]) && - fAttribIndices[i] != state.fAttribIndices[i]) { - return false; - } - } - if (fVertexAttribs != state.fVertexAttribs) { - return false; - } for (int i = 0; i < kNumStages; ++i) { if (!fStages[i].isEqual(state.fStages[i])) { return false; @@ -1220,22 +1116,15 @@ public: private: GrRenderTarget* fRenderTarget; CommonState fCommon; - int fAttribIndices[kAttribIndexCount]; - GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs; GrEffectStage::DeferredStage fStages[kNumStages]; GR_DEBUGCODE(bool fInitialized;) }; private: - // helper array to let us check the current bindings so we know what bound attrib indices - // we care about - static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount]; SkAutoTUnref<GrRenderTarget> fRenderTarget; CommonState fCommon; - int fAttribIndices[kAttribIndexCount]; - GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs; GrEffectStage fStages[kNumStages]; typedef GrRefCnt INHERITED; 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 (requiresAttributeCoverage) { - GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt); - GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4); - } - if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { - GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt); - GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2); + if (requiresCoverageAttrib) { + desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); + } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) { + GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); + desc->fCoverageAttributeIndex = availableAttributeIndex; + } else { + desc->fCoverageAttributeIndex = -1; } -#endif } 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<int>::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]; |