From 170f90b4576f291879371ecd6ae4bc2b1d85c64a Mon Sep 17 00:00:00 2001 From: egdaniel Date: Tue, 16 Sep 2014 12:54:40 -0700 Subject: [PATCH] Attach GrOptDrawState into shader building pipeline The OptDrawState is now used for creating the actual gl shader. Current optimizations dones in GrOptDrawState include: All blend optimizations Constant color/coverage stage optimizations BUG=skia: Committed: https://skia.googlesource.com/skia/+/ee6206572b42fec11f83ad0c1e6d435903640518 R=bsalomon@google.com, joshualitt@google.com Author: egdaniel@google.com Review URL: https://codereview.chromium.org/504203004 --- src/gpu/GrDrawState.cpp | 30 ++- src/gpu/GrDrawState.h | 17 +- src/gpu/GrOptDrawState.cpp | 46 +++- src/gpu/GrOptDrawState.h | 30 ++- src/gpu/GrRODrawState.cpp | 31 +-- src/gpu/GrRODrawState.h | 113 ++++------ src/gpu/gl/GrGLProgram.cpp | 46 ++-- src/gpu/gl/GrGLProgram.h | 10 +- src/gpu/gl/GrGLProgramDesc.cpp | 199 +++++++----------- src/gpu/gl/GrGLProgramDesc.h | 12 +- src/gpu/gl/GrGpuGL.cpp | 1 + src/gpu/gl/GrGpuGL_program.cpp | 46 ++-- .../gl/builders/GrGLVertexShaderBuilder.cpp | 11 +- 13 files changed, 272 insertions(+), 320 deletions(-) diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 642ec2669f..f639744665 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -15,9 +15,17 @@ GrOptDrawState* GrDrawState::createOptState() const { if (NULL == fCachedOptState) { - fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this)); + GrBlendCoeff srcCoeff; + GrBlendCoeff dstCoeff; + BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff); + fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff)); } else { - SkASSERT(GrOptDrawState(*this) == *fCachedOptState); +#ifdef SK_DEBUG + GrBlendCoeff srcCoeff; + GrBlendCoeff dstCoeff; + BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff); + SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff) == *fCachedOptState); +#endif } fCachedOptState->ref(); return fCachedOptState; @@ -106,9 +114,6 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) { } fColorStages = that.fColorStages; fCoverageStages = that.fCoverageStages; - fOptSrcBlend = that.fOptSrcBlend; - fOptDstBlend = that.fOptDstBlend; - fBlendOptFlags = that.fBlendOptFlags; fHints = that.fHints; @@ -299,7 +304,7 @@ bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const { // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color GrBlendCoeff srcCoeff; GrBlendCoeff dstCoeff; - GrRODrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff); + BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff); return GrRODrawState::kNone_BlendOpt != flag || (this->willEffectReadDstColor() && kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff); @@ -455,3 +460,16 @@ void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& co } } +//////////////////////////////////////////////////////////////////////////////// + +void GrDrawState::invalidateOptState() const { + SkSafeSetNull(fCachedOptState); +} + +//////////////////////////////////////////////////////////////////////////////// + +GrDrawState::~GrDrawState() { + SkSafeUnref(fCachedOptState); + SkASSERT(0 == fBlockEffectRemovalCnt); +} + diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 6a1e38056b..4869658b4f 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -9,11 +9,12 @@ #define GrDrawState_DEFINED #include "GrBlend.h" -#include "GrOptDrawState.h" #include "GrProgramResource.h" #include "GrRODrawState.h" #include "effects/GrSimpleTextureEffect.h" +class GrOptDrawState; + /** * Modifiable subclass derived from GrRODrawState. The majority of the data that represents a draw * state is stored in the parent class. GrDrawState contains methods for setting, adding to, etc. @@ -47,10 +48,7 @@ public: **/ GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix); - virtual ~GrDrawState() { - SkSafeUnref(fCachedOptState); - SkASSERT(0 == fBlockEffectRemovalCnt); - } + virtual ~GrDrawState(); /** * Resets to the default state. GrEffects will be removed from all stages. @@ -552,17 +550,10 @@ public: GrOptDrawState* createOptState() const; private: - void invalidateOptState() const { - SkSafeSetNull(fCachedOptState); - fBlendOptFlags = kInvalid_BlendOptFlag; - } + void invalidateOptState() const; void onReset(const SkMatrix* initialViewMatrix); - void invalidateBlendOptFlags() { - fBlendOptFlags = kInvalid_BlendOptFlag; - } - // Some of the auto restore objects assume that no effects are removed during their lifetime. // This is used to assert that this condition holds. SkDEBUGCODE(int fBlockEffectRemovalCnt;) diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp index 83546ba3b7..5f352966b8 100644 --- a/src/gpu/GrOptDrawState.cpp +++ b/src/gpu/GrOptDrawState.cpp @@ -9,7 +9,10 @@ #include "GrDrawState.h" -GrOptDrawState::GrOptDrawState(const GrDrawState& drawState) : INHERITED(drawState) { +GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, + BlendOptFlags blendOptFlags, + GrBlendCoeff optSrcCoeff, + GrBlendCoeff optDstCoeff) : INHERITED(drawState) { fColor = drawState.getColor(); fCoverage = drawState.getCoverage(); fViewMatrix = drawState.getViewMatrix(); @@ -20,13 +23,15 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState) : INHERITED(drawSta fVAStride = drawState.getVertexStride(); fStencilSettings = drawState.getStencil(); fDrawFace = drawState.getDrawFace(); - - fBlendOptFlags = drawState.getBlendOpts(false, &fSrcBlend, &fDstBlend); + fBlendOptFlags = blendOptFlags; + fSrcBlend = optSrcCoeff; + fDstBlend = optDstCoeff; memcpy(fFixedFunctionVertexAttribIndices, drawState.getFixedFunctionVertexAttribIndices(), sizeof(fFixedFunctionVertexAttribIndices)); + fInputColorIsUsed = true; fInputCoverageIsUsed = true; @@ -38,8 +43,40 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState) : INHERITED(drawSta this->copyEffectiveColorStages(drawState); this->copyEffectiveCoverageStages(drawState); + this->adjustFromBlendOpts(); }; +void GrOptDrawState::adjustFromBlendOpts() { + + switch (fBlendOptFlags) { + case kNone_BlendOpt: + case kSkipDraw_BlendOptFlag: + break; + case kCoverageAsAlpha_BlendOptFlag: + fFlagBits |= kCoverageDrawing_StateBit; + break; + case kEmitCoverage_BlendOptFlag: + fColor = 0xffffffff; + fInputColorIsUsed = true; + fColorStages.reset(); + this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding); + break; + case kEmitTransBlack_BlendOptFlag: + fColor = 0; + fCoverage = 0xff; + fInputColorIsUsed = true; + fInputCoverageIsUsed = true; + fColorStages.reset(); + fCoverageStages.reset(); + this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding | + 0x1 << kCoverage_GrVertexAttribBinding); + break; + default: + SkFAIL("Unknown BlendOptFlag"); + + } +} + void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) { int numToRemove = 0; uint8_t maskCheck = 0x1; @@ -50,6 +87,7 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) { } maskCheck <<= 1; } + fOptVA.reset(fVACount - numToRemove); GrVertexAttrib* dst = fOptVA.get(); @@ -64,9 +102,9 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) { fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1; continue; } + fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx; } memcpy(dst, src, sizeof(GrVertexAttrib)); - fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx; ++newIdx; ++dst; } diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h index a4edc01c8a..457f035423 100644 --- a/src/gpu/GrOptDrawState.h +++ b/src/gpu/GrOptDrawState.h @@ -8,10 +8,9 @@ #ifndef GrOptDrawState_DEFINED #define GrOptDrawState_DEFINED +#include "GrDrawState.h" #include "GrRODrawState.h" -class GrDrawState; - /** * Subclass of GrRODrawState that holds an optimized version of a GrDrawState. Like it's parent * it is meant to be an immutable class, and simply adds a few helpful data members not in the @@ -19,15 +18,19 @@ class GrDrawState; */ class GrOptDrawState : public GrRODrawState { public: + bool operator== (const GrOptDrawState& that) const; + + bool inputColorIsUsed() const { return fInputColorIsUsed; } + bool inputCoverageIsUsed() const { return fInputCoverageIsUsed; } + +private: /** * Constructs and optimized drawState out of a GrRODrawState. */ - explicit GrOptDrawState(const GrDrawState& drawState); + GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags, + GrBlendCoeff optSrcCoeff, GrBlendCoeff optDstCoeff); - bool operator== (const GrOptDrawState& that) const; - -private: - /* + /** * Loops through all the color stage effects to check if the stage will ignore color input or * always output a constant color. In the ignore color input case we can ignore all previous * stages. In the constant color case, we can ignore all previous stages and @@ -37,7 +40,7 @@ private: */ void copyEffectiveColorStages(const GrDrawState& ds); - /* + /** * Loops through all the coverage stage effects to check if the stage will ignore color input. * If a coverage stage will ignore input, then we can ignore all coverage stages before it. We * loop to determine the first effective coverage stage, and then copy all of our effective @@ -45,14 +48,18 @@ private: */ void copyEffectiveCoverageStages(const GrDrawState& ds); - /* + /** * This function takes in a flag and removes the corresponding fixed function vertex attributes. * The flags are in the same order as GrVertexAttribBinding array. If bit i of removeVAFlags is * set, then vertex attributes with binding (GrVertexAttribute)i will be removed. */ void removeFixedFunctionVertexAttribs(uint8_t removeVAFlags); - void removeColorVertexAttrib(); + /** + * Alter the OptDrawState (adjusting stages, vertex attribs, flags, etc.) based on the + * BlendOptFlags. + */ + void adjustFromBlendOpts(); // These flags are needed to protect the code from creating an unused uniform color/coverage // which will cause shader compiler errors. @@ -61,6 +68,9 @@ private: SkAutoSTArray<4, GrVertexAttrib> fOptVA; + BlendOptFlags fBlendOptFlags; + + friend GrOptDrawState* GrDrawState::createOptState() const; typedef GrRODrawState INHERITED; }; diff --git a/src/gpu/GrRODrawState.cpp b/src/gpu/GrRODrawState.cpp index f7e486f925..26edb18c06 100644 --- a/src/gpu/GrRODrawState.cpp +++ b/src/gpu/GrRODrawState.cpp @@ -184,26 +184,6 @@ GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage, dstCoeff = &bogusDstCoeff; } - if (forceCoverage) { - return this->calcBlendOpts(true, srcCoeff, dstCoeff); - } - - if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) { - *srcCoeff = fOptSrcBlend; - *dstCoeff = fOptDstBlend; - return fBlendOptFlags; - } - - fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff); - fOptSrcBlend = *srcCoeff; - fOptDstBlend = *dstCoeff; - - return fBlendOptFlags; -} - -GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage, - GrBlendCoeff* srcCoeff, - GrBlendCoeff* dstCoeff) const { *srcCoeff = this->getSrcBlendCoeff(); *dstCoeff = this->getDstBlendCoeff(); @@ -225,6 +205,7 @@ GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage, if (this->getStencil().doesWrite()) { return kEmitCoverage_BlendOptFlag; } else { + *dstCoeff = kOne_GrBlendCoeff; return kSkipDraw_BlendOptFlag; } } @@ -372,13 +353,3 @@ bool GrRODrawState::srcAlphaWillBeOne() const { return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color); } -//////////////////////////////////////////////////////////////////////////////// - -bool GrRODrawState::canIgnoreColorAttribute() const { - if (fBlendOptFlags & kInvalid_BlendOptFlag) { - this->getBlendOpts(); - } - return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFlag | - GrRODrawState::kEmitCoverage_BlendOptFlag)); -} - diff --git a/src/gpu/GrRODrawState.h b/src/gpu/GrRODrawState.h index d748e7d83a..eea6f9b98a 100644 --- a/src/gpu/GrRODrawState.h +++ b/src/gpu/GrRODrawState.h @@ -166,12 +166,6 @@ public: */ GrColor getBlendConstant() const { return fBlendConstant; } - /** - * We don't use supplied vertex color attributes if our blend mode is EmitCoverage or - * EmitTransBlack - */ - bool canIgnoreColorAttribute() const; - /** * Determines whether multiplying the computed per-pixel color by the pixel's fractional * coverage before the blend will give the correct final destination color. In general it @@ -179,56 +173,6 @@ public: */ bool canTweakAlphaForCoverage() const; - /** - * Optimizations for blending / coverage to that can be applied based on the current state. - */ - enum BlendOptFlags { - /** - * No optimization - */ - kNone_BlendOpt = 0, - /** - * Don't draw at all - */ - kSkipDraw_BlendOptFlag = 0x1, - /** - * The coverage value does not have to be computed separately from alpha, the output - * color can be the modulation of the two. - */ - kCoverageAsAlpha_BlendOptFlag = 0x2, - /** - * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are - * "don't cares". - */ - kEmitCoverage_BlendOptFlag = 0x4, - /** - * Emit transparent black instead of the src color, no need to compute coverage. - */ - kEmitTransBlack_BlendOptFlag = 0x8, - /** - * Flag used to invalidate the cached BlendOptFlags, OptSrcCoeff, and OptDstCoeff cached by - * the get BlendOpts function. - */ - kInvalid_BlendOptFlag = 1 << 31, - }; - GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags); - - /** - * Determines what optimizations can be applied based on the blend. The coefficients may have - * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional - * params that receive the tweaked coefficients. Normally the function looks at the current - * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively - * determine the blend optimizations that would be used if there was partial pixel coverage. - * - * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for - * playback) must call this function and respect the flags that replace the output color. - * - * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will - * simply returned the cached flags and coefficients. Otherwise it will calculate the values. - */ - BlendOptFlags getBlendOpts(bool forceCoverage = false, - GrBlendCoeff* srcCoeff = NULL, - GrBlendCoeff* dstCoeff = NULL) const; /// @} /////////////////////////////////////////////////////////////////////////// @@ -407,6 +351,52 @@ protected: bool isEqual(const GrRODrawState& that) const; + /** + * Optimizations for blending / coverage to that can be applied based on the current state. + */ + enum BlendOptFlags { + /** + * No optimization + */ + kNone_BlendOpt = 0, + /** + * Don't draw at all + */ + kSkipDraw_BlendOptFlag = 0x1, + /** + * The coverage value does not have to be computed separately from alpha, the the output + * color can be the modulation of the two. + */ + kCoverageAsAlpha_BlendOptFlag = 0x2, + /** + * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are + * "don't cares". + */ + kEmitCoverage_BlendOptFlag = 0x4, + /** + * Emit transparent black instead of the src color, no need to compute coverage. + */ + kEmitTransBlack_BlendOptFlag = 0x8, + }; + GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags); + + /** + * Determines what optimizations can be applied based on the blend. The coefficients may have + * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional + * params that receive the tweaked coefficients. Normally the function looks at the current + * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively + * determine the blend optimizations that would be used if there was partial pixel coverage. + * + * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for + * playback) must call this function and respect the flags that replace the output color. + * + * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will + * simply returned the cached flags and coefficients. Otherwise it will calculate the values. + */ + BlendOptFlags getBlendOpts(bool forceCoverage = false, + GrBlendCoeff* srcCoeff = NULL, + GrBlendCoeff* dstCoeff = NULL) const; + // These fields are roughly sorted by decreasing likelihood of being different in op== GrProgramResource fRenderTarget; GrColor fColor; @@ -429,10 +419,6 @@ protected: uint32_t fHints; - mutable GrBlendCoeff fOptSrcBlend; - mutable GrBlendCoeff fOptDstBlend; - mutable BlendOptFlags fBlendOptFlags; - // This is simply a different representation of info in fVertexAttribs and thus does // not need to be compared in op==. int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; @@ -443,13 +429,6 @@ private: */ bool srcAlphaWillBeOne() const; - /** - * Helper function for getBlendOpts. - */ - BlendOptFlags calcBlendOpts(bool forceCoverage = false, - GrBlendCoeff* srcCoeff = NULL, - GrBlendCoeff* dstCoeff = NULL) const; - typedef SkRefCnt INHERITED; }; diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 1ad05eb9c9..112cecd995 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -4,7 +4,6 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - #include "GrGLProgram.h" #include "GrAllocator.h" @@ -15,6 +14,7 @@ #include "GrGLPathRendering.h" #include "GrGLShaderVar.h" #include "GrGLSL.h" +#include "GrOptDrawState.h" #include "SkXfermode.h" #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) @@ -108,31 +108,19 @@ void GrGLProgram::initSamplerUniforms() { /////////////////////////////////////////////////////////////////////////////// -void GrGLProgram::setData(GrGpu::DrawType drawType, - GrDrawState::BlendOptFlags blendOpts, +void GrGLProgram::setData(const GrOptDrawState& optState, + GrGpu::DrawType drawType, const GrEffectStage* geometryProcessor, const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[], const GrDeviceCoordTexture* dstCopy, SharedGLState* sharedState) { - const GrDrawState& drawState = fGpu->getDrawState(); + GrColor color = optState.getColor(); + GrColor coverage = optState.getCoverageColor(); - GrColor color; - GrColor coverage; - if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) { - color = 0; - coverage = 0; - } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) { - color = 0xffffffff; - coverage = drawState.getCoverageColor(); - } else { - color = drawState.getColor(); - coverage = drawState.getCoverageColor(); - } - - this->setColor(drawState, color, sharedState); - this->setCoverage(drawState, coverage, sharedState); - this->setMatrixAndRenderTargetHeight(drawType, drawState); + this->setColor(optState, color, sharedState); + this->setCoverage(optState, coverage, sharedState); + this->setMatrixAndRenderTargetHeight(drawType, optState); if (dstCopy) { if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) { @@ -170,11 +158,11 @@ void GrGLProgram::setData(GrGpu::DrawType drawType, } } -void GrGLProgram::setColor(const GrDrawState& drawState, +void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color, SharedGLState* sharedState) { const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); - if (!drawState.hasColorVertexAttribute() || drawState.canIgnoreColorAttribute()) { + if (!optState.hasColorVertexAttribute()) { switch (header.fColorInput) { case GrGLProgramDesc::kAttribute_ColorInput: SkASSERT(-1 != header.fColorAttributeIndex); @@ -209,11 +197,11 @@ void GrGLProgram::setColor(const GrDrawState& drawState, } } -void GrGLProgram::setCoverage(const GrDrawState& drawState, +void GrGLProgram::setCoverage(const GrOptDrawState& optState, GrColor coverage, SharedGLState* sharedState) { const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); - if (!drawState.hasCoverageVertexAttribute()) { + if (!optState.hasCoverageVertexAttribute()) { switch (header.fCoverageInput) { case GrGLProgramDesc::kAttribute_ColorInput: if (sharedState->fConstAttribCoverage != coverage || @@ -248,8 +236,8 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState, } void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, - const GrDrawState& drawState) { - const GrRenderTarget* rt = drawState.getRenderTarget(); + const GrOptDrawState& optState) { + const GrRenderTarget* rt = optState.getRenderTarget(); SkISize size; size.set(rt->width(), rt->height()); @@ -261,13 +249,13 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, } if (GrGpu::IsPathRenderingDrawType(drawType)) { - fGpu->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); + fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin()); } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || fMatrixState.fRenderTargetSize != size || - !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) { + !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) { SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid()); - fMatrixState.fViewMatrix = drawState.getViewMatrix(); + fMatrixState.fViewMatrix = optState.getViewMatrix(); fMatrixState.fRenderTargetSize = size; fMatrixState.fRenderTargetOrigin = rt->origin(); diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 0f89e07b0d..a520bc20de 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -157,8 +157,8 @@ public: * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage * stages come from GrGLProgramDesc::Build(). */ - void setData(GrGpu::DrawType, - GrDrawState::BlendOptFlags, + void setData(const GrOptDrawState&, + GrGpu::DrawType, const GrEffectStage* geometryProcessor, const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[], @@ -177,14 +177,14 @@ private: // 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*); + void setColor(const GrOptDrawState&, 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*); + void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*); // Helper for setData() that sets the view matrix and loads the render target height uniform - void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrDrawState&); + void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState&); // these reflect the current values of uniforms (GL uniform values travel with program) MatrixState fMatrixState; diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 4056c77808..b49cff97af 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -10,6 +10,7 @@ #include "GrBackendEffectFactory.h" #include "GrEffect.h" #include "GrGpuGL.h" +#include "GrOptDrawState.h" #include "SkChecksum.h" @@ -48,9 +49,8 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage, return true; } -bool GrGLProgramDesc::Build(const GrDrawState& drawState, +bool GrGLProgramDesc::Build(const GrOptDrawState& optState, GrGpu::DrawType drawType, - GrDrawState::BlendOptFlags blendOpts, GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff, const GrGpuGL* gpu, @@ -62,47 +62,19 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, colorStages->reset(); coverageStages->reset(); - // 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(); - } - } + bool inputColorIsUsed = optState.inputColorIsUsed(); + bool inputCoverageIsUsed = optState.inputColorIsUsed(); // 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 = !skipColor && drawState.hasColorVertexAttribute(); - bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute(); + bool requiresColorAttrib = optState.hasColorVertexAttribute(); + bool requiresCoverageAttrib = optState.hasCoverageVertexAttribute(); // we only need the local coords if we're actually going to generate effect code - bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) && - drawState.hasLocalCoordAttribute(); + bool requiresLocalCoordAttrib = optState.numTotalStages() > 0 && + optState.hasLocalCoordAttribute(); bool readsDst = false; bool readFragPosition = false; @@ -110,16 +82,8 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, // Provide option for shader programs without vertex shader only when drawing paths. bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType); - int numStages = 0; - if (drawState.hasGeometryProcessor()) { - numStages++; - } - if (!skipColor) { - numStages += drawState.numColorStages() - firstEffectiveColorStage; - } - if (!skipCoverage) { - numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage; - } + int numStages = optState.numTotalStages(); + 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(); @@ -133,7 +97,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, memset(desc->header(), 0, kHeaderSize); // We can only have one effect which touches the vertex shader - if (drawState.hasGeometryProcessor()) { + if (optState.hasGeometryProcessor()) { uint16_t* offsetAndSize = reinterpret_cast(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + offsetAndSizeIndex * 2 * sizeof(uint16_t)); @@ -142,7 +106,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, uint16_t effectKeySize; uint32_t effectOffset = desc->fKey.count(); effectKeySuccess |= GetEffectKeyAndUpdateStats( - *drawState.getGeometryProcessor(), gpu->glCaps(), + *optState.getGeometryProcessor(), gpu->glCaps(), requiresLocalCoordAttrib, &b, &effectKeySize, &readsDst, &readFragPosition, &requiresVertexShader); @@ -151,57 +115,55 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, offsetAndSize[0] = SkToU16(effectOffset); offsetAndSize[1] = effectKeySize; ++offsetAndSizeIndex; - *geometryProcessor = drawState.getGeometryProcessor(); + *geometryProcessor = optState.getGeometryProcessor(); SkASSERT(requiresVertexShader); header->fHasGeometryProcessor = true; } - if (!skipColor) { - for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { - uint16_t* offsetAndSize = - reinterpret_cast(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + - offsetAndSizeIndex * 2 * sizeof(uint16_t)); + for (int s = 0; s < optState.numColorStages(); ++s) { + uint16_t* offsetAndSize = + reinterpret_cast(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); + 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); - } + 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(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); + for (int s = 0; s < optState.numCoverageStages(); ++s) { + uint16_t* offsetAndSize = + reinterpret_cast(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + + offsetAndSizeIndex * 2 * sizeof(uint16_t)); - offsetAndSize[0] = SkToU16(effectOffset); - offsetAndSize[1] = effectKeySize; - ++offsetAndSizeIndex; - SkASSERT(!effectRequiresVertexShader); - } + 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 (!effectKeySuccess) { desc->fKey.reset(); return false; @@ -224,20 +186,20 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, #endif bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport(); - if (!inputColorIsUsed && !skipColor) { + if (!inputColorIsUsed) { header->fColorInput = kAllOnes_ColorInput; - } else if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) { + } else if (defaultToUniformInputs && !requiresColorAttrib) { header->fColorInput = kUniform_ColorInput; } else { header->fColorInput = kAttribute_ColorInput; header->fRequiresVertexShader = true; } - bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor(); + bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == optState.getCoverageColor(); - if ((covIsSolidWhite || !inputCoverageIsUsed) && !skipCoverage) { + if (covIsSolidWhite || !inputCoverageIsUsed) { header->fCoverageInput = kAllOnes_ColorInput; - } else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) { + } else if (defaultToUniformInputs && !requiresCoverageAttrib) { header->fCoverageInput = kUniform_ColorInput; } else { header->fCoverageInput = kAttribute_ColorInput; @@ -259,19 +221,19 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, if (readFragPosition) { header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition( - drawState.getRenderTarget(), gpu->glCaps()); + optState.getRenderTarget(), gpu->glCaps()); } else { header->fFragPosKey = 0; } // Record attribute indices - header->fPositionAttributeIndex = drawState.positionAttributeIndex(); - header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); + header->fPositionAttributeIndex = optState.positionAttributeIndex(); + header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex(); // For constant color and coverage we need an attribute with an index beyond those already set - int availableAttributeIndex = drawState.getVertexAttribCount(); + int availableAttributeIndex = optState.getVertexAttribCount(); if (requiresColorAttrib) { - header->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); + header->fColorAttributeIndex = optState.colorVertexAttributeIndex(); } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); header->fColorAttributeIndex = availableAttributeIndex; @@ -281,7 +243,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, } if (requiresCoverageAttrib) { - header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); + header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex(); } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); header->fCoverageAttributeIndex = availableAttributeIndex; @@ -295,15 +257,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, header->fCoverageOutput = kModulate_CoverageOutput; // If we do have coverage determine whether it matters. - bool separateCoverageFromColor = drawState.hasGeometryProcessor(); - if (!drawState.isCoverageDrawing() && !skipCoverage && - (drawState.numCoverageStages() > 0 || - drawState.hasGeometryProcessor() || + bool separateCoverageFromColor = optState.hasGeometryProcessor(); + if (!optState.isCoverageDrawing() && + (optState.numCoverageStages() > 0 || + optState.hasGeometryProcessor() || requiresCoverageAttrib)) { - if (gpu->caps()->dualSourceBlendingSupport() && - !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | - GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { + if (gpu->caps()->dualSourceBlendingSupport()) { if (kZero_GrBlendCoeff == dstCoeff) { // write the coverage value to second color header->fCoverageOutput = kSecondaryCoverage_CoverageOutput; @@ -325,22 +285,19 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, } } - if (!skipColor) { - for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { - colorStages->push_back(&drawState.getColorStage(s)); - } + for (int s = 0; s < optState.numColorStages(); ++s) { + colorStages->push_back(&optState.getColorStage(s)); } - if (!skipCoverage) { - SkTArray* array; - if (separateCoverageFromColor) { - array = coverageStages; - } else { - array = colorStages; - } - for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { - array->push_back(&drawState.getCoverageStage(s)); - } + SkTArray* array; + if (separateCoverageFromColor) { + array = coverageStages; + } else { + array = colorStages; } + for (int s = 0; s < optState.numCoverageStages(); ++s) { + array->push_back(&optState.getCoverageStage(s)); + } + header->fColorEffectCnt = colorStages->count(); header->fCoverageEffectCnt = coverageStages->count(); diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index b1f54b7e29..e91dbe0950 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -55,15 +55,13 @@ public: int currAttribIndex); /** - * 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. It also - * outputs the color and coverage stages referenced by the generated descriptor. This may - * not contain all stages from the draw state and coverage stages from the drawState may - * be treated as color stages in the output. + * Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and + * the caps of the GrGpuGL are also inputs. It also outputs the color and coverage stages + * referenced by the generated descriptor. Coverage stages from the drawState may be treated as + * color stages in the output. */ - static bool Build(const GrDrawState&, + static bool Build(const GrOptDrawState&, GrGpu::DrawType drawType, - GrDrawState::BlendOptFlags, GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff, const GrGpuGL* gpu, diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index c335e128c7..5ff868ccaf 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -8,6 +8,7 @@ #include "GrGpuGL.h" #include "GrGLStencilBuffer.h" +#include "GrOptDrawState.h" #include "GrTemplates.h" #include "GrTypes.h" #include "SkStrokeRec.h" diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index be21abf3e9..476f174cdc 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -9,8 +9,9 @@ #include "GrEffect.h" #include "GrGLEffect.h" -#include "SkRTConf.h" #include "GrGLPathRendering.h" +#include "GrOptDrawState.h" +#include "SkRTConf.h" #include "SkTSearch.h" #ifdef PROGRAM_CACHE_STATS @@ -204,23 +205,25 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { - const GrDrawState& drawState = this->getDrawState(); + SkAutoTUnref optState(this->getDrawState().createOptState()); // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. - SkASSERT(drawState.getRenderTarget()); + SkASSERT(optState->getRenderTarget()); if (kStencilPath_DrawType == type) { - const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); + const GrRenderTarget* rt = optState->getRenderTarget(); SkISize size; size.set(rt->width(), rt->height()); - this->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); + this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(), size, rt->origin()); } else { this->flushMiscFixedFunctionState(); - GrBlendCoeff srcCoeff; - GrBlendCoeff dstCoeff; - GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff); - if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { + GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff(); + GrBlendCoeff dstCoeff = optState->getDstBlendCoeff(); + + // In these blend coeff's we end up drawing nothing so we can skip draw all together + if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff && + !optState->getStencil().doesWrite()) { return false; } @@ -228,9 +231,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC SkSTArray<8, const GrEffectStage*, true> colorStages; SkSTArray<8, const GrEffectStage*, true> coverageStages; GrGLProgramDesc desc; - if (!GrGLProgramDesc::Build(this->getDrawState(), + if (!GrGLProgramDesc::Build(*optState.get(), type, - blendOpts, srcCoeff, dstCoeff, this, @@ -263,8 +265,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); - fCurrentProgram->setData(type, - blendOpts, + fCurrentProgram->setData(*optState.get(), + type, geometryProcessor, colorStages.begin(), coverageStages.begin(), @@ -272,15 +274,15 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC &fSharedGLProgramState); } - GrGLRenderTarget* glRT = static_cast(drawState.getRenderTarget()); + GrGLRenderTarget* glRT = static_cast(optState->getRenderTarget()); this->flushStencil(type); this->flushScissor(glRT->getViewport(), glRT->origin()); this->flushAAState(type); SkIRect* devRect = NULL; SkIRect devClipBounds; - if (drawState.isClipState()) { - this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); + if (optState->isClipState()) { + this->getClip()->getConservativeBounds(optState->getRenderTarget(), &devClipBounds); devRect = &devClipBounds; } // This must come after textures are flushed because a texture may need @@ -291,8 +293,9 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC } void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { + SkAutoTUnref optState(this->getDrawState().createOptState()); - GrGLsizei stride = static_cast(this->getDrawState().getVertexStride()); + GrGLsizei stride = static_cast(optState->getVertexStride()); size_t vertexOffsetInBytes = stride * info.startVertex(); @@ -346,16 +349,12 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); if (fCurrentProgram->hasVertexShader()) { - int vertexAttribCount = this->getDrawState().getVertexAttribCount(); + int vertexAttribCount = optState->getVertexAttribCount(); uint32_t usedAttribArraysMask = 0; - const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); - - bool canIgnoreColorAttrib = this->getDrawState().canIgnoreColorAttribute(); + const GrVertexAttrib* vertexAttrib = optState->getVertexAttribs(); for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; ++vertexAttribIndex, ++vertexAttrib) { - - if (kColor_GrVertexAttribBinding != vertexAttrib->fBinding || !canIgnoreColorAttrib) { usedAttribArraysMask |= (1 << vertexAttribIndex); GrVertexAttribType attribType = vertexAttrib->fType; attribState->set(this, @@ -367,7 +366,6 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { stride, reinterpret_cast( vertexOffsetInBytes + vertexAttrib->fOffset)); - } } attribState->disableUnusedArrays(this, usedAttribArraysMask); } diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index f06c6468cc..5c074a2901 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -9,6 +9,7 @@ #include "GrGLProgramBuilder.h" #include "GrGLShaderStringBuilder.h" #include "../GrGpuGL.h" +#include "../../GrOptDrawState.h" #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) @@ -83,10 +84,12 @@ void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) { coverage_attribute_name())); } - // We pull the current state of attributes off of drawstate and bind them in order - const GrRODrawState* ds = fProgramBuilder->gpu()->drawState(); - const GrVertexAttrib* vaPtr = ds->getVertexAttribs(); - const int vaCount = ds->getVertexAttribCount(); + // We pull the current state of attributes off of drawstate's optimized state and bind them in + // order. This assumes that the drawState has not changed since we called flushGraphicsState() + // higher up in the stack. + SkAutoTUnref optState(fProgramBuilder->gpu()->drawState()->createOptState()); + const GrVertexAttrib* vaPtr = optState->getVertexAttribs(); + const int vaCount = optState->getVertexAttribCount(); int i = fEffectAttribOffset; for (int index = 0; index < vaCount; index++) {