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; }
#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,
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,
};
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 <int N>
-class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
+template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
#endif
// 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
// 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();
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)) {
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,
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()) {
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()) {
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()) {
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);
// 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);
////////////////////////////////////////////////////////////////////////////////
-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;
}
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 {
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;
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;
GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
GrBlendCoeff* srcCoeff,
GrBlendCoeff* dstCoeff) const {
- GrAttribBindings bindings = this->getAttribBindings();
GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
if (NULL == srcCoeff) {
*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
// 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;
}
#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)
* 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.
};
GrDrawState() {
-#if GR_DEBUG
- VertexAttributesUnitTest();
-#endif
this->reset();
}
////
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.
*/
/**
/// @}
- ///////////////////////////////////////////////////////////////////////////
- /// @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;
/// @}
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)) {
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];
/** 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); }
};
// 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).
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]);
}
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;
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;
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;
}
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");
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
// 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
}
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");
// 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);
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
- drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrEffectRef* effect = GrCircleEdgeEffect::Create(isStroked);
static const int kCircleEdgeAttrIndex = 1;
// 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);
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
- drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrEffectRef* effect = GrEllipseEdgeEffect::Create(isStroked);
static const int kEllipseCenterAttrIndex = 1;
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.
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);
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();
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();
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:
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:
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;
}
}
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;
}
};
// 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;
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;
firstCoverageStage = drawState.getFirstCoverageStage();
hasCoverage = true;
} else {
- hasCoverage = requiresAttributeCoverage;
+ hasCoverage = requiresCoverageAttrib;
}
}
}
}
- 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
}
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
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).
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));
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,
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
GR_DEBUGCODE(test_bsearch();)
test_binHashKey();
GrRedBlackTree<int>::UnitTest();
- GrDrawState::VertexAttributesUnitTest();
}
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
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;
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) {
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) {
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;
}
}
}
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];