blob: 9fbb4c19531d086171ea46898fd7d3f5c7127fe7 [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
joshualitt47bb3822014-10-07 16:43:25 -07008#include "GrGLProgramBuilder.h"
joshualitt30ba4362014-08-21 20:18:45 -07009#include "gl/GrGLProgram.h"
10#include "gl/GrGLSLPrettyPrint.h"
11#include "gl/GrGLUniformHandle.h"
egdanielc2304142014-12-11 13:15:13 -080012#include "../GrGLXferProcessor.h"
jvanverth39edf762014-12-22 11:44:19 -080013#include "../GrGLGpu.h"
joshualitt47bb3822014-10-07 16:43:25 -070014#include "GrCoordTransform.h"
joshualitt30ba4362014-08-21 20:18:45 -070015#include "GrGLProgramBuilder.h"
16#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070017#include "SkRTConf.h"
18#include "SkTraceEvent.h"
19
joshualitt30ba4362014-08-21 20:18:45 -070020#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
21#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
22
joshualittabb52a12015-01-13 15:02:10 -080023///////////////////////////////////////////////////////////////////////////////////////////////////
24
25class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
26public:
joshualitt873ad0e2015-01-20 09:08:51 -080027 GrGLNvprProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
28 : INHERITED(gpu, args) {}
joshualittabb52a12015-01-13 15:02:10 -080029
30 GrGLProgram* createProgram(GrGLuint programID) SK_OVERRIDE {
31 // this is just for nvpr es, which has separable varyings that are plugged in after
32 // building
33 GrGLPathProcessor* pathProc =
34 static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get());
35 pathProc->resolveSeparableVaryings(fGpu, programID);
joshualitt873ad0e2015-01-20 09:08:51 -080036 return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles, programID,
37 fUniforms,
joshualittabb52a12015-01-13 15:02:10 -080038 fGeometryProcessor,
39 fXferProcessor, fFragmentProcessors.get()));
40 }
41
42private:
43 typedef GrGLProgramBuilder INHERITED;
44};
45
46
47
joshualitt30ba4362014-08-21 20:18:45 -070048//////////////////////////////////////////////////////////////////////////////
49
joshualitt47bb3822014-10-07 16:43:25 -070050const int GrGLProgramBuilder::kVarsPerBlock = 8;
51
joshualitt873ad0e2015-01-20 09:08:51 -080052GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
joshualitt47bb3822014-10-07 16:43:25 -070053 // create a builder. This will be handed off to effects so they can use it to add
54 // uniforms, varyings, textures, etc
joshualitt873ad0e2015-01-20 09:08:51 -080055 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu));
joshualitt47bb3822014-10-07 16:43:25 -070056
57 GrGLProgramBuilder* pb = builder.get();
joshualitt47bb3822014-10-07 16:43:25 -070058
59 // emit code to read the dst copy texture, if necessary
joshualitt71c92602015-01-14 08:12:47 -080060 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != pb->header().fDstReadKey &&
joshualitt9b989322014-12-15 14:16:27 -080061 !gpu->glCaps().fbFetchSupport()) {
joshualitt47bb3822014-10-07 16:43:25 -070062 pb->fFS.emitCodeToReadDstTexture();
63 }
64
egdaniel37b4d862014-11-03 10:07:07 -080065 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
joshualitt9b989322014-12-15 14:16:27 -080066 // seed correctly here
67 GrGLSLExpr4 inputColor;
68 GrGLSLExpr4 inputCoverage;
egdaniel37b4d862014-11-03 10:07:07 -080069
joshualitt9b989322014-12-15 14:16:27 -080070 pb->emitAndInstallProcs(&inputColor, &inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -070071
joshualitt47bb3822014-10-07 16:43:25 -070072 return pb->finalize();
73}
74
joshualitt873ad0e2015-01-20 09:08:51 -080075GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& args,
bsalomon861e1032014-12-16 07:33:49 -080076 GrGLGpu* gpu) {
joshualitt17e73142015-01-21 11:52:36 -080077 if (args.fPrimitiveProcessor->isPathRendering()) {
joshualitt71c92602015-01-14 08:12:47 -080078 SkASSERT(gpu->glCaps().pathRenderingSupport() &&
joshualitt873ad0e2015-01-20 09:08:51 -080079 !args.fPrimitiveProcessor->willUseGeoShader() &&
80 args.fPrimitiveProcessor->numAttribs() == 0);
81 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args));
joshualitt47bb3822014-10-07 16:43:25 -070082 } else {
joshualitt873ad0e2015-01-20 09:08:51 -080083 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args));
joshualitt47bb3822014-10-07 16:43:25 -070084 }
85}
86
87/////////////////////////////////////////////////////////////////////////////
88
joshualitt873ad0e2015-01-20 09:08:51 -080089GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
joshualitt47bb3822014-10-07 16:43:25 -070090 : fVS(this)
91 , fGS(this)
joshualitt873ad0e2015-01-20 09:08:51 -080092 , fFS(this, args.fDesc->header().fFragPosKey)
joshualitt47bb3822014-10-07 16:43:25 -070093 , fOutOfStage(true)
94 , fStageIndex(-1)
joshualitta5305a12014-10-10 17:47:00 -070095 , fGeometryProcessor(NULL)
egdanielc2304142014-12-11 13:15:13 -080096 , fXferProcessor(NULL)
joshualitt873ad0e2015-01-20 09:08:51 -080097 , fArgs(args)
joshualitt30ba4362014-08-21 20:18:45 -070098 , fGpu(gpu)
99 , fUniforms(kVarsPerBlock) {
100}
101
joshualitt74077b92014-10-24 11:26:03 -0700102void GrGLProgramBuilder::addVarying(const char* name,
103 GrGLVarying* varying,
bsalomonc0bd6482014-12-09 10:04:14 -0800104 GrSLPrecision fsPrecision) {
joshualitt74077b92014-10-24 11:26:03 -0700105 SkASSERT(varying);
106 if (varying->vsVarying()) {
107 fVS.addVarying(name, varying);
108 }
joshualitt873ad0e2015-01-20 09:08:51 -0800109 if (this->primitiveProcessor().willUseGeoShader()) {
joshualitt74077b92014-10-24 11:26:03 -0700110 fGS.addVarying(name, varying);
111 }
112 if (varying->fsVarying()) {
113 fFS.addVarying(varying, fsPrecision);
114 }
joshualitt47bb3822014-10-07 16:43:25 -0700115}
116
joshualitt71c92602015-01-14 08:12:47 -0800117void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input,
joshualitt2dd1ae02014-12-03 06:24:10 -0800118 const char* output) {
119 GrSLType type = GrVertexAttribTypeToSLType(input->fType);
120 GrGLVertToFrag v(type);
121 this->addVarying(input->fName, &v);
122 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
123 fFS.codeAppendf("%s = %s;", output, v.fsIn());
124}
125
joshualitt30ba4362014-08-21 20:18:45 -0700126void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
127 if ('\0' == prefix) {
128 *out = name;
129 } else {
130 out->printf("%c%s", prefix, name);
131 }
joshualitt47bb3822014-10-07 16:43:25 -0700132 if (!fOutOfStage) {
joshualitt30ba4362014-08-21 20:18:45 -0700133 if (out->endsWith('_')) {
134 // Names containing "__" are reserved.
135 out->append("x");
136 }
joshualitt47bb3822014-10-07 16:43:25 -0700137 out->appendf("_Stage%d", fStageIndex);
joshualitt30ba4362014-08-21 20:18:45 -0700138 }
139}
140
bsalomon422f56f2014-12-09 10:18:12 -0800141GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(
142 uint32_t visibility,
143 GrSLType type,
144 GrSLPrecision precision,
145 const char* name,
146 int count,
147 const char** outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700148 SkASSERT(name && strlen(name));
149 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
150 SkASSERT(0 == (~kVisibilityMask & visibility));
151 SkASSERT(0 != visibility);
bsalomon422f56f2014-12-09 10:18:12 -0800152 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type));
joshualitt30ba4362014-08-21 20:18:45 -0700153
154 UniformInfo& uni = fUniforms.push_back();
155 uni.fVariable.setType(type);
156 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
joshualitt4973d9d2014-11-08 09:24:25 -0800157 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use
158 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
159 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then
160 // the names will mismatch. I think the correct solution is to have all GPs which need the
161 // uniform view matrix, they should upload the view matrix in their setData along with regular
162 // uniforms.
163 char prefix = 'u';
164 if ('u' == name[0]) {
165 prefix = '\0';
166 }
167 this->nameVariable(uni.fVariable.accessName(), prefix, name);
joshualitt30ba4362014-08-21 20:18:45 -0700168 uni.fVariable.setArrayCount(count);
169 uni.fVisibility = visibility;
bsalomon422f56f2014-12-09 10:18:12 -0800170 uni.fVariable.setPrecision(precision);
joshualitt30ba4362014-08-21 20:18:45 -0700171
bsalomon49f085d2014-09-05 13:34:00 -0700172 if (outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700173 *outName = uni.fVariable.c_str();
174 }
175 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
176}
177
joshualitt30ba4362014-08-21 20:18:45 -0700178void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
179 SkString* out) const {
180 for (int i = 0; i < fUniforms.count(); ++i) {
181 if (fUniforms[i].fVisibility & visibility) {
182 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
183 out->append(";\n");
184 }
185 }
186}
187
joshualitt47bb3822014-10-07 16:43:25 -0700188const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
189 return fGpu->ctxInfo();
190}
191
joshualitt2dd1ae02014-12-03 06:24:10 -0800192void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
joshualittabb52a12015-01-13 15:02:10 -0800193 // First we loop over all of the installed processors and collect coord transforms. These will
194 // be sent to the GrGLPrimitiveProcessor in its emitCode function
195 SkSTArray<8, GrGLProcessor::TransformedCoordsArray> outCoords;
joshualitt873ad0e2015-01-20 09:08:51 -0800196 for (int i = 0; i < this->optState().numFragmentStages(); i++) {
197 const GrFragmentProcessor* processor = this->optState().getFragmentStage(i).processor();
joshualittabb52a12015-01-13 15:02:10 -0800198 SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
199 for (int t = 0; t < processor->numTransforms(); t++) {
200 procCoords.push_back(&processor->coordTransform(t));
201 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800202 }
203
joshualitt873ad0e2015-01-20 09:08:51 -0800204 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
joshualitt9b989322014-12-15 14:16:27 -0800205 this->emitAndInstallProc(primProc, inputColor, inputCoverage);
206
joshualitta5305a12014-10-10 17:47:00 -0700207 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
joshualitt873ad0e2015-01-20 09:08:51 -0800208 int numProcs = this->optState().numFragmentStages();
209 this->emitAndInstallFragProcs(0, this->optState().numColorStages(), inputColor);
210 this->emitAndInstallFragProcs(this->optState().numColorStages(), numProcs, inputCoverage);
211 this->emitAndInstallXferProc(*this->optState().getXferProcessor(), *inputColor, *inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700212}
213
joshualitt2dd1ae02014-12-03 06:24:10 -0800214void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
215 int numProcs,
216 GrGLSLExpr4* inOut) {
joshualitta5305a12014-10-10 17:47:00 -0700217 for (int e = procOffset; e < numProcs; ++e) {
218 GrGLSLExpr4 output;
joshualitt873ad0e2015-01-20 09:08:51 -0800219 const GrPendingFragmentStage& stage = this->optState().getFragmentStage(e);
joshualitt2dd1ae02014-12-03 06:24:10 -0800220 this->emitAndInstallProc(stage, e, *inOut, &output);
joshualitta5305a12014-10-10 17:47:00 -0700221 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700222 }
joshualitta5305a12014-10-10 17:47:00 -0700223}
joshualitt30ba4362014-08-21 20:18:45 -0700224
joshualitt2dd1ae02014-12-03 06:24:10 -0800225void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
226 // create var to hold stage result. If we already have a valid output name, just use that
227 // otherwise create a new mangled one. This name is only valid if we are reordering stages
228 // and have to tell stage exactly where to put its output.
229 SkString outName;
230 if (output->isValid()) {
231 outName = output->c_str();
232 } else {
233 this->nameVariable(&outName, '\0', baseName);
234 }
235 fFS.codeAppendf("vec4 %s;", outName.c_str());
236 *output = outName;
237}
238
joshualitta5305a12014-10-10 17:47:00 -0700239// TODO Processors cannot output zeros because an empty string is all 1s
240// the fix is to allow effects to take the GrGLSLExpr4 directly
joshualitt2dd1ae02014-12-03 06:24:10 -0800241void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc,
joshualitta5305a12014-10-10 17:47:00 -0700242 int index,
joshualitta5305a12014-10-10 17:47:00 -0700243 const GrGLSLExpr4& input,
244 GrGLSLExpr4* output) {
245 // Program builders have a bit of state we need to clear with each effect
246 AutoStageAdvance adv(this);
joshualitt2dd1ae02014-12-03 06:24:10 -0800247 this->nameExpression(output, "output");
joshualitta5305a12014-10-10 17:47:00 -0700248
249 // Enclose custom code in a block to avoid namespace conflicts
250 SkString openBrace;
egdanielec03a462014-11-19 06:22:39 -0800251 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
joshualitta5305a12014-10-10 17:47:00 -0700252 fFS.codeAppend(openBrace.c_str());
253
joshualittabb52a12015-01-13 15:02:10 -0800254 this->emitAndInstallProc(proc, index, output->c_str(), input.isOnes() ? NULL : input.c_str());
joshualitta5305a12014-10-10 17:47:00 -0700255
256 fFS.codeAppend("}");
257}
258
joshualitt9b989322014-12-15 14:16:27 -0800259void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
joshualitt2dd1ae02014-12-03 06:24:10 -0800260 GrGLSLExpr4* outputColor,
261 GrGLSLExpr4* outputCoverage) {
262 // Program builders have a bit of state we need to clear with each effect
263 AutoStageAdvance adv(this);
264 this->nameExpression(outputColor, "outputColor");
265 this->nameExpression(outputCoverage, "outputCoverage");
266
267 // Enclose custom code in a block to avoid namespace conflicts
268 SkString openBrace;
269 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
270 fFS.codeAppend(openBrace.c_str());
271
272 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
273
274 fFS.codeAppend("}");
275}
276
bsalomonae59b772014-11-19 08:23:49 -0800277void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
joshualittabb52a12015-01-13 15:02:10 -0800278 int index,
joshualitta5305a12014-10-10 17:47:00 -0700279 const char* outColor,
280 const char* inColor) {
joshualitt2dd1ae02014-12-03 06:24:10 -0800281 GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc);
joshualitta5305a12014-10-10 17:47:00 -0700282
joshualitt40d4bd82014-12-29 09:04:40 -0800283 const GrFragmentProcessor& fp = *fs.processor();
joshualitteb2a6762014-12-04 11:35:33 -0800284 ifp->fGLProc.reset(fp.createGLInstance());
joshualitta5305a12014-10-10 17:47:00 -0700285
286 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
287 this->emitSamplers(fp, &samplers, ifp);
288
joshualittabb52a12015-01-13 15:02:10 -0800289 ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers);
joshualitta5305a12014-10-10 17:47:00 -0700290
291 // We have to check that effects and the code they emit are consistent, ie if an effect
292 // asks for dst color, then the emit code needs to follow suit
293 verify(fp);
294 fFragmentProcessors->fProcs.push_back(ifp);
295}
296
joshualitt9b989322014-12-15 14:16:27 -0800297void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
joshualitt2dd1ae02014-12-03 06:24:10 -0800298 const char* outColor,
299 const char* outCoverage) {
joshualitta5305a12014-10-10 17:47:00 -0700300 SkASSERT(!fGeometryProcessor);
301 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
302
joshualitt873ad0e2015-01-20 09:08:51 -0800303 const GrBatchTracker& bt = this->batchTracker();
joshualittabb52a12015-01-13 15:02:10 -0800304 fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, fGpu->glCaps()));
joshualitta5305a12014-10-10 17:47:00 -0700305
306 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
307 this->emitSamplers(gp, &samplers, fGeometryProcessor);
308
joshualittabb52a12015-01-13 15:02:10 -0800309 GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers,
310 fCoordTransforms, &fOutCoords);
joshualittc369e7c2014-10-22 10:56:26 -0700311 fGeometryProcessor->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700312
313 // We have to check that effects and the code they emit are consistent, ie if an effect
314 // asks for dst color, then the emit code needs to follow suit
315 verify(gp);
joshualitt30ba4362014-08-21 20:18:45 -0700316}
317
egdanielc2304142014-12-11 13:15:13 -0800318void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
319 const GrGLSLExpr4& colorIn,
320 const GrGLSLExpr4& coverageIn) {
321 // Program builders have a bit of state we need to clear with each effect
322 AutoStageAdvance adv(this);
323
324 SkASSERT(!fXferProcessor);
325 fXferProcessor = SkNEW(GrGLInstalledXferProc);
326
327 fXferProcessor->fGLProc.reset(xp.createGLInstance());
328
329 // Enable dual source secondary output if we have one
330 if (xp.hasSecondaryOutput()) {
331 fFS.enableSecondaryOutput();
332 }
333
334 // On any post 1.10 GLSL supporting GPU, we declare custom output
335 if (k110_GrGLSLGeneration != fFS.fProgramBuilder->gpu()->glslGeneration()) {
336 fFS.enableCustomOutput();
337 }
338
339 SkString openBrace;
340 openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
341 fFS.codeAppend(openBrace.c_str());
342
343 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(xp.numTextures());
344 this->emitSamplers(xp, &samplers, fXferProcessor);
345
346 GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(),
347 fFS.getPrimaryColorOutputName(),
348 fFS.getSecondaryColorOutputName(), samplers);
349 fXferProcessor->fGLProc->emitCode(args);
350
351 // We have to check that effects and the code they emit are consistent, ie if an effect
352 // asks for dst color, then the emit code needs to follow suit
353 verify(xp);
354 fFS.codeAppend("}");
355}
356
joshualitt9b989322014-12-15 14:16:27 -0800357void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
joshualitt47bb3822014-10-07 16:43:25 -0700358 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
joshualittfe1233c2014-10-07 12:16:35 -0700359}
360
egdanielc2304142014-12-11 13:15:13 -0800361void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
egdaniel71e236c2015-01-20 06:34:51 -0800362 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
egdanielc2304142014-12-11 13:15:13 -0800363}
364
joshualitt47bb3822014-10-07 16:43:25 -0700365void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
366 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
joshualitt47bb3822014-10-07 16:43:25 -0700367}
368
joshualittabb52a12015-01-13 15:02:10 -0800369template <class Proc>
joshualitt47bb3822014-10-07 16:43:25 -0700370void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
371 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualittabb52a12015-01-13 15:02:10 -0800372 GrGLInstalledProc<Proc>* ip) {
joshualitt47bb3822014-10-07 16:43:25 -0700373 int numTextures = processor.numTextures();
joshualitta5305a12014-10-10 17:47:00 -0700374 ip->fSamplers.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700375 SkString name;
376 for (int t = 0; t < numTextures; ++t) {
377 name.printf("Sampler%d", t);
joshualitta5305a12014-10-10 17:47:00 -0700378 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800379 kSampler2D_GrSLType, kDefault_GrSLPrecision,
joshualitta5305a12014-10-10 17:47:00 -0700380 name.c_str());
joshualittb0a8a372014-09-23 09:50:21 -0700381 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
joshualitta5305a12014-10-10 17:47:00 -0700382 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700383 }
384}
385
joshualitt47bb3822014-10-07 16:43:25 -0700386GrGLProgram* GrGLProgramBuilder::finalize() {
387 // verify we can get a program id
388 GrGLuint programID;
389 GL_CALL_RET(programID, CreateProgram());
390 if (0 == programID) {
391 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700392 }
393
joshualitt47bb3822014-10-07 16:43:25 -0700394 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700395 SkTDArray<GrGLuint> shadersToDelete;
joshualitt71c92602015-01-14 08:12:47 -0800396
397 // Legacy nvpr will not compile with a vertex shader, but newer nvpr requires a dummy vertex
398 // shader
joshualitt17e73142015-01-21 11:52:36 -0800399 bool useNvpr = primitiveProcessor().isPathRendering();
joshualitt71c92602015-01-14 08:12:47 -0800400 if (!(useNvpr && fGpu->glCaps().nvprSupport() == GrGLCaps::kLegacy_NvprSupport)) {
joshualitt47bb3822014-10-07 16:43:25 -0700401 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
402 this->cleanupProgram(programID, shadersToDelete);
403 return NULL;
404 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800405
406 // Non fixed function NVPR actually requires a vertex shader to compile
joshualitt71c92602015-01-14 08:12:47 -0800407 if (!useNvpr) {
joshualitt2dd1ae02014-12-03 06:24:10 -0800408 fVS.bindVertexAttributes(programID);
409 }
joshualitt47bb3822014-10-07 16:43:25 -0700410 }
joshualitt9b989322014-12-15 14:16:27 -0800411
412 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
413 this->cleanupProgram(programID, shadersToDelete);
414 return NULL;
415 }
416
joshualitt47bb3822014-10-07 16:43:25 -0700417 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
418 if (usingBindUniform) {
419 this->bindUniformLocations(programID);
420 }
421 fFS.bindFragmentShaderLocations(programID);
422 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700423
424 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
425 bool checkLinked = !fGpu->ctxInfo().isChromium();
426#ifdef SK_DEBUG
427 checkLinked = true;
428#endif
429 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700430 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700431 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700432 if (!usingBindUniform) {
joshualitt47bb3822014-10-07 16:43:25 -0700433 this->resolveUniformLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700434 }
435
joshualitt47bb3822014-10-07 16:43:25 -0700436 this->cleanupShaders(shadersToDelete);
437
438 return this->createProgram(programID);
439}
440
441void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
442 int count = fUniforms.count();
443 for (int i = 0; i < count; ++i) {
444 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
445 fUniforms[i].fLocation = i;
446 }
447}
448
449bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
450 GrGLint linked = GR_GL_INIT_ZERO;
451 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
452 if (!linked) {
453 GrGLint infoLen = GR_GL_INIT_ZERO;
454 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
455 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
456 if (infoLen > 0) {
457 // retrieve length even though we don't need it to workaround
458 // bug in chrome cmd buffer param validation.
459 GrGLsizei length = GR_GL_INIT_ZERO;
460 GL_CALL(GetProgramInfoLog(programID,
461 infoLen+1,
462 &length,
463 (char*)log.get()));
tfarina38406c82014-10-31 07:11:12 -0700464 SkDebugf((char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700465 }
466 SkDEBUGFAIL("Error linking program");
467 GL_CALL(DeleteProgram(programID));
468 programID = 0;
469 }
470 return SkToBool(linked);
471}
472
473void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
474 int count = fUniforms.count();
kkinnunenec56e452014-08-25 22:21:16 -0700475 for (int i = 0; i < count; ++i) {
476 GrGLint location;
joshualitt47bb3822014-10-07 16:43:25 -0700477 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
478 fUniforms[i].fLocation = location;
kkinnunenec56e452014-08-25 22:21:16 -0700479 }
joshualitt30ba4362014-08-21 20:18:45 -0700480}
481
joshualitt47bb3822014-10-07 16:43:25 -0700482void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
483 GL_CALL(DeleteProgram(programID));
484 cleanupShaders(shaderIDs);
485}
486void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
487 for (int i = 0; i < shaderIDs.count(); ++i) {
488 GL_CALL(DeleteShader(shaderIDs[i]));
489 }
490}
491
492GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
joshualitt873ad0e2015-01-20 09:08:51 -0800493 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, programID, fUniforms,
egdanielc2304142014-12-11 13:15:13 -0800494 fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700495}
496
joshualitta5305a12014-10-10 17:47:00 -0700497///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700498
joshualitta5305a12014-10-10 17:47:00 -0700499GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
500 int numProcs = fProcs.count();
501 for (int e = 0; e < numProcs; ++e) {
502 SkDELETE(fProcs[e]);
joshualitt47bb3822014-10-07 16:43:25 -0700503 }
joshualitt30ba4362014-08-21 20:18:45 -0700504}