Chromium Code Reviews| Index: src/gpu/gl/GrGLProgramDesc.cpp |
| =================================================================== |
| --- src/gpu/gl/GrGLProgramDesc.cpp (revision 0) |
| +++ src/gpu/gl/GrGLProgramDesc.cpp (revision 0) |
| @@ -0,0 +1,199 @@ |
| +/* |
| + * Copyright 2013 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "GrGLProgramDesc.h" |
| +#include "GrBackendEffectFactory.h" |
| +#include "GrDrawEffect.h" |
| +#include "GrEffect.h" |
| +#include "GrGpuGL.h" |
| + |
| +void GrGLProgramDesc::Build(const GrDrawState& drawState, |
| + bool isPoints, |
| + GrDrawState::BlendOptFlags blendOpts, |
| + GrBlendCoeff srcCoeff, |
| + GrBlendCoeff dstCoeff, |
| + const GrGpuGL* gpu, |
| + GrGLProgramDesc* desc) { |
| + |
| + // This should already have been caught |
| + GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts)); |
| + |
| + bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); |
| + |
| + bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag | |
| + GrDrawState::kEmitCoverage_BlendOptFlag)); |
| + |
| + // 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. |
| + |
| + // 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); |
| + |
|
robertphillips
2013/03/27 18:44:52
So -> so
bsalomon
2013/03/27 19:50:31
Done.
|
| + // 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 ? |
|
robertphillips
2013/03/27 18:44:52
spaces
bsalomon
2013/03/27 19:50:31
Done.
|
| + 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()); |
| + if (colorIsTransBlack) { |
| + desc->fColorInput = kTransBlack_ColorInput; |
| + } else if (colorIsSolidWhite) { |
| + desc->fColorInput = kSolidWhite_ColorInput; |
| + } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { |
| + desc->fColorInput = kUniform_ColorInput; |
| + } else { |
| + desc->fColorInput = kAttribute_ColorInput; |
| + } |
| + |
| + 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 && !requiresAttributeCoverage) { |
| + desc->fCoverageInput = kUniform_ColorInput; |
| + } else { |
| + desc->fCoverageInput = kAttribute_ColorInput; |
| + } |
| + |
| + int lastEnabledStage = -1; |
| + |
| + for (int s = 0; s < GrDrawState::kNumStages; ++s) { |
| + |
| + bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage; |
| + if (!skip && drawState.isStageEnabled(s)) { |
| + 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); |
| + desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps()); |
| + } else { |
| + desc->fEffectKeys[s] = 0; |
| + } |
| + } |
| + |
| + desc->fDualSrcOutput = kNone_DualSrcOutput; |
| + |
| + // Currently the experimental GS will only work with triangle prims (and it doesn't do anything |
| + // other than pass through values from the VS to the FS anyway). |
| +#if GR_GL_EXPERIMENTAL_GS |
| +#if 0 |
| + desc->fExperimentalGS = gpu->caps().geometryShaderSupport(); |
| +#else |
| + desc->fExperimentalGS = false; |
| +#endif |
| +#endif |
| + |
| + // We leave this set to kNumStages until we discover that the coverage/color distinction is |
| + // material to the generated program. We do this to avoid distinct keys that generate equivalent |
| + // programs. |
| + desc->fFirstCoverageStage = GrDrawState::kNumStages; |
| + // This tracks the actual first coverage stage. |
| + int firstCoverageStage = GrDrawState::kNumStages; |
| + desc->fDiscardIfZeroCoverage = false; // Enabled below if stenciling and there is coverage. |
| + bool hasCoverage = false; |
|
robertphillips
2013/03/27 18:44:52
its -> it's
bsalomon
2013/03/27 19:50:31
Done.
|
| + // If we're rendering coverage-as-color then its as though there are no coverage stages. |
| + if (!drawState.isCoverageDrawing()) { |
| + // We can have coverage either through a stage or coverage vertex attributes. |
| + if (drawState.getFirstCoverageStage() <= lastEnabledStage) { |
| + firstCoverageStage = drawState.getFirstCoverageStage(); |
| + hasCoverage = true; |
| + } else { |
| + hasCoverage = requiresAttributeCoverage; |
| + } |
| + } |
| + |
| + if (hasCoverage) { |
| + // color filter is applied between color/coverage computation |
| + if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { |
| + desc->fFirstCoverageStage = firstCoverageStage; |
| + } |
| + |
| + // If we're stenciling then we want to discard samples that have zero coverage |
| + if (drawState.getStencil().doesWrite()) { |
| + desc->fDiscardIfZeroCoverage = true; |
| + desc->fFirstCoverageStage = firstCoverageStage; |
| + } |
| + |
| + if (gpu->caps()->dualSourceBlendingSupport() && |
| + !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | |
| + GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { |
| + if (kZero_GrBlendCoeff == dstCoeff) { |
| + // write the coverage value to second color |
| + desc->fDualSrcOutput = kCoverage_DualSrcOutput; |
| + desc->fFirstCoverageStage = firstCoverageStage; |
| + } else if (kSA_GrBlendCoeff == dstCoeff) { |
| + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. |
| + desc->fDualSrcOutput = kCoverageISA_DualSrcOutput; |
| + desc->fFirstCoverageStage = firstCoverageStage; |
| + } else if (kSC_GrBlendCoeff == dstCoeff) { |
| + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. |
| + desc->fDualSrcOutput = kCoverageISC_DualSrcOutput; |
| + desc->fFirstCoverageStage = firstCoverageStage; |
| + } |
| + } |
| + } |
| + |
| + desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex); |
| + if (requiresAttributeColors) { |
| + desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex); |
| + } 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); |
| + } |
|
robertphillips
2013/03/27 18:44:52
do we not have a kLocalCoordsOverrideAttribIndexVa
bsalomon
2013/03/27 19:50:31
No. The override values are there because we somet
|
| + |
| +#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 |
| +} |