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