blob: a2b8a34157a07615e95bc3481edc6efd3e5fb21e [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"
joshualitt8072caa2015-02-12 14:20:52 -08009
10#include "gl/GrGLGeometryProcessor.h"
11#include "gl/GrGLGpu.h"
12#include "gl/GrGLPathProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070013#include "gl/GrGLProgram.h"
14#include "gl/GrGLSLPrettyPrint.h"
15#include "gl/GrGLUniformHandle.h"
joshualitt8072caa2015-02-12 14:20:52 -080016#include "gl/GrGLXferProcessor.h"
bsalomon6f7f2012015-03-16 14:00:52 -070017#include "GrAutoLocaleSetter.h"
joshualitt47bb3822014-10-07 16:43:25 -070018#include "GrCoordTransform.h"
joshualitt30ba4362014-08-21 20:18:45 -070019#include "GrGLProgramBuilder.h"
20#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070021#include "SkRTConf.h"
22#include "SkTraceEvent.h"
23
joshualitt30ba4362014-08-21 20:18:45 -070024#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
25#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
26
joshualittabb52a12015-01-13 15:02:10 -080027///////////////////////////////////////////////////////////////////////////////////////////////////
28
29class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
30public:
joshualitt873ad0e2015-01-20 09:08:51 -080031 GrGLNvprProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
32 : INHERITED(gpu, args) {}
joshualittabb52a12015-01-13 15:02:10 -080033
34 GrGLProgram* createProgram(GrGLuint programID) SK_OVERRIDE {
35 // this is just for nvpr es, which has separable varyings that are plugged in after
36 // building
37 GrGLPathProcessor* pathProc =
38 static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get());
39 pathProc->resolveSeparableVaryings(fGpu, programID);
joshualitt873ad0e2015-01-20 09:08:51 -080040 return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles, programID,
41 fUniforms,
joshualittabb52a12015-01-13 15:02:10 -080042 fGeometryProcessor,
43 fXferProcessor, fFragmentProcessors.get()));
44 }
45
46private:
47 typedef GrGLProgramBuilder INHERITED;
48};
49
50
51
joshualitt30ba4362014-08-21 20:18:45 -070052//////////////////////////////////////////////////////////////////////////////
53
joshualitt47bb3822014-10-07 16:43:25 -070054const int GrGLProgramBuilder::kVarsPerBlock = 8;
55
joshualitt873ad0e2015-01-20 09:08:51 -080056GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
bsalomon3318ee72015-03-16 11:56:29 -070057 GrAutoLocaleSetter als("C");
58
joshualitt47bb3822014-10-07 16:43:25 -070059 // create a builder. This will be handed off to effects so they can use it to add
60 // uniforms, varyings, textures, etc
joshualitt873ad0e2015-01-20 09:08:51 -080061 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu));
joshualitt47bb3822014-10-07 16:43:25 -070062
63 GrGLProgramBuilder* pb = builder.get();
joshualitt47bb3822014-10-07 16:43:25 -070064
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;
egdaniel8dd688b2015-01-22 10:16:09 -0800196 for (int i = 0; i < this->pipeline().numFragmentStages(); i++) {
197 const GrFragmentProcessor* processor = this->pipeline().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));
egdaniel8dd688b2015-01-22 10:16:09 -0800208 int numProcs = this->pipeline().numFragmentStages();
bsalomon6be6f7c2015-02-26 13:05:21 -0800209 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentStages(), inputColor);
210 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentStages(), numProcs,
211 inputCoverage);
egdaniel8dd688b2015-01-22 10:16:09 -0800212 this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700213}
214
joshualitt2dd1ae02014-12-03 06:24:10 -0800215void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
216 int numProcs,
217 GrGLSLExpr4* inOut) {
joshualitta5305a12014-10-10 17:47:00 -0700218 for (int e = procOffset; e < numProcs; ++e) {
219 GrGLSLExpr4 output;
egdaniel8dd688b2015-01-22 10:16:09 -0800220 const GrPendingFragmentStage& stage = this->pipeline().getFragmentStage(e);
joshualitt2dd1ae02014-12-03 06:24:10 -0800221 this->emitAndInstallProc(stage, e, *inOut, &output);
joshualitta5305a12014-10-10 17:47:00 -0700222 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700223 }
joshualitta5305a12014-10-10 17:47:00 -0700224}
joshualitt30ba4362014-08-21 20:18:45 -0700225
joshualitt2dd1ae02014-12-03 06:24:10 -0800226void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
227 // create var to hold stage result. If we already have a valid output name, just use that
228 // otherwise create a new mangled one. This name is only valid if we are reordering stages
229 // and have to tell stage exactly where to put its output.
230 SkString outName;
231 if (output->isValid()) {
232 outName = output->c_str();
233 } else {
234 this->nameVariable(&outName, '\0', baseName);
235 }
236 fFS.codeAppendf("vec4 %s;", outName.c_str());
237 *output = outName;
238}
239
joshualitta5305a12014-10-10 17:47:00 -0700240// TODO Processors cannot output zeros because an empty string is all 1s
241// the fix is to allow effects to take the GrGLSLExpr4 directly
joshualitt2dd1ae02014-12-03 06:24:10 -0800242void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc,
joshualitta5305a12014-10-10 17:47:00 -0700243 int index,
joshualitta5305a12014-10-10 17:47:00 -0700244 const GrGLSLExpr4& input,
245 GrGLSLExpr4* output) {
246 // Program builders have a bit of state we need to clear with each effect
247 AutoStageAdvance adv(this);
joshualitt2dd1ae02014-12-03 06:24:10 -0800248 this->nameExpression(output, "output");
joshualitta5305a12014-10-10 17:47:00 -0700249
250 // Enclose custom code in a block to avoid namespace conflicts
251 SkString openBrace;
egdanielec03a462014-11-19 06:22:39 -0800252 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
joshualitta5305a12014-10-10 17:47:00 -0700253 fFS.codeAppend(openBrace.c_str());
254
joshualittabb52a12015-01-13 15:02:10 -0800255 this->emitAndInstallProc(proc, index, output->c_str(), input.isOnes() ? NULL : input.c_str());
joshualitta5305a12014-10-10 17:47:00 -0700256
257 fFS.codeAppend("}");
258}
259
joshualitt9b989322014-12-15 14:16:27 -0800260void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
joshualitt2dd1ae02014-12-03 06:24:10 -0800261 GrGLSLExpr4* outputColor,
262 GrGLSLExpr4* outputCoverage) {
263 // Program builders have a bit of state we need to clear with each effect
264 AutoStageAdvance adv(this);
265 this->nameExpression(outputColor, "outputColor");
266 this->nameExpression(outputCoverage, "outputCoverage");
267
268 // Enclose custom code in a block to avoid namespace conflicts
269 SkString openBrace;
270 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
271 fFS.codeAppend(openBrace.c_str());
272
273 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
274
275 fFS.codeAppend("}");
276}
277
bsalomonae59b772014-11-19 08:23:49 -0800278void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
joshualittabb52a12015-01-13 15:02:10 -0800279 int index,
joshualitta5305a12014-10-10 17:47:00 -0700280 const char* outColor,
281 const char* inColor) {
joshualitt2dd1ae02014-12-03 06:24:10 -0800282 GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc);
joshualitta5305a12014-10-10 17:47:00 -0700283
joshualitt40d4bd82014-12-29 09:04:40 -0800284 const GrFragmentProcessor& fp = *fs.processor();
joshualitteb2a6762014-12-04 11:35:33 -0800285 ifp->fGLProc.reset(fp.createGLInstance());
joshualitta5305a12014-10-10 17:47:00 -0700286
287 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
288 this->emitSamplers(fp, &samplers, ifp);
289
joshualittabb52a12015-01-13 15:02:10 -0800290 ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers);
joshualitta5305a12014-10-10 17:47:00 -0700291
292 // We have to check that effects and the code they emit are consistent, ie if an effect
293 // asks for dst color, then the emit code needs to follow suit
294 verify(fp);
295 fFragmentProcessors->fProcs.push_back(ifp);
296}
297
joshualitt9b989322014-12-15 14:16:27 -0800298void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
joshualitt2dd1ae02014-12-03 06:24:10 -0800299 const char* outColor,
300 const char* outCoverage) {
joshualitta5305a12014-10-10 17:47:00 -0700301 SkASSERT(!fGeometryProcessor);
302 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
303
joshualitt873ad0e2015-01-20 09:08:51 -0800304 const GrBatchTracker& bt = this->batchTracker();
joshualittabb52a12015-01-13 15:02:10 -0800305 fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, fGpu->glCaps()));
joshualitta5305a12014-10-10 17:47:00 -0700306
307 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
308 this->emitSamplers(gp, &samplers, fGeometryProcessor);
309
joshualittabb52a12015-01-13 15:02:10 -0800310 GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers,
311 fCoordTransforms, &fOutCoords);
joshualittc369e7c2014-10-22 10:56:26 -0700312 fGeometryProcessor->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700313
314 // We have to check that effects and the code they emit are consistent, ie if an effect
315 // asks for dst color, then the emit code needs to follow suit
316 verify(gp);
joshualitt30ba4362014-08-21 20:18:45 -0700317}
318
egdanielc2304142014-12-11 13:15:13 -0800319void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
320 const GrGLSLExpr4& colorIn,
321 const GrGLSLExpr4& coverageIn) {
322 // Program builders have a bit of state we need to clear with each effect
323 AutoStageAdvance adv(this);
324
325 SkASSERT(!fXferProcessor);
326 fXferProcessor = SkNEW(GrGLInstalledXferProc);
327
328 fXferProcessor->fGLProc.reset(xp.createGLInstance());
329
330 // Enable dual source secondary output if we have one
331 if (xp.hasSecondaryOutput()) {
332 fFS.enableSecondaryOutput();
333 }
334
335 // On any post 1.10 GLSL supporting GPU, we declare custom output
336 if (k110_GrGLSLGeneration != fFS.fProgramBuilder->gpu()->glslGeneration()) {
337 fFS.enableCustomOutput();
338 }
339
340 SkString openBrace;
341 openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
342 fFS.codeAppend(openBrace.c_str());
343
344 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(xp.numTextures());
345 this->emitSamplers(xp, &samplers, fXferProcessor);
346
347 GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(),
348 fFS.getPrimaryColorOutputName(),
349 fFS.getSecondaryColorOutputName(), samplers);
350 fXferProcessor->fGLProc->emitCode(args);
351
352 // We have to check that effects and the code they emit are consistent, ie if an effect
353 // asks for dst color, then the emit code needs to follow suit
354 verify(xp);
355 fFS.codeAppend("}");
356}
357
joshualitt9b989322014-12-15 14:16:27 -0800358void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
joshualitt47bb3822014-10-07 16:43:25 -0700359 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
joshualittfe1233c2014-10-07 12:16:35 -0700360}
361
egdanielc2304142014-12-11 13:15:13 -0800362void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
egdaniel71e236c2015-01-20 06:34:51 -0800363 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
egdanielc2304142014-12-11 13:15:13 -0800364}
365
joshualitt47bb3822014-10-07 16:43:25 -0700366void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
367 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
joshualitt47bb3822014-10-07 16:43:25 -0700368}
369
joshualittabb52a12015-01-13 15:02:10 -0800370template <class Proc>
joshualitt47bb3822014-10-07 16:43:25 -0700371void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
372 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualittabb52a12015-01-13 15:02:10 -0800373 GrGLInstalledProc<Proc>* ip) {
joshualitt47bb3822014-10-07 16:43:25 -0700374 int numTextures = processor.numTextures();
joshualitta5305a12014-10-10 17:47:00 -0700375 ip->fSamplers.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700376 SkString name;
377 for (int t = 0; t < numTextures; ++t) {
378 name.printf("Sampler%d", t);
joshualitta5305a12014-10-10 17:47:00 -0700379 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800380 kSampler2D_GrSLType, kDefault_GrSLPrecision,
joshualitta5305a12014-10-10 17:47:00 -0700381 name.c_str());
joshualittb0a8a372014-09-23 09:50:21 -0700382 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
joshualitta5305a12014-10-10 17:47:00 -0700383 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700384 }
385}
386
joshualitt47bb3822014-10-07 16:43:25 -0700387GrGLProgram* GrGLProgramBuilder::finalize() {
388 // verify we can get a program id
389 GrGLuint programID;
390 GL_CALL_RET(programID, CreateProgram());
391 if (0 == programID) {
392 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700393 }
394
joshualitt47bb3822014-10-07 16:43:25 -0700395 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700396 SkTDArray<GrGLuint> shadersToDelete;
joshualitt71c92602015-01-14 08:12:47 -0800397
398 // Legacy nvpr will not compile with a vertex shader, but newer nvpr requires a dummy vertex
399 // shader
joshualitt17e73142015-01-21 11:52:36 -0800400 bool useNvpr = primitiveProcessor().isPathRendering();
joshualitt71c92602015-01-14 08:12:47 -0800401 if (!(useNvpr && fGpu->glCaps().nvprSupport() == GrGLCaps::kLegacy_NvprSupport)) {
joshualitt47bb3822014-10-07 16:43:25 -0700402 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
403 this->cleanupProgram(programID, shadersToDelete);
404 return NULL;
405 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800406
407 // Non fixed function NVPR actually requires a vertex shader to compile
joshualitt71c92602015-01-14 08:12:47 -0800408 if (!useNvpr) {
joshualitt2dd1ae02014-12-03 06:24:10 -0800409 fVS.bindVertexAttributes(programID);
410 }
joshualitt47bb3822014-10-07 16:43:25 -0700411 }
joshualitt9b989322014-12-15 14:16:27 -0800412
413 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
414 this->cleanupProgram(programID, shadersToDelete);
415 return NULL;
416 }
417
joshualitt47bb3822014-10-07 16:43:25 -0700418 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
419 if (usingBindUniform) {
420 this->bindUniformLocations(programID);
421 }
422 fFS.bindFragmentShaderLocations(programID);
423 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700424
425 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
426 bool checkLinked = !fGpu->ctxInfo().isChromium();
427#ifdef SK_DEBUG
428 checkLinked = true;
429#endif
430 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700431 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700432 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700433 if (!usingBindUniform) {
joshualitt47bb3822014-10-07 16:43:25 -0700434 this->resolveUniformLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700435 }
436
joshualitt47bb3822014-10-07 16:43:25 -0700437 this->cleanupShaders(shadersToDelete);
438
439 return this->createProgram(programID);
440}
441
442void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
443 int count = fUniforms.count();
444 for (int i = 0; i < count; ++i) {
445 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
446 fUniforms[i].fLocation = i;
447 }
448}
449
450bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
451 GrGLint linked = GR_GL_INIT_ZERO;
452 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
453 if (!linked) {
454 GrGLint infoLen = GR_GL_INIT_ZERO;
455 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
456 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
457 if (infoLen > 0) {
458 // retrieve length even though we don't need it to workaround
459 // bug in chrome cmd buffer param validation.
460 GrGLsizei length = GR_GL_INIT_ZERO;
461 GL_CALL(GetProgramInfoLog(programID,
462 infoLen+1,
463 &length,
464 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800465 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700466 }
467 SkDEBUGFAIL("Error linking program");
468 GL_CALL(DeleteProgram(programID));
469 programID = 0;
470 }
471 return SkToBool(linked);
472}
473
474void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
475 int count = fUniforms.count();
kkinnunenec56e452014-08-25 22:21:16 -0700476 for (int i = 0; i < count; ++i) {
477 GrGLint location;
joshualitt47bb3822014-10-07 16:43:25 -0700478 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
479 fUniforms[i].fLocation = location;
kkinnunenec56e452014-08-25 22:21:16 -0700480 }
joshualitt30ba4362014-08-21 20:18:45 -0700481}
482
joshualitt47bb3822014-10-07 16:43:25 -0700483void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
484 GL_CALL(DeleteProgram(programID));
485 cleanupShaders(shaderIDs);
486}
487void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
488 for (int i = 0; i < shaderIDs.count(); ++i) {
489 GL_CALL(DeleteShader(shaderIDs[i]));
490 }
491}
492
493GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
joshualitt873ad0e2015-01-20 09:08:51 -0800494 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, programID, fUniforms,
egdanielc2304142014-12-11 13:15:13 -0800495 fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700496}
497
joshualitta5305a12014-10-10 17:47:00 -0700498///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700499
joshualitta5305a12014-10-10 17:47:00 -0700500GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
501 int numProcs = fProcs.count();
502 for (int e = 0; e < numProcs; ++e) {
503 SkDELETE(fProcs[e]);
joshualitt47bb3822014-10-07 16:43:25 -0700504 }
joshualitt30ba4362014-08-21 20:18:45 -0700505}