Index: src/gpu/gl/builders/GrGLProgramBuilder.cpp |
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
index fbf78d763464a3b0175fff9d60474c5db0beaa7f..e19e92839aa2eb60134c3932222001b7e077732e 100644 |
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
@@ -29,19 +29,58 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar: |
const int GrGLProgramBuilder::kVarsPerBlock = 8; |
+// Below are some helper classes which help keep the create and emit pipeline general |
+template <class Derived> |
+struct FragmentStageClassMap { |
+ static const GrFragmentProcessor* GetProcessor(const GrOptDrawState& opt, int index) { |
+ SkASSERT(Derived::GetStage(opt, index)->getProcessor()); |
+ return Derived::GetStage(opt, index)->getProcessor(); |
+ } |
+ typedef GrFragmentProcessor Processor; |
+ typedef GrFragmentStage ProcessorStaged; |
+ typedef GrGLFragmentProcessor GLProcessor; |
+}; |
+ |
+struct ColorStageClassMap : public FragmentStageClassMap<ColorStageClassMap> { |
+ static int GetCount(const GrOptDrawState& opt) { return opt.numColorStages(); } |
+ static const GrFragmentStage* GetStage(const GrOptDrawState& opt, int index) { |
+ return &opt.getColorStage(index); |
+ } |
+}; |
+ |
+struct CoverageStageClassMap : public FragmentStageClassMap<CoverageStageClassMap> { |
+ static int GetCount(const GrOptDrawState& opt) { return opt.numCoverageStages(); } |
+ static const GrFragmentStage* GetStage(const GrOptDrawState& opt, int index) { |
+ return &opt.getCoverageStage(index); |
+ } |
+}; |
+ |
+struct GeometryProcessorClassMap { |
+ static int GetCount(const GrOptDrawState& opt) { return 1; } |
+ static const GrGeometryProcessor* GetStage(const GrOptDrawState& opt, int index) { |
+ SkASSERT(0 == index && opt.hasGeometryProcessor()); |
+ return opt.getGeometryProcessor(); |
+ } |
+ static const GrGeometryProcessor* GetProcessor(const GrOptDrawState& opt, int index) { |
+ return GetStage(opt, index); |
+ } |
+ typedef GrGeometryProcessor Processor; |
+ typedef GrGeometryProcessor ProcessorStaged; |
+ typedef GrGLGeometryProcessor GLProcessor; |
+}; |
+ |
+////////////////////////////////////////////////////////////////////////////////////////////////// |
+ |
GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, |
const GrGLProgramDesc& desc, |
GrGpu::DrawType drawType, |
- const GrGeometryStage* geometryProcessor, |
- const GrFragmentStage* colorStages[], |
- const GrFragmentStage* coverageStages[], |
GrGpuGL* gpu) { |
// create a builder. This will be handed off to effects so they can use it to add |
// uniforms, varyings, textures, etc |
SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc, |
optState, |
drawType, |
- SkToBool(geometryProcessor), |
+ optState.hasGeometryProcessor(), |
gpu)); |
GrGLProgramBuilder* pb = builder.get(); |
@@ -74,8 +113,23 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, |
} |
} |
- pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor, |
- &inputCoverage); |
+ bool useLocalCoords = pb->fVS.hasExplicitLocalCoords(); |
+ pb->createAndEmitProcessors<ColorStageClassMap>(EffectKeyProvider::kColor_EffectType, |
+ useLocalCoords, |
+ &pb->fColorEffects, |
+ &inputColor); |
+ if (optState.hasGeometryProcessor()) { |
+ pb->fVS.emitAttributes(*optState.getGeometryProcessor()); |
+ pb->createAndEmitProcessors<GeometryProcessorClassMap>( |
+ EffectKeyProvider::kGeometryProcessor_EffectType, |
+ false, |
+ &pb->fGeometryProcessor, |
+ &inputCoverage); |
+ } |
+ pb->createAndEmitProcessors<CoverageStageClassMap>(EffectKeyProvider::kCoverage_EffectType, |
+ useLocalCoords, |
+ &pb->fCoverageEffects, |
+ &inputCoverage); |
if (hasVertexShader) { |
pb->fVS.transformSkiaToGLCoords(); |
@@ -225,54 +279,24 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input |
} |
} |
-void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometryProcessor, |
- const GrFragmentStage* colorStages[], |
- const GrFragmentStage* coverageStages[], |
- GrGLSLExpr4* inputColor, |
- GrGLSLExpr4* inputCoverage) { |
- bool useLocalCoords = fVS.hasExplicitLocalCoords(); |
- |
- EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectType); |
- int numColorEffects = fDesc.numColorEffects(); |
- GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorEffects, |
- useLocalCoords)); |
- this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider, |
- inputColor, ip); |
- fColorEffects.reset(ip); |
- |
- if (geometryProcessor) { |
- fVS.emitAttributes(*geometryProcessor->getProcessor()); |
- EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProcessor_EffectType); |
- ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords)); |
- this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gpKeyProvider, |
- inputCoverage, ip); |
- fGeometryProcessor.reset(ip); |
- } |
- |
- EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_EffectType); |
- int numCoverageEffects = fDesc.numCoverageEffects(); |
- ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords)); |
- this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEffects, |
- coverageKeyProvider, inputCoverage, ip); |
- fCoverageEffects.reset(ip); |
-} |
+template <class ClassMap> |
+void GrGLProgramBuilder::createAndEmitProcessors(const EffectKeyProvider::EffectType type, |
+ bool useLocalCoords, |
+ SkAutoTUnref<GrGLInstalledProcessors>* installProc, |
+ GrGLSLExpr4* fsInOutColor) { |
+ // setup key provider and install point |
+ EffectKeyProvider keyProvider(&fDesc, type); |
+ int numProcs = ClassMap::GetCount(fOptState); |
+ GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numProcs, useLocalCoords)); |
-template <class ProcessorStage> |
-void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processStages[], |
- int effectCnt, |
- const EffectKeyProvider& keyProvider, |
- GrGLSLExpr4* fsInOutColor, |
- GrGLInstalledProcessors* installedProcessors) { |
bool effectEmitted = false; |
GrGLSLExpr4 inColor = *fsInOutColor; |
GrGLSLExpr4 outColor; |
- for (int e = 0; e < effectCnt; ++e) { |
+ for (int e = 0; e < numProcs; ++e) { |
// Program builders have a bit of state we need to clear with each effect |
AutoStageAdvance adv(this); |
- const ProcessorStage& stage = *processStages[e]; |
- SkASSERT(stage.getProcessor()); |
if (inColor.isZeros()) { |
SkString inColorName; |
@@ -289,32 +313,30 @@ void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processSt |
fFS.codeAppendf("vec4 %s;", outColorName.c_str()); |
outColor = outColorName; |
- SkASSERT(installedProcessors); |
- const typename ProcessorStage::Processor& processor = *stage.getProcessor(); |
- SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTransforms()); |
- SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures()); |
- |
- this->emitTransforms(stage, &coords, installedProcessors); |
- this->emitSamplers(processor, &samplers, installedProcessors); |
+ SkASSERT(ip); |
+ const typename ClassMap::Processor& processor = *ClassMap::GetProcessor(fOptState, e); |
- typename ProcessorStage::GLProcessor* glEffect = |
- processor.getFactory().createGLInstance(processor); |
- installedProcessors->addEffect(glEffect); |
+ typename ClassMap::GLProcessor* glProc = processor.getFactory().createGLInstance(processor); |
+ ip->addEffect(glProc); |
// Enclose custom code in a block to avoid namespace conflicts |
SkString openBrace; |
- openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name()); |
+ openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glProc->name()); |
fFS.codeAppend(openBrace.c_str()); |
fVS.codeAppend(openBrace.c_str()); |
- glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(), |
- inColor.isOnes() ? NULL : inColor.c_str(), coords, samplers); |
+ SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures()); |
+ this->emitSamplers(processor, &samplers, ip); |
+ |
+ this->emit(*ClassMap::GetStage(fOptState, e), keyProvider.get(e), outColor.c_str(), |
+ inColor.isOnes() ? NULL : inColor.c_str(), samplers, ip, glProc); |
+ |
+ fFS.codeAppend("}"); |
+ fVS.codeAppend("}"); |
// We have to check that effects and the code they emit are consistent, ie if an effect |
// asks for dst color, then the emit code needs to follow suit |
verify(processor); |
- fFS.codeAppend("}"); |
- fVS.codeAppend("}"); |
inColor = outColor; |
effectEmitted = true; |
@@ -323,6 +345,38 @@ void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processSt |
if (effectEmitted) { |
*fsInOutColor = outColor; |
} |
+ |
+ // write to output array |
+ SkASSERT(installProc); |
+ installProc->reset(ip); |
+} |
+ |
+void GrGLProgramBuilder::emit(const GrFragmentStage& fs, |
+ const GrProcessorKey& key, |
+ const char* outColor, |
+ const char* inColor, |
+ const GrGLProcessor::TextureSamplerArray& samplers, |
+ GrGLInstalledProcessors* ip, |
+ GrGLFragmentProcessor* glProc) { |
+ // Fragment processors can have coord transforms |
+ const GrFragmentProcessor* fp = fs.getProcessor(); |
+ SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp->numTransforms()); |
+ this->emitTransforms(fs, &coords, ip); |
+ |
+ glProc->emitCode(this, *fp, key, outColor, inColor, coords, samplers); |
+} |
+ |
+void GrGLProgramBuilder::emit(const GrGeometryProcessor& gp, |
+ const GrProcessorKey& key, |
+ const char* outColor, |
+ const char* inColor, |
+ const GrGLProcessor::TextureSamplerArray& samplers, |
+ GrGLInstalledProcessors* ip, |
+ GrGLGeometryProcessor* glProc) { |
+ // TODO remove coords from emit code signature, probably best to use a struct here so these |
+ // updates are less painful |
+ SkSTArray<2, GrGLProcessor::TransformedCoords> coords; |
+ glProc->emitCode(this, gp, key, outColor, inColor, coords, samplers); |
} |
void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { |
@@ -334,12 +388,12 @@ void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { |
SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor()); |
} |
-void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage, |
+void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage, |
GrGLProcessor::TransformedCoordsArray* outCoords, |
GrGLInstalledProcessors* installedProcessors) { |
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = |
installedProcessors->addTransforms(); |
- const GrProcessor* effect = effectStage.getProcessor(); |
+ const GrFragmentProcessor* effect = effectStage.getProcessor(); |
int numTransforms = effect->numTransforms(); |
transforms.push_back_n(numTransforms); |