diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-02-12 21:45:24 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-02-12 21:45:24 +0000 |
commit | 91207482c9398944fc997aeb99ed5f8674be58cb (patch) | |
tree | 8cfff3ef4be16e52065220df1160bdc130c40d37 /src/gpu/gl | |
parent | 2b446734cfa8201e5478648988de86b646cb9544 (diff) |
Move code that builds GrGLProgram::Desc to GrGLProgram. Move color and coverage flush to GrGLProgram.
Review URL: https://codereview.appspot.com/7322058
git-svn-id: http://skia.googlecode.com/svn/trunk@7708 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 235 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 54 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 24 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 255 |
5 files changed, 302 insertions, 269 deletions
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index a4f0df2fed..75f9ea6ad5 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -40,6 +40,155 @@ inline const char* dual_source_output_name() { return "dualSourceOut"; } } +void GrGLProgram::BuildDesc(const GrDrawState& drawState, + bool isPoints, + GrDrawState::BlendOptFlags blendOpts, + GrBlendCoeff srcCoeff, + GrBlendCoeff dstCoeff, + const GrGpuGL* gpu, + Desc* 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 vertex + // layout 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->fVertexLayout = drawState.getVertexLayout(); + + desc->fEmitsPointSize = isPoints; + + bool requiresAttributeColors = !skipColor && + SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit); + bool requiresAttributeCoverage = !skipCoverage && + SkToBool(desc->fVertexLayout & GrDrawState::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 &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); + + 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->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | + GrDrawState::kCoverage_VertexLayoutBit); + } + + bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); + bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) || + (!requiresAttributeColors && 0xffffffff == drawState.getColor()); + if (colorIsTransBlack) { + desc->fColorInput = Desc::kTransBlack_ColorInput; + } else if (colorIsSolidWhite) { + desc->fColorInput = Desc::kSolidWhite_ColorInput; + } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { + desc->fColorInput = Desc::kUniform_ColorInput; + } else { + desc->fColorInput = Desc::kAttribute_ColorInput; + } + + bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage(); + + if (skipCoverage) { + desc->fCoverageInput = Desc::kTransBlack_ColorInput; + } else if (covIsSolidWhite) { + desc->fCoverageInput = Desc::kSolidWhite_ColorInput; + } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { + desc->fCoverageInput = Desc::kUniform_ColorInput; + } else { + desc->fCoverageInput = Desc::kAttribute_ColorInput; + } + + int lastEnabledStage = -1; + + if (!skipCoverage && (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit)) { + desc->fVertexEdgeType = drawState.getVertexEdgeType(); + desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite(); + } else { + // Use canonical values when edge-aa is not enabled to avoid program cache misses. + desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType; + desc->fDiscardIfOutsideEdge = false; + } + + 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(); + desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), gpu->glCaps()); + } else { + desc->fEffectKeys[s] = 0; + } + } + + desc->fDualSrcOutput = Desc::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->getCaps().geometryShaderSupport(); +#else + desc->fExperimentalGS = false; +#endif +#endif + + // We want to avoid generating programs with different "first cov stage" values when they would + // compute the same result. We set field in the desc to kNumStages when either there are no + // coverage stages or the distinction between coverage and color is immaterial. + int firstCoverageStage = GrDrawState::kNumStages; + desc->fFirstCoverageStage = GrDrawState::kNumStages; + bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; + if (hasCoverage) { + firstCoverageStage = drawState.getFirstCoverageStage(); + } + + // other coverage inputs + if (!hasCoverage) { + hasCoverage = requiresAttributeCoverage || + (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit); + } + + if (hasCoverage) { + // color filter is applied between color/coverage computation + if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { + desc->fFirstCoverageStage = firstCoverageStage; + } + + if (gpu->getCaps().dualSourceBlendingSupport() && + !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | + GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { + if (kZero_GrBlendCoeff == dstCoeff) { + // write the coverage value to second color + desc->fDualSrcOutput = Desc::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 = Desc::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 = Desc::kCoverageISC_DualSrcOutput; + desc->fFirstCoverageStage = firstCoverageStage; + } + } + } +} + GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl, const Desc& desc, const GrEffectStage* stages[]) { @@ -896,7 +1045,10 @@ void GrGLProgram::initSamplerUniforms() { /////////////////////////////////////////////////////////////////////////////// -void GrGLProgram::setData(GrGpuGL* gpu) { +void GrGLProgram::setData(GrGpuGL* gpu, + GrColor color, + GrColor coverage, + SharedGLState* sharedState) { const GrDrawState& drawState = gpu->getDrawState(); int rtHeight = drawState.getRenderTarget()->height(); @@ -905,6 +1057,19 @@ void GrGLProgram::setData(GrGpuGL* gpu) { fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(rtHeight)); fRTHeight = rtHeight; } + + this->setColor(drawState, color, sharedState); + this->setCoverage(drawState, coverage, sharedState); + + // Setup the SkXfermode::Mode-based colorfilter uniform if necessary + if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fColorFilterUni && + fColorFilterColor != drawState.getColorFilterColor()) { + GrGLfloat c[4]; + GrColorToRGBAFloat(drawState.getColorFilterColor(), c); + fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c); + fColorFilterColor = drawState.getColorFilterColor(); + } + GrGLint texUnitIdx = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (NULL != fEffects[s]) { @@ -924,3 +1089,71 @@ void GrGLProgram::setData(GrGpuGL* gpu) { } } } + +void GrGLProgram::setColor(const GrDrawState& drawState, + GrColor color, + SharedGLState* sharedState) { + if (!(drawState.getVertexLayout() & GrDrawState::kColor_VertexLayoutBit)) { + switch (fDesc.fColorInput) { + case GrGLProgram::Desc::kAttribute_ColorInput: + if (sharedState->fConstAttribColor != color) { + // OpenGL ES only supports the float varieties of glVertexAttrib + GrGLfloat c[4]; + GrColorToRGBAFloat(color, c); + GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c)); + sharedState->fConstAttribColor = color; + } + break; + case GrGLProgram::Desc::kUniform_ColorInput: + if (fColor != color) { + // OpenGL ES doesn't support unsigned byte varieties of glUniform + GrGLfloat c[4]; + GrColorToRGBAFloat(color, c); + GrAssert(GrGLUniformManager::kInvalidUniformHandle != + fUniformHandles.fColorUni); + fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c); + fColor = color; + } + break; + case GrGLProgram::Desc::kSolidWhite_ColorInput: + case GrGLProgram::Desc::kTransBlack_ColorInput: + break; + default: + GrCrash("Unknown color type."); + } + } +} + +void GrGLProgram::setCoverage(const GrDrawState& drawState, + GrColor coverage, + SharedGLState* sharedState) { + if (!(drawState.getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit)) { + switch (fDesc.fCoverageInput) { + case Desc::kAttribute_ColorInput: + if (sharedState->fConstAttribCoverage != coverage) { + // OpenGL ES only supports the float varieties of glVertexAttrib + GrGLfloat c[4]; + GrColorToRGBAFloat(coverage, c); + GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), c)); + sharedState->fConstAttribCoverage = coverage; + } + break; + case Desc::kUniform_ColorInput: + if (fCoverage != coverage) { + // OpenGL ES doesn't support unsigned byte varieties of glUniform + GrGLfloat c[4]; + GrColorToRGBAFloat(coverage, c); + GrAssert(GrGLUniformManager::kInvalidUniformHandle != + fUniformHandles.fCoverageUni); + fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c); + fCoverage = coverage; + } + break; + case Desc::kSolidWhite_ColorInput: + case Desc::kTransBlack_ColorInput: + break; + default: + GrCrash("Unknown coverage type."); + } + } +} diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 8b494c8cef..fd5e8e4b8e 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -22,6 +22,7 @@ class GrBinHashKeyBuilder; class GrGLEffect; class GrGLShaderBuilder; +class SkMWCRandom; // optionally compile the experimental GS code. Set to GR_DEBUG // so that debug build bots will execute the code. @@ -40,7 +41,19 @@ class GrGLProgram : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrGLProgram) - struct Desc; + class Desc; + + /** + * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the + * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. + */ + static void BuildDesc(const GrDrawState&, + bool isPoints, + GrDrawState::BlendOptFlags, + GrBlendCoeff srcCoeff, + GrBlendCoeff dstCoeff, + const GrGpuGL* gpu, + Desc* outDesc); static GrGLProgram* Create(const GrGLContextInfo& gl, const Desc& desc, @@ -70,15 +83,34 @@ public: static int TexCoordAttributeIdx(int tcIdx) { return 4 + tcIdx; } /** + * 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; + GrColor fConstAttribCoverage; + + SharedGLState() { this->invalidate(); } + void invalidate() { + fConstAttribColor = GrColor_ILLEGAL; + fConstAttribCoverage = GrColor_ILLEGAL; + } + }; + + /** * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a * draw occurs using the program after the program has already been bound. It also uses the * GrGpuGL object to bind the textures required by the GrGLEffects. + * + * The color and coverage params override the GrDrawState's getColor() and getCoverage() values. */ - void setData(GrGpuGL*); + void setData(GrGpuGL*, GrColor color, GrColor coverage, SharedGLState*); // Parameters that affect code generation // This structs should be kept compact; it is input to an expensive hash key generator. - struct Desc { + class Desc { + public: Desc() { // since we use this as part of a key we can't have any uninitialized // padding @@ -90,6 +122,12 @@ public: return reinterpret_cast<const uint32_t*>(this); } + // For unit testing. + void setRandom(SkMWCRandom*, + const GrGpuGL* gpu, + const GrEffectStage stages[GrDrawState::kNumStages]); + + private: // Specifies where the initial color comes from before the stages are applied. enum ColorInput { kSolidWhite_ColorInput, @@ -133,6 +171,8 @@ public: int8_t fFirstCoverageStage; SkBool8 fEmitsPointSize; uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode + + friend class GrGLProgram; }; private: GrGLProgram(const GrGLContextInfo& gl, @@ -172,6 +212,14 @@ private: const char* adjustInColor(const SkString& inColor) const; + // Helper for setData(). Makes GL calls to specify the initial color when there is not + // per-vertex colors. + void setColor(const GrDrawState&, GrColor color, SharedGLState*); + + // Helper for setData(). Makes GL calls to specify the initial coverage when there is not + // per-vertex coverages. + void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*); + typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray; struct UniformHandles { diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index ff3941dc6b..56a29919fc 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -497,8 +497,7 @@ void GrGpuGL::onResetContext() { } fHWProgramID = 0; - fHWConstAttribColor = GrColor_ILLEGAL; - fHWConstAttribCoverage = GrColor_ILLEGAL; + fSharedGLProgramState.invalidate(); } namespace { diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 7bb458d7ea..b911f40b76 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -55,6 +55,8 @@ public: virtual void abandonResources() SK_OVERRIDE; + const GrGLCaps& glCaps() const { return fGLContextInfo.caps(); } + private: // GrGpu overrides virtual void onResetContext() SK_OVERRIDE; @@ -107,8 +109,6 @@ private: bool insideClip) SK_OVERRIDE; virtual bool flushGraphicsState(DrawType) SK_OVERRIDE; - const GrGLCaps& glCaps() const { return fGLContextInfo.caps(); } - // binds texture unit in GL void setTextureUnit(int unitIdx); @@ -135,9 +135,6 @@ private: static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); - // for readability of function impls - typedef GrGLProgram::Desc ProgramDesc; - class ProgramCache : public ::GrNoncopyable { public: ProgramCache(const GrGLContextInfo& gl); @@ -146,7 +143,7 @@ private: GrGLProgram* getProgram(const GrGLProgram::Desc& desc, const GrEffectStage* stages[]); private: enum { - kKeySize = sizeof(ProgramDesc), + kKeySize = sizeof(GrGLProgram::Desc), // We may actually have kMaxEntries+1 shaders in the GL context because we create a new // shader before evicting from the cache. kMaxEntries = 32 @@ -184,16 +181,10 @@ private: const GrGLContextInfo& fGL; }; - // 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(DrawType type); - // flushes dithering, color-mask, and face culling stat void flushMiscFixedFunctionState(); @@ -201,11 +192,6 @@ private: // flushing the scissor after that function is called. void flushScissor(); - void buildProgram(bool isPoints, - GrDrawState::BlendOptFlags blendOpts, - GrBlendCoeff dstCoeff, - ProgramDesc* desc); - // Inits GrDrawTarget::Caps, subclass may enable additional caps. void initCaps(); @@ -266,8 +252,8 @@ private: ///@{ int fHWActiveTextureUnitIdx; GrGLuint fHWProgramID; - GrColor fHWConstAttribColor; - GrColor fHWConstAttribCoverage; + + GrGLProgram::SharedGLState fSharedGLProgramState; enum TriState { kNo_TriState, diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 570ca19fd8..feff02e94d 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -31,7 +31,7 @@ void GrGpuGL::ProgramCache::abandon() { fCount = 0; } -GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, +GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgram::Desc& desc, const GrEffectStage* stages[]) { Entry newEntry; newEntry.fKey.setKeyData(desc.asKey()); @@ -174,101 +174,6 @@ void GrGpuGL::flushViewMatrix(DrawType type) { } } -/////////////////////////////////////////////////////////////////////////////// - -void GrGpuGL::flushColor(GrColor color) { - const ProgramDesc& desc = fCurrentProgram->getDesc(); - const GrDrawState& drawState = this->getDrawState(); - - if (drawState.getVertexLayout() & GrDrawState::kColor_VertexLayoutBit) { - // color will be specified per-vertex as an attribute - // invalidate the const vertex attrib color - fHWConstAttribColor = GrColor_ILLEGAL; - } else { - switch (desc.fColorInput) { - case ProgramDesc::kAttribute_ColorInput: - if (fHWConstAttribColor != color) { - // OpenGL ES only supports the float varieties of glVertexAttrib - GrGLfloat c[4]; - GrColorToRGBAFloat(color, c); - GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c)); - fHWConstAttribColor = color; - } - break; - case ProgramDesc::kUniform_ColorInput: - if (fCurrentProgram->fColor != color) { - // OpenGL ES doesn't support unsigned byte varieties of glUniform - GrGLfloat c[4]; - GrColorToRGBAFloat(color, c); - GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniformHandles.fColorUni); - fCurrentProgram->fUniformManager.set4fv( - fCurrentProgram->fUniformHandles.fColorUni, - 0, 1, c); - fCurrentProgram->fColor = color; - } - break; - case ProgramDesc::kSolidWhite_ColorInput: - case ProgramDesc::kTransBlack_ColorInput: - break; - default: - GrCrash("Unknown color type."); - } - } - UniformHandle filterColorUni = fCurrentProgram->fUniformHandles.fColorFilterUni; - if (kInvalidUniformHandle != filterColorUni && - fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) { - GrGLfloat c[4]; - GrColorToRGBAFloat(drawState.getColorFilterColor(), c); - fCurrentProgram->fUniformManager.set4fv(filterColorUni, 0, 1, c); - fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor(); - } -} - -void GrGpuGL::flushCoverage(GrColor coverage) { - const ProgramDesc& desc = fCurrentProgram->getDesc(); - // const GrDrawState& drawState = this->getDrawState(); - - - if (this->getDrawState().getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit) { - // coverage will be specified per-vertex as an attribute - // invalidate the const vertex attrib coverage - fHWConstAttribCoverage = GrColor_ILLEGAL; - } else { - switch (desc.fCoverageInput) { - case ProgramDesc::kAttribute_ColorInput: - if (fHWConstAttribCoverage != coverage) { - // OpenGL ES only supports the float varieties of - // glVertexAttrib - GrGLfloat c[4]; - GrColorToRGBAFloat(coverage, c); - GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), - c)); - fHWConstAttribCoverage = coverage; - } - break; - case ProgramDesc::kUniform_ColorInput: - if (fCurrentProgram->fCoverage != coverage) { - // OpenGL ES doesn't support unsigned byte varieties of - // glUniform - GrGLfloat c[4]; - GrColorToRGBAFloat(coverage, c); - GrAssert(kInvalidUniformHandle != - fCurrentProgram->fUniformHandles.fCoverageUni); - fCurrentProgram->fUniformManager.set4fv( - fCurrentProgram->fUniformHandles.fCoverageUni, - 0, 1, c); - fCurrentProgram->fCoverage = coverage; - } - break; - case ProgramDesc::kSolidWhite_ColorInput: - case ProgramDesc::kTransBlack_ColorInput: - break; - default: - GrCrash("Unknown coverage type."); - } - } -} - bool GrGpuGL::flushGraphicsState(DrawType type) { const GrDrawState& drawState = this->getDrawState(); @@ -291,7 +196,13 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL; } GrGLProgram::Desc desc; - this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, &desc); + GrGLProgram::BuildDesc(this->getDrawState(), + kDrawPoints_DrawType == type, + blendOpts, + srcCoeff, + dstCoeff, + this, + &desc); fCurrentProgram.reset(fProgramCache->getProgram(desc, stages)); if (NULL == fCurrentProgram.get()) { @@ -319,10 +230,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { color = drawState.getColor(); coverage = drawState.getCoverage(); } - this->flushColor(color); - this->flushCoverage(coverage); - - fCurrentProgram->setData(this); + fCurrentProgram->setData(this, color, coverage, &fSharedGLProgramState); } this->flushStencil(type); this->flushViewMatrix(type); @@ -399,6 +307,7 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { } if (newColorOffset > 0) { + fSharedGLProgramState.fConstAttribColor = GrColor_ILLEGAL; GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); int idx = GrGLProgram::ColorAttributeIdx(); if (oldColorOffset <= 0) { @@ -412,6 +321,7 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { } if (newCoverageOffset > 0) { + fSharedGLProgramState.fConstAttribColor = GrColor_ILLEGAL; GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); int idx = GrGLProgram::CoverageAttributeIdx(); if (oldCoverageOffset <= 0) { @@ -442,146 +352,3 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { fHWGeometryState.fVertexLayout = currLayout; fHWGeometryState.fArrayPtrsDirty = false; } - -void GrGpuGL::buildProgram(bool isPoints, - GrDrawState::BlendOptFlags blendOpts, - GrBlendCoeff dstCoeff, - ProgramDesc* desc) { - const GrDrawState& drawState = this->getDrawState(); - - // 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 vertex - // layout 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->fVertexLayout = this->getDrawState().getVertexLayout(); - - desc->fEmitsPointSize = isPoints; - - bool requiresAttributeColors = !skipColor && - SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit); - bool requiresAttributeCoverage = !skipCoverage && - SkToBool(desc->fVertexLayout & GrDrawState::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 &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); - - 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->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); - } - - bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); - bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) || - (!requiresAttributeColors && 0xffffffff == drawState.getColor()); - if (colorIsTransBlack) { - desc->fColorInput = ProgramDesc::kTransBlack_ColorInput; - } else if (colorIsSolidWhite) { - desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput; - } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { - desc->fColorInput = ProgramDesc::kUniform_ColorInput; - } 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; - } - - int lastEnabledStage = -1; - - if (!skipCoverage && (desc->fVertexLayout &GrDrawState::kEdge_VertexLayoutBit)) { - desc->fVertexEdgeType = drawState.getVertexEdgeType(); - desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite(); - } else { - // Use canonical values when edge-aa is not enabled to avoid program cache misses. - desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType; - desc->fDiscardIfOutsideEdge = false; - } - - 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(); - desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), this->glCaps()); - } else { - desc->fEffectKeys[s] = 0; - } - } - - desc->fDualSrcOutput = ProgramDesc::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 0 && GR_GL_EXPERIMENTAL_GS - desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport; -#endif - - // We want to avoid generating programs with different "first cov stage" values when they would - // compute the same result. We set field in the desc to kNumStages when either there are no - // coverage stages or the distinction between coverage and color is immaterial. - int firstCoverageStage = GrDrawState::kNumStages; - desc->fFirstCoverageStage = GrDrawState::kNumStages; - bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; - if (hasCoverage) { - firstCoverageStage = drawState.getFirstCoverageStage(); - } - - // other coverage inputs - if (!hasCoverage) { - hasCoverage = requiresAttributeCoverage || - (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit); - } - - if (hasCoverage) { - // color filter is applied between color/coverage computation - if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { - desc->fFirstCoverageStage = firstCoverageStage; - } - - if (this->getCaps().dualSourceBlendingSupport() && - !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | - GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { - if (kZero_GrBlendCoeff == dstCoeff) { - // write the coverage value to second color - desc->fDualSrcOutput = ProgramDesc::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 = ProgramDesc::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 = ProgramDesc::kCoverageISC_DualSrcOutput; - desc->fFirstCoverageStage = firstCoverageStage; - } - } - } -} |