| 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];
|
| - }
|
| -}
|
|
|