Index: src/gpu/gl/GrGLProgramDesc.cpp |
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp |
index bde4072cc3650b1bc2487bb4df30adcc1caf4901..d7ba287cfa623bc9050cd3b93ccdba686c5ff302 100644 |
--- a/src/gpu/gl/GrGLProgramDesc.cpp |
+++ b/src/gpu/gl/GrGLProgramDesc.cpp |
@@ -11,7 +11,6 @@ |
#include "GrDrawEffect.h" |
#include "GrEffect.h" |
#include "GrGpuGL.h" |
-#include "GrOptDrawState.h" |
#include "SkChecksum.h" |
@@ -47,8 +46,9 @@ |
return true; |
} |
-bool GrGLProgramDesc::Build(const GrOptDrawState& optState, |
+bool GrGLProgramDesc::Build(const GrDrawState& drawState, |
GrGpu::DrawType drawType, |
+ GrDrawState::BlendOptFlags blendOpts, |
GrBlendCoeff srcCoeff, |
GrBlendCoeff dstCoeff, |
const GrGpuGL* gpu, |
@@ -60,19 +60,47 @@ |
colorStages->reset(); |
coverageStages->reset(); |
- bool inputColorIsUsed = optState.inputColorIsUsed(); |
- bool inputCoverageIsUsed = optState.inputColorIsUsed(); |
+ // This should already have been caught |
+ SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts)); |
+ |
+ bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); |
+ |
+ bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag | |
+ GrDrawState::kEmitCoverage_BlendOptFlag)); |
+ |
+ int firstEffectiveColorStage = 0; |
+ bool inputColorIsUsed = true; |
+ |
+ if (!skipColor) { |
+ firstEffectiveColorStage = drawState.numColorStages(); |
+ while (firstEffectiveColorStage > 0 && inputColorIsUsed) { |
+ --firstEffectiveColorStage; |
+ const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect(); |
+ inputColorIsUsed = effect->willUseInputColor(); |
+ } |
+ } |
+ |
+ int firstEffectiveCoverageStage = 0; |
+ bool inputCoverageIsUsed = true; |
+ if (!skipCoverage) { |
+ firstEffectiveCoverageStage = drawState.numCoverageStages(); |
+ while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) { |
+ --firstEffectiveCoverageStage; |
+ const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect(); |
+ inputCoverageIsUsed = effect->willUseInputColor(); |
+ } |
+ } |
// The descriptor is used as a cache key. Thus when a field of the |
// descriptor will not affect program generation (because of the attribute |
// bindings in use or other descriptor field settings) it should be set |
// to a canonical value to avoid duplicate programs with different keys. |
- bool requiresColorAttrib = optState.hasColorVertexAttribute(); |
- bool requiresCoverageAttrib = optState.hasCoverageVertexAttribute(); |
+ 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 = optState.numTotalStages() > 0 && |
- optState.hasLocalCoordAttribute(); |
+ bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) && |
+ drawState.hasLocalCoordAttribute(); |
bool readsDst = false; |
bool readFragPosition = false; |
@@ -80,8 +108,16 @@ |
// Provide option for shader programs without vertex shader only when drawing paths. |
bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType); |
- int numStages = optState.numTotalStages(); |
- |
+ int numStages = 0; |
+ if (drawState.hasGeometryProcessor()) { |
+ numStages++; |
+ } |
+ if (!skipColor) { |
+ numStages += drawState.numColorStages() - firstEffectiveColorStage; |
+ } |
+ if (!skipCoverage) { |
+ numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage; |
+ } |
GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); |
// Make room for everything up to and including the array of offsets to effect keys. |
desc->fKey.reset(); |
@@ -95,7 +131,7 @@ |
memset(desc->header(), 0, kHeaderSize); |
// We can only have one effect which touches the vertex shader |
- if (optState.hasGeometryProcessor()) { |
+ if (drawState.hasGeometryProcessor()) { |
uint16_t* offsetAndSize = |
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + |
offsetAndSizeIndex * 2 * sizeof(uint16_t)); |
@@ -104,7 +140,7 @@ |
uint16_t effectKeySize; |
uint32_t effectOffset = desc->fKey.count(); |
effectKeySuccess |= GetEffectKeyAndUpdateStats( |
- *optState.getGeometryProcessor(), gpu->glCaps(), |
+ *drawState.getGeometryProcessor(), gpu->glCaps(), |
requiresLocalCoordAttrib, &b, |
&effectKeySize, &readsDst, |
&readFragPosition, &requiresVertexShader); |
@@ -113,55 +149,57 @@ |
offsetAndSize[0] = SkToU16(effectOffset); |
offsetAndSize[1] = effectKeySize; |
++offsetAndSizeIndex; |
- *geometryProcessor = optState.getGeometryProcessor(); |
+ *geometryProcessor = drawState.getGeometryProcessor(); |
SkASSERT(requiresVertexShader); |
header->fHasGeometryProcessor = true; |
} |
- for (int s = 0; s < optState.numColorStages(); ++s) { |
- uint16_t* offsetAndSize = |
- reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + |
- offsetAndSizeIndex * 2 * sizeof(uint16_t)); |
- |
- bool effectRequiresVertexShader = false; |
- GrEffectKeyBuilder b(&desc->fKey); |
- uint16_t effectKeySize; |
- uint32_t effectOffset = desc->fKey.count(); |
- effectKeySuccess |= GetEffectKeyAndUpdateStats( |
- optState.getColorStage(s), gpu->glCaps(), |
- requiresLocalCoordAttrib, &b, |
- &effectKeySize, &readsDst, |
- &readFragPosition, &effectRequiresVertexShader); |
- effectKeySuccess |= (effectOffset <= SK_MaxU16); |
- |
- offsetAndSize[0] = SkToU16(effectOffset); |
- offsetAndSize[1] = effectKeySize; |
- ++offsetAndSizeIndex; |
- SkASSERT(!effectRequiresVertexShader); |
- } |
- |
- for (int s = 0; s < optState.numCoverageStages(); ++s) { |
- uint16_t* offsetAndSize = |
- reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + |
- offsetAndSizeIndex * 2 * sizeof(uint16_t)); |
- |
- bool effectRequiresVertexShader = false; |
- GrEffectKeyBuilder b(&desc->fKey); |
- uint16_t effectKeySize; |
- uint32_t effectOffset = desc->fKey.count(); |
- effectKeySuccess |= GetEffectKeyAndUpdateStats( |
- optState.getCoverageStage(s), gpu->glCaps(), |
- requiresLocalCoordAttrib, &b, |
- &effectKeySize, &readsDst, |
- &readFragPosition, &effectRequiresVertexShader); |
- effectKeySuccess |= (effectOffset <= SK_MaxU16); |
- |
- offsetAndSize[0] = SkToU16(effectOffset); |
- offsetAndSize[1] = effectKeySize; |
- ++offsetAndSizeIndex; |
- SkASSERT(!effectRequiresVertexShader); |
- } |
- |
+ if (!skipColor) { |
+ for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { |
+ uint16_t* offsetAndSize = |
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + |
+ offsetAndSizeIndex * 2 * sizeof(uint16_t)); |
+ |
+ bool effectRequiresVertexShader = false; |
+ GrEffectKeyBuilder b(&desc->fKey); |
+ uint16_t effectKeySize; |
+ uint32_t effectOffset = desc->fKey.count(); |
+ effectKeySuccess |= GetEffectKeyAndUpdateStats( |
+ drawState.getColorStage(s), gpu->glCaps(), |
+ requiresLocalCoordAttrib, &b, |
+ &effectKeySize, &readsDst, |
+ &readFragPosition, &effectRequiresVertexShader); |
+ effectKeySuccess |= (effectOffset <= SK_MaxU16); |
+ |
+ offsetAndSize[0] = SkToU16(effectOffset); |
+ offsetAndSize[1] = effectKeySize; |
+ ++offsetAndSizeIndex; |
+ SkASSERT(!effectRequiresVertexShader); |
+ } |
+ } |
+ if (!skipCoverage) { |
+ for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { |
+ uint16_t* offsetAndSize = |
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + |
+ offsetAndSizeIndex * 2 * sizeof(uint16_t)); |
+ |
+ bool effectRequiresVertexShader = false; |
+ GrEffectKeyBuilder b(&desc->fKey); |
+ uint16_t effectKeySize; |
+ uint32_t effectOffset = desc->fKey.count(); |
+ effectKeySuccess |= GetEffectKeyAndUpdateStats( |
+ drawState.getCoverageStage(s), gpu->glCaps(), |
+ requiresLocalCoordAttrib, &b, |
+ &effectKeySize, &readsDst, |
+ &readFragPosition, &effectRequiresVertexShader); |
+ effectKeySuccess |= (effectOffset <= SK_MaxU16); |
+ |
+ offsetAndSize[0] = SkToU16(effectOffset); |
+ offsetAndSize[1] = effectKeySize; |
+ ++offsetAndSizeIndex; |
+ SkASSERT(!effectRequiresVertexShader); |
+ } |
+ } |
if (!effectKeySuccess) { |
desc->fKey.reset(); |
return false; |
@@ -184,20 +222,20 @@ |
#endif |
bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport(); |
- if (!inputColorIsUsed) { |
+ if (!inputColorIsUsed && !skipColor) { |
header->fColorInput = kAllOnes_ColorInput; |
- } else if (defaultToUniformInputs && !requiresColorAttrib) { |
+ } else if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) { |
header->fColorInput = kUniform_ColorInput; |
} else { |
header->fColorInput = kAttribute_ColorInput; |
header->fRequiresVertexShader = true; |
} |
- bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == optState.getCoverageColor(); |
- |
- if (covIsSolidWhite || !inputCoverageIsUsed) { |
+ bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor(); |
+ |
+ if ((covIsSolidWhite || !inputCoverageIsUsed) && !skipCoverage) { |
header->fCoverageInput = kAllOnes_ColorInput; |
- } else if (defaultToUniformInputs && !requiresCoverageAttrib) { |
+ } else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) { |
header->fCoverageInput = kUniform_ColorInput; |
} else { |
header->fCoverageInput = kAttribute_ColorInput; |
@@ -219,19 +257,19 @@ |
if (readFragPosition) { |
header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition( |
- optState.getRenderTarget(), gpu->glCaps()); |
+ drawState.getRenderTarget(), gpu->glCaps()); |
} else { |
header->fFragPosKey = 0; |
} |
// Record attribute indices |
- header->fPositionAttributeIndex = optState.positionAttributeIndex(); |
- header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex(); |
+ header->fPositionAttributeIndex = drawState.positionAttributeIndex(); |
+ header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); |
// For constant color and coverage we need an attribute with an index beyond those already set |
- int availableAttributeIndex = optState.getVertexAttribCount(); |
+ int availableAttributeIndex = drawState.getVertexAttribCount(); |
if (requiresColorAttrib) { |
- header->fColorAttributeIndex = optState.colorVertexAttributeIndex(); |
+ header->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); |
} else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { |
SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); |
header->fColorAttributeIndex = availableAttributeIndex; |
@@ -241,7 +279,7 @@ |
} |
if (requiresCoverageAttrib) { |
- header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex(); |
+ header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); |
} else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { |
SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); |
header->fCoverageAttributeIndex = availableAttributeIndex; |
@@ -255,13 +293,15 @@ |
header->fCoverageOutput = kModulate_CoverageOutput; |
// If we do have coverage determine whether it matters. |
- bool separateCoverageFromColor = optState.hasGeometryProcessor(); |
- if (!optState.isCoverageDrawing() && |
- (optState.numCoverageStages() > 0 || |
- optState.hasGeometryProcessor() || |
+ bool separateCoverageFromColor = drawState.hasGeometryProcessor(); |
+ if (!drawState.isCoverageDrawing() && !skipCoverage && |
+ (drawState.numCoverageStages() > 0 || |
+ drawState.hasGeometryProcessor() || |
requiresCoverageAttrib)) { |
- if (gpu->caps()->dualSourceBlendingSupport()) { |
+ if (gpu->caps()->dualSourceBlendingSupport() && |
+ !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | |
+ GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { |
if (kZero_GrBlendCoeff == dstCoeff) { |
// write the coverage value to second color |
header->fCoverageOutput = kSecondaryCoverage_CoverageOutput; |
@@ -283,19 +323,22 @@ |
} |
} |
- for (int s = 0; s < optState.numColorStages(); ++s) { |
- colorStages->push_back(&optState.getColorStage(s)); |
- } |
- SkTArray<const GrEffectStage*, true>* array; |
- if (separateCoverageFromColor) { |
- array = coverageStages; |
- } else { |
- array = colorStages; |
- } |
- for (int s = 0; s < optState.numCoverageStages(); ++s) { |
- array->push_back(&optState.getCoverageStage(s)); |
- } |
- |
+ if (!skipColor) { |
+ for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { |
+ colorStages->push_back(&drawState.getColorStage(s)); |
+ } |
+ } |
+ if (!skipCoverage) { |
+ SkTArray<const GrEffectStage*, true>* array; |
+ if (separateCoverageFromColor) { |
+ array = coverageStages; |
+ } else { |
+ array = colorStages; |
+ } |
+ for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { |
+ array->push_back(&drawState.getCoverageStage(s)); |
+ } |
+ } |
header->fColorEffectCnt = colorStages->count(); |
header->fCoverageEffectCnt = coverageStages->count(); |