joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 8 | #include "GrGLProgramBuilder.h" |
joshualitt | 8072caa | 2015-02-12 14:20:52 -0800 | [diff] [blame] | 9 | |
bsalomon | 6f7f201 | 2015-03-16 14:00:52 -0700 | [diff] [blame] | 10 | #include "GrAutoLocaleSetter.h" |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 11 | #include "GrCoordTransform.h" |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 12 | #include "GrGLProgramBuilder.h" |
| 13 | #include "GrTexture.h" |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 14 | #include "SkRTConf.h" |
| 15 | #include "SkTraceEvent.h" |
egdaniel | 574a4c1 | 2015-11-02 06:22:44 -0800 | [diff] [blame] | 16 | #include "gl/GrGLFragmentProcessor.h" |
joshualitt | e7afc2d | 2015-09-11 10:44:13 -0700 | [diff] [blame] | 17 | #include "gl/GrGLGeometryProcessor.h" |
| 18 | #include "gl/GrGLGpu.h" |
joshualitt | e7afc2d | 2015-09-11 10:44:13 -0700 | [diff] [blame] | 19 | #include "gl/GrGLProgram.h" |
| 20 | #include "gl/GrGLSLPrettyPrint.h" |
| 21 | #include "gl/GrGLXferProcessor.h" |
egdaniel | 574a4c1 | 2015-11-02 06:22:44 -0800 | [diff] [blame] | 22 | #include "gl/builders/GrGLShaderStringBuilder.h" |
joshualitt | e7afc2d | 2015-09-11 10:44:13 -0700 | [diff] [blame] | 23 | #include "glsl/GrGLSLCaps.h" |
egdaniel | 018fb62 | 2015-10-28 07:26:40 -0700 | [diff] [blame] | 24 | #include "glsl/GrGLSLProgramDataManager.h" |
egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 25 | #include "glsl/GrGLSLTextureSampler.h" |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 26 | |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 27 | #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) |
| 28 | #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
| 29 | |
joshualitt | 873ad0e | 2015-01-20 09:08:51 -0800 | [diff] [blame] | 30 | GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) { |
bsalomon | 3318ee7 | 2015-03-16 11:56:29 -0700 | [diff] [blame] | 31 | GrAutoLocaleSetter als("C"); |
| 32 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 33 | // create a builder. This will be handed off to effects so they can use it to add |
| 34 | // uniforms, varyings, textures, etc |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 35 | SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args)); |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 36 | |
| 37 | GrGLProgramBuilder* pb = builder.get(); |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 38 | |
egdaniel | 37b4d86 | 2014-11-03 10:07:07 -0800 | [diff] [blame] | 39 | // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 40 | // seed correctly here |
| 41 | GrGLSLExpr4 inputColor; |
| 42 | GrGLSLExpr4 inputCoverage; |
egdaniel | 37b4d86 | 2014-11-03 10:07:07 -0800 | [diff] [blame] | 43 | |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 44 | if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 45 | return nullptr; |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 46 | } |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 47 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 48 | return pb->finalize(); |
| 49 | } |
| 50 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 51 | ///////////////////////////////////////////////////////////////////////////// |
| 52 | |
joshualitt | 873ad0e | 2015-01-20 09:08:51 -0800 | [diff] [blame] | 53 | GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 54 | : INHERITED(args) |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 55 | , fGeometryProcessor(nullptr) |
| 56 | , fXferProcessor(nullptr) |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 57 | , fGpu(gpu) |
cdalton | 4271765 | 2015-06-18 11:54:30 -0700 | [diff] [blame] | 58 | , fUniforms(kVarsPerBlock) |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 59 | , fSamplerUniforms(4) |
| 60 | , fSeparableVaryingInfos(kVarsPerBlock) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 61 | } |
| 62 | |
joshualitt | 74077b9 | 2014-10-24 11:26:03 -0700 | [diff] [blame] | 63 | void GrGLProgramBuilder::addVarying(const char* name, |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 64 | GrGLSLVarying* varying, |
joshualitt | eb00eab | 2015-09-15 14:12:22 -0700 | [diff] [blame] | 65 | GrSLPrecision precision) { |
joshualitt | 74077b9 | 2014-10-24 11:26:03 -0700 | [diff] [blame] | 66 | SkASSERT(varying); |
| 67 | if (varying->vsVarying()) { |
joshualitt | eb00eab | 2015-09-15 14:12:22 -0700 | [diff] [blame] | 68 | fVS.addVarying(name, precision, varying); |
joshualitt | 74077b9 | 2014-10-24 11:26:03 -0700 | [diff] [blame] | 69 | } |
joshualitt | 873ad0e | 2015-01-20 09:08:51 -0800 | [diff] [blame] | 70 | if (this->primitiveProcessor().willUseGeoShader()) { |
joshualitt | eb00eab | 2015-09-15 14:12:22 -0700 | [diff] [blame] | 71 | fGS.addVarying(name, precision, varying); |
joshualitt | 74077b9 | 2014-10-24 11:26:03 -0700 | [diff] [blame] | 72 | } |
| 73 | if (varying->fsVarying()) { |
joshualitt | eb00eab | 2015-09-15 14:12:22 -0700 | [diff] [blame] | 74 | fFS.addVarying(varying, precision); |
joshualitt | 74077b9 | 2014-10-24 11:26:03 -0700 | [diff] [blame] | 75 | } |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 76 | } |
| 77 | |
joshualitt | 71c9260 | 2015-01-14 08:12:47 -0800 | [diff] [blame] | 78 | void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input, |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 79 | const char* output) { |
| 80 | GrSLType type = GrVertexAttribTypeToSLType(input->fType); |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 81 | GrGLSLVertToFrag v(type); |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 82 | this->addVarying(input->fName, &v); |
| 83 | fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); |
| 84 | fFS.codeAppendf("%s = %s;", output, v.fsIn()); |
| 85 | } |
| 86 | |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 87 | GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVarying( |
| 88 | const char* name, |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 89 | GrGLSLVertToFrag* v, |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 90 | GrSLPrecision fsPrecision) { |
| 91 | // This call is not used for non-NVPR backends. |
| 92 | SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() && |
| 93 | fArgs.fPrimitiveProcessor->isPathRendering() && |
| 94 | !fArgs.fPrimitiveProcessor->willUseGeoShader() && |
| 95 | fArgs.fPrimitiveProcessor->numAttribs() == 0); |
| 96 | this->addVarying(name, v, fsPrecision); |
| 97 | SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back(); |
| 98 | varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back(); |
| 99 | varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1; |
| 100 | return SeparableVaryingHandle(varyingInfo.fLocation); |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 101 | } |
| 102 | |
egdaniel | f3bace9 | 2015-11-06 06:57:12 -0800 | [diff] [blame] | 103 | GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformArray( |
bsalomon | 422f56f | 2014-12-09 10:18:12 -0800 | [diff] [blame] | 104 | uint32_t visibility, |
| 105 | GrSLType type, |
| 106 | GrSLPrecision precision, |
| 107 | const char* name, |
egdaniel | f3bace9 | 2015-11-06 06:57:12 -0800 | [diff] [blame] | 108 | bool mangleName, |
bsalomon | 422f56f | 2014-12-09 10:18:12 -0800 | [diff] [blame] | 109 | int count, |
| 110 | const char** outName) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 111 | SkASSERT(name && strlen(name)); |
| 112 | SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); |
| 113 | SkASSERT(0 == (~kVisibilityMask & visibility)); |
| 114 | SkASSERT(0 != visibility); |
bsalomon | 422f56f | 2014-12-09 10:18:12 -0800 | [diff] [blame] | 115 | SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 116 | |
| 117 | UniformInfo& uni = fUniforms.push_back(); |
| 118 | uni.fVariable.setType(type); |
egdaniel | 0d3f061 | 2015-10-21 10:45:48 -0700 | [diff] [blame] | 119 | uni.fVariable.setTypeModifier(GrGLSLShaderVar::kUniform_TypeModifier); |
joshualitt | 4973d9d | 2014-11-08 09:24:25 -0800 | [diff] [blame] | 120 | // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use |
| 121 | // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB |
| 122 | // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then |
| 123 | // the names will mismatch. I think the correct solution is to have all GPs which need the |
| 124 | // uniform view matrix, they should upload the view matrix in their setData along with regular |
| 125 | // uniforms. |
| 126 | char prefix = 'u'; |
| 127 | if ('u' == name[0]) { |
| 128 | prefix = '\0'; |
| 129 | } |
egdaniel | f3bace9 | 2015-11-06 06:57:12 -0800 | [diff] [blame] | 130 | this->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 131 | uni.fVariable.setArrayCount(count); |
| 132 | uni.fVisibility = visibility; |
bsalomon | 422f56f | 2014-12-09 10:18:12 -0800 | [diff] [blame] | 133 | uni.fVariable.setPrecision(precision); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 134 | |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame] | 135 | if (outName) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 136 | *outName = uni.fVariable.c_str(); |
| 137 | } |
egdaniel | 018fb62 | 2015-10-28 07:26:40 -0700 | [diff] [blame] | 138 | return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 139 | } |
| 140 | |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 141 | void GrGLProgramBuilder::onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 142 | for (int i = 0; i < fUniforms.count(); ++i) { |
| 143 | if (fUniforms[i].fVisibility & visibility) { |
egdaniel | f529439 | 2015-10-21 07:14:17 -0700 | [diff] [blame] | 144 | fUniforms[i].fVariable.appendDecl(this->glslCaps(), out); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 145 | out->append(";\n"); |
| 146 | } |
| 147 | } |
| 148 | } |
| 149 | |
egdaniel | f529439 | 2015-10-21 07:14:17 -0700 | [diff] [blame] | 150 | const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 151 | return this->fGpu->ctxInfo().caps()->glslCaps(); |
egdaniel | f529439 | 2015-10-21 07:14:17 -0700 | [diff] [blame] | 152 | } |
| 153 | |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 154 | bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { |
joshualitt | abb52a1 | 2015-01-13 15:02:10 -0800 | [diff] [blame] | 155 | // First we loop over all of the installed processors and collect coord transforms. These will |
| 156 | // be sent to the GrGLPrimitiveProcessor in its emitCode function |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 157 | const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
| 158 | int totalTextures = primProc.numTextures(); |
| 159 | const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); |
joshualitt | b2aa7cb | 2015-08-05 11:05:22 -0700 | [diff] [blame] | 160 | |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 161 | for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { |
| 162 | const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i); |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 163 | |
joshualitt | b2aa7cb | 2015-08-05 11:05:22 -0700 | [diff] [blame] | 164 | if (!primProc.hasTransformedLocalCoords()) { |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 165 | SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back(); |
| 166 | processor.gatherCoordTransforms(&procCoords); |
joshualitt | b2aa7cb | 2015-08-05 11:05:22 -0700 | [diff] [blame] | 167 | } |
wangyix | 4b3050b | 2015-08-04 07:59:37 -0700 | [diff] [blame] | 168 | |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 169 | totalTextures += processor.numTextures(); |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 170 | if (totalTextures >= maxTextureUnits) { |
bsalomon | 682c269 | 2015-05-22 14:01:46 -0700 | [diff] [blame] | 171 | GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n"); |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 172 | return false; |
| 173 | } |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 174 | } |
| 175 | |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 176 | this->emitAndInstallProc(primProc, inputColor, inputCoverage); |
| 177 | |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 178 | fFragmentProcessors.reset(new GrGLInstalledFragProcs); |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 179 | int numProcs = this->pipeline().numFragmentProcessors(); |
| 180 | this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor); |
| 181 | this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, |
bsalomon | 6be6f7c | 2015-02-26 13:05:21 -0800 | [diff] [blame] | 182 | inputCoverage); |
egdaniel | 8dd688b | 2015-01-22 10:16:09 -0800 | [diff] [blame] | 183 | this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage); |
joshualitt | 6c89110 | 2015-05-13 08:51:49 -0700 | [diff] [blame] | 184 | return true; |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 185 | } |
| 186 | |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 187 | void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, |
| 188 | int numProcs, |
| 189 | GrGLSLExpr4* inOut) { |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 190 | for (int i = procOffset; i < numProcs; ++i) { |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 191 | GrGLSLExpr4 output; |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 192 | const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); |
| 193 | this->emitAndInstallProc(fp, i, *inOut, &output); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 194 | *inOut = output; |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 195 | } |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 196 | } |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 197 | |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 198 | void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) { |
| 199 | // create var to hold stage result. If we already have a valid output name, just use that |
| 200 | // otherwise create a new mangled one. This name is only valid if we are reordering stages |
| 201 | // and have to tell stage exactly where to put its output. |
| 202 | SkString outName; |
| 203 | if (output->isValid()) { |
| 204 | outName = output->c_str(); |
| 205 | } else { |
| 206 | this->nameVariable(&outName, '\0', baseName); |
| 207 | } |
| 208 | fFS.codeAppendf("vec4 %s;", outName.c_str()); |
| 209 | *output = outName; |
| 210 | } |
| 211 | |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 212 | // TODO Processors cannot output zeros because an empty string is all 1s |
| 213 | // the fix is to allow effects to take the GrGLSLExpr4 directly |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 214 | void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 215 | int index, |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 216 | const GrGLSLExpr4& input, |
| 217 | GrGLSLExpr4* output) { |
| 218 | // Program builders have a bit of state we need to clear with each effect |
| 219 | AutoStageAdvance adv(this); |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 220 | this->nameExpression(output, "output"); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 221 | |
| 222 | // Enclose custom code in a block to avoid namespace conflicts |
| 223 | SkString openBrace; |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 224 | openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 225 | fFS.codeAppend(openBrace.c_str()); |
| 226 | |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 227 | this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullptr : input.c_str()); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 228 | |
| 229 | fFS.codeAppend("}"); |
| 230 | } |
| 231 | |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 232 | void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 233 | GrGLSLExpr4* outputColor, |
| 234 | GrGLSLExpr4* outputCoverage) { |
| 235 | // Program builders have a bit of state we need to clear with each effect |
| 236 | AutoStageAdvance adv(this); |
| 237 | this->nameExpression(outputColor, "outputColor"); |
| 238 | this->nameExpression(outputCoverage, "outputCoverage"); |
| 239 | |
| 240 | // Enclose custom code in a block to avoid namespace conflicts |
| 241 | SkString openBrace; |
| 242 | openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); |
| 243 | fFS.codeAppend(openBrace.c_str()); |
wangyix | 150714f | 2015-07-23 08:02:09 -0700 | [diff] [blame] | 244 | fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 245 | |
| 246 | this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()); |
| 247 | |
| 248 | fFS.codeAppend("}"); |
| 249 | } |
| 250 | |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 251 | void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, |
joshualitt | abb52a1 | 2015-01-13 15:02:10 -0800 | [diff] [blame] | 252 | int index, |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 253 | const char* outColor, |
| 254 | const char* inColor) { |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 255 | GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc; |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 256 | |
joshualitt | eb2a676 | 2014-12-04 11:35:33 -0800 | [diff] [blame] | 257 | ifp->fGLProc.reset(fp.createGLInstance()); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 258 | |
egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 259 | SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures()); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 260 | this->emitSamplers(fp, &samplers, ifp); |
| 261 | |
wangyix | 7c157a9 | 2015-07-22 15:08:53 -0700 | [diff] [blame] | 262 | GrGLFragmentProcessor::EmitArgs args(this, fp, outColor, inColor, fOutCoords[index], samplers); |
| 263 | ifp->fGLProc->emitCode(args); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 264 | |
| 265 | // We have to check that effects and the code they emit are consistent, ie if an effect |
| 266 | // asks for dst color, then the emit code needs to follow suit |
| 267 | verify(fp); |
| 268 | fFragmentProcessors->fProcs.push_back(ifp); |
| 269 | } |
| 270 | |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 271 | void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 272 | const char* outColor, |
| 273 | const char* outCoverage) { |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 274 | SkASSERT(!fGeometryProcessor); |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 275 | fGeometryProcessor = new GrGLInstalledGeoProc; |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 276 | |
joshualitt | 465283c | 2015-09-11 08:19:35 -0700 | [diff] [blame] | 277 | fGeometryProcessor->fGLProc.reset(gp.createGLInstance(*fGpu->glCaps().glslCaps())); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 278 | |
egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 279 | SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures()); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 280 | this->emitSamplers(gp, &samplers, fGeometryProcessor); |
| 281 | |
joshualitt | 465283c | 2015-09-11 08:19:35 -0700 | [diff] [blame] | 282 | GrGLGeometryProcessor::EmitArgs args(this, gp, outColor, outCoverage, samplers, |
joshualitt | abb52a1 | 2015-01-13 15:02:10 -0800 | [diff] [blame] | 283 | fCoordTransforms, &fOutCoords); |
joshualitt | c369e7c | 2014-10-22 10:56:26 -0700 | [diff] [blame] | 284 | fGeometryProcessor->fGLProc->emitCode(args); |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 285 | |
| 286 | // We have to check that effects and the code they emit are consistent, ie if an effect |
| 287 | // asks for dst color, then the emit code needs to follow suit |
| 288 | verify(gp); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 289 | } |
| 290 | |
egdaniel | c230414 | 2014-12-11 13:15:13 -0800 | [diff] [blame] | 291 | void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp, |
| 292 | const GrGLSLExpr4& colorIn, |
| 293 | const GrGLSLExpr4& coverageIn) { |
| 294 | // Program builders have a bit of state we need to clear with each effect |
| 295 | AutoStageAdvance adv(this); |
| 296 | |
| 297 | SkASSERT(!fXferProcessor); |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 298 | fXferProcessor = new GrGLInstalledXferProc; |
egdaniel | c230414 | 2014-12-11 13:15:13 -0800 | [diff] [blame] | 299 | |
| 300 | fXferProcessor->fGLProc.reset(xp.createGLInstance()); |
| 301 | |
| 302 | // Enable dual source secondary output if we have one |
| 303 | if (xp.hasSecondaryOutput()) { |
| 304 | fFS.enableSecondaryOutput(); |
| 305 | } |
| 306 | |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 307 | if (this->glslCaps()->mustDeclareFragmentShaderOutput()) { |
egdaniel | c230414 | 2014-12-11 13:15:13 -0800 | [diff] [blame] | 308 | fFS.enableCustomOutput(); |
| 309 | } |
| 310 | |
| 311 | SkString openBrace; |
| 312 | openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); |
| 313 | fFS.codeAppend(openBrace.c_str()); |
| 314 | |
egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 315 | SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); |
egdaniel | c230414 | 2014-12-11 13:15:13 -0800 | [diff] [blame] | 316 | this->emitSamplers(xp, &samplers, fXferProcessor); |
| 317 | |
| 318 | GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(), |
| 319 | fFS.getPrimaryColorOutputName(), |
| 320 | fFS.getSecondaryColorOutputName(), samplers); |
| 321 | fXferProcessor->fGLProc->emitCode(args); |
| 322 | |
| 323 | // We have to check that effects and the code they emit are consistent, ie if an effect |
| 324 | // asks for dst color, then the emit code needs to follow suit |
| 325 | verify(xp); |
| 326 | fFS.codeAppend("}"); |
| 327 | } |
| 328 | |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 329 | void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 330 | SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); |
joshualitt | fe1233c | 2014-10-07 12:16:35 -0700 | [diff] [blame] | 331 | } |
| 332 | |
egdaniel | c230414 | 2014-12-11 13:15:13 -0800 | [diff] [blame] | 333 | void GrGLProgramBuilder::verify(const GrXferProcessor& xp) { |
egdaniel | 71e236c | 2015-01-20 06:34:51 -0800 | [diff] [blame] | 334 | SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); |
egdaniel | c230414 | 2014-12-11 13:15:13 -0800 | [diff] [blame] | 335 | } |
| 336 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 337 | void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { |
| 338 | SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 339 | } |
| 340 | |
joshualitt | abb52a1 | 2015-01-13 15:02:10 -0800 | [diff] [blame] | 341 | template <class Proc> |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 342 | void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 343 | GrGLSLTextureSampler::TextureSamplerArray* outSamplers, |
joshualitt | abb52a1 | 2015-01-13 15:02:10 -0800 | [diff] [blame] | 344 | GrGLInstalledProc<Proc>* ip) { |
cdalton | 4271765 | 2015-06-18 11:54:30 -0700 | [diff] [blame] | 345 | SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();) |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 346 | int numTextures = processor.numTextures(); |
cdalton | 4271765 | 2015-06-18 11:54:30 -0700 | [diff] [blame] | 347 | UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures); |
joshualitt | 23e280d | 2014-09-18 12:26:38 -0700 | [diff] [blame] | 348 | SkString name; |
| 349 | for (int t = 0; t < numTextures; ++t) { |
| 350 | name.printf("Sampler%d", t); |
cdalton | 4271765 | 2015-06-18 11:54:30 -0700 | [diff] [blame] | 351 | localSamplerUniforms[t] = this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
| 352 | kSampler2D_GrSLType, kDefault_GrSLPrecision, |
| 353 | name.c_str()); |
egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 354 | SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLSLTextureSampler, |
cdalton | 4271765 | 2015-06-18 11:54:30 -0700 | [diff] [blame] | 355 | (localSamplerUniforms[t], processor.textureAccess(t))); |
joshualitt | 23e280d | 2014-09-18 12:26:38 -0700 | [diff] [blame] | 356 | } |
| 357 | } |
| 358 | |
egdaniel | 2d721d3 | 2015-11-11 13:06:05 -0800 | [diff] [blame^] | 359 | bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader, |
egdaniel | 574a4c1 | 2015-11-02 06:22:44 -0800 | [diff] [blame] | 360 | GrGLuint programId, |
| 361 | GrGLenum type, |
| 362 | SkTDArray<GrGLuint>* shaderIds) { |
| 363 | GrGLGpu* gpu = this->gpu(); |
| 364 | GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(), |
| 365 | programId, |
| 366 | type, |
| 367 | shader.fCompilerStrings.begin(), |
| 368 | shader.fCompilerStringLengths.begin(), |
| 369 | shader.fCompilerStrings.count(), |
| 370 | gpu->stats()); |
| 371 | |
| 372 | if (!shaderId) { |
| 373 | return false; |
| 374 | } |
| 375 | |
| 376 | *shaderIds->append() = shaderId; |
| 377 | |
| 378 | return true; |
| 379 | } |
| 380 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 381 | GrGLProgram* GrGLProgramBuilder::finalize() { |
| 382 | // verify we can get a program id |
| 383 | GrGLuint programID; |
| 384 | GL_CALL_RET(programID, CreateProgram()); |
| 385 | if (0 == programID) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 386 | return nullptr; |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 387 | } |
| 388 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 389 | // compile shaders and bind attributes / uniforms |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 390 | SkTDArray<GrGLuint> shadersToDelete; |
egdaniel | 574a4c1 | 2015-11-02 06:22:44 -0800 | [diff] [blame] | 391 | fVS.finalize(kVertex_Visibility); |
| 392 | if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) { |
jvanverth | 5053063 | 2015-04-27 10:36:27 -0700 | [diff] [blame] | 393 | this->cleanupProgram(programID, shadersToDelete); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 394 | return nullptr; |
jvanverth | 5053063 | 2015-04-27 10:36:27 -0700 | [diff] [blame] | 395 | } |
joshualitt | 2dd1ae0 | 2014-12-03 06:24:10 -0800 | [diff] [blame] | 396 | |
jvanverth | 5053063 | 2015-04-27 10:36:27 -0700 | [diff] [blame] | 397 | // NVPR actually requires a vertex shader to compile |
| 398 | bool useNvpr = primitiveProcessor().isPathRendering(); |
| 399 | if (!useNvpr) { |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 400 | const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
| 401 | |
| 402 | int vaCount = primProc.numAttribs(); |
| 403 | for (int i = 0; i < vaCount; i++) { |
| 404 | GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName)); |
| 405 | } |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 406 | } |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 407 | |
egdaniel | 574a4c1 | 2015-11-02 06:22:44 -0800 | [diff] [blame] | 408 | fFS.finalize(kFragment_Visibility); |
| 409 | if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) { |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 410 | this->cleanupProgram(programID, shadersToDelete); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 411 | return nullptr; |
joshualitt | 9b98932 | 2014-12-15 14:16:27 -0800 | [diff] [blame] | 412 | } |
| 413 | |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 414 | this->bindProgramResourceLocations(programID); |
| 415 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 416 | GL_CALL(LinkProgram(programID)); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 417 | |
| 418 | // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. |
cdalton | 1acea86 | 2015-06-02 13:05:52 -0700 | [diff] [blame] | 419 | bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 420 | #ifdef SK_DEBUG |
| 421 | checkLinked = true; |
| 422 | #endif |
| 423 | if (checkLinked) { |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 424 | checkLinkStatus(programID); |
joshualitt | fe1233c | 2014-10-07 12:16:35 -0700 | [diff] [blame] | 425 | } |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 426 | this->resolveProgramResourceLocations(programID); |
joshualitt | db0d3ca | 2014-10-07 12:42:26 -0700 | [diff] [blame] | 427 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 428 | this->cleanupShaders(shadersToDelete); |
| 429 | |
| 430 | return this->createProgram(programID); |
| 431 | } |
| 432 | |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 433 | void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) { |
joshualitt | 7bdd70a | 2015-10-01 06:28:11 -0700 | [diff] [blame] | 434 | if (fGpu->glCaps().bindUniformLocationSupport()) { |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 435 | int count = fUniforms.count(); |
| 436 | for (int i = 0; i < count; ++i) { |
| 437 | GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str())); |
| 438 | fUniforms[i].fLocation = i; |
| 439 | } |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 440 | } |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 441 | |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 442 | const GrGLCaps& caps = this->gpu()->glCaps(); |
| 443 | if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) { |
| 444 | GL_CALL(BindFragDataLocation(programID, 0, |
egdaniel | 2d721d3 | 2015-11-11 13:06:05 -0800 | [diff] [blame^] | 445 | GrGLSLFragmentShaderBuilder::DeclaredColorOutputName())); |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 446 | } |
| 447 | if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOutput()) { |
| 448 | GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, |
egdaniel | 2d721d3 | 2015-11-11 13:06:05 -0800 | [diff] [blame^] | 449 | GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName())); |
egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 450 | } |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 451 | |
| 452 | // handle NVPR separable varyings |
| 453 | if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() || |
| 454 | !fGpu->glPathRendering()->shouldBindFragmentInputs()) { |
| 455 | return; |
| 456 | } |
| 457 | int count = fSeparableVaryingInfos.count(); |
| 458 | for (int i = 0; i < count; ++i) { |
| 459 | GL_CALL(BindFragmentInputLocation(programID, |
| 460 | i, |
| 461 | fSeparableVaryingInfos[i].fVariable.c_str())); |
| 462 | fSeparableVaryingInfos[i].fLocation = i; |
| 463 | } |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 464 | } |
| 465 | |
| 466 | bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { |
| 467 | GrGLint linked = GR_GL_INIT_ZERO; |
| 468 | GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); |
| 469 | if (!linked) { |
| 470 | GrGLint infoLen = GR_GL_INIT_ZERO; |
| 471 | GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
| 472 | SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
| 473 | if (infoLen > 0) { |
| 474 | // retrieve length even though we don't need it to workaround |
| 475 | // bug in chrome cmd buffer param validation. |
| 476 | GrGLsizei length = GR_GL_INIT_ZERO; |
| 477 | GL_CALL(GetProgramInfoLog(programID, |
| 478 | infoLen+1, |
| 479 | &length, |
| 480 | (char*)log.get())); |
kkinnunen | 297aaf9 | 2015-02-19 06:32:12 -0800 | [diff] [blame] | 481 | SkDebugf("%s", (char*)log.get()); |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 482 | } |
| 483 | SkDEBUGFAIL("Error linking program"); |
| 484 | GL_CALL(DeleteProgram(programID)); |
| 485 | programID = 0; |
| 486 | } |
| 487 | return SkToBool(linked); |
| 488 | } |
| 489 | |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 490 | void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { |
kkinnunen | 177519e | 2015-10-28 06:18:35 -0700 | [diff] [blame] | 491 | if (!fGpu->glCaps().bindUniformLocationSupport()) { |
kkinnunen | 7aedda5 | 2015-06-29 23:01:28 -0700 | [diff] [blame] | 492 | int count = fUniforms.count(); |
| 493 | for (int i = 0; i < count; ++i) { |
| 494 | GrGLint location; |
| 495 | GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str())); |
| 496 | fUniforms[i].fLocation = location; |
| 497 | } |
kkinnunen | ec56e45 | 2014-08-25 22:21:16 -0700 | [diff] [blame] | 498 | } |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 499 | |
| 500 | // handle NVPR separable varyings |
| 501 | if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() || |
| 502 | !fGpu->glPathRendering()->shouldBindFragmentInputs()) { |
| 503 | return; |
| 504 | } |
| 505 | int count = fSeparableVaryingInfos.count(); |
| 506 | for (int i = 0; i < count; ++i) { |
| 507 | GrGLint location; |
| 508 | GL_CALL_RET(location, |
| 509 | GetProgramResourceLocation(programID, |
| 510 | GR_GL_FRAGMENT_INPUT, |
| 511 | fSeparableVaryingInfos[i].fVariable.c_str())); |
| 512 | fSeparableVaryingInfos[i].fLocation = location; |
| 513 | } |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 514 | } |
| 515 | |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 516 | void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) { |
| 517 | GL_CALL(DeleteProgram(programID)); |
| 518 | cleanupShaders(shaderIDs); |
| 519 | } |
| 520 | void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { |
| 521 | for (int i = 0; i < shaderIDs.count(); ++i) { |
| 522 | GL_CALL(DeleteShader(shaderIDs[i])); |
| 523 | } |
| 524 | } |
| 525 | |
| 526 | GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 527 | return new GrGLProgram(fGpu, this->desc(), fUniformHandles, programID, fUniforms, |
joshualitt | d8dd47b | 2015-09-11 11:45:01 -0700 | [diff] [blame] | 528 | fSeparableVaryingInfos, |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 529 | fGeometryProcessor, fXferProcessor, fFragmentProcessors.get(), |
| 530 | &fSamplerUniforms); |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 531 | } |
| 532 | |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 533 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 534 | |
joshualitt | a5305a1 | 2014-10-10 17:47:00 -0700 | [diff] [blame] | 535 | GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
| 536 | int numProcs = fProcs.count(); |
bsalomon | ac856c9 | 2015-08-27 06:30:17 -0700 | [diff] [blame] | 537 | for (int i = 0; i < numProcs; ++i) { |
| 538 | delete fProcs[i]; |
joshualitt | 47bb382 | 2014-10-07 16:43:25 -0700 | [diff] [blame] | 539 | } |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 540 | } |