| 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..7af7e8c21588296f2dd901fe14703e20e41aeec4 100644
|
| --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| @@ -6,7 +6,6 @@
|
| */
|
|
|
| #include "GrGLProgramBuilder.h"
|
| -#include "gl/GrGLGeometryProcessor.h"
|
| #include "gl/GrGLProgram.h"
|
| #include "gl/GrGLSLPrettyPrint.h"
|
| #include "gl/GrGLUniformHandle.h"
|
| @@ -32,16 +31,13 @@ const int GrGLProgramBuilder::kVarsPerBlock = 8;
|
| 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 +70,7 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
|
| }
|
| }
|
|
|
| - pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
|
| - &inputCoverage);
|
| + pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage);
|
|
|
| if (hasVertexShader) {
|
| pb->fVS.transformSkiaToGLCoords();
|
| @@ -116,13 +111,15 @@ GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
|
|
|
| /////////////////////////////////////////////////////////////////////////////
|
|
|
| -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)
|
| @@ -225,104 +222,106 @@ 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);
|
| +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);
|
| +}
|
|
|
| - 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);
|
| +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;
|
| + }
|
| }
|
|
|
| -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;
|
| - }
|
| +// 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("}");
|
| +}
|
|
|
| - // 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;
|
| - }
|
| +void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs,
|
| + const GrProcessorKey& key,
|
| + const char* outColor,
|
| + const char* inColor) {
|
| + GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
|
|
|
| - if (effectEmitted) {
|
| - *fsInOutColor = outColor;
|
| - }
|
| + const GrFragmentProcessor& fp = *fs.getProcessor();
|
| + ifp->fGLProc.reset(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.reset(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::verify(const GrGeometryProcessor& gp) {
|
| @@ -334,19 +333,17 @@ 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();
|
| + GrGLInstalledFragProc* ifp) {
|
| + const GrFragmentProcessor* effect = effectStage.getProcessor();
|
| int numTransforms = effect->numTransforms();
|
| - transforms.push_back_n(numTransforms);
|
| + ifp->fTransforms.push_back_n(numTransforms);
|
|
|
| for (int t = 0; t < numTransforms; t++) {
|
| const char* uniName = "StageMatrix";
|
| GrSLType varyingType =
|
| - effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
|
| + effectStage.isPerspectiveCoordTransform(t, fVS.hasLocalCoords()) ?
|
| kVec3f_GrSLType :
|
| kVec2f_GrSLType;
|
|
|
| @@ -356,10 +353,10 @@ void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
|
| suffixedUniName.appendf("_%i", t);
|
| uniName = suffixedUniName.c_str();
|
| }
|
| - transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
| - kMat33f_GrSLType,
|
| - uniName,
|
| - &uniName).toShaderBuilderIndex();
|
| + ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
| + kMat33f_GrSLType,
|
| + uniName,
|
| + &uniName).toShaderBuilderIndex();
|
|
|
| const char* varyingName = "MatrixCoord";
|
| SkString suffixedVaryingName;
|
| @@ -393,18 +390,17 @@ void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
|
|
|
| void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
|
| GrGLProcessor::TextureSamplerArray* outSamplers,
|
| - GrGLInstalledProcessors* installedProcessors) {
|
| - SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
|
| + GrGLInstalledProc* ip) {
|
| int numTextures = processor.numTextures();
|
| - samplers.push_back_n(numTextures);
|
| + ip->fSamplers.push_back_n(numTextures);
|
| SkString name;
|
| for (int t = 0; t < numTextures; ++t) {
|
| name.printf("Sampler%d", t);
|
| - samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| - kSampler2D_GrSLType,
|
| - name.c_str());
|
| + ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| + kSampler2D_GrSLType,
|
| + name.c_str());
|
| SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
|
| - (samplers[t].fUniform, processor.textureAccess(t)));
|
| + (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
|
| }
|
| }
|
|
|
| @@ -506,14 +502,14 @@ void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
|
|
|
| GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
|
| return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
|
| - fGeometryProcessor, fColorEffects, fCoverageEffects));
|
| + fGeometryProcessor, fFragmentProcessors.get()));
|
| }
|
|
|
| -////////////////////////////////////////////////////////////////////////////////
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| -GrGLInstalledProcessors::~GrGLInstalledProcessors() {
|
| - int numEffects = fGLProcessors.count();
|
| - for (int e = 0; e < numEffects; ++e) {
|
| - SkDELETE(fGLProcessors[e]);
|
| +GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
|
| + int numProcs = fProcs.count();
|
| + for (int e = 0; e < numProcs; ++e) {
|
| + SkDELETE(fProcs[e]);
|
| }
|
| }
|
|
|