| 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);
|
|
|
|
|