Index: src/gpu/gl/builders/GrGLProgramBuilder.cpp |
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
index 4360f7858d2129171fb19382dfb02bb0e1e64d34..4503d1a1972d49f2c259d31ae41b4d44b469175a 100644 |
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
@@ -42,7 +42,10 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp |
GrGLSLExpr4 inputColor; |
GrGLSLExpr4 inputCoverage; |
- if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { |
+ if (!pb->emitAndInstallProcs(&inputColor, |
+ &inputCoverage, |
+ gpu->glCaps().maxFragmentTextureUnits())) { |
+ pb->cleanupFragmentProcessors(); |
return nullptr; |
} |
@@ -53,243 +56,18 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp |
GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
: INHERITED(args) |
- , fGeometryProcessor(nullptr) |
- , fXferProcessor(nullptr) |
, fGpu(gpu) |
, fSamplerUniforms(4) |
, fVaryingHandler(this) |
, fUniformHandler(this) { |
} |
-const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { |
- return this->fGpu->ctxInfo().caps()->glslCaps(); |
-} |
- |
-bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { |
- // First we loop over all of the installed processors and collect coord transforms. These will |
- // be sent to the GrGLSLPrimitiveProcessor in its emitCode function |
- const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
- int totalTextures = primProc.numTextures(); |
- const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); |
- |
- for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { |
- const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i); |
- |
- if (!primProc.hasTransformedLocalCoords()) { |
- SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back(); |
- processor.gatherCoordTransforms(&procCoords); |
- } |
- |
- totalTextures += processor.numTextures(); |
- if (totalTextures >= maxTextureUnits) { |
- GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n"); |
- return false; |
- } |
- } |
- |
- this->emitAndInstallProc(primProc, inputColor, inputCoverage); |
- |
- fFragmentProcessors.reset(new GrGLInstalledFragProcs); |
- int numProcs = this->pipeline().numFragmentProcessors(); |
- this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor); |
- this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, |
- inputCoverage); |
- this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage, |
- this->pipeline().ignoresCoverage()); |
- this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput()); |
- return true; |
-} |
- |
-void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, |
- int numProcs, |
- GrGLSLExpr4* inOut) { |
- for (int i = procOffset; i < numProcs; ++i) { |
- GrGLSLExpr4 output; |
- const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); |
- this->emitAndInstallProc(fp, i, *inOut, &output); |
- *inOut = output; |
- } |
-} |
- |
-void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) { |
- // create var to hold stage result. If we already have a valid output name, just use that |
- // otherwise create a new mangled one. This name is only valid if we are reordering stages |
- // and have to tell stage exactly where to put its output. |
- SkString outName; |
- if (output->isValid()) { |
- outName = output->c_str(); |
- } else { |
- this->nameVariable(&outName, '\0', baseName); |
- } |
- fFS.codeAppendf("vec4 %s;", outName.c_str()); |
- *output = outName; |
-} |
- |
-// TODO Processors cannot output zeros because an empty string is all 1s |
-// the fix is to allow effects to take the GrGLSLExpr4 directly |
-void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, |
- int index, |
- const GrGLSLExpr4& input, |
- GrGLSLExpr4* output) { |
- // Program builders have a bit of state we need to clear with each effect |
- AutoStageAdvance adv(this); |
- this->nameExpression(output, "output"); |
- |
- // Enclose custom code in a block to avoid namespace conflicts |
- SkString openBrace; |
- openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); |
- fFS.codeAppend(openBrace.c_str()); |
- |
- this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullptr : input.c_str()); |
- |
- fFS.codeAppend("}"); |
-} |
- |
-void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, |
- GrGLSLExpr4* outputColor, |
- GrGLSLExpr4* outputCoverage) { |
- // Program builders have a bit of state we need to clear with each effect |
- AutoStageAdvance adv(this); |
- this->nameExpression(outputColor, "outputColor"); |
- this->nameExpression(outputCoverage, "outputCoverage"); |
- |
- // Enclose custom code in a block to avoid namespace conflicts |
- SkString openBrace; |
- openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); |
- fFS.codeAppend(openBrace.c_str()); |
- fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); |
- |
- this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()); |
- |
- fFS.codeAppend("}"); |
-} |
- |
-void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, |
- int index, |
- const char* outColor, |
- const char* inColor) { |
- GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc; |
- |
- ifp->fGLProc.reset(fp.createGLSLInstance()); |
- |
- SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures()); |
- this->emitSamplers(fp, &samplers, ifp); |
- |
- GrGLSLFragmentProcessor::EmitArgs args(&fFS, |
- &fUniformHandler, |
- this->glslCaps(), |
- fp, |
- outColor, |
- inColor, |
- fOutCoords[index], |
- samplers); |
- ifp->fGLProc->emitCode(args); |
- |
- // 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); |
+const GrCaps* GrGLProgramBuilder::caps() const { |
+ return fGpu->caps(); |
} |
-void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, |
- const char* outColor, |
- const char* outCoverage) { |
- SkASSERT(!fGeometryProcessor); |
- fGeometryProcessor = new GrGLInstalledGeoProc; |
- |
- fGeometryProcessor->fGLProc.reset(gp.createGLSLInstance(*fGpu->glCaps().glslCaps())); |
- |
- SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures()); |
- this->emitSamplers(gp, &samplers, fGeometryProcessor); |
- |
- GrGLSLGeometryProcessor::EmitArgs args(&fVS, |
- &fFS, |
- &fVaryingHandler, |
- &fUniformHandler, |
- this->glslCaps(), |
- gp, |
- outColor, |
- outCoverage, |
- samplers, |
- fCoordTransforms, |
- &fOutCoords); |
- fGeometryProcessor->fGLProc->emitCode(args); |
- |
- // 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::emitAndInstallXferProc(const GrXferProcessor& xp, |
- const GrGLSLExpr4& colorIn, |
- const GrGLSLExpr4& coverageIn, |
- bool ignoresCoverage) { |
- // Program builders have a bit of state we need to clear with each effect |
- AutoStageAdvance adv(this); |
- |
- SkASSERT(!fXferProcessor); |
- fXferProcessor = new GrGLInstalledXferProc; |
- |
- fXferProcessor->fGLProc.reset(xp.createGLSLInstance()); |
- |
- // Enable dual source secondary output if we have one |
- if (xp.hasSecondaryOutput()) { |
- fFS.enableSecondaryOutput(); |
- } |
- |
- if (this->glslCaps()->mustDeclareFragmentShaderOutput()) { |
- fFS.enableCustomOutput(); |
- } |
- |
- SkString openBrace; |
- openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); |
- fFS.codeAppend(openBrace.c_str()); |
- |
- SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); |
- this->emitSamplers(xp, &samplers, fXferProcessor); |
- |
- GrGLSLXferProcessor::EmitArgs args(&fFS, |
- &fUniformHandler, |
- this->glslCaps(), |
- xp, colorIn.c_str(), |
- ignoresCoverage ? nullptr : coverageIn.c_str(), |
- fFS.getPrimaryColorOutputName(), |
- fFS.getSecondaryColorOutputName(), |
- samplers); |
- fXferProcessor->fGLProc->emitCode(args); |
- |
- // 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(xp); |
- fFS.codeAppend("}"); |
-} |
- |
-void GrGLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { |
- // Swizzle the fragment shader outputs if necessary. |
- GrSwizzle swizzle; |
- swizzle.setFromKey(this->desc().header().fOutputSwizzle); |
- if (swizzle != GrSwizzle::RGBA()) { |
- fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), |
- fFS.getPrimaryColorOutputName(), |
- swizzle.c_str()); |
- if (hasSecondaryOutput) { |
- fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), |
- fFS.getSecondaryColorOutputName(), |
- swizzle.c_str()); |
- } |
- } |
-} |
- |
-void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { |
- SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); |
-} |
- |
-void GrGLProgramBuilder::verify(const GrXferProcessor& xp) { |
- SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); |
-} |
- |
-void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { |
- SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); |
+const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { |
+ return fGpu->ctxInfo().caps()->glslCaps(); |
} |
static GrSLType get_sampler_type(const GrTextureAccess& access) { |
@@ -302,11 +80,8 @@ static GrSLType get_sampler_type(const GrTextureAccess& access) { |
} |
} |
-template <class Proc> |
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
- GrGLSLTextureSampler::TextureSamplerArray* outSamplers, |
- GrGLInstalledProc<Proc>* ip) { |
- SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();) |
+ GrGLSLTextureSampler::TextureSamplerArray* outSamplers) { |
int numTextures = processor.numTextures(); |
UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures); |
SkString name; |
@@ -356,6 +131,7 @@ GrGLProgram* GrGLProgramBuilder::finalize() { |
GrGLuint programID; |
GL_CALL_RET(programID, CreateProgram()); |
if (0 == programID) { |
+ this->cleanupFragmentProcessors(); |
return nullptr; |
} |
@@ -474,7 +250,8 @@ void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { |
void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) { |
GL_CALL(DeleteProgram(programID)); |
- cleanupShaders(shaderIDs); |
+ this->cleanupShaders(shaderIDs); |
+ this->cleanupFragmentProcessors(); |
} |
void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { |
for (int i = 0; i < shaderIDs.count(); ++i) { |
@@ -491,15 +268,7 @@ GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
fVaryingHandler.fPathProcVaryingInfos, |
fGeometryProcessor, |
fXferProcessor, |
- fFragmentProcessors.get(), |
+ fFragmentProcessors, |
&fSamplerUniforms); |
} |
-/////////////////////////////////////////////////////////////////////////////////////////////////// |
- |
-GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
- int numProcs = fProcs.count(); |
- for (int i = 0; i < numProcs; ++i) { |
- delete fProcs[i]; |
- } |
-} |