| Index: src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| index 687c2fd4c927331ff7efb662ed53ae4728a0219b..fbf78d763464a3b0175fff9d60474c5db0beaa7f 100644
|
| --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| @@ -32,13 +32,16 @@
|
| 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,
|
| - optState.hasGeometryProcessor(),
|
| + SkToBool(geometryProcessor),
|
| gpu));
|
|
|
| GrGLProgramBuilder* pb = builder.get();
|
| @@ -71,7 +74,8 @@
|
| }
|
| }
|
|
|
| - pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage);
|
| + pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
|
| + &inputCoverage);
|
|
|
| if (hasVertexShader) {
|
| pb->fVS.transformSkiaToGLCoords();
|
| @@ -112,15 +116,13 @@
|
|
|
| /////////////////////////////////////////////////////////////////////////////
|
|
|
| -GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
|
| - const GrOptDrawState& optState,
|
| +GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
|
| const GrGLProgramDesc& desc)
|
| : fVS(this)
|
| , fGS(this)
|
| , fFS(this, desc)
|
| , fOutOfStage(true)
|
| , fStageIndex(-1)
|
| - , fGeometryProcessor(NULL)
|
| , fOptState(optState)
|
| , fDesc(desc)
|
| , fGpu(gpu)
|
| @@ -223,106 +225,104 @@
|
| }
|
| }
|
|
|
| -void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState,
|
| - GrGLSLExpr4* inputColor,
|
| - GrGLSLExpr4* inputCoverage) {
|
| - fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
|
| - int numProcs = optState.numFragmentStages();
|
| - this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor);
|
| - if (optState.hasGeometryProcessor()) {
|
| - const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
|
| - fVS.emitAttributes(gp);
|
| - ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType);
|
| - GrGLSLExpr4 output;
|
| - this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output);
|
| - *inputCoverage = output;
|
| - }
|
| - this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage);
|
| -}
|
| -
|
| -void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) {
|
| - ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kFragment_ProcessorType);
|
| - for (int e = procOffset; e < numProcs; ++e) {
|
| - GrGLSLExpr4 output;
|
| - const GrFragmentStage& stage = fOptState.getFragmentStage(e);
|
| - this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut, &output);
|
| - *inOut = output;
|
| - }
|
| -}
|
| -
|
| -// TODO Processors cannot output zeros because an empty string is all 1s
|
| -// the fix is to allow effects to take the GrGLSLExpr4 directly
|
| -template <class Proc>
|
| -void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
|
| - int index,
|
| - const ProcKeyProvider keyProvider,
|
| - const GrGLSLExpr4& input,
|
| - GrGLSLExpr4* output) {
|
| - // Program builders have a bit of state we need to clear with each effect
|
| - AutoStageAdvance adv(this);
|
| -
|
| - // create var to hold stage result
|
| - SkString outColorName;
|
| - this->nameVariable(&outColorName, '\0', "output");
|
| - fFS.codeAppendf("vec4 %s;", outColorName.c_str());
|
| - *output = outColorName;
|
| -
|
| - // Enclose custom code in a block to avoid namespace conflicts
|
| - SkString openBrace;
|
| - openBrace.printf("{ // Stage %d\n", fStageIndex);
|
| - fFS.codeAppend(openBrace.c_str());
|
| -
|
| - this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(),
|
| - input.isOnes() ? NULL : input.c_str());
|
| -
|
| - fFS.codeAppend("}");
|
| -}
|
| -
|
| -void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs,
|
| - const GrProcessorKey& key,
|
| - const char* outColor,
|
| - const char* inColor) {
|
| - GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
|
| -
|
| - const GrFragmentProcessor& fp = *fs.getProcessor();
|
| - ifp->fGLProc = fp.getFactory().createGLInstance(fp);
|
| -
|
| - SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
|
| - this->emitSamplers(fp, &samplers, ifp);
|
| -
|
| - // Fragment processors can have coord transforms
|
| - SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms());
|
| - this->emitTransforms(fs, &coords, ifp);
|
| -
|
| - ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers);
|
| -
|
| - // 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(fp);
|
| - fFragmentProcessors->fProcs.push_back(ifp);
|
| -}
|
| -
|
| -void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
|
| - const GrProcessorKey& key,
|
| - const char* outColor,
|
| - const char* inColor) {
|
| - SkASSERT(!fGeometryProcessor);
|
| - fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
|
| -
|
| - fGeometryProcessor->fGLProc = gp.getFactory().createGLInstance(gp);
|
| -
|
| - SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
|
| - this->emitSamplers(gp, &samplers, fGeometryProcessor);
|
| -
|
| - SkSTArray<2, GrGLProcessor::TransformedCoords> coords;
|
| -
|
| - // TODO remove coords from emit code signature, probably best to use a struct here so these
|
| - // updates are less painful
|
| - fGeometryProcessor->fGLProc->emitCode(this, gp, key, outColor, inColor, coords, samplers);
|
| -
|
| - // 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(gp);
|
| +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 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) {
|
| + // 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;
|
| +
|
| + // Effects have no way to communicate zeros, they treat an empty string as ones.
|
| + this->nameVariable(&inColorName, '\0', "input");
|
| + fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
|
| + inColor = inColorName;
|
| + }
|
| +
|
| + // create var to hold stage result
|
| + SkString outColorName;
|
| + this->nameVariable(&outColorName, '\0', "output");
|
| + 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);
|
| +
|
| + typename ProcessorStage::GLProcessor* glEffect =
|
| + processor.getFactory().createGLInstance(processor);
|
| + installedProcessors->addEffect(glEffect);
|
| +
|
| + // Enclose custom code in a block to avoid namespace conflicts
|
| + SkString openBrace;
|
| + openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->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);
|
| +
|
| + // 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;
|
| + }
|
| +
|
| + if (effectEmitted) {
|
| + *fsInOutColor = outColor;
|
| + }
|
| }
|
|
|
| void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
|
| @@ -334,17 +334,19 @@
|
| SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
|
| }
|
|
|
| -void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
|
| +void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
|
| GrGLProcessor::TransformedCoordsArray* outCoords,
|
| - GrGLInstalledFragProc* ifp) {
|
| - const GrFragmentProcessor* effect = effectStage.getProcessor();
|
| + GrGLInstalledProcessors* installedProcessors) {
|
| + SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
|
| + installedProcessors->addTransforms();
|
| + const GrProcessor* effect = effectStage.getProcessor();
|
| int numTransforms = effect->numTransforms();
|
| - ifp->fTransforms.push_back_n(numTransforms);
|
| + transforms.push_back_n(numTransforms);
|
|
|
| for (int t = 0; t < numTransforms; t++) {
|
| const char* uniName = "StageMatrix";
|
| GrSLType varyingType =
|
| - effectStage.isPerspectiveCoordTransform(t, fVS.hasLocalCoords()) ?
|
| + effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
|
| kVec3f_GrSLType :
|
| kVec2f_GrSLType;
|
|
|
| @@ -354,10 +356,10 @@
|
| suffixedUniName.appendf("_%i", t);
|
| uniName = suffixedUniName.c_str();
|
| }
|
| - ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
| - kMat33f_GrSLType,
|
| - uniName,
|
| - &uniName).toShaderBuilderIndex();
|
| + transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
| + kMat33f_GrSLType,
|
| + uniName,
|
| + &uniName).toShaderBuilderIndex();
|
|
|
| const char* varyingName = "MatrixCoord";
|
| SkString suffixedVaryingName;
|
| @@ -391,17 +393,18 @@
|
|
|
| void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
|
| GrGLProcessor::TextureSamplerArray* outSamplers,
|
| - GrGLInstalledProc* ip) {
|
| + GrGLInstalledProcessors* installedProcessors) {
|
| + SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
|
| int numTextures = processor.numTextures();
|
| - ip->fSamplers.push_back_n(numTextures);
|
| + samplers.push_back_n(numTextures);
|
| SkString name;
|
| for (int t = 0; t < numTextures; ++t) {
|
| name.printf("Sampler%d", t);
|
| - ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| - kSampler2D_GrSLType,
|
| - name.c_str());
|
| + samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| + kSampler2D_GrSLType,
|
| + name.c_str());
|
| SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
|
| - (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
|
| + (samplers[t].fUniform, processor.textureAccess(t)));
|
| }
|
| }
|
|
|
| @@ -503,14 +506,14 @@
|
|
|
| GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
|
| return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
|
| - fGeometryProcessor, fFragmentProcessors.get()));
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
|
| - int numProcs = fProcs.count();
|
| - for (int e = 0; e < numProcs; ++e) {
|
| - SkDELETE(fProcs[e]->fGLProc);
|
| - }
|
| -}
|
| + fGeometryProcessor, fColorEffects, fCoverageEffects));
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GrGLInstalledProcessors::~GrGLInstalledProcessors() {
|
| + int numEffects = fGLProcessors.count();
|
| + for (int e = 0; e < numEffects; ++e) {
|
| + SkDELETE(fGLProcessors[e]);
|
| + }
|
| +}
|
|
|