aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-01 19:29:32 +0000
committerGravatar jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-01 19:29:32 +0000
commitc7bf2963f00a29bd28e5e2a446da79f93c1d9383 (patch)
tree065de5e21129c28201547891d806bff2f60bb646 /src/gpu
parentfb495b537f5ddd6966f02cfe38f6b106a4869934 (diff)
Rolling back r8466.
Not reviewed. git-svn-id: http://skia.googlecode.com/svn/trunk@8467 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp7
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.cpp6
-rw-r--r--src/gpu/GrAARectRenderer.cpp52
-rw-r--r--src/gpu/GrContext.cpp26
-rw-r--r--src/gpu/GrDrawState.cpp220
-rw-r--r--src/gpu/GrDrawState.h277
-rw-r--r--src/gpu/GrDrawTarget.cpp9
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp33
-rw-r--r--src/gpu/GrOvalRenderer.cpp14
-rw-r--r--src/gpu/GrTextContext.cpp7
-rw-r--r--src/gpu/gl/GrGLProgram.cpp37
-rw-r--r--src/gpu/gl/GrGLProgram.h11
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp80
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h26
-rw-r--r--src/gpu/gl/GrGLSL.cpp9
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp2
-rw-r--r--src/gpu/gl/GrGpuGL.cpp4
-rw-r--r--src/gpu/gr_unittests.cpp1
18 files changed, 531 insertions, 290 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 53c237b522..9f24190889 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -485,10 +485,13 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
// position + edge
static const GrVertexAttrib kAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
};
+
drawState->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
enum {
// the edge effects share this stage with glyph rendering
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index ffc9c50b2a..0c64a3b3b7 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -507,8 +507,8 @@ bool GrAAHairLinePathRenderer::createGeom(
// position + edge
static const GrVertexAttrib kAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
};
SkMatrix viewM = drawState->getViewMatrix();
@@ -522,6 +522,8 @@ bool GrAAHairLinePathRenderer::createGeom(
int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
+ target->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ target->drawState()->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
if (!arg->set(target, vertCnt, 0)) {
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index 0093b08078..b4f02ba8cc 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -13,17 +13,15 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer)
namespace {
-static void aa_rect_attributes(bool useCoverage, const GrVertexAttrib** attribs, int* count) {
- static const GrVertexAttrib kCoverageAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
- };
- static const GrVertexAttrib kColorAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
- };
- *attribs = useCoverage ? kCoverageAttribs : kColorAttribs;
- *count = 2;
+static void aa_rect_attributes(bool useCoverage, GrAttribBindings* bindings,
+ GrDrawState::AttribIndex* index) {
+ if (useCoverage) {
+ *bindings = GrDrawState::kCoverage_AttribBindingsBit;
+ *index = GrDrawState::kCoverage_AttribIndex;
+ } else {
+ *bindings = GrDrawState::kColor_AttribBindingsBit;
+ *index = GrDrawState::kColor_AttribIndex;
+ }
}
static void set_inset_fan(GrPoint* pts, size_t stride,
@@ -130,10 +128,18 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu,
bool useVertexCoverage) {
GrDrawState* drawState = target->drawState();
- const GrVertexAttrib* attribs;
- int attribCount;
- aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
- drawState->setVertexAttribs(attribs, attribCount);
+ // position + color/coverage
+ static const GrVertexAttrib kVertexAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec4ub_GrVertexAttribType, sizeof(GrPoint)}
+ };
+ GrAttribBindings bindings;
+ GrDrawState::AttribIndex attribIndex;
+ aa_rect_attributes(useVertexCoverage, &bindings, &attribIndex);
+ drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
+ drawState->setAttribBindings(bindings);
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ drawState->setAttribIndex(attribIndex, 1);
GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
if (!geo.succeeded()) {
@@ -206,10 +212,18 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
return;
}
- const GrVertexAttrib* attribs;
- int attribCount;
- aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
- drawState->setVertexAttribs(attribs, attribCount);
+ // position + color/coverage
+ static const GrVertexAttrib kVertexAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec4ub_GrVertexAttribType, sizeof(GrPoint)}
+ };
+ GrAttribBindings bindings;
+ GrDrawState::AttribIndex attribIndex;
+ aa_rect_attributes(useVertexCoverage, &bindings, &attribIndex);
+ drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
+ drawState->setAttribBindings(bindings);
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ drawState->setAttribIndex(attribIndex, 1);
GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
if (!geo.succeeded()) {
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 85b2c83384..32b4d6ae9c 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -358,13 +358,17 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
- // position + local coordinate
+ // position + texture coordinate
static const GrVertexAttrib kVertexAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
};
- drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
+ static const GrAttribBindings kAttribBindings = GrDrawState::kLocalCoords_AttribBindingsBit;
+ drawState->setAttribBindings(kAttribBindings);
+ drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
if (arg.succeeded()) {
@@ -921,16 +925,19 @@ void GrContext::drawVertices(const GrPaint& paint,
GrVertexAttribArray<3> attribs;
size_t currentOffset = 0;
int colorOffset = -1, texOffset = -1;
+ GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings;
// set position attribute
- GrVertexAttrib currAttrib =
- {kVec2f_GrVertexAttribType, currentOffset, kPosition_GrVertexAttribBinding};
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count());
+ GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset};
attribs.push_back(currAttrib);
currentOffset += sizeof(GrPoint);
// set up optional texture coordinate attributes
if (NULL != texCoords) {
- currAttrib.set(kVec2f_GrVertexAttribType, currentOffset, kLocalCoord_GrVertexAttribBinding);
+ bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
+ drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count());
+ currAttrib.set(kVec2f_GrVertexAttribType, currentOffset);
attribs.push_back(currAttrib);
texOffset = currentOffset;
currentOffset += sizeof(GrPoint);
@@ -938,13 +945,16 @@ void GrContext::drawVertices(const GrPaint& paint,
// set up optional color attributes
if (NULL != colors) {
- currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset, kColor_GrVertexAttribBinding);
+ bindings |= GrDrawState::kColor_AttribBindingsBit;
+ drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
+ currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset);
attribs.push_back(currAttrib);
colorOffset = currentOffset;
currentOffset += sizeof(GrColor);
}
drawState->setVertexAttribs(attribs.begin(), attribs.count());
+ drawState->setAttribBindings(bindings);
size_t vertexSize = drawState->getVertexSize();
GrAssert(vertexSize == currentOffset);
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 6d7969f024..f9e12cc207 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -46,15 +46,23 @@ void GrDrawState::setFromPaint(const GrPaint& paint) {
////////////////////////////////////////////////////////////////////////////////
+const size_t GrDrawState::kVertexAttribSizes[kGrVertexAttribTypeCount] = {
+ sizeof(float), // kFloat_GrVertexAttribType
+ 2*sizeof(float), // kVec2_GrVertexAttribType
+ 3*sizeof(float), // kVec3_GrVertexAttribType
+ 4*sizeof(float), // kVec4_GrVertexAttribType
+ 4*sizeof(char) // kCVec4_GrVertexAttribType
+};
+
static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
// this works as long as we're 4 byte-aligned
#if GR_DEBUG
uint32_t overlapCheck = 0;
#endif
- GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
+ GrAssert(count <= GrDrawState::kVertexAttribCnt);
size_t size = 0;
for (int index = 0; index < count; ++index) {
- size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
+ size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType];
size += attribSize;
#if GR_DEBUG
size_t dwordCount = attribSize >> 2;
@@ -68,102 +76,163 @@ static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
}
size_t GrDrawState::getVertexSize() const {
- return vertex_size(fCommon.fVertexAttribs.begin(), fCommon.fVertexAttribs.count());
+ return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count());
}
+const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = {
+ 0, // position is not reflected in the bindings
+ kColor_AttribBindingsBit,
+ kCoverage_AttribBindingsBit,
+ kLocalCoords_AttribBindingsBit,
+};
+
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
- GrAssert(count <= kMaxVertexAttribCnt);
- fCommon.fVertexAttribs.reset(attribs, count);
-
- // Set all the indices to -1
- memset(fCommon.fFixedFunctionVertexAttribIndices,
- 0xff,
- sizeof(fCommon.fFixedFunctionVertexAttribIndices));
-#if GR_DEBUG
- uint32_t overlapCheck = 0;
-#endif
- for (int i = 0; i < count; ++i) {
- if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
- // The fixed function attribs can only be specified once
- GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
- GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
- GrVertexAttribTypeVectorCount(attribs[i].fType));
- fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
- }
-#if GR_DEBUG
- size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
- uint32_t mask = (1 << dwordCount)-1;
- size_t offsetShift = attribs[i].fOffset >> 2;
- GrAssert(!(overlapCheck & (mask << offsetShift)));
- overlapCheck |= (mask << offsetShift);
-#endif
+ GrAssert(count <= GrDrawState::kVertexAttribCnt);
+ fVertexAttribs.reset();
+ for (int index = 0; index < count; ++index) {
+ fVertexAttribs.push_back(attribs[index]);
}
- // Positions must be specified.
- GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
}
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::setDefaultVertexAttribs() {
- static const GrVertexAttrib kPositionAttrib =
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
- fCommon.fVertexAttribs.reset(&kPositionAttrib, 1);
- // set all the fixed function indices to -1 except position.
- memset(fCommon.fFixedFunctionVertexAttribIndices,
- 0xff,
- sizeof(fCommon.fFixedFunctionVertexAttribIndices));
- fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
+ static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0};
+ fVertexAttribs.reset();
+ fVertexAttribs.push_back(kPositionAttrib);
+
+ fCommon.fAttribBindings = kDefault_AttribBindings;
+
+ fAttribIndices[kPosition_AttribIndex] = 0;
}
////////////////////////////////////////////////////////////////////////////////
bool GrDrawState::validateVertexAttribs() const {
- // check consistency of effects and attributes
- GrSLType slTypes[kMaxVertexAttribCnt];
- for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
- slTypes[i] = static_cast<GrSLType>(-1);
+ // color and coverage can set indices beyond the standard count
+ static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
+ int attributeTypes[kMaxValidAttribIndex];
+ for (int i = 0; i < kMaxValidAttribIndex; ++i) {
+ attributeTypes[i] = -1;
}
+
+ // sentinel to make sure effects don't try to use built-in attributes
+ static const int kBuiltInAttributeType = 10000;
+
+ // check our built-in indices
+ if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
+ return false;
+ }
+ attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
+ for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
+ if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
+ int attributeIndex = fAttribIndices[j];
+ if (attributeIndex >= kMaxValidAttribIndex) {
+ return false;
+ }
+ // they should not be shared at all
+ if (attributeTypes[attributeIndex] != -1) {
+ return false;
+ }
+ attributeTypes[attributeIndex] = kBuiltInAttributeType;
+ }
+ }
+ if (fCommon.fAttribBindings & kAttribIndexMasks[kLocalCoords_AttribIndex]) {
+ int attributeIndex = fAttribIndices[kLocalCoords_AttribIndex];
+ if (attributeIndex >= kVertexAttribCnt) {
+ return false;
+ }
+ // they should not be shared at all
+ if (attributeTypes[attributeIndex] != -1) {
+ return false;
+ }
+ attributeTypes[attributeIndex] = kBuiltInAttributeType;
+ }
+
+ // now those set by effects
for (int s = 0; s < kNumStages; ++s) {
- if (this->isStageEnabled(s)) {
- const GrEffectStage& stage = fStages[s];
- const GrEffectRef* effect = stage.getEffect();
- // make sure that any attribute indices have the correct binding type, that the attrib
- // type and effect's shader lang type are compatible, and that attributes shared by
- // multiple effects use the same shader lang type.
- const int* attributeIndices = stage.getVertexAttribIndices();
- int numAttributes = stage.getVertexAttribIndexCount();
- for (int i = 0; i < numAttributes; ++i) {
- int attribIndex = attributeIndices[i];
- if (attribIndex >= fCommon.fVertexAttribs.count() ||
- kEffect_GrVertexAttribBinding != fCommon.fVertexAttribs[attribIndex].fBinding) {
- return false;
- }
-
- GrSLType effectSLType = (*effect)->vertexAttribType(i);
- GrVertexAttribType attribType = fCommon.fVertexAttribs[attribIndex].fType;
- int slVecCount = GrSLTypeVectorCount(effectSLType);
- int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
- if (slVecCount != attribVecCount ||
- (-1 != slTypes[attribIndex] && slTypes[attribIndex] != effectSLType)) {
- return false;
- }
- slTypes[attribIndex] = effectSLType;
+ const GrEffectStage& stage = fStages[s];
+ const GrEffectRef* effect = stage.getEffect();
+ if (effect == NULL) {
+ continue;
+ }
+
+ // make sure that the count in the stage and the effect matches
+ int numAttributes = stage.getVertexAttribIndexCount();
+ if (numAttributes != effect->get()->numVertexAttribs()) {
+ return false;
+ }
+
+ // make sure that any shared indices have the same type
+ const int* attributeIndices = stage.getVertexAttribIndices();
+ for (int i = 0; i < numAttributes; ++i) {
+ int attributeIndex = attributeIndices[i];
+ if (attributeIndex >= kVertexAttribCnt) {
+ return false;
+ }
+
+ GrSLType attributeType = effect->get()->vertexAttribType(i);
+ if (attributeTypes[attributeIndex] != -1 &&
+ attributeTypes[attributeIndex] != attributeType) {
+ return false;
}
+ attributeTypes[attributeIndex] = attributeType;
}
}
return true;
}
+
+void GrDrawState::VertexAttributesUnitTest() {
+ // not necessarily exhaustive
+ static bool run;
+ if (!run) {
+ run = true;
+
+ GrVertexAttribArray<6> attribs;
+ GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
+
+ GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
+ attribs.push_back(currAttrib);
+ GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
+ attribs[0].fType = kVec2f_GrVertexAttribType;
+ GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
+ attribs[0].fType = kVec3f_GrVertexAttribType;
+ GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
+ attribs[0].fType = kVec4f_GrVertexAttribType;
+ GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
+ attribs[0].fType = kVec4ub_GrVertexAttribType;
+ GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count()));
+
+ currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
+ attribs.push_back(currAttrib);
+ GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
+ currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
+ attribs.push_back(currAttrib);
+ GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
+ vertex_size(attribs.begin(), attribs.count()));
+ currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
+ attribs.push_back(currAttrib);
+ GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
+ vertex_size(attribs.begin(), attribs.count()));
+ currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
+ attribs.push_back(currAttrib);
+ GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
+ vertex_size(attribs.begin(), attribs.count()));
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
-bool GrDrawState::srcAlphaWillBeOne() const {
+bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
+
uint32_t validComponentFlags;
GrColor color;
// Check if per-vertex or constant color may have partial alpha
- if (this->hasColorVertexAttribute()) {
+ if (bindings & kColor_AttribBindingsBit) {
validComponentFlags = 0;
color = 0; // not strictly necessary but we get false alarms from tools about uninit.
} else {
@@ -209,7 +278,7 @@ bool GrDrawState::srcAlphaWillBeOne() const {
return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
}
-bool GrDrawState::hasSolidCoverage() const {
+bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
// If we're drawing coverage directly then coverage is effectively treated as color.
if (this->isCoverageDrawing()) {
return true;
@@ -218,7 +287,7 @@ bool GrDrawState::hasSolidCoverage() const {
GrColor coverage;
uint32_t validComponentFlags;
// Initialize to an unknown starting coverage if per-vertex coverage is specified.
- if (this->hasCoverageVertexAttribute()) {
+ if (bindings & kCoverage_AttribBindingsBit) {
validComponentFlags = 0;
} else {
coverage = fCommon.fCoverage;
@@ -260,6 +329,7 @@ bool GrDrawState::canTweakAlphaForCoverage() const {
GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
GrBlendCoeff* srcCoeff,
GrBlendCoeff* dstCoeff) const {
+ GrAttribBindings bindings = this->getAttribBindings();
GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
if (NULL == srcCoeff) {
@@ -277,14 +347,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
*dstCoeff = kOne_GrBlendCoeff;
}
- bool srcAIsOne = this->srcAlphaWillBeOne();
+ bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
(kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
(kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bool covIsZero = !this->isCoverageDrawing() &&
- !this->hasCoverageVertexAttribute() &&
+ !(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
0 == this->getCoverage();
// When coeffs are (0,1) there is no reason to draw at all, unless
// stenciling is enabled. Having color writes disabled is effectively
@@ -301,8 +371,10 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
// check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bool hasCoverage = forceCoverage ||
0xffffffff != this->getCoverage() ||
- this->hasCoverageVertexAttribute();
- for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
+ (bindings & GrDrawState::kCoverage_AttribBindingsBit);
+ for (int s = this->getFirstCoverageStage();
+ !hasCoverage && s < GrDrawState::kNumStages;
+ ++s) {
if (this->isStageEnabled(s)) {
hasCoverage = true;
}
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 2f96c15671..d16efa893c 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -23,6 +23,11 @@
#include "SkMatrix.h"
#include "SkXfermode.h"
+/**
+ * Type used to describe how attributes bind to program usage
+ */
+typedef int GrAttribBindings;
+
class GrDrawState : public GrRefCnt {
public:
SK_DECLARE_INST_COUNT(GrDrawState)
@@ -40,8 +45,8 @@ public:
* coverage rather than as input to the src/dst color blend step.
*
* The input color to the first enabled color-stage is either the constant color or interpolated
- * per-vertex colors. The input to the first coverage stage is either a constant coverage
- * (usually full-coverage) or interpolated per-vertex coverage.
+ * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is
+ * either a constant coverage (usually full-coverage) or interpolated per-vertex coverage.
*
* See the documentation of kCoverageDrawing_StateBit for information about disabling the
* the color / coverage distinction.
@@ -57,6 +62,9 @@ public:
};
GrDrawState() {
+#if GR_DEBUG
+ VertexAttributesUnitTest();
+#endif
this->reset();
}
@@ -107,72 +115,53 @@ public:
////
enum {
- kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+ kVertexAttribCnt = 6,
};
/**
- * The format of vertices is represented as an array of GrVertexAttribs, with each representing
- * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
- * GrTypesPriv.h).
+ * The format of vertices is represented as an array of vertex attribute
+ * pair, with each pair representing the type of the attribute and the
+ * offset in the vertex structure (see GrVertexAttrib, above).
*
- * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
- * setEffect is called.
+ * This will only set up the vertex geometry. To bind the attributes in
+ * the shaders, attribute indices and attribute bindings need to be set
+ * as well.
*/
/**
* Sets vertex attributes for next draw.
*
* @param attribs the array of vertex attributes to set.
- * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
+ * @param count the number of attributes being set.
+ * limited to a count of kVertexAttribCnt.
*/
void setVertexAttribs(const GrVertexAttrib attribs[], int count);
- const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVertexAttribs.begin(); }
- int getVertexAttribCount() const { return fCommon.fVertexAttribs.count(); }
+ const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
+ int getVertexAttribCount() const { return fVertexAttribs.count(); }
size_t getVertexSize() const;
/**
- * Sets default vertex attributes for next draw. The default is a single attribute:
- * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
+ * Sets default vertex attributes for next draw.
+ *
+ * This will also set default vertex attribute indices and bindings
*/
void setDefaultVertexAttribs();
- /**
- * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
- * binding does not appear in the current attribs. These bindings should appear only once in
- * the attrib array.
- */
-
- int positionAttributeIndex() const {
- return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
- }
- int localCoordAttributeIndex() const {
- return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
- }
- int colorVertexAttributeIndex() const {
- return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
- }
- int coverageVertexAttributeIndex() const {
- return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
- }
+ bool validateVertexAttribs() const;
- bool hasLocalCoordAttribute() const {
- return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
- }
- bool hasColorVertexAttribute() const {
- return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
- }
- bool hasCoverageVertexAttribute() const {
- return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
- }
+ ////////////////////////////////////////////////////////////////////////////
+ // Helpers for picking apart vertex attributes
- bool validateVertexAttribs() const;
+ // helper array to let us check the expected so we know what bound attrib indices
+ // we care about
+ static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount];
/**
- * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
- * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
- * nicer looking.
+ * Accessing positions, texture coords, or colors, of a vertex within an
+ * array is a hassle involving casts and simple math. These helpers exist
+ * to keep GrDrawTarget clients' code a bit nicer looking.
*/
/**
@@ -229,15 +218,110 @@ public:
/// @}
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Attribute Bindings
+ ////
+
+ /**
+ * The vertex data used by the current program is represented as a bitfield
+ * of flags. Programs always use positions and may also use texture
+ * coordinates, per-vertex colors, per-vertex coverage and edge data. The
+ * local coords accessible by effects may either come from positions or
+ * be specified explicitly.
+ */
+
+ /**
+ * Additional Bits that can be specified in GrAttribBindings.
+ */
+ enum AttribBindingsBits {
+ /** explicit local coords are provided (instead of using pre-view-matrix positions) */
+ kLocalCoords_AttribBindingsBit = 0x1,
+ /* program uses colors (GrColor) */
+ kColor_AttribBindingsBit = 0x2,
+ /* program uses coverage (GrColor)
+ */
+ kCoverage_AttribBindingsBit = 0x4,
+ // for below assert
+ kDummyAttribBindingsBit,
+ kHighAttribBindingsBit = kDummyAttribBindingsBit - 1
+ };
+ // make sure we haven't exceeded the number of bits in GrAttribBindings.
+ GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings)));
+
+ enum AttribBindings {
+ kDefault_AttribBindings = 0
+ };
+
+ /**
+ * Sets attribute bindings for next draw.
+ *
+ * @param bindings the attribute bindings to set.
+ */
+ void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; }
+
+ GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Helpers for picking apart attribute bindings
+
/**
* Determines whether src alpha is guaranteed to be one for all src pixels
*/
- bool srcAlphaWillBeOne() const;
+ bool srcAlphaWillBeOne(GrAttribBindings) const;
/**
* Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
*/
- bool hasSolidCoverage() const;
+ bool hasSolidCoverage(GrAttribBindings) const;
+
+ static void VertexAttributesUnitTest();
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Vertex Attribute Indices
+ ////
+
+ /**
+ * Vertex attribute indices map the data set in the vertex attribute array
+ * to the bindings specified in the attribute bindings. Each binding type
+ * has an associated index in the attribute array. This index is used to
+ * look up the vertex attribute data from the array, and potentially as the
+ * attribute index if we're binding attributes in GL.
+ *
+ * Indices which do not have active attribute bindings will be ignored.
+ */
+
+ enum AttribIndex {
+ kPosition_AttribIndex = 0,
+ kColor_AttribIndex,
+ kCoverage_AttribIndex,
+ kLocalCoords_AttribIndex,
+
+ kLast_AttribIndex = kLocalCoords_AttribIndex
+ };
+ static const int kAttribIndexCount = kLast_AttribIndex + 1;
+
+ // these are used when vertex color and coverage isn't set
+ enum {
+ kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt,
+ kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1,
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Helpers to set attribute indices. These should match the index in the
+ // current attribute index array.
+
+ /**
+ * Sets index for next draw. This is used to look up the offset
+ * from the current vertex attribute array and to bind the attributes.
+ *
+ * @param index the attribute index we're setting
+ * @param value the value of the index
+ */
+ void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; }
+
+ int getAttribIndex(AttribIndex index) const { return fAttribIndices[index]; }
/// @}
@@ -984,6 +1068,15 @@ public:
if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
return false;
}
+ if (fVertexAttribs != s.fVertexAttribs) {
+ return false;
+ }
+ for (int i = 0; i < kAttribIndexCount; ++i) {
+ if ((i == kPosition_AttribIndex || s.fCommon.fAttribBindings & (1 << i)) &&
+ fAttribIndices[i] != s.fAttribIndices[i]) {
+ return false;
+ }
+ }
for (int i = 0; i < kNumStages; i++) {
bool enabled = this->isStageEnabled(i);
if (enabled != s.isStageEnabled(i)) {
@@ -1000,6 +1093,10 @@ public:
GrDrawState& operator= (const GrDrawState& s) {
this->setRenderTarget(s.fRenderTarget.get());
fCommon = s.fCommon;
+ fVertexAttribs = s.fVertexAttribs;
+ for (int i = 0; i < kAttribIndexCount; i++) {
+ fAttribIndices[i] = s.fAttribIndices[i];
+ }
for (int i = 0; i < kNumStages; i++) {
if (s.isStageEnabled(i)) {
this->fStages[i] = s.fStages[i];
@@ -1013,44 +1110,33 @@ private:
/** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
struct CommonState {
// These fields are roughly sorted by decreasing likelihood of being different in op==
- GrColor fColor;
- SkMatrix fViewMatrix;
- GrBlendCoeff fSrcBlend;
- GrBlendCoeff fDstBlend;
- GrColor fBlendConstant;
- uint32_t fFlagBits;
- GrVertexAttribArray<kMaxVertexAttribCnt> fVertexAttribs;
- GrStencilSettings fStencilSettings;
- int fFirstCoverageStage;
- GrColor fCoverage;
- SkXfermode::Mode fColorFilterMode;
- GrColor fColorFilterColor;
- DrawFace fDrawFace;
-
- // This is simply a different representation of info in fVertexAttribs and thus does
- // not need to be compared in op==.
- int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
-
- GR_STATIC_ASSERT(kGrVertexAttribBindingCnt <= 8*sizeof(uint32_t));
-
+ GrColor fColor;
+ GrAttribBindings fAttribBindings;
+ SkMatrix fViewMatrix;
+ GrBlendCoeff fSrcBlend;
+ GrBlendCoeff fDstBlend;
+ GrColor fBlendConstant;
+ uint32_t fFlagBits;
+ GrStencilSettings fStencilSettings;
+ int fFirstCoverageStage;
+ GrColor fCoverage;
+ SkXfermode::Mode fColorFilterMode;
+ GrColor fColorFilterColor;
+ DrawFace fDrawFace;
bool operator== (const CommonState& other) const {
- bool result = fColor == other.fColor &&
- fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
- fSrcBlend == other.fSrcBlend &&
- fDstBlend == other.fDstBlend &&
- fBlendConstant == other.fBlendConstant &&
- fFlagBits == other.fFlagBits &&
- fVertexAttribs == other.fVertexAttribs &&
- fStencilSettings == other.fStencilSettings &&
- fFirstCoverageStage == other.fFirstCoverageStage &&
- fCoverage == other.fCoverage &&
- fColorFilterMode == other.fColorFilterMode &&
- fColorFilterColor == other.fColorFilterColor &&
- fDrawFace == other.fDrawFace;
- GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
- other.fFixedFunctionVertexAttribIndices,
- sizeof(fFixedFunctionVertexAttribIndices)));
- return result;
+ return fColor == other.fColor &&
+ fAttribBindings == other.fAttribBindings &&
+ fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
+ fSrcBlend == other.fSrcBlend &&
+ fDstBlend == other.fDstBlend &&
+ fBlendConstant == other.fBlendConstant &&
+ fFlagBits == other.fFlagBits &&
+ fStencilSettings == other.fStencilSettings &&
+ fFirstCoverageStage == other.fFirstCoverageStage &&
+ fCoverage == other.fCoverage &&
+ fColorFilterMode == other.fColorFilterMode &&
+ fColorFilterColor == other.fColorFilterColor &&
+ fDrawFace == other.fDrawFace;
}
bool operator!= (const CommonState& other) const { return !(*this == other); }
};
@@ -1083,6 +1169,10 @@ public:
// TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
fRenderTarget = drawState.fRenderTarget.get();
SkSafeRef(fRenderTarget);
+ fVertexAttribs = drawState.fVertexAttribs;
+ for (int i = 0; i < kAttribIndexCount; i++) {
+ fAttribIndices[i] = drawState.fAttribIndices[i];
+ }
// Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
// ref gets fully unref'ed it will cause the underlying effect to unref its resources
// and recycle them to the cache (if no one else is holding a ref to the resources).
@@ -1096,6 +1186,10 @@ public:
GrAssert(fInitialized);
drawState->fCommon = fCommon;
drawState->setRenderTarget(fRenderTarget);
+ drawState->fVertexAttribs = fVertexAttribs;
+ for (int i = 0; i < kAttribIndexCount; i++) {
+ drawState->fAttribIndices[i] = fAttribIndices[i];
+ }
for (int i = 0; i < kNumStages; ++i) {
fStages[i].restoreTo(&drawState->fStages[i]);
}
@@ -1105,6 +1199,16 @@ public:
if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
return false;
}
+ for (int i = 0; i < kAttribIndexCount; ++i) {
+ if ((i == kPosition_AttribIndex ||
+ state.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
+ fAttribIndices[i] != state.fAttribIndices[i]) {
+ return false;
+ }
+ }
+ if (fVertexAttribs != state.fVertexAttribs) {
+ return false;
+ }
for (int i = 0; i < kNumStages; ++i) {
if (!fStages[i].isEqual(state.fStages[i])) {
return false;
@@ -1116,15 +1220,22 @@ public:
private:
GrRenderTarget* fRenderTarget;
CommonState fCommon;
+ int fAttribIndices[kAttribIndexCount];
+ GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
GrEffectStage::DeferredStage fStages[kNumStages];
GR_DEBUGCODE(bool fInitialized;)
};
private:
+ // helper array to let us check the current bindings so we know what bound attrib indices
+ // we care about
+ static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount];
SkAutoTUnref<GrRenderTarget> fRenderTarget;
CommonState fCommon;
+ int fAttribIndices[kAttribIndexCount];
+ GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
GrEffectStage fStages[kNumStages];
typedef GrRefCnt INHERITED;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index ea7787153f..bc7d39e573 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -615,15 +615,18 @@ void GrDrawTarget::drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* localRect,
const SkMatrix* localMatrix) {
+ GrAttribBindings bindings = 0;
// position + (optional) texture coord
static const GrVertexAttrib kAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
};
int attribCount = 1;
if (NULL != localRect) {
+ bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
attribCount = 2;
+ this->drawState()->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
}
GrDrawState::AutoViewMatrixRestore avmr;
@@ -632,6 +635,8 @@ void GrDrawTarget::drawRect(const GrRect& rect,
}
this->drawState()->setVertexAttribs(kAttribs, attribCount);
+ this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ this->drawState()->setAttribBindings(bindings);
AutoReleaseGeometry geo(this, 4, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 8074f26a87..a090dcf823 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -77,21 +77,22 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* localRect,
const SkMatrix* localMatrix) {
+
+ GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings;
GrDrawState::AutoColorRestore acr;
GrDrawState* drawState = this->drawState();
GrColor color = drawState->getColor();
GrVertexAttribArray<3> attribs;
+ size_t currentOffset = 0;
+ int colorOffset = -1, localOffset = -1;
// set position attrib
- static const GrVertexAttrib kPosAttrib =
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
- attribs.push_back(kPosAttrib);
-
- size_t currentOffset = sizeof(GrPoint);
- int colorOffset = -1;
- int localOffset = -1;
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count());
+ GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset};
+ attribs.push_back(currAttrib);
+ currentOffset += sizeof(GrPoint);
// Using per-vertex colors allows batching across colors. (A lot of rects in a row differing
// only in color is a common occurrence in tables). However, having per-vertex colors disables
@@ -99,11 +100,13 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
// optimizations help determine whether coverage and color can be blended correctly when
// dual-source blending isn't available. This comes into play when there is coverage. If colors
// were a stage it could take a hint that every vertex's color will be opaque.
- if (this->caps()->dualSourceBlendingSupport() || drawState->hasSolidCoverage()) {
+ if (this->caps()->dualSourceBlendingSupport() ||
+ drawState->hasSolidCoverage(drawState->getAttribBindings())) {
+ bindings |= GrDrawState::kColor_AttribBindingsBit;
+ drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
+ currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset);
+ attribs.push_back(currAttrib);
colorOffset = currentOffset;
- GrVertexAttrib colorAttrib =
- {kVec4ub_GrVertexAttribType, colorOffset, kColor_GrVertexAttribBinding};
- attribs.push_back(colorAttrib);
currentOffset += sizeof(GrColor);
// We set the draw state's color to white here. This is done so that any batching performed
// in our subclass's onDraw() won't get a false from GrDrawState::op== due to a color
@@ -113,14 +116,16 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
}
if (NULL != localRect) {
+ bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
+ drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count());
+ currAttrib.set(kVec2f_GrVertexAttribType, currentOffset);
+ attribs.push_back(currAttrib);
localOffset = currentOffset;
- GrVertexAttrib localCoordAttrib =
- {kVec2f_GrVertexAttribType, localOffset, kLocalCoord_GrVertexAttribBinding};
- attribs.push_back(localCoordAttrib);
currentOffset += sizeof(GrPoint);
}
drawState->setVertexAttribs(attribs.begin(), attribs.count());
+ drawState->setAttribBindings(bindings);
AutoReleaseGeometry geo(this, 4, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index 2955c75641..8bc0428bdb 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -85,10 +85,11 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
// position + edge
static const GrVertexAttrib kVertexAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
};
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
GrAssert(sizeof(CircleVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@@ -107,6 +108,7 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
+ drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrEffectRef* effect = GrCircleEdgeEffect::Create(isStroked);
static const int kCircleEdgeAttrIndex = 1;
@@ -183,11 +185,12 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
// position + edge
static const GrVertexAttrib kVertexAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec2f_GrVertexAttribType, sizeof(GrPoint)},
+ {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint)}
};
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
+ drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@@ -206,6 +209,7 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
+ drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrEffectRef* effect = GrEllipseEdgeEffect::Create(isStroked);
static const int kEllipseCenterAttrIndex = 1;
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 58b3e92c61..ab2bc424d6 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -194,9 +194,10 @@ HAS_ATLAS:
if (NULL == fVertices) {
// position + texture coord
static const GrVertexAttrib kVertexAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, 0},
+ {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
};
+ static const GrAttribBindings kAttribBindings = 0;
// If we need to reserve vertices allow the draw target to suggest
// a number of verts to reserve and whether to perform a flush.
@@ -214,6 +215,8 @@ HAS_ATLAS:
fDrawTarget = fContext->getTextTarget(fPaint);
fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
}
+ fDrawTarget->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
+ fDrawTarget->drawState()->setAttribBindings(kAttribBindings);
fMaxVertices = kDefaultRequestedVerts;
// ignore return, no point in flushing again.
fDrawTarget->geometryHints(&fMaxVertices, NULL);
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 51cae5c8c8..cbaa765440 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -705,17 +705,14 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
GL_CALL(BindAttribLocation(fProgramID,
fDesc.fPositionAttributeIndex,
builder.positionAttribute().c_str()));
- if (-1 != fDesc.fLocalCoordAttributeIndex) {
+ GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
+
+ if (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
GL_CALL(BindAttribLocation(fProgramID,
- fDesc.fLocalCoordAttributeIndex,
+ fDesc.fLocalCoordsAttributeIndex,
builder.localCoordsAttribute().c_str()));
}
- if (-1 != fDesc.fColorAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
- }
- if (-1 != fDesc.fCoverageAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
- }
const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end();
for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin();
@@ -829,7 +826,8 @@ void GrGLProgram::setData(GrGpuGL* gpu,
const GrEffectStage& stage = drawState.getStage(s);
GrAssert(NULL != stage.getEffect());
- bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex;
+ bool explicitLocalCoords =
+ (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit);
GrDrawEffect drawEffect(stage, explicitLocalCoords);
fEffects[s]->setData(fUniformManager, drawEffect);
int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count();
@@ -849,18 +847,15 @@ void GrGLProgram::setData(GrGpuGL* gpu,
void GrGLProgram::setColor(const GrDrawState& drawState,
GrColor color,
SharedGLState* sharedState) {
- if (!drawState.hasColorVertexAttribute()) {
+ if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) {
switch (fDesc.fColorInput) {
case GrGLProgramDesc::kAttribute_ColorInput:
- GrAssert(-1 != fDesc.fColorAttributeIndex);
- if (sharedState->fConstAttribColor != color ||
- sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) {
+ if (sharedState->fConstAttribColor != color) {
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c));
sharedState->fConstAttribColor = color;
- sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex;
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
@@ -873,34 +868,28 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
fColor = color;
}
- sharedState->fConstAttribColorIndex = -1;
break;
case GrGLProgramDesc::kSolidWhite_ColorInput:
case GrGLProgramDesc::kTransBlack_ColorInput:
- sharedState->fConstAttribColorIndex = -1;
break;
default:
GrCrash("Unknown color type.");
}
- } else {
- sharedState->fConstAttribColorIndex = -1;
}
}
void GrGLProgram::setCoverage(const GrDrawState& drawState,
GrColor coverage,
SharedGLState* sharedState) {
- if (!drawState.hasCoverageVertexAttribute()) {
+ if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) {
switch (fDesc.fCoverageInput) {
case GrGLProgramDesc::kAttribute_ColorInput:
- if (sharedState->fConstAttribCoverage != coverage ||
- sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) {
+ if (sharedState->fConstAttribCoverage != coverage) {
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(coverage, c);
GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c));
sharedState->fConstAttribCoverage = coverage;
- sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex;
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
@@ -913,17 +902,13 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
fCoverage = coverage;
}
- sharedState->fConstAttribCoverageIndex = -1;
break;
case GrGLProgramDesc::kSolidWhite_ColorInput:
case GrGLProgramDesc::kTransBlack_ColorInput:
- sharedState->fConstAttribCoverageIndex = -1;
break;
default:
GrCrash("Unknown coverage type.");
}
- } else {
- sharedState->fConstAttribCoverageIndex = -1;
}
}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 4b5dfea69d..27b6f802f5 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -60,23 +60,18 @@ public:
GrGLuint programID() const { return fProgramID; }
/**
- * Some GL state that is relevant to programs is not stored per-program. In particular color
- * and coverage attributes can be global state. This struct is read and updated by
- * GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state
- * redundantly.
+ * Some GL state that is relevant to programs is not stored per-program. In particular vertex
+ * attributes are global state. This struct is read and updated by GrGLProgram::setData to
+ * allow us to avoid setting this state redundantly.
*/
struct SharedGLState {
GrColor fConstAttribColor;
- int fConstAttribColorIndex;
GrColor fConstAttribCoverage;
- int fConstAttribCoverageIndex;
SharedGLState() { this->invalidate(); }
void invalidate() {
fConstAttribColor = GrColor_ILLEGAL;
- fConstAttribColorIndex = -1;
fConstAttribCoverage = GrColor_ILLEGAL;
- fConstAttribCoverageIndex = -1;
}
};
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 73846b8df3..6ed5473a39 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -34,42 +34,49 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
// bindings in use or other descriptor field settings) it should be set
// to a canonical value to avoid duplicate programs with different keys.
+ // Must initialize all fields or cache will have false negatives!
+ desc->fAttribBindings = drawState.getAttribBindings();
desc->fEmitsPointSize = isPoints;
- bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
- bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
- // we only need the local coords if we're actually going to generate effect code
- bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) &&
- drawState.hasLocalCoordAttribute();
+ bool requiresAttributeColors =
+ !skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit);
+ bool requiresAttributeCoverage =
+ !skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit);
// fColorInput/fCoverageInput records how colors are specified for the program so we strip the
// bits from the bindings to avoid false negatives when searching for an existing program in the
// cache.
+ desc->fAttribBindings &=
+ ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit);
desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
+ // no reason to do edge aa or look at per-vertex coverage if coverage is ignored
+ if (skipCoverage) {
+ desc->fAttribBindings &= ~(GrDrawState::kCoverage_AttribBindingsBit);
+ }
bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
- (!requiresColorAttrib && 0xffffffff == drawState.getColor());
+ (!requiresAttributeColors && 0xffffffff == drawState.getColor());
if (colorIsTransBlack) {
desc->fColorInput = kTransBlack_ColorInput;
} else if (colorIsSolidWhite) {
desc->fColorInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
desc->fColorInput = kUniform_ColorInput;
} else {
desc->fColorInput = kAttribute_ColorInput;
}
- bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
+ bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
if (skipCoverage) {
desc->fCoverageInput = kTransBlack_ColorInput;
} else if (covIsSolidWhite) {
desc->fCoverageInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
desc->fCoverageInput = kUniform_ColorInput;
} else {
desc->fCoverageInput = kAttribute_ColorInput;
@@ -85,7 +92,9 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
lastEnabledStage = s;
const GrEffectRef& effect = *drawState.getStage(s).getEffect();
const GrBackendEffectFactory& factory = effect->getFactory();
- GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
+ bool explicitLocalCoords = (drawState.getAttribBindings() &
+ GrDrawState::kLocalCoords_AttribBindingsBit);
+ GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords);
desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
if (effect->willReadDst()) {
readsDst = true;
@@ -130,7 +139,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
firstCoverageStage = drawState.getFirstCoverageStage();
hasCoverage = true;
} else {
- hasCoverage = requiresCoverageAttrib;
+ hasCoverage = requiresAttributeCoverage;
}
}
@@ -165,27 +174,38 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
}
- desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
- desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
-
- // For constant color and coverage we need an attribute with an index beyond those already set
- int availableAttributeIndex = drawState.getVertexAttribCount();
- if (requiresColorAttrib) {
- desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
- } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
- GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
- desc->fColorAttributeIndex = availableAttributeIndex;
- availableAttributeIndex++;
+ desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex);
+ if (requiresAttributeColors) {
+ desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex);
} else {
- desc->fColorAttributeIndex = -1;
+ desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue;
}
-
- if (requiresCoverageAttrib) {
- desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
- } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
- GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
- desc->fCoverageAttributeIndex = availableAttributeIndex;
+ if (requiresAttributeCoverage) {
+ desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex);
} else {
- desc->fCoverageAttributeIndex = -1;
+ desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue;
}
+ if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+ desc->fLocalCoordsAttributeIndex = drawState.getAttribIndex(GrDrawState::kLocalCoords_AttribIndex);
+ }
+
+#if GR_DEBUG
+ // Verify valid vertex attribute state. These assertions should probably be done somewhere
+ // higher up the callstack
+ const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs();
+ GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt);
+ GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fPositionAttributeIndex].fType).fCount == 2);
+ if (requiresAttributeColors) {
+ GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt);
+ GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fColorAttributeIndex].fType).fCount == 4);
+ }
+ if (requiresAttributeCoverage) {
+ GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt);
+ GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4);
+ }
+ if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+ GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt);
+ GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2);
+ }
+#endif
}
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index a77ed71665..df5729fb18 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -39,8 +39,7 @@ public:
void setRandom(SkMWCRandom*,
const GrGpuGL* gpu,
const GrTexture* dummyDstTexture,
- const GrEffectStage stages[GrDrawState::kNumStages],
- int currAttribIndex);
+ const GrEffectStage stages[GrDrawState::kNumStages]);
/**
* Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
@@ -77,34 +76,35 @@ private:
kDualSrcOutputCnt
};
+ // should the FS discard if the coverage is zero (to avoid stencil manipulation)
+ bool fDiscardIfZeroCoverage;
+
+ // stripped of bits that don't affect program generation
+ GrAttribBindings fAttribBindings;
+
/** Non-zero if this stage has an effect */
GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages];
- // To enable experimental geometry shader code (not for use in
- // production)
-#if GR_GL_EXPERIMENTAL_GS
- bool fExperimentalGS;
-#endif
-
+ // To enable experimental geometry shader code (not for use in
+ // production)
+#if GR_GL_EXPERIMENTAL_GS
+ bool fExperimentalGS;
+#endif
GrGLShaderBuilder::DstReadKey fDstRead; // set by GrGLShaderBuilder if there
// are effects that must read the dst.
// Otherwise, 0.
- // should the FS discard if the coverage is zero (to avoid stencil manipulation)
- SkBool8 fDiscardIfZeroCoverage;
-
uint8_t fColorInput; // casts to enum ColorInput
uint8_t fCoverageInput; // casts to enum ColorInput
uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
-
int8_t fFirstCoverageStage;
SkBool8 fEmitsPointSize;
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
int8_t fPositionAttributeIndex;
- int8_t fLocalCoordAttributeIndex;
int8_t fColorAttributeIndex;
int8_t fCoverageAttributeIndex;
+ int8_t fLocalCoordsAttributeIndex;
// GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
// code generation to GrGLShaderBuilder (and maybe add getters rather than friending).
diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp
index 3ec7fc45b2..570e61e53a 100644
--- a/src/gpu/gl/GrGLSL.cpp
+++ b/src/gpu/gl/GrGLSL.cpp
@@ -67,6 +67,15 @@ bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, const char* nameIfDeclared, G
return declaredOutput;
}
+GrSLType GrSLFloatVectorType (int count) {
+ GR_STATIC_ASSERT(kFloat_GrSLType == 1);
+ GR_STATIC_ASSERT(kVec2f_GrSLType == 2);
+ GR_STATIC_ASSERT(kVec3f_GrSLType == 3);
+ GR_STATIC_ASSERT(kVec4f_GrSLType == 4);
+ GrAssert(count > 0 && count <= 4);
+ return (GrSLType)(count);
+}
+
const char* GrGLSLVectorHomogCoord(int count) {
static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 1104cd0cb7..86cead41c3 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -117,7 +117,7 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
fPositionVar = &fVSAttrs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
- if (-1 != desc.fLocalCoordAttributeIndex) {
+ if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
fLocalCoordsVar = &fVSAttrs.push_back();
fLocalCoordsVar->set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index d2996564f3..d03ef781e1 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -180,7 +180,9 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
- GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt);
+ GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
+ GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue);
+ GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue);
fLastSuccessfulStencilFmtIdx = 0;
if (false) { // avoid bit rot, suppress warning
diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp
index 618d412bb5..ab5049a36a 100644
--- a/src/gpu/gr_unittests.cpp
+++ b/src/gpu/gr_unittests.cpp
@@ -77,4 +77,5 @@ void gr_run_unittests() {
GR_DEBUGCODE(test_bsearch();)
test_binHashKey();
GrRedBlackTree<int>::UnitTest();
+ GrDrawState::VertexAttributesUnitTest();
}