Take two for r8466:
Replace the old attribute binding and index interface with one where we include the binding as part of the attribute array. Also removed the fixed attribute indices for constant color and coverage attributes, and replaced with dynamic ones based on current attribute set. Removed binding of color and coverage attributes unless they're actually set.
Original author: bsalomon@google.com
Author: jvanverth@google.com
Reviewed By: bsalomon@google.com,robertphillips@google.com
Review URL: https://chromiumcodereview.appspot.com/13296005
git-svn-id: http://skia.googlecode.com/svn/trunk@8468 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index cbaa765..51cae5c 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -705,14 +705,17 @@
GL_CALL(BindAttribLocation(fProgramID,
fDesc.fPositionAttributeIndex,
builder.positionAttribute().c_str()));
- GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
- GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
-
- if (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+ if (-1 != fDesc.fLocalCoordAttributeIndex) {
GL_CALL(BindAttribLocation(fProgramID,
- fDesc.fLocalCoordsAttributeIndex,
+ fDesc.fLocalCoordAttributeIndex,
builder.localCoordsAttribute().c_str()));
}
+ if (-1 != fDesc.fColorAttributeIndex) {
+ GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
+ }
+ if (-1 != fDesc.fCoverageAttributeIndex) {
+ GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
+ }
const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end();
for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin();
@@ -826,8 +829,7 @@
const GrEffectStage& stage = drawState.getStage(s);
GrAssert(NULL != stage.getEffect());
- bool explicitLocalCoords =
- (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit);
+ bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex;
GrDrawEffect drawEffect(stage, explicitLocalCoords);
fEffects[s]->setData(fUniformManager, drawEffect);
int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count();
@@ -847,15 +849,18 @@
void GrGLProgram::setColor(const GrDrawState& drawState,
GrColor color,
SharedGLState* sharedState) {
- if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) {
+ if (!drawState.hasColorVertexAttribute()) {
switch (fDesc.fColorInput) {
case GrGLProgramDesc::kAttribute_ColorInput:
- if (sharedState->fConstAttribColor != color) {
+ GrAssert(-1 != fDesc.fColorAttributeIndex);
+ if (sharedState->fConstAttribColor != color ||
+ sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) {
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c));
sharedState->fConstAttribColor = color;
+ sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex;
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
@@ -868,28 +873,34 @@
fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
fColor = color;
}
+ sharedState->fConstAttribColorIndex = -1;
break;
case GrGLProgramDesc::kSolidWhite_ColorInput:
case GrGLProgramDesc::kTransBlack_ColorInput:
+ sharedState->fConstAttribColorIndex = -1;
break;
default:
GrCrash("Unknown color type.");
}
+ } else {
+ sharedState->fConstAttribColorIndex = -1;
}
}
void GrGLProgram::setCoverage(const GrDrawState& drawState,
GrColor coverage,
SharedGLState* sharedState) {
- if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) {
+ if (!drawState.hasCoverageVertexAttribute()) {
switch (fDesc.fCoverageInput) {
case GrGLProgramDesc::kAttribute_ColorInput:
- if (sharedState->fConstAttribCoverage != coverage) {
+ if (sharedState->fConstAttribCoverage != coverage ||
+ sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) {
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(coverage, c);
GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c));
sharedState->fConstAttribCoverage = coverage;
+ sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex;
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
@@ -902,13 +913,17 @@
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 27b6f80..4b5dfea 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -60,18 +60,23 @@
GrGLuint programID() const { return fProgramID; }
/**
- * Some GL state that is relevant to programs is not stored per-program. In particular vertex
- * attributes are global state. This struct is read and updated by GrGLProgram::setData to
- * allow us to avoid setting this state redundantly.
+ * Some GL state that is relevant to programs is not stored per-program. In particular color
+ * and coverage attributes can be global state. This struct is read and updated by
+ * GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state
+ * redundantly.
*/
struct SharedGLState {
GrColor fConstAttribColor;
+ int fConstAttribColorIndex;
GrColor fConstAttribCoverage;
+ int fConstAttribCoverageIndex;
SharedGLState() { this->invalidate(); }
void invalidate() {
fConstAttribColor = GrColor_ILLEGAL;
+ fConstAttribColorIndex = -1;
fConstAttribCoverage = GrColor_ILLEGAL;
+ fConstAttribCoverageIndex = -1;
}
};
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 6ed5473..73846b8 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -34,49 +34,42 @@
// bindings in use or other descriptor field settings) it should be set
// to a canonical value to avoid duplicate programs with different keys.
- // Must initialize all fields or cache will have false negatives!
- desc->fAttribBindings = drawState.getAttribBindings();
desc->fEmitsPointSize = isPoints;
- bool requiresAttributeColors =
- !skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit);
- bool requiresAttributeCoverage =
- !skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit);
+ bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
+ bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
+ // we only need the local coords if we're actually going to generate effect code
+ bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) &&
+ drawState.hasLocalCoordAttribute();
// fColorInput/fCoverageInput records how colors are specified for the program so we strip the
// bits from the bindings to avoid false negatives when searching for an existing program in the
// cache.
- desc->fAttribBindings &=
- ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit);
desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
- // no reason to do edge aa or look at per-vertex coverage if coverage is ignored
- if (skipCoverage) {
- desc->fAttribBindings &= ~(GrDrawState::kCoverage_AttribBindingsBit);
- }
bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
- (!requiresAttributeColors && 0xffffffff == drawState.getColor());
+ (!requiresColorAttrib && 0xffffffff == drawState.getColor());
if (colorIsTransBlack) {
desc->fColorInput = kTransBlack_ColorInput;
} else if (colorIsSolidWhite) {
desc->fColorInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
desc->fColorInput = kUniform_ColorInput;
} else {
desc->fColorInput = kAttribute_ColorInput;
}
- bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
+ bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
if (skipCoverage) {
desc->fCoverageInput = kTransBlack_ColorInput;
} else if (covIsSolidWhite) {
desc->fCoverageInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
desc->fCoverageInput = kUniform_ColorInput;
} else {
desc->fCoverageInput = kAttribute_ColorInput;
@@ -92,9 +85,7 @@
lastEnabledStage = s;
const GrEffectRef& effect = *drawState.getStage(s).getEffect();
const GrBackendEffectFactory& factory = effect->getFactory();
- bool explicitLocalCoords = (drawState.getAttribBindings() &
- GrDrawState::kLocalCoords_AttribBindingsBit);
- GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords);
+ GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
if (effect->willReadDst()) {
readsDst = true;
@@ -139,7 +130,7 @@
firstCoverageStage = drawState.getFirstCoverageStage();
hasCoverage = true;
} else {
- hasCoverage = requiresAttributeCoverage;
+ hasCoverage = requiresCoverageAttrib;
}
}
@@ -174,38 +165,27 @@
}
}
- desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex);
- if (requiresAttributeColors) {
- desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex);
+ desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
+ desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
+
+ // For constant color and coverage we need an attribute with an index beyond those already set
+ int availableAttributeIndex = drawState.getVertexAttribCount();
+ if (requiresColorAttrib) {
+ desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
+ } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
+ GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
+ desc->fColorAttributeIndex = availableAttributeIndex;
+ availableAttributeIndex++;
} else {
- desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue;
- }
- if (requiresAttributeCoverage) {
- desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex);
- } else {
- desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue;
- }
- if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
- desc->fLocalCoordsAttributeIndex = drawState.getAttribIndex(GrDrawState::kLocalCoords_AttribIndex);
+ desc->fColorAttributeIndex = -1;
}
-#if GR_DEBUG
- // Verify valid vertex attribute state. These assertions should probably be done somewhere
- // higher up the callstack
- const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs();
- GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt);
- GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fPositionAttributeIndex].fType).fCount == 2);
- if (requiresAttributeColors) {
- GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt);
- GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fColorAttributeIndex].fType).fCount == 4);
+ if (requiresCoverageAttrib) {
+ desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
+ } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
+ GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
+ desc->fCoverageAttributeIndex = availableAttributeIndex;
+ } else {
+ desc->fCoverageAttributeIndex = -1;
}
- if (requiresAttributeCoverage) {
- GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt);
- GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4);
- }
- if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
- GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt);
- GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2);
- }
-#endif
}
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index df5729f..a77ed71 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -39,7 +39,8 @@
void setRandom(SkMWCRandom*,
const GrGpuGL* gpu,
const GrTexture* dummyDstTexture,
- const GrEffectStage stages[GrDrawState::kNumStages]);
+ const GrEffectStage stages[GrDrawState::kNumStages],
+ int currAttribIndex);
/**
* Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
@@ -76,35 +77,34 @@
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 570e61e..3ec7fc4 100644
--- a/src/gpu/gl/GrGLSL.cpp
+++ b/src/gpu/gl/GrGLSL.cpp
@@ -67,15 +67,6 @@
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 86cead4..1104cd0 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -117,7 +117,7 @@
fPositionVar = &fVSAttrs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
- if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
+ if (-1 != desc.fLocalCoordAttributeIndex) {
fLocalCoordsVar = &fVSAttrs.push_back();
fLocalCoordsVar->set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index d03ef78..d299656 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -180,9 +180,7 @@
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