aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-17 21:03:05 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-17 21:03:05 +0000
commit2401ae8fd3c1f6282f571b5a7e0a499e9f4c09ab (patch)
tree6139a092cc23a3123640d6be55ca80e56dcd51b8
parent8b39f8f2bcbcd5f95908c34edb3cc70816c949b0 (diff)
Attempt to reland 3054
git-svn-id: http://skia.googlecode.com/svn/trunk@3056 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/gpu/GrDrawState.h35
-rw-r--r--src/gpu/GrDrawTarget.cpp10
-rw-r--r--src/gpu/GrDrawTarget.h3
-rw-r--r--src/gpu/GrGLProgram.cpp164
-rw-r--r--src/gpu/GrGLProgram.h4
-rw-r--r--src/gpu/GrGpuGLShaders.cpp85
-rw-r--r--src/gpu/GrGpuGLShaders.h5
7 files changed, 234 insertions, 72 deletions
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index b8417baf96..c736f1e3df 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -70,6 +70,7 @@ struct GrDrawState {
// memset exceptions
fColor = 0xffffffff;
+ fCoverage = 0xffffffff;
fFirstCoverageStage = kNumStages;
fColorFilterMode = SkXfermode::kDst_Mode;
fSrcBlend = kOne_BlendCoeff;
@@ -78,9 +79,9 @@ struct GrDrawState {
// ensure values that will be memcmp'ed in == but not memset in reset()
// are tightly packed
- GrAssert(kMemsetSize + sizeof(fColor) + sizeof(fFirstCoverageStage) +
- sizeof(fColorFilterMode) + sizeof(fSrcBlend) +
- sizeof(fDstBlend) + sizeof(GrMatrix) ==
+ GrAssert(kMemsetSize + sizeof(fColor) + sizeof(fCoverage) +
+ sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
+ sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(GrMatrix) ==
reinterpret_cast<intptr_t>(&fEdgeAANumEdges) -
reinterpret_cast<intptr_t>(this));
@@ -125,6 +126,33 @@ struct GrDrawState {
/// @}
///////////////////////////////////////////////////////////////////////////
+ /// @name Coverage
+ ////
+
+ /**
+ * Sets a constant fractional coverage to be applied to the draw. The
+ * initial value (after construction or reset()) is 0xff. The constant
+ * coverage is ignored when per-vertex coverage is provided.
+ */
+ void setCoverage(uint8_t coverage) {
+ fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
+ }
+
+ /**
+ * Version of above that specifies 4 channel per-vertex color. The value
+ * should be premultiplied.
+ */
+ void setCoverage4(GrColor coverage) {
+ fCoverage = coverage;
+ }
+
+ GrColor getCoverage() const {
+ return fCoverage;
+ }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
/// @name Textures
////
@@ -753,6 +781,7 @@ private:
// @{ Initialized to values other than zero
GrColor fColor;
+ GrColor fCoverage;
int fFirstCoverageStage;
SkXfermode::Mode fColorFilterMode;
GrBlendCoeff fSrcBlend;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index be6bd0a95c..fa266d1cef 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -885,8 +885,10 @@ GrDrawTarget::getBlendOpts(bool forceCoverage,
// When coeffs are (0,1) there is no reason to draw at all, unless
// stenciling is enabled. Having color writes disabled is effectively
- // (0,1).
- if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) {
+ // (0,1). The same applies when coverage is known to be 0.
+ if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne) ||
+ (!(layout & kCoverage_VertexLayoutBit) &&
+ 0 == drawState.getCoverage())) {
if (drawState.getStencil().doesWrite()) {
return kDisableBlend_BlendOptFlag |
kEmitTransBlack_BlendOptFlag;
@@ -895,8 +897,10 @@ GrDrawTarget::getBlendOpts(bool forceCoverage,
}
}
- // check for coverage due to edge aa or coverage texture stage
+ // check for coverage due to constant coverage, per-vertex coverage,
+ // edge aa or coverage texture stage
bool hasCoverage = forceCoverage ||
+ 0xffffffff != drawState.getCoverage() ||
drawState.getNumAAEdges() > 0 ||
(layout & kCoverage_VertexLayoutBit) ||
(layout & kEdge_VertexLayoutBit);
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 2635ddd6bf..5fc420d416 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -239,8 +239,7 @@ public:
enum VertexLayoutBits {
/* vertices have colors (GrColor) */
kColor_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 0),
- /* vertices have coverage (GrColor where all channels should have the
- * same value)
+ /* vertices have coverage (GrColor)
*/
kCoverage_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1),
/* Use text vertices. (Pos and tex coords may be a different type for
diff --git a/src/gpu/GrGLProgram.cpp b/src/gpu/GrGLProgram.cpp
index d159f5a4f1..ce5a284710 100644
--- a/src/gpu/GrGLProgram.cpp
+++ b/src/gpu/GrGLProgram.cpp
@@ -92,6 +92,7 @@ typedef GrGLProgram::ProgramDesc::StageDesc StageDesc;
#define COV_ATTR_NAME "aCoverage"
#define EDGE_ATTR_NAME "aEdge"
#define COL_UNI_NAME "uColor"
+#define COV_UNI_NAME "uCoverage"
#define EDGES_UNI_NAME "uEdges"
#define COL_FILTER_UNI_NAME "uColorFilter"
#define COL_MATRIX_UNI_NAME "uColorMatrix"
@@ -611,21 +612,37 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
}
}
-void genPerVertexCoverage(ShaderCodeSegments* segments,
- GrStringBuilder* inCoverage) {
- segments->fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
+void genAttributeCoverage(ShaderCodeSegments* segments,
+ GrStringBuilder* inOutCoverage) {
+ segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
GrGLShaderVar::kAttribute_TypeModifier,
COV_ATTR_NAME);
const char *vsName, *fsName;
- append_varying(GrGLShaderVar::kFloat_Type, "Coverage",
+ append_varying(GrGLShaderVar::kVec4f_Type, "Coverage",
segments, &vsName, &fsName);
segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
- if (inCoverage->size()) {
- segments->fFSCode.appendf("\tfloat edgeAndAttrCov = %s * %s;\n",
- fsName, inCoverage->c_str());
- *inCoverage = "edgeAndAttrCov";
+ if (inOutCoverage->size()) {
+ segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
+ fsName, inOutCoverage->c_str());
+ *inOutCoverage = "attrCoverage";
} else {
- *inCoverage = fsName;
+ *inOutCoverage = fsName;
+ }
+}
+
+void genUniformCoverage(ShaderCodeSegments* segments,
+ GrGLProgram::CachedData* programData,
+ GrStringBuilder* inOutCoverage) {
+ segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
+ GrGLShaderVar::kUniform_TypeModifier,
+ COV_UNI_NAME);
+ programData->fUniLocations.fCoverageUni = kUseUniform;
+ if (inOutCoverage->size()) {
+ segments->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
+ COV_UNI_NAME, inOutCoverage->c_str());
+ *inOutCoverage = "uniCoverage";
+ } else {
+ *inOutCoverage = COV_UNI_NAME;
}
}
@@ -661,7 +678,6 @@ void GrGLProgram::genGeometryShader(const GrGLInterface* gl,
}
const char* GrGLProgram::adjustInColor(const GrStringBuilder& inColor) const {
- const char* color;
if (inColor.size()) {
return inColor.c_str();
} else {
@@ -673,6 +689,7 @@ const char* GrGLProgram::adjustInColor(const GrStringBuilder& inColor) const {
}
}
+
bool GrGLProgram::genProgram(const GrGLInterface* gl,
GrGLSLGeneration glslGeneration,
GrGLProgram::CachedData* programData) const {
@@ -687,6 +704,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
#endif
SkXfermode::Coeff colorCoeff, uniformCoeff;
+ bool applyColorMatrix = SkToBool(fProgramDesc.fColorMatrixEnabled);
// The rest of transfer mode color filters have not been implemented
if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
GR_DEBUGCODE(bool success =)
@@ -699,6 +717,15 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
uniformCoeff = SkXfermode::kZero_Coeff;
}
+ // no need to do the color filter / matrix at all if coverage is 0. The
+ // output color is scaled by the coverage. All the dual source outputs are
+ // scaled by the coverage as well.
+ if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) {
+ colorCoeff = SkXfermode::kZero_Coeff;
+ uniformCoeff = SkXfermode::kZero_Coeff;
+ applyColorMatrix = false;
+ }
+
// If we know the final color is going to be all zeros then we can
// simplify the color filter coeffecients. needComputedColor will then
// come out false below.
@@ -832,7 +859,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
bool wroteFragColorZero = false;
if (SkXfermode::kZero_Coeff == uniformCoeff &&
SkXfermode::kZero_Coeff == colorCoeff &&
- !fProgramDesc.fColorMatrixEnabled) {
+ !applyColorMatrix) {
segments.fFSCode.appendf("\t%s = %s;\n",
fsColorOutput,
all_zeros_vec(4));
@@ -844,7 +871,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
colorCoeff, color);
inColor = "filteredColor";
}
- if (fProgramDesc.fColorMatrixEnabled) {
+ if (applyColorMatrix) {
segments.fFSUnis.push_back().set(GrGLShaderVar::kMat44f_Type,
GrGLShaderVar::kUniform_TypeModifier,
COL_MATRIX_UNI_NAME);
@@ -863,58 +890,78 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
// compute the partial coverage (coverage stages and edge aa)
GrStringBuilder inCoverage;
-
+ bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput ==
+ fProgramDesc.fCoverageInput;
// we don't need to compute coverage at all if we know the final shader
// output will be zero and we don't have a dual src blend output.
if (!wroteFragColorZero ||
ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
- // get edge AA coverage and use it as inCoverage to first coverage stage
- this->genEdgeCoverage(gl, layout, programData, &inCoverage, &segments);
-
- // include explicit per-vertex coverage if we have it
- if (GrDrawTarget::kCoverage_VertexLayoutBit & layout) {
- genPerVertexCoverage(&segments, &inCoverage);
- }
+ if (!coverageIsZero) {
+ this->genEdgeCoverage(gl,
+ layout,
+ programData,
+ &inCoverage,
+ &segments);
+
+ switch (fProgramDesc.fCoverageInput) {
+ case ProgramDesc::kSolidWhite_ColorInput:
+ // empty string implies solid white
+ break;
+ case ProgramDesc::kAttribute_ColorInput:
+ genAttributeCoverage(&segments, &inCoverage);
+ break;
+ case ProgramDesc::kUniform_ColorInput:
+ genUniformCoverage(&segments, programData, &inCoverage);
+ break;
+ default:
+ GrCrash("Unexpected input coverage.");
+ }
- GrStringBuilder outCoverage;
- const int& startStage = fProgramDesc.fFirstCoverageStage;
- for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
- if (fProgramDesc.fStages[s].isEnabled()) {
- // create var to hold stage output
- outCoverage = "coverage";
- outCoverage.appendS32(s);
- segments.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str());
+ GrStringBuilder outCoverage;
+ const int& startStage = fProgramDesc.fFirstCoverageStage;
+ for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
+ if (fProgramDesc.fStages[s].isEnabled()) {
+ // create var to hold stage output
+ outCoverage = "coverage";
+ outCoverage.appendS32(s);
+ segments.fFSCode.appendf("\tvec4 %s;\n",
+ outCoverage.c_str());
+
+ const char* inCoords;
+ // figure out what our input coords are
+ if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) &
+ layout) {
+ inCoords = POS_ATTR_NAME;
+ } else {
+ int tcIdx =
+ GrDrawTarget::VertexTexCoordsForStage(s, layout);
+ // we better have input tex coordinates if stage is
+ // enabled.
+ GrAssert(tcIdx >= 0);
+ GrAssert(texCoordAttrs[tcIdx].size());
+ inCoords = texCoordAttrs[tcIdx].c_str();
+ }
- const char* inCoords;
- // figure out what our input coords are
- if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) {
- inCoords = POS_ATTR_NAME;
- } else {
- int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
- // we better have input tex coordinates if stage is enabled.
- GrAssert(tcIdx >= 0);
- GrAssert(texCoordAttrs[tcIdx].size());
- inCoords = texCoordAttrs[tcIdx].c_str();
+ genStageCode(gl, s,
+ fProgramDesc.fStages[s],
+ inCoverage.size() ? inCoverage.c_str() : NULL,
+ outCoverage.c_str(),
+ inCoords,
+ &segments,
+ &programData->fUniLocations.fStages[s]);
+ inCoverage = outCoverage;
}
-
- genStageCode(gl, s,
- fProgramDesc.fStages[s],
- inCoverage.size() ? inCoverage.c_str() : NULL,
- outCoverage.c_str(),
- inCoords,
- &segments,
- &programData->fUniLocations.fStages[s]);
- inCoverage = outCoverage;
}
}
if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
segments.fFSOutputs.push_back().set(GrGLShaderVar::kVec4f_Type,
GrGLShaderVar::kOut_TypeModifier,
dual_source_output_name());
- bool outputIsZero = false;
+ bool outputIsZero = coverageIsZero;
GrStringBuilder coeff;
- if (ProgramDesc::kCoverage_DualSrcOutput !=
+ if (!outputIsZero &&
+ ProgramDesc::kCoverage_DualSrcOutput !=
fProgramDesc.fDualSrcOutput && !wroteFragColorZero) {
if (!inColor.size()) {
outputIsZero = true;
@@ -945,10 +992,16 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
// combine color and coverage as frag color
if (!wroteFragColorZero) {
- modulate_helper(fsColorOutput,
- inColor.c_str(),
- inCoverage.c_str(),
- &segments.fFSCode);
+ if (coverageIsZero) {
+ segments.fFSCode.appendf("\t%s = %s;\n",
+ fsColorOutput,
+ all_zeros_vec(4));
+ } else {
+ modulate_helper(fsColorOutput,
+ inColor.c_str(),
+ inCoverage.c_str(),
+ &segments.fFSCode);
+ }
if (ProgramDesc::kNo_OutputPM == fProgramDesc.fOutputPM) {
segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(%s.rgb / %s.a, %s.a);\n",
fsColorOutput,
@@ -1288,6 +1341,11 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLInterface* gl,
GR_GL_CALL_RET(gl, programData->fUniLocations.fColorMatrixVecUni,
GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME));
}
+ if (kUseUniform == programData->fUniLocations.fCoverageUni) {
+ GR_GL_CALL_RET(gl, programData->fUniLocations.fCoverageUni,
+ GetUniformLocation(progID, COV_UNI_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni);
+ }
if (kUseUniform == programData->fUniLocations.fEdgesUni) {
GR_GL_CALL_RET(gl, programData->fUniLocations.fEdgesUni,
diff --git a/src/gpu/GrGLProgram.h b/src/gpu/GrGLProgram.h
index b4ad4af8c0..4d80f50032 100644
--- a/src/gpu/GrGLProgram.h
+++ b/src/gpu/GrGLProgram.h
@@ -211,6 +211,7 @@ public:
#endif
uint8_t fColorInput; // casts to enum ColorInput
+ uint8_t fCoverageInput; // casts to enum CoverageInput
uint8_t fOutputPM; // cases to enum OutputPM
uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
int8_t fFirstCoverageStage;
@@ -261,6 +262,7 @@ public:
struct UniLocations {
GrGLint fViewMatrixUni;
GrGLint fColorUni;
+ GrGLint fCoverageUni;
GrGLint fEdgesUni;
GrGLint fColorFilterUni;
GrGLint fColorMatrixUni;
@@ -269,6 +271,7 @@ public:
void reset() {
fViewMatrixUni = kUnusedUniform;
fColorUni = kUnusedUniform;
+ fCoverageUni = kUnusedUniform;
fEdgesUni = kUnusedUniform;
fColorFilterUni = kUnusedUniform;
fColorMatrixUni = kUnusedUniform;
@@ -306,6 +309,7 @@ public:
// these reflect the current values of uniforms
// (GL uniform values travel with program)
GrColor fColor;
+ GrColor fCoverage;
GrColor fColorFilterColor;
GrMatrix fTextureMatrices[GrDrawState::kNumStages];
// width and height used for normalized texel size
diff --git a/src/gpu/GrGpuGLShaders.cpp b/src/gpu/GrGpuGLShaders.cpp
index 251fc41cdc..b8e0999ab8 100644
--- a/src/gpu/GrGpuGLShaders.cpp
+++ b/src/gpu/GrGpuGLShaders.cpp
@@ -198,6 +198,7 @@ bool GrGpuGLShaders::programUnitTest() {
pdesc.fVertexLayout = 0;
pdesc.fEmitsPointSize = random.nextF() > .5f;
pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt);
+ pdesc.fCoverageInput = random_int(&random, ProgramDesc::kColorInputCnt);
pdesc.fColorFilterXfermode = random_int(&random, SkXfermode::kCoeffModesCnt);
@@ -653,7 +654,8 @@ void GrGpuGLShaders::flushColor(GrColor color) {
switch (desc.fColorInput) {
case ProgramDesc::kAttribute_ColorInput:
if (fHWDrawState.getColor() != color) {
- // OpenGL ES only supports the float varities of glVertexAttrib
+ // OpenGL ES only supports the float varieties of
+ // glVertexAttrib
float c[] = GR_COLOR_TO_VEC4(color);
GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(),
c));
@@ -662,7 +664,8 @@ void GrGpuGLShaders::flushColor(GrColor color) {
break;
case ProgramDesc::kUniform_ColorInput:
if (fProgramData->fColor != color) {
- // OpenGL ES only supports the float varities of glVertexAttrib
+ // OpenGL ES doesn't support unsigned byte varieties of
+ // glUniform
float c[] = GR_COLOR_TO_VEC4(color);
GrAssert(GrGLProgram::kUnusedUniform !=
fProgramData->fUniLocations.fColorUni);
@@ -688,6 +691,47 @@ void GrGpuGLShaders::flushColor(GrColor color) {
}
}
+void GrGpuGLShaders::flushCoverage(GrColor coverage) {
+ const ProgramDesc& desc = fCurrentProgram.getDesc();
+ const GrDrawState& drawState = this->getDrawState();
+
+
+ if (this->getGeomSrc().fVertexLayout & kCoverage_VertexLayoutBit) {
+ // coverage will be specified per-vertex as an attribute
+ // invalidate the const vertex attrib coverage
+ fHWDrawState.setCoverage4(GrColor_ILLEGAL);
+ } else {
+ switch (desc.fCoverageInput) {
+ case ProgramDesc::kAttribute_ColorInput:
+ if (fHWDrawState.getCoverage() != coverage) {
+ // OpenGL ES only supports the float varieties of
+ // glVertexAttrib
+ float c[] = GR_COLOR_TO_VEC4(coverage);
+ GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(),
+ c));
+ fHWDrawState.setCoverage(coverage);
+ }
+ break;
+ case ProgramDesc::kUniform_ColorInput:
+ if (fProgramData->fCoverage != coverage) {
+ // OpenGL ES doesn't support unsigned byte varieties of
+ // glUniform
+ float c[] = GR_COLOR_TO_VEC4(coverage);
+ GrAssert(GrGLProgram::kUnusedUniform !=
+ fProgramData->fUniLocations.fCoverageUni);
+ GL_CALL(Uniform4fv(fProgramData->fUniLocations.fCoverageUni,
+ 1, c));
+ fProgramData->fCoverage = coverage;
+ }
+ break;
+ case ProgramDesc::kSolidWhite_ColorInput:
+ case ProgramDesc::kTransBlack_ColorInput:
+ break;
+ default:
+ GrCrash("Unknown coverage type.");
+ }
+ }
+}
bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
if (!flushGLStateCommon(type)) {
@@ -726,14 +770,19 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
this->flushBlend(type, srcCoeff, dstCoeff);
GrColor color;
+ GrColor coverage;
if (blendOpts & kEmitTransBlack_BlendOptFlag) {
color = 0;
+ coverage = 0;
} else if (blendOpts & kEmitCoverage_BlendOptFlag) {
color = 0xffffffff;
+ coverage = drawState.getCoverage();
} else {
color = drawState.getColor();
+ coverage = drawState.getCoverage();
}
this->flushColor(color);
+ this->flushCoverage(coverage);
this->flushViewMatrix();
@@ -862,15 +911,14 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
}
if (newCoverageOffset > 0) {
- // bind a single channel, they should all have the same value.
GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset);
int idx = GrGLProgram::CoverageAttributeIdx();
if (oldCoverageOffset <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
- GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE,
+ GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
true, newStride, coverageOffset));
} else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
- GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE,
+ GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
true, newStride, coverageOffset));
}
} else if (oldCoverageOffset > 0) {
@@ -922,10 +970,14 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
bool requiresAttributeColors =
!skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit);
- // fColorInput records how colors are specified for the program. Strip
- // the bit from the layout to avoid false negatives when searching for an
- // existing program in the cache.
- desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
+ bool requiresAttributeCoverage =
+ !skipCoverage && SkToBool(desc.fVertexLayout &
+ kCoverage_VertexLayoutBit);
+
+ // fColorInput/fCoverageInput records how colors are specified for the.
+ // program. So we strip the bits from the layout to avoid false negatives
+ // when searching for an existing program in the cache.
+ desc.fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit);
desc.fColorFilterXfermode = skipColor ?
SkXfermode::kDst_Mode :
@@ -953,6 +1005,19 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
} else {
desc.fColorInput = ProgramDesc::kAttribute_ColorInput;
}
+
+ bool covIsSolidWhite = !requiresAttributeCoverage &&
+ 0xffffffff == drawState.getCoverage();
+
+ if (skipCoverage) {
+ desc.fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
+ } else if (covIsSolidWhite) {
+ desc.fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
+ desc.fCoverageInput = ProgramDesc::kUniform_ColorInput;
+ } else {
+ desc.fCoverageInput = ProgramDesc::kAttribute_ColorInput;
+ }
desc.fEdgeAANumEdges = skipCoverage ? 0 : drawState.getNumAAEdges();
desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 &&
@@ -1101,7 +1166,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
if (!hasCoverage) {
hasCoverage =
desc.fEdgeAANumEdges ||
- (desc.fVertexLayout & GrDrawTarget::kCoverage_VertexLayoutBit) ||
+ requiresAttributeCoverage ||
(desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
}
diff --git a/src/gpu/GrGpuGLShaders.h b/src/gpu/GrGpuGLShaders.h
index 4b972b5f47..d875fe9590 100644
--- a/src/gpu/GrGpuGLShaders.h
+++ b/src/gpu/GrGpuGLShaders.h
@@ -57,9 +57,12 @@ private:
// sets the texture domain uniform for currently bound program
void flushTextureDomain(int stage);
- // sets the color specified by GrDrawTarget::setColor()
+ // sets the color specified by GrDrawState::setColor()
void flushColor(GrColor color);
+ // sets the color specified by GrDrawState::setCoverage()
+ void flushCoverage(GrColor color);
+
// sets the MVP matrix uniform for currently bound program
void flushViewMatrix();