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
This commit is contained in:
egdaniel 2014-09-16 12:54:40 -07:00 committed by Commit bot
parent 3375c8047e
commit 170f90b457
13 changed files with 272 additions and 320 deletions

View File

@ -15,9 +15,17 @@
GrOptDrawState* GrDrawState::createOptState() const { GrOptDrawState* GrDrawState::createOptState() const {
if (NULL == fCachedOptState) { 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 { } 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(); fCachedOptState->ref();
return fCachedOptState; return fCachedOptState;
@ -106,9 +114,6 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
} }
fColorStages = that.fColorStages; fColorStages = that.fColorStages;
fCoverageStages = that.fCoverageStages; fCoverageStages = that.fCoverageStages;
fOptSrcBlend = that.fOptSrcBlend;
fOptDstBlend = that.fOptDstBlend;
fBlendOptFlags = that.fBlendOptFlags;
fHints = that.fHints; 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 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
GrBlendCoeff srcCoeff; GrBlendCoeff srcCoeff;
GrBlendCoeff dstCoeff; GrBlendCoeff dstCoeff;
GrRODrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff); BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
return GrRODrawState::kNone_BlendOpt != flag || return GrRODrawState::kNone_BlendOpt != flag ||
(this->willEffectReadDstColor() && (this->willEffectReadDstColor() &&
kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff); 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);
}

View File

@ -9,11 +9,12 @@
#define GrDrawState_DEFINED #define GrDrawState_DEFINED
#include "GrBlend.h" #include "GrBlend.h"
#include "GrOptDrawState.h"
#include "GrProgramResource.h" #include "GrProgramResource.h"
#include "GrRODrawState.h" #include "GrRODrawState.h"
#include "effects/GrSimpleTextureEffect.h" #include "effects/GrSimpleTextureEffect.h"
class GrOptDrawState;
/** /**
* Modifiable subclass derived from GrRODrawState. The majority of the data that represents a draw * 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. * 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); GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix);
virtual ~GrDrawState() { virtual ~GrDrawState();
SkSafeUnref(fCachedOptState);
SkASSERT(0 == fBlockEffectRemovalCnt);
}
/** /**
* Resets to the default state. GrEffects will be removed from all stages. * Resets to the default state. GrEffects will be removed from all stages.
@ -552,17 +550,10 @@ public:
GrOptDrawState* createOptState() const; GrOptDrawState* createOptState() const;
private: private:
void invalidateOptState() const { void invalidateOptState() const;
SkSafeSetNull(fCachedOptState);
fBlendOptFlags = kInvalid_BlendOptFlag;
}
void onReset(const SkMatrix* initialViewMatrix); 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. // Some of the auto restore objects assume that no effects are removed during their lifetime.
// This is used to assert that this condition holds. // This is used to assert that this condition holds.
SkDEBUGCODE(int fBlockEffectRemovalCnt;) SkDEBUGCODE(int fBlockEffectRemovalCnt;)

View File

@ -9,7 +9,10 @@
#include "GrDrawState.h" #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(); fColor = drawState.getColor();
fCoverage = drawState.getCoverage(); fCoverage = drawState.getCoverage();
fViewMatrix = drawState.getViewMatrix(); fViewMatrix = drawState.getViewMatrix();
@ -20,13 +23,15 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState) : INHERITED(drawSta
fVAStride = drawState.getVertexStride(); fVAStride = drawState.getVertexStride();
fStencilSettings = drawState.getStencil(); fStencilSettings = drawState.getStencil();
fDrawFace = drawState.getDrawFace(); fDrawFace = drawState.getDrawFace();
fBlendOptFlags = blendOptFlags;
fBlendOptFlags = drawState.getBlendOpts(false, &fSrcBlend, &fDstBlend); fSrcBlend = optSrcCoeff;
fDstBlend = optDstCoeff;
memcpy(fFixedFunctionVertexAttribIndices, memcpy(fFixedFunctionVertexAttribIndices,
drawState.getFixedFunctionVertexAttribIndices(), drawState.getFixedFunctionVertexAttribIndices(),
sizeof(fFixedFunctionVertexAttribIndices)); sizeof(fFixedFunctionVertexAttribIndices));
fInputColorIsUsed = true; fInputColorIsUsed = true;
fInputCoverageIsUsed = true; fInputCoverageIsUsed = true;
@ -38,8 +43,40 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState) : INHERITED(drawSta
this->copyEffectiveColorStages(drawState); this->copyEffectiveColorStages(drawState);
this->copyEffectiveCoverageStages(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) { void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
int numToRemove = 0; int numToRemove = 0;
uint8_t maskCheck = 0x1; uint8_t maskCheck = 0x1;
@ -50,6 +87,7 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
} }
maskCheck <<= 1; maskCheck <<= 1;
} }
fOptVA.reset(fVACount - numToRemove); fOptVA.reset(fVACount - numToRemove);
GrVertexAttrib* dst = fOptVA.get(); GrVertexAttrib* dst = fOptVA.get();
@ -64,9 +102,9 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1; fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
continue; continue;
} }
fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
} }
memcpy(dst, src, sizeof(GrVertexAttrib)); memcpy(dst, src, sizeof(GrVertexAttrib));
fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
++newIdx; ++newIdx;
++dst; ++dst;
} }

View File

@ -8,10 +8,9 @@
#ifndef GrOptDrawState_DEFINED #ifndef GrOptDrawState_DEFINED
#define GrOptDrawState_DEFINED #define GrOptDrawState_DEFINED
#include "GrDrawState.h"
#include "GrRODrawState.h" #include "GrRODrawState.h"
class GrDrawState;
/** /**
* Subclass of GrRODrawState that holds an optimized version of a GrDrawState. Like it's parent * 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 * 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 { class GrOptDrawState : public GrRODrawState {
public: 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. * 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 * 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 * 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 * stages. In the constant color case, we can ignore all previous stages and
@ -37,7 +40,7 @@ private:
*/ */
void copyEffectiveColorStages(const GrDrawState& ds); void copyEffectiveColorStages(const GrDrawState& ds);
/* /**
* Loops through all the coverage stage effects to check if the stage will ignore color input. * 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 * 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 * 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); void copyEffectiveCoverageStages(const GrDrawState& ds);
/* /**
* This function takes in a flag and removes the corresponding fixed function vertex attributes. * 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 * 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. * set, then vertex attributes with binding (GrVertexAttribute)i will be removed.
*/ */
void removeFixedFunctionVertexAttribs(uint8_t removeVAFlags); 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 // These flags are needed to protect the code from creating an unused uniform color/coverage
// which will cause shader compiler errors. // which will cause shader compiler errors.
@ -61,6 +68,9 @@ private:
SkAutoSTArray<4, GrVertexAttrib> fOptVA; SkAutoSTArray<4, GrVertexAttrib> fOptVA;
BlendOptFlags fBlendOptFlags;
friend GrOptDrawState* GrDrawState::createOptState() const;
typedef GrRODrawState INHERITED; typedef GrRODrawState INHERITED;
}; };

View File

@ -184,26 +184,6 @@ GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage,
dstCoeff = &bogusDstCoeff; 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(); *srcCoeff = this->getSrcBlendCoeff();
*dstCoeff = this->getDstBlendCoeff(); *dstCoeff = this->getDstBlendCoeff();
@ -225,6 +205,7 @@ GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage,
if (this->getStencil().doesWrite()) { if (this->getStencil().doesWrite()) {
return kEmitCoverage_BlendOptFlag; return kEmitCoverage_BlendOptFlag;
} else { } else {
*dstCoeff = kOne_GrBlendCoeff;
return kSkipDraw_BlendOptFlag; return kSkipDraw_BlendOptFlag;
} }
} }
@ -372,13 +353,3 @@ bool GrRODrawState::srcAlphaWillBeOne() const {
return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color); 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));
}

View File

@ -166,12 +166,6 @@ public:
*/ */
GrColor getBlendConstant() const { return fBlendConstant; } 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 * 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 * coverage before the blend will give the correct final destination color. In general it
@ -179,56 +173,6 @@ public:
*/ */
bool canTweakAlphaForCoverage() const; 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; 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== // These fields are roughly sorted by decreasing likelihood of being different in op==
GrProgramResource fRenderTarget; GrProgramResource fRenderTarget;
GrColor fColor; GrColor fColor;
@ -429,10 +419,6 @@ protected:
uint32_t fHints; 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 // This is simply a different representation of info in fVertexAttribs and thus does
// not need to be compared in op==. // not need to be compared in op==.
int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
@ -443,13 +429,6 @@ private:
*/ */
bool srcAlphaWillBeOne() const; bool srcAlphaWillBeOne() const;
/**
* Helper function for getBlendOpts.
*/
BlendOptFlags calcBlendOpts(bool forceCoverage = false,
GrBlendCoeff* srcCoeff = NULL,
GrBlendCoeff* dstCoeff = NULL) const;
typedef SkRefCnt INHERITED; typedef SkRefCnt INHERITED;
}; };

View File

@ -4,7 +4,6 @@
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrGLProgram.h" #include "GrGLProgram.h"
#include "GrAllocator.h" #include "GrAllocator.h"
@ -15,6 +14,7 @@
#include "GrGLPathRendering.h" #include "GrGLPathRendering.h"
#include "GrGLShaderVar.h" #include "GrGLShaderVar.h"
#include "GrGLSL.h" #include "GrGLSL.h"
#include "GrOptDrawState.h"
#include "SkXfermode.h" #include "SkXfermode.h"
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
@ -108,31 +108,19 @@ void GrGLProgram::initSamplerUniforms() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void GrGLProgram::setData(GrGpu::DrawType drawType, void GrGLProgram::setData(const GrOptDrawState& optState,
GrDrawState::BlendOptFlags blendOpts, GrGpu::DrawType drawType,
const GrEffectStage* geometryProcessor, const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[], const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[], const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy, const GrDeviceCoordTexture* dstCopy,
SharedGLState* sharedState) { SharedGLState* sharedState) {
const GrDrawState& drawState = fGpu->getDrawState(); GrColor color = optState.getColor();
GrColor coverage = optState.getCoverageColor();
GrColor color; this->setColor(optState, color, sharedState);
GrColor coverage; this->setCoverage(optState, coverage, sharedState);
if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) { this->setMatrixAndRenderTargetHeight(drawType, optState);
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);
if (dstCopy) { if (dstCopy) {
if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) { 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, GrColor color,
SharedGLState* sharedState) { SharedGLState* sharedState) {
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
if (!drawState.hasColorVertexAttribute() || drawState.canIgnoreColorAttribute()) { if (!optState.hasColorVertexAttribute()) {
switch (header.fColorInput) { switch (header.fColorInput) {
case GrGLProgramDesc::kAttribute_ColorInput: case GrGLProgramDesc::kAttribute_ColorInput:
SkASSERT(-1 != header.fColorAttributeIndex); 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, GrColor coverage,
SharedGLState* sharedState) { SharedGLState* sharedState) {
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
if (!drawState.hasCoverageVertexAttribute()) { if (!optState.hasCoverageVertexAttribute()) {
switch (header.fCoverageInput) { switch (header.fCoverageInput) {
case GrGLProgramDesc::kAttribute_ColorInput: case GrGLProgramDesc::kAttribute_ColorInput:
if (sharedState->fConstAttribCoverage != coverage || if (sharedState->fConstAttribCoverage != coverage ||
@ -248,8 +236,8 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
} }
void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
const GrDrawState& drawState) { const GrOptDrawState& optState) {
const GrRenderTarget* rt = drawState.getRenderTarget(); const GrRenderTarget* rt = optState.getRenderTarget();
SkISize size; SkISize size;
size.set(rt->width(), rt->height()); size.set(rt->width(), rt->height());
@ -261,13 +249,13 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
} }
if (GrGpu::IsPathRenderingDrawType(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() || } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size || fMatrixState.fRenderTargetSize != size ||
!fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) { !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid()); SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = drawState.getViewMatrix(); fMatrixState.fViewMatrix = optState.getViewMatrix();
fMatrixState.fRenderTargetSize = size; fMatrixState.fRenderTargetSize = size;
fMatrixState.fRenderTargetOrigin = rt->origin(); fMatrixState.fRenderTargetOrigin = rt->origin();

View File

@ -157,8 +157,8 @@ public:
* GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage
* stages come from GrGLProgramDesc::Build(). * stages come from GrGLProgramDesc::Build().
*/ */
void setData(GrGpu::DrawType, void setData(const GrOptDrawState&,
GrDrawState::BlendOptFlags, GrGpu::DrawType,
const GrEffectStage* geometryProcessor, const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[], const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[], const GrEffectStage* coverageStages[],
@ -177,14 +177,14 @@ private:
// Helper for setData(). Makes GL calls to specify the initial color when there is not // Helper for setData(). Makes GL calls to specify the initial color when there is not
// per-vertex colors. // 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 // Helper for setData(). Makes GL calls to specify the initial coverage when there is not
// per-vertex coverages. // 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 // 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) // these reflect the current values of uniforms (GL uniform values travel with program)
MatrixState fMatrixState; MatrixState fMatrixState;

View File

@ -10,6 +10,7 @@
#include "GrBackendEffectFactory.h" #include "GrBackendEffectFactory.h"
#include "GrEffect.h" #include "GrEffect.h"
#include "GrGpuGL.h" #include "GrGpuGL.h"
#include "GrOptDrawState.h"
#include "SkChecksum.h" #include "SkChecksum.h"
@ -48,9 +49,8 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
return true; return true;
} }
bool GrGLProgramDesc::Build(const GrDrawState& drawState, bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
GrGpu::DrawType drawType, GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags blendOpts,
GrBlendCoeff srcCoeff, GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff, GrBlendCoeff dstCoeff,
const GrGpuGL* gpu, const GrGpuGL* gpu,
@ -62,47 +62,19 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
colorStages->reset(); colorStages->reset();
coverageStages->reset(); coverageStages->reset();
// This should already have been caught bool inputColorIsUsed = optState.inputColorIsUsed();
SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts)); bool inputCoverageIsUsed = optState.inputColorIsUsed();
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 // The descriptor is used as a cache key. Thus when a field of the
// descriptor will not affect program generation (because of the attribute // descriptor will not affect program generation (because of the attribute
// bindings in use or other descriptor field settings) it should be set // bindings in use or other descriptor field settings) it should be set
// to a canonical value to avoid duplicate programs with different keys. // to a canonical value to avoid duplicate programs with different keys.
bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute(); bool requiresColorAttrib = optState.hasColorVertexAttribute();
bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute(); bool requiresCoverageAttrib = optState.hasCoverageVertexAttribute();
// we only need the local coords if we're actually going to generate effect code // we only need the local coords if we're actually going to generate effect code
bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) && bool requiresLocalCoordAttrib = optState.numTotalStages() > 0 &&
drawState.hasLocalCoordAttribute(); optState.hasLocalCoordAttribute();
bool readsDst = false; bool readsDst = false;
bool readFragPosition = 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. // Provide option for shader programs without vertex shader only when drawing paths.
bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType); bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
int numStages = 0; int numStages = optState.numTotalStages();
if (drawState.hasGeometryProcessor()) {
numStages++;
}
if (!skipColor) {
numStages += drawState.numColorStages() - firstEffectiveColorStage;
}
if (!skipCoverage) {
numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
}
GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
// Make room for everything up to and including the array of offsets to effect keys. // Make room for everything up to and including the array of offsets to effect keys.
desc->fKey.reset(); desc->fKey.reset();
@ -133,7 +97,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
memset(desc->header(), 0, kHeaderSize); memset(desc->header(), 0, kHeaderSize);
// We can only have one effect which touches the vertex shader // We can only have one effect which touches the vertex shader
if (drawState.hasGeometryProcessor()) { if (optState.hasGeometryProcessor()) {
uint16_t* offsetAndSize = uint16_t* offsetAndSize =
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t)); offsetAndSizeIndex * 2 * sizeof(uint16_t));
@ -142,7 +106,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
uint16_t effectKeySize; uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count(); uint32_t effectOffset = desc->fKey.count();
effectKeySuccess |= GetEffectKeyAndUpdateStats( effectKeySuccess |= GetEffectKeyAndUpdateStats(
*drawState.getGeometryProcessor(), gpu->glCaps(), *optState.getGeometryProcessor(), gpu->glCaps(),
requiresLocalCoordAttrib, &b, requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst, &effectKeySize, &readsDst,
&readFragPosition, &requiresVertexShader); &readFragPosition, &requiresVertexShader);
@ -151,57 +115,55 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
offsetAndSize[0] = SkToU16(effectOffset); offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize; offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex; ++offsetAndSizeIndex;
*geometryProcessor = drawState.getGeometryProcessor(); *geometryProcessor = optState.getGeometryProcessor();
SkASSERT(requiresVertexShader); SkASSERT(requiresVertexShader);
header->fHasGeometryProcessor = true; header->fHasGeometryProcessor = true;
} }
if (!skipColor) { for (int s = 0; s < optState.numColorStages(); ++s) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { uint16_t* offsetAndSize =
uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + offsetAndSizeIndex * 2 * sizeof(uint16_t));
offsetAndSizeIndex * 2 * sizeof(uint16_t));
bool effectRequiresVertexShader = false; bool effectRequiresVertexShader = false;
GrEffectKeyBuilder b(&desc->fKey); GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize; uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count(); uint32_t effectOffset = desc->fKey.count();
effectKeySuccess |= GetEffectKeyAndUpdateStats( effectKeySuccess |= GetEffectKeyAndUpdateStats(
drawState.getColorStage(s), gpu->glCaps(), optState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b, requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst, &effectKeySize, &readsDst,
&readFragPosition, &effectRequiresVertexShader); &readFragPosition, &effectRequiresVertexShader);
effectKeySuccess |= (effectOffset <= SK_MaxU16); effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset); offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize; offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex; ++offsetAndSizeIndex;
SkASSERT(!effectRequiresVertexShader); 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; for (int s = 0; s < optState.numCoverageStages(); ++s) {
GrEffectKeyBuilder b(&desc->fKey); uint16_t* offsetAndSize =
uint16_t effectKeySize; reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
uint32_t effectOffset = desc->fKey.count(); offsetAndSizeIndex * 2 * sizeof(uint16_t));
effectKeySuccess |= GetEffectKeyAndUpdateStats(
drawState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
&readFragPosition, &effectRequiresVertexShader);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset); bool effectRequiresVertexShader = false;
offsetAndSize[1] = effectKeySize; GrEffectKeyBuilder b(&desc->fKey);
++offsetAndSizeIndex; uint16_t effectKeySize;
SkASSERT(!effectRequiresVertexShader); 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) { if (!effectKeySuccess) {
desc->fKey.reset(); desc->fKey.reset();
return false; return false;
@ -224,20 +186,20 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
#endif #endif
bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport(); bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
if (!inputColorIsUsed && !skipColor) { if (!inputColorIsUsed) {
header->fColorInput = kAllOnes_ColorInput; header->fColorInput = kAllOnes_ColorInput;
} else if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) { } else if (defaultToUniformInputs && !requiresColorAttrib) {
header->fColorInput = kUniform_ColorInput; header->fColorInput = kUniform_ColorInput;
} else { } else {
header->fColorInput = kAttribute_ColorInput; header->fColorInput = kAttribute_ColorInput;
header->fRequiresVertexShader = true; 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; header->fCoverageInput = kAllOnes_ColorInput;
} else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) { } else if (defaultToUniformInputs && !requiresCoverageAttrib) {
header->fCoverageInput = kUniform_ColorInput; header->fCoverageInput = kUniform_ColorInput;
} else { } else {
header->fCoverageInput = kAttribute_ColorInput; header->fCoverageInput = kAttribute_ColorInput;
@ -259,19 +221,19 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
if (readFragPosition) { if (readFragPosition) {
header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition( header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
drawState.getRenderTarget(), gpu->glCaps()); optState.getRenderTarget(), gpu->glCaps());
} else { } else {
header->fFragPosKey = 0; header->fFragPosKey = 0;
} }
// Record attribute indices // Record attribute indices
header->fPositionAttributeIndex = drawState.positionAttributeIndex(); header->fPositionAttributeIndex = optState.positionAttributeIndex();
header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex();
// For constant color and coverage we need an attribute with an index beyond those already set // 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) { if (requiresColorAttrib) {
header->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); header->fColorAttributeIndex = optState.colorVertexAttributeIndex();
} else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
header->fColorAttributeIndex = availableAttributeIndex; header->fColorAttributeIndex = availableAttributeIndex;
@ -281,7 +243,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
} }
if (requiresCoverageAttrib) { if (requiresCoverageAttrib) {
header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex();
} else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
header->fCoverageAttributeIndex = availableAttributeIndex; header->fCoverageAttributeIndex = availableAttributeIndex;
@ -295,15 +257,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fCoverageOutput = kModulate_CoverageOutput; header->fCoverageOutput = kModulate_CoverageOutput;
// If we do have coverage determine whether it matters. // If we do have coverage determine whether it matters.
bool separateCoverageFromColor = drawState.hasGeometryProcessor(); bool separateCoverageFromColor = optState.hasGeometryProcessor();
if (!drawState.isCoverageDrawing() && !skipCoverage && if (!optState.isCoverageDrawing() &&
(drawState.numCoverageStages() > 0 || (optState.numCoverageStages() > 0 ||
drawState.hasGeometryProcessor() || optState.hasGeometryProcessor() ||
requiresCoverageAttrib)) { requiresCoverageAttrib)) {
if (gpu->caps()->dualSourceBlendingSupport() && if (gpu->caps()->dualSourceBlendingSupport()) {
!(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
if (kZero_GrBlendCoeff == dstCoeff) { if (kZero_GrBlendCoeff == dstCoeff) {
// write the coverage value to second color // write the coverage value to second color
header->fCoverageOutput = kSecondaryCoverage_CoverageOutput; header->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
@ -325,22 +285,19 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
} }
} }
if (!skipColor) { for (int s = 0; s < optState.numColorStages(); ++s) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { colorStages->push_back(&optState.getColorStage(s));
colorStages->push_back(&drawState.getColorStage(s));
}
} }
if (!skipCoverage) { SkTArray<const GrEffectStage*, true>* array;
SkTArray<const GrEffectStage*, true>* array; if (separateCoverageFromColor) {
if (separateCoverageFromColor) { array = coverageStages;
array = coverageStages; } else {
} else { array = colorStages;
array = colorStages;
}
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
array->push_back(&drawState.getCoverageStage(s));
}
} }
for (int s = 0; s < optState.numCoverageStages(); ++s) {
array->push_back(&optState.getCoverageStage(s));
}
header->fColorEffectCnt = colorStages->count(); header->fColorEffectCnt = colorStages->count();
header->fCoverageEffectCnt = coverageStages->count(); header->fCoverageEffectCnt = coverageStages->count();

View File

@ -55,15 +55,13 @@ public:
int currAttribIndex); int currAttribIndex);
/** /**
* Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the * Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and
* output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. It also * the caps of the GrGpuGL are also inputs. It also outputs the color and coverage stages
* outputs the color and coverage stages referenced by the generated descriptor. This may * referenced by the generated descriptor. Coverage stages from the drawState may be treated as
* not contain all stages from the draw state and coverage stages from the drawState may * color stages in the output.
* be treated as color stages in the output.
*/ */
static bool Build(const GrDrawState&, static bool Build(const GrOptDrawState&,
GrGpu::DrawType drawType, GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags,
GrBlendCoeff srcCoeff, GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff, GrBlendCoeff dstCoeff,
const GrGpuGL* gpu, const GrGpuGL* gpu,

View File

@ -8,6 +8,7 @@
#include "GrGpuGL.h" #include "GrGpuGL.h"
#include "GrGLStencilBuffer.h" #include "GrGLStencilBuffer.h"
#include "GrOptDrawState.h"
#include "GrTemplates.h" #include "GrTemplates.h"
#include "GrTypes.h" #include "GrTypes.h"
#include "SkStrokeRec.h" #include "SkStrokeRec.h"

View File

@ -9,8 +9,9 @@
#include "GrEffect.h" #include "GrEffect.h"
#include "GrGLEffect.h" #include "GrGLEffect.h"
#include "SkRTConf.h"
#include "GrGLPathRendering.h" #include "GrGLPathRendering.h"
#include "GrOptDrawState.h"
#include "SkRTConf.h"
#include "SkTSearch.h" #include "SkTSearch.h"
#ifdef PROGRAM_CACHE_STATS #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) #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
const GrDrawState& drawState = this->getDrawState(); SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState());
// GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
SkASSERT(drawState.getRenderTarget()); SkASSERT(optState->getRenderTarget());
if (kStencilPath_DrawType == type) { if (kStencilPath_DrawType == type) {
const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); const GrRenderTarget* rt = optState->getRenderTarget();
SkISize size; SkISize size;
size.set(rt->width(), rt->height()); size.set(rt->width(), rt->height());
this->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(), size, rt->origin());
} else { } else {
this->flushMiscFixedFunctionState(); this->flushMiscFixedFunctionState();
GrBlendCoeff srcCoeff; GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff();
GrBlendCoeff dstCoeff; GrBlendCoeff dstCoeff = optState->getDstBlendCoeff();
GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff);
if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { // 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; 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> colorStages;
SkSTArray<8, const GrEffectStage*, true> coverageStages; SkSTArray<8, const GrEffectStage*, true> coverageStages;
GrGLProgramDesc desc; GrGLProgramDesc desc;
if (!GrGLProgramDesc::Build(this->getDrawState(), if (!GrGLProgramDesc::Build(*optState.get(),
type, type,
blendOpts,
srcCoeff, srcCoeff,
dstCoeff, dstCoeff,
this, this,
@ -263,8 +265,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
fCurrentProgram->setData(type, fCurrentProgram->setData(*optState.get(),
blendOpts, type,
geometryProcessor, geometryProcessor,
colorStages.begin(), colorStages.begin(),
coverageStages.begin(), coverageStages.begin(),
@ -272,15 +274,15 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
&fSharedGLProgramState); &fSharedGLProgramState);
} }
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(drawState.getRenderTarget()); GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(optState->getRenderTarget());
this->flushStencil(type); this->flushStencil(type);
this->flushScissor(glRT->getViewport(), glRT->origin()); this->flushScissor(glRT->getViewport(), glRT->origin());
this->flushAAState(type); this->flushAAState(type);
SkIRect* devRect = NULL; SkIRect* devRect = NULL;
SkIRect devClipBounds; SkIRect devClipBounds;
if (drawState.isClipState()) { if (optState->isClipState()) {
this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); this->getClip()->getConservativeBounds(optState->getRenderTarget(), &devClipBounds);
devRect = &devClipBounds; devRect = &devClipBounds;
} }
// This must come after textures are flushed because a texture may need // 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) { void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState());
GrGLsizei stride = static_cast<GrGLsizei>(this->getDrawState().getVertexStride()); GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride());
size_t vertexOffsetInBytes = stride * info.startVertex(); size_t vertexOffsetInBytes = stride * info.startVertex();
@ -346,16 +349,12 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
if (fCurrentProgram->hasVertexShader()) { if (fCurrentProgram->hasVertexShader()) {
int vertexAttribCount = this->getDrawState().getVertexAttribCount(); int vertexAttribCount = optState->getVertexAttribCount();
uint32_t usedAttribArraysMask = 0; uint32_t usedAttribArraysMask = 0;
const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); const GrVertexAttrib* vertexAttrib = optState->getVertexAttribs();
bool canIgnoreColorAttrib = this->getDrawState().canIgnoreColorAttribute();
for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
++vertexAttribIndex, ++vertexAttrib) { ++vertexAttribIndex, ++vertexAttrib) {
if (kColor_GrVertexAttribBinding != vertexAttrib->fBinding || !canIgnoreColorAttrib) {
usedAttribArraysMask |= (1 << vertexAttribIndex); usedAttribArraysMask |= (1 << vertexAttribIndex);
GrVertexAttribType attribType = vertexAttrib->fType; GrVertexAttribType attribType = vertexAttrib->fType;
attribState->set(this, attribState->set(this,
@ -367,7 +366,6 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
stride, stride,
reinterpret_cast<GrGLvoid*>( reinterpret_cast<GrGLvoid*>(
vertexOffsetInBytes + vertexAttrib->fOffset)); vertexOffsetInBytes + vertexAttrib->fOffset));
}
} }
attribState->disableUnusedArrays(this, usedAttribArraysMask); attribState->disableUnusedArrays(this, usedAttribArraysMask);
} }

View File

@ -9,6 +9,7 @@
#include "GrGLProgramBuilder.h" #include "GrGLProgramBuilder.h"
#include "GrGLShaderStringBuilder.h" #include "GrGLShaderStringBuilder.h"
#include "../GrGpuGL.h" #include "../GrGpuGL.h"
#include "../../GrOptDrawState.h"
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, 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())); coverage_attribute_name()));
} }
// We pull the current state of attributes off of drawstate and bind them in order // We pull the current state of attributes off of drawstate's optimized state and bind them in
const GrRODrawState* ds = fProgramBuilder->gpu()->drawState(); // order. This assumes that the drawState has not changed since we called flushGraphicsState()
const GrVertexAttrib* vaPtr = ds->getVertexAttribs(); // higher up in the stack.
const int vaCount = ds->getVertexAttribCount(); SkAutoTUnref<GrOptDrawState> optState(fProgramBuilder->gpu()->drawState()->createOptState());
const GrVertexAttrib* vaPtr = optState->getVertexAttribs();
const int vaCount = optState->getVertexAttribCount();
int i = fEffectAttribOffset; int i = fEffectAttribOffset;
for (int index = 0; index < vaCount; index++) { for (int index = 0; index < vaCount; index++) {