separate arrays for color and coverage effects.
R=robertphillips@google.com
Review URL: https://codereview.chromium.org/16180006
git-svn-id: http://skia.googlecode.com/svn/trunk@9465 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 1039b3b..8a24d60 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -38,8 +38,9 @@
GrGLProgram* GrGLProgram::Create(const GrGLContext& gl,
const GrGLProgramDesc& desc,
- const GrEffectStage* stages[]) {
- GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages));
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]) {
+ GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, colorStages, coverageStages));
if (!program->succeeded()) {
delete program;
program = NULL;
@@ -49,7 +50,8 @@
GrGLProgram::GrGLProgram(const GrGLContext& gl,
const GrGLProgramDesc& desc,
- const GrEffectStage* stages[])
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[])
: fContext(gl)
, fUniformManager(gl) {
fDesc = desc;
@@ -63,9 +65,10 @@
fColor = GrColor_ILLEGAL;
fColorFilterColor = GrColor_ILLEGAL;
- fEffectStates.reset(desc.numTotalEffects());
+ fColorEffects.reset(desc.numColorEffects());
+ fCoverageEffects.reset(desc.numCoverageEffects());
- this->genProgram(stages);
+ this->genProgram(colorStages, coverageStages);
}
GrGLProgram::~GrGLProgram() {
@@ -432,7 +435,8 @@
return true;
}
-bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
+bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]) {
GrAssert(0 == fProgramID);
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
@@ -491,10 +495,10 @@
if (needColor) {
for (int e = 0; e < fDesc.numColorEffects(); ++e) {
- effectUniformArrays[e] = &fEffectStates[e].fSamplerUnis;
+ effectUniformArrays[e] = &fColorEffects[e].fSamplerUnis;
}
- builder.emitEffects(stages,
+ builder.emitEffects(colorStages,
fDesc.effectKeys(),
fDesc.numColorEffects(),
&inColor,
@@ -503,7 +507,7 @@
glEffects.get());
for (int e = 0; e < fDesc.numColorEffects(); ++e) {
- fEffectStates[e].fGLEffect = glEffects[e];
+ fColorEffects[e].fGLEffect = glEffects[e];
}
}
@@ -535,10 +539,10 @@
GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
- effectUniformArrays[e] = &fEffectStates[e + fDesc.numColorEffects()].fSamplerUnis;
+ effectUniformArrays[e] = &fCoverageEffects[e].fSamplerUnis;
}
- builder.emitEffects(stages + fDesc.numColorEffects(),
+ builder.emitEffects(coverageStages,
fDesc.getEffectKeys() + fDesc.numColorEffects(),
fDesc.numCoverageEffects(),
&inCoverage,
@@ -546,7 +550,7 @@
effectUniformArrays.get(),
glEffects.get());
for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
- fEffectStates[e + fDesc.numColorEffects()].fGLEffect = glEffects[e];
+ fCoverageEffects[e].fGLEffect = glEffects[e];
}
// discard if coverage is zero
@@ -754,24 +758,56 @@
fDstCopyTexUnit = texUnitIdx++;
}
- for (int e = 0; e < fEffectStates.count(); ++e) {
- int numSamplers = fEffectStates[e].fSamplerUnis.count();
- fEffectStates[e].fTextureUnits.reset(numSamplers);
- for (int s = 0; s < numSamplers; ++s) {
- UniformHandle handle = fEffectStates[e].fSamplerUnis[s];
- if (GrGLUniformManager::kInvalidUniformHandle != handle) {
- fUniformManager.setSampler(handle, texUnitIdx);
- fEffectStates[e].fTextureUnits[s] = texUnitIdx++;
- }
+ for (int e = 0; e < fColorEffects.count(); ++e) {
+ this->initEffectSamplerUniforms(&fColorEffects[e], &texUnitIdx);
+ }
+
+ for (int e = 0; e < fCoverageEffects.count(); ++e) {
+ this->initEffectSamplerUniforms(&fCoverageEffects[e], &texUnitIdx);
+ }
+}
+
+void GrGLProgram::initEffectSamplerUniforms(EffectAndSamplers* effect, int* texUnitIdx) {
+ int numSamplers = effect->fSamplerUnis.count();
+ effect->fTextureUnits.reset(numSamplers);
+ for (int s = 0; s < numSamplers; ++s) {
+ UniformHandle handle = effect->fSamplerUnis[s];
+ if (GrGLUniformManager::kInvalidUniformHandle != handle) {
+ fUniformManager.setSampler(handle, *texUnitIdx);
+ effect->fTextureUnits[s] = (*texUnitIdx)++;
}
}
}
///////////////////////////////////////////////////////////////////////////////
+void GrGLProgram::setEffectData(GrGpuGL* gpu,
+ const GrEffectStage& stage,
+ const EffectAndSamplers& effect) {
+
+ // Let the GrGLEffect set its data.
+ bool explicitLocalCoords = -1 != fDesc.getHeader().fLocalCoordAttributeIndex;
+ GrDrawEffect drawEffect(stage, explicitLocalCoords);
+ effect.fGLEffect->setData(fUniformManager, drawEffect);
+
+ // Bind the texures for the effect.
+ int numSamplers = effect.fSamplerUnis.count();
+ GrAssert((*stage.getEffect())->numTextures() == numSamplers);
+ for (int s = 0; s < numSamplers; ++s) {
+ UniformHandle handle = effect.fSamplerUnis[s];
+ if (GrGLUniformManager::kInvalidUniformHandle != handle) {
+ const GrTextureAccess& access = (*stage.getEffect())->textureAccess(s);
+ GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
+ int unit = effect.fTextureUnits[s];
+ gpu->bindTexture(unit, access.getParams(), texture);
+ }
+ }
+}
+
void GrGLProgram::setData(GrGpuGL* gpu,
GrDrawState::BlendOptFlags blendOpts,
- const GrEffectStage* stages[],
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy,
SharedGLState* sharedState) {
const GrDrawState& drawState = gpu->getDrawState();
@@ -828,26 +864,17 @@
GrAssert(GrGLUniformManager::kInvalidUniformHandle == fUniformHandles.fDstCopySamplerUni);
}
- int numEffects = fDesc.numTotalEffects();
- for (int e = 0; e < numEffects; ++e) {
- GrAssert(NULL != stages[e]);
+ for (int e = 0; e < fColorEffects.count(); ++e) {
// We may have omitted the GrGLEffect because of the color filter logic in genProgram.
// This can be removed when the color filter is an effect.
- if (NULL != fEffectStates[e].fGLEffect) {
- bool explicitLocalCoords = -1 != fDesc.getHeader().fLocalCoordAttributeIndex;
- GrDrawEffect drawEffect(*stages[e], explicitLocalCoords);
- fEffectStates[e].fGLEffect->setData(fUniformManager, drawEffect);
- int numSamplers = fEffectStates[e].fSamplerUnis.count();
- GrAssert((*stages[e]->getEffect())->numTextures() == numSamplers);
- for (int s = 0; s < numSamplers; ++s) {
- UniformHandle handle = fEffectStates[e].fSamplerUnis[s];
- if (GrGLUniformManager::kInvalidUniformHandle != handle) {
- const GrTextureAccess& access = (*stages[e]->getEffect())->textureAccess(s);
- GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
- int unit = fEffectStates[e].fTextureUnits[s];
- gpu->bindTexture(unit, access.getParams(), texture);
- }
- }
+ if (NULL != fColorEffects[e].fGLEffect) {
+ this->setEffectData(gpu, *colorStages[e], fColorEffects[e]);
+ }
+ }
+
+ for (int e = 0; e < fCoverageEffects.count(); ++e) {
+ if (NULL != fCoverageEffects[e].fGLEffect) {
+ this->setEffectData(gpu, *coverageStages[e], fCoverageEffects[e]);
}
}
}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index ce43b71..3534552 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -38,7 +38,8 @@
static GrGLProgram* Create(const GrGLContext& gl,
const GrGLProgramDesc& desc,
- const GrEffectStage* stages[]);
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]);
virtual ~GrGLProgram();
@@ -103,59 +104,19 @@
/**
* 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.
+ * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage
+ * stages come from GrGLProgramDesc::Build().
*/
void setData(GrGpuGL*,
GrDrawState::BlendOptFlags,
- const GrEffectStage* stages[], // output of GrGLProgramDesc:Build()
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy, // can be NULL
SharedGLState*);
private:
- GrGLProgram(const GrGLContext& gl,
- const GrGLProgramDesc& desc,
- const GrEffectStage* stages[]);
-
- bool succeeded() const { return 0 != fProgramID; }
-
- /**
- * This is the heavy initialization routine for building a GLProgram. stages is all the enabled
- * color stages followed by all the enabled coverage stages as output by
- * GrGLProgramDesc::Build()
- */
- bool genProgram(const GrEffectStage* stages[]);
-
- GrSLConstantVec genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
-
- GrSLConstantVec genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage);
-
- void genGeometryShader(GrGLShaderBuilder* segments) const;
-
typedef GrGLUniformManager::UniformHandle UniformHandle;
- // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
- bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
- bool bindColorOut,
- bool bindDualSrcOut);
-
- // Sets the texture units for samplers
- void initSamplerUniforms();
-
- bool compileShaders(const GrGLShaderBuilder& builder);
-
- 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*);
-
- // Helper for setData() that sets the view matrix and loads the render target height uniform
- void setMatrixAndRenderTargetHeight(const GrDrawState&);
-
// handles for uniforms (aside from per-effect samplers)
struct UniformHandles {
UniformHandle fViewMatrixUni;
@@ -195,6 +156,52 @@
TextureUnitSArray fTextureUnits; // texture unit used for each entry of fSamplerUnis
};
+ GrGLProgram(const GrGLContext& gl,
+ const GrGLProgramDesc& desc,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]);
+
+ bool succeeded() const { return 0 != fProgramID; }
+
+ /**
+ * This is the heavy initialization routine for building a GLProgram. colorStages and
+ * coverageStages correspond to the output of GrGLProgramDesc::Build().
+ */
+ bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
+
+ GrSLConstantVec genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
+
+ GrSLConstantVec genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage);
+
+ void genGeometryShader(GrGLShaderBuilder* segments) const;
+
+ // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
+ bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
+ bool bindColorOut,
+ bool bindDualSrcOut);
+
+ // Sets the texture units for samplers
+ void initSamplerUniforms();
+ void initEffectSamplerUniforms(EffectAndSamplers* effect, int* texUnitIdx);
+
+ bool compileShaders(const GrGLShaderBuilder& builder);
+
+ const char* adjustInColor(const SkString& inColor) const;
+
+ // Helper for setData().
+ void setEffectData(GrGpuGL* gpu, const GrEffectStage& stage, const EffectAndSamplers& effect);
+
+ // 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*);
+
+ // Helper for setData() that sets the view matrix and loads the render target height uniform
+ void setMatrixAndRenderTargetHeight(const GrDrawState&);
+
// GL IDs
GrGLuint fVShaderID;
GrGLuint fGShaderID;
@@ -208,7 +215,8 @@
GrColor fColorFilterColor;
int fDstCopyTexUnit;
- SkTArray<EffectAndSamplers> fEffectStates;
+ SkTArray<EffectAndSamplers> fColorEffects;
+ SkTArray<EffectAndSamplers> fCoverageEffects;
GrGLProgramDesc fDesc;
const GrGLContext& fContext;
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index d040658..4f00118 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -21,8 +21,12 @@
GrBlendCoeff dstCoeff,
const GrGpuGL* gpu,
const GrDeviceCoordTexture* dstCopy,
- const GrEffectStage* stages[],
+ SkTArray<const GrEffectStage*, true>* colorStages,
+ SkTArray<const GrEffectStage*, true>* coverageStages,
GrGLProgramDesc* desc) {
+ colorStages->reset();
+ coverageStages->reset();
+
// This should already have been caught
GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
@@ -51,26 +55,22 @@
// effects as color in desc. Two things will allow simplication of this mess: GrDrawState will
// have tight lists of color and coverage stages rather than a fixed size array with NULLS and
// the xfermode-color filter will be removed.
- int colorEffectCnt = 0;
- int coverageEffectCnt = 0;
if (!skipColor) {
for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
if (drawState.isStageEnabled(s)) {
- stages[colorEffectCnt] = &drawState.getStage(s);
- ++colorEffectCnt;
+ colorStages->push_back(&drawState.getStage(s));
}
}
}
if (!skipCoverage) {
for (int s = drawState.getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
if (drawState.isStageEnabled(s)) {
- stages[colorEffectCnt + coverageEffectCnt] = &drawState.getStage(s);
- ++coverageEffectCnt;
+ coverageStages->push_back(&drawState.getStage(s));
}
}
}
- size_t newKeyLength = KeyLength(colorEffectCnt + coverageEffectCnt);
+ size_t newKeyLength = KeyLength(colorStages->count() + coverageStages->count());
bool allocChanged;
desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged);
if (allocChanged || !desc->fInitialized) {
@@ -189,7 +189,7 @@
// If we do have coverage determine whether it matters.
bool separateCoverageFromColor = false;
- if (!drawState.isCoverageDrawing() && (coverageEffectCnt > 0 || requiresCoverageAttrib)) {
+ if (!drawState.isCoverageDrawing() && (coverageStages->count() > 0 || requiresCoverageAttrib)) {
// color filter is applied between color/coverage computation
if (SkXfermode::kDst_Mode != header->fColorFilterXfermode) {
separateCoverageFromColor = true;
@@ -225,11 +225,13 @@
}
}
if (separateCoverageFromColor) {
- header->fColorEffectCnt = colorEffectCnt;
- header->fCoverageEffectCnt = coverageEffectCnt;
+ header->fColorEffectCnt = colorStages->count();
+ header->fCoverageEffectCnt = coverageStages->count();
} else {
- header->fColorEffectCnt = colorEffectCnt + coverageEffectCnt;
+ header->fColorEffectCnt = colorStages->count() + coverageStages->count();
header->fCoverageEffectCnt = 0;
+ colorStages->push_back_n(coverageStages->count(), coverageStages->begin());
+ coverageStages->reset();
}
*desc->checksum() = 0;
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index 0cf3b22..e85133c 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -55,7 +55,9 @@
/**
* 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
- * writes a tightly packed array of GrEffectStage* from the drawState.
+ * 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.
*/
static void Build(const GrDrawState&,
bool isPoints,
@@ -64,7 +66,8 @@
GrBlendCoeff dstCoeff,
const GrGpuGL* gpu,
const GrDeviceCoordTexture* dstCopy,
- const GrEffectStage* outStages[GrDrawState::kNumStages],
+ SkTArray<const GrEffectStage*, true>* outColorStages,
+ SkTArray<const GrEffectStage*, true>* outCoverageStages,
GrGLProgramDesc* outDesc);
int numColorEffects() const {
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 85cace7..c644fbb 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -178,7 +178,9 @@
~ProgramCache();
void abandon();
- GrGLProgram* getProgram(const GrGLProgramDesc& desc, const GrEffectStage* stages[]);
+ GrGLProgram* getProgram(const GrGLProgramDesc& desc,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]);
private:
enum {
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 5dab982..5da8ecf 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -84,7 +84,8 @@
}
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
- const GrEffectStage* stages[]) {
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]) {
#ifdef PROGRAM_CACHE_STATS
++fTotalRequests;
#endif
@@ -119,7 +120,7 @@
#ifdef PROGRAM_CACHE_STATS
++fCacheMisses;
#endif
- GrGLProgram* program = GrGLProgram::Create(fGL, desc, stages);
+ GrGLProgram* program = GrGLProgram::Create(fGL, desc, colorStages, coverageStages);
if (NULL == program) {
return NULL;
}
@@ -273,7 +274,8 @@
return false;
}
- const GrEffectStage* stages[GrDrawState::kNumStages];
+ SkSTArray<8, const GrEffectStage*, true> colorStages;
+ SkSTArray<8, const GrEffectStage*, true> coverageStages;
GrGLProgramDesc desc;
GrGLProgramDesc::Build(this->getDrawState(),
kDrawPoints_DrawType == type,
@@ -282,10 +284,13 @@
dstCoeff,
this,
dstCopy,
- stages,
+ &colorStages,
+ &coverageStages,
&desc);
- fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
+ fCurrentProgram.reset(fProgramCache->getProgram(desc,
+ colorStages.begin(),
+ coverageStages.begin()));
if (NULL == fCurrentProgram.get()) {
GrAssert(!"Failed to create program!");
return false;
@@ -301,7 +306,12 @@
fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
- fCurrentProgram->setData(this, blendOpts, stages, dstCopy, &fSharedGLProgramState);
+ fCurrentProgram->setData(this,
+ blendOpts,
+ colorStages.begin(),
+ coverageStages.begin(),
+ dstCopy,
+ &fSharedGLProgramState);
}
this->flushStencil(type);
this->flushScissor();