blob: 5a623033fb6adf4fd6cd05a3bc72e5992c15567f [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"
joshualitt47bb3822014-10-07 16:43:25 -070017#include "GrCoordTransform.h"
joshualitt30ba4362014-08-21 20:18:45 -070018#include "GrGLProgramBuilder.h"
19#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070020#include "SkRTConf.h"
21#include "SkTraceEvent.h"
22
joshualitt30ba4362014-08-21 20:18:45 -070023#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
24#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
25
joshualittabb52a12015-01-13 15:02:10 -080026///////////////////////////////////////////////////////////////////////////////////////////////////
27
28class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
29public:
joshualitt873ad0e2015-01-20 09:08:51 -080030 GrGLNvprProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
31 : INHERITED(gpu, args) {}
joshualittabb52a12015-01-13 15:02:10 -080032
33 GrGLProgram* createProgram(GrGLuint programID) SK_OVERRIDE {
34 // this is just for nvpr es, which has separable varyings that are plugged in after
35 // building
36 GrGLPathProcessor* pathProc =
37 static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get());
38 pathProc->resolveSeparableVaryings(fGpu, programID);
joshualitt873ad0e2015-01-20 09:08:51 -080039 return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles, programID,
40 fUniforms,
joshualittabb52a12015-01-13 15:02:10 -080041 fGeometryProcessor,
42 fXferProcessor, fFragmentProcessors.get()));
43 }
44
45private:
46 typedef GrGLProgramBuilder INHERITED;
47};
48
49
50
joshualitt30ba4362014-08-21 20:18:45 -070051//////////////////////////////////////////////////////////////////////////////
52
joshualitt47bb3822014-10-07 16:43:25 -070053const int GrGLProgramBuilder::kVarsPerBlock = 8;
54
joshualitt873ad0e2015-01-20 09:08:51 -080055GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
joshualitt47bb3822014-10-07 16:43:25 -070056 // create a builder. This will be handed off to effects so they can use it to add
57 // uniforms, varyings, textures, etc
joshualitt873ad0e2015-01-20 09:08:51 -080058 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu));
joshualitt47bb3822014-10-07 16:43:25 -070059
60 GrGLProgramBuilder* pb = builder.get();
joshualitt47bb3822014-10-07 16:43:25 -070061
egdaniel37b4d862014-11-03 10:07:07 -080062 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
joshualitt9b989322014-12-15 14:16:27 -080063 // seed correctly here
64 GrGLSLExpr4 inputColor;
65 GrGLSLExpr4 inputCoverage;
egdaniel37b4d862014-11-03 10:07:07 -080066
joshualitt9b989322014-12-15 14:16:27 -080067 pb->emitAndInstallProcs(&inputColor, &inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -070068
joshualitt47bb3822014-10-07 16:43:25 -070069 return pb->finalize();
70}
71
joshualitt873ad0e2015-01-20 09:08:51 -080072GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& args,
bsalomon861e1032014-12-16 07:33:49 -080073 GrGLGpu* gpu) {
joshualitt17e73142015-01-21 11:52:36 -080074 if (args.fPrimitiveProcessor->isPathRendering()) {
joshualitt71c92602015-01-14 08:12:47 -080075 SkASSERT(gpu->glCaps().pathRenderingSupport() &&
joshualitt873ad0e2015-01-20 09:08:51 -080076 !args.fPrimitiveProcessor->willUseGeoShader() &&
77 args.fPrimitiveProcessor->numAttribs() == 0);
78 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args));
joshualitt47bb3822014-10-07 16:43:25 -070079 } else {
joshualitt873ad0e2015-01-20 09:08:51 -080080 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args));
joshualitt47bb3822014-10-07 16:43:25 -070081 }
82}
83
84/////////////////////////////////////////////////////////////////////////////
85
joshualitt873ad0e2015-01-20 09:08:51 -080086GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
joshualitt47bb3822014-10-07 16:43:25 -070087 : fVS(this)
88 , fGS(this)
joshualitt873ad0e2015-01-20 09:08:51 -080089 , fFS(this, args.fDesc->header().fFragPosKey)
joshualitt47bb3822014-10-07 16:43:25 -070090 , fOutOfStage(true)
91 , fStageIndex(-1)
joshualitta5305a12014-10-10 17:47:00 -070092 , fGeometryProcessor(NULL)
egdanielc2304142014-12-11 13:15:13 -080093 , fXferProcessor(NULL)
joshualitt873ad0e2015-01-20 09:08:51 -080094 , fArgs(args)
joshualitt30ba4362014-08-21 20:18:45 -070095 , fGpu(gpu)
96 , fUniforms(kVarsPerBlock) {
97}
98
joshualitt74077b92014-10-24 11:26:03 -070099void GrGLProgramBuilder::addVarying(const char* name,
100 GrGLVarying* varying,
bsalomonc0bd6482014-12-09 10:04:14 -0800101 GrSLPrecision fsPrecision) {
joshualitt74077b92014-10-24 11:26:03 -0700102 SkASSERT(varying);
103 if (varying->vsVarying()) {
104 fVS.addVarying(name, varying);
105 }
joshualitt873ad0e2015-01-20 09:08:51 -0800106 if (this->primitiveProcessor().willUseGeoShader()) {
joshualitt74077b92014-10-24 11:26:03 -0700107 fGS.addVarying(name, varying);
108 }
109 if (varying->fsVarying()) {
110 fFS.addVarying(varying, fsPrecision);
111 }
joshualitt47bb3822014-10-07 16:43:25 -0700112}
113
joshualitt71c92602015-01-14 08:12:47 -0800114void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input,
joshualitt2dd1ae02014-12-03 06:24:10 -0800115 const char* output) {
116 GrSLType type = GrVertexAttribTypeToSLType(input->fType);
117 GrGLVertToFrag v(type);
118 this->addVarying(input->fName, &v);
119 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
120 fFS.codeAppendf("%s = %s;", output, v.fsIn());
121}
122
joshualitt30ba4362014-08-21 20:18:45 -0700123void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
124 if ('\0' == prefix) {
125 *out = name;
126 } else {
127 out->printf("%c%s", prefix, name);
128 }
joshualitt47bb3822014-10-07 16:43:25 -0700129 if (!fOutOfStage) {
joshualitt30ba4362014-08-21 20:18:45 -0700130 if (out->endsWith('_')) {
131 // Names containing "__" are reserved.
132 out->append("x");
133 }
joshualitt47bb3822014-10-07 16:43:25 -0700134 out->appendf("_Stage%d", fStageIndex);
joshualitt30ba4362014-08-21 20:18:45 -0700135 }
136}
137
bsalomon422f56f2014-12-09 10:18:12 -0800138GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(
139 uint32_t visibility,
140 GrSLType type,
141 GrSLPrecision precision,
142 const char* name,
143 int count,
144 const char** outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700145 SkASSERT(name && strlen(name));
146 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
147 SkASSERT(0 == (~kVisibilityMask & visibility));
148 SkASSERT(0 != visibility);
bsalomon422f56f2014-12-09 10:18:12 -0800149 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type));
joshualitt30ba4362014-08-21 20:18:45 -0700150
151 UniformInfo& uni = fUniforms.push_back();
152 uni.fVariable.setType(type);
153 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
joshualitt4973d9d2014-11-08 09:24:25 -0800154 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use
155 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
156 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then
157 // the names will mismatch. I think the correct solution is to have all GPs which need the
158 // uniform view matrix, they should upload the view matrix in their setData along with regular
159 // uniforms.
160 char prefix = 'u';
161 if ('u' == name[0]) {
162 prefix = '\0';
163 }
164 this->nameVariable(uni.fVariable.accessName(), prefix, name);
joshualitt30ba4362014-08-21 20:18:45 -0700165 uni.fVariable.setArrayCount(count);
166 uni.fVisibility = visibility;
bsalomon422f56f2014-12-09 10:18:12 -0800167 uni.fVariable.setPrecision(precision);
joshualitt30ba4362014-08-21 20:18:45 -0700168
bsalomon49f085d2014-09-05 13:34:00 -0700169 if (outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700170 *outName = uni.fVariable.c_str();
171 }
172 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
173}
174
joshualitt30ba4362014-08-21 20:18:45 -0700175void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
176 SkString* out) const {
177 for (int i = 0; i < fUniforms.count(); ++i) {
178 if (fUniforms[i].fVisibility & visibility) {
179 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
180 out->append(";\n");
181 }
182 }
183}
184
joshualitt47bb3822014-10-07 16:43:25 -0700185const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
186 return fGpu->ctxInfo();
187}
188
joshualitt2dd1ae02014-12-03 06:24:10 -0800189void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
joshualittabb52a12015-01-13 15:02:10 -0800190 // First we loop over all of the installed processors and collect coord transforms. These will
191 // be sent to the GrGLPrimitiveProcessor in its emitCode function
192 SkSTArray<8, GrGLProcessor::TransformedCoordsArray> outCoords;
egdaniel8dd688b2015-01-22 10:16:09 -0800193 for (int i = 0; i < this->pipeline().numFragmentStages(); i++) {
194 const GrFragmentProcessor* processor = this->pipeline().getFragmentStage(i).processor();
joshualittabb52a12015-01-13 15:02:10 -0800195 SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
196 for (int t = 0; t < processor->numTransforms(); t++) {
197 procCoords.push_back(&processor->coordTransform(t));
198 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800199 }
200
joshualitt873ad0e2015-01-20 09:08:51 -0800201 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
joshualitt9b989322014-12-15 14:16:27 -0800202 this->emitAndInstallProc(primProc, inputColor, inputCoverage);
203
joshualitta5305a12014-10-10 17:47:00 -0700204 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
egdaniel8dd688b2015-01-22 10:16:09 -0800205 int numProcs = this->pipeline().numFragmentStages();
206 this->emitAndInstallFragProcs(0, this->pipeline().numColorStages(), inputColor);
207 this->emitAndInstallFragProcs(this->pipeline().numColorStages(), numProcs, inputCoverage);
208 this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700209}
210
joshualitt2dd1ae02014-12-03 06:24:10 -0800211void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
212 int numProcs,
213 GrGLSLExpr4* inOut) {
joshualitta5305a12014-10-10 17:47:00 -0700214 for (int e = procOffset; e < numProcs; ++e) {
215 GrGLSLExpr4 output;
egdaniel8dd688b2015-01-22 10:16:09 -0800216 const GrPendingFragmentStage& stage = this->pipeline().getFragmentStage(e);
joshualitt2dd1ae02014-12-03 06:24:10 -0800217 this->emitAndInstallProc(stage, e, *inOut, &output);
joshualitta5305a12014-10-10 17:47:00 -0700218 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700219 }
joshualitta5305a12014-10-10 17:47:00 -0700220}
joshualitt30ba4362014-08-21 20:18:45 -0700221
joshualitt2dd1ae02014-12-03 06:24:10 -0800222void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
223 // create var to hold stage result. If we already have a valid output name, just use that
224 // otherwise create a new mangled one. This name is only valid if we are reordering stages
225 // and have to tell stage exactly where to put its output.
226 SkString outName;
227 if (output->isValid()) {
228 outName = output->c_str();
229 } else {
230 this->nameVariable(&outName, '\0', baseName);
231 }
232 fFS.codeAppendf("vec4 %s;", outName.c_str());
233 *output = outName;
234}
235
joshualitta5305a12014-10-10 17:47:00 -0700236// TODO Processors cannot output zeros because an empty string is all 1s
237// the fix is to allow effects to take the GrGLSLExpr4 directly
joshualitt2dd1ae02014-12-03 06:24:10 -0800238void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc,
joshualitta5305a12014-10-10 17:47:00 -0700239 int index,
joshualitta5305a12014-10-10 17:47:00 -0700240 const GrGLSLExpr4& input,
241 GrGLSLExpr4* output) {
242 // Program builders have a bit of state we need to clear with each effect
243 AutoStageAdvance adv(this);
joshualitt2dd1ae02014-12-03 06:24:10 -0800244 this->nameExpression(output, "output");
joshualitta5305a12014-10-10 17:47:00 -0700245
246 // Enclose custom code in a block to avoid namespace conflicts
247 SkString openBrace;
egdanielec03a462014-11-19 06:22:39 -0800248 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
joshualitta5305a12014-10-10 17:47:00 -0700249 fFS.codeAppend(openBrace.c_str());
250
joshualittabb52a12015-01-13 15:02:10 -0800251 this->emitAndInstallProc(proc, index, output->c_str(), input.isOnes() ? NULL : input.c_str());
joshualitta5305a12014-10-10 17:47:00 -0700252
253 fFS.codeAppend("}");
254}
255
joshualitt9b989322014-12-15 14:16:27 -0800256void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
joshualitt2dd1ae02014-12-03 06:24:10 -0800257 GrGLSLExpr4* outputColor,
258 GrGLSLExpr4* outputCoverage) {
259 // Program builders have a bit of state we need to clear with each effect
260 AutoStageAdvance adv(this);
261 this->nameExpression(outputColor, "outputColor");
262 this->nameExpression(outputCoverage, "outputCoverage");
263
264 // Enclose custom code in a block to avoid namespace conflicts
265 SkString openBrace;
266 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
267 fFS.codeAppend(openBrace.c_str());
268
269 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
270
271 fFS.codeAppend("}");
272}
273
bsalomonae59b772014-11-19 08:23:49 -0800274void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
joshualittabb52a12015-01-13 15:02:10 -0800275 int index,
joshualitta5305a12014-10-10 17:47:00 -0700276 const char* outColor,
277 const char* inColor) {
joshualitt2dd1ae02014-12-03 06:24:10 -0800278 GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc);
joshualitta5305a12014-10-10 17:47:00 -0700279
joshualitt40d4bd82014-12-29 09:04:40 -0800280 const GrFragmentProcessor& fp = *fs.processor();
joshualitteb2a6762014-12-04 11:35:33 -0800281 ifp->fGLProc.reset(fp.createGLInstance());
joshualitta5305a12014-10-10 17:47:00 -0700282
283 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
284 this->emitSamplers(fp, &samplers, ifp);
285
joshualittabb52a12015-01-13 15:02:10 -0800286 ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers);
joshualitta5305a12014-10-10 17:47:00 -0700287
288 // We have to check that effects and the code they emit are consistent, ie if an effect
289 // asks for dst color, then the emit code needs to follow suit
290 verify(fp);
291 fFragmentProcessors->fProcs.push_back(ifp);
292}
293
joshualitt9b989322014-12-15 14:16:27 -0800294void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
joshualitt2dd1ae02014-12-03 06:24:10 -0800295 const char* outColor,
296 const char* outCoverage) {
joshualitta5305a12014-10-10 17:47:00 -0700297 SkASSERT(!fGeometryProcessor);
298 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
299
joshualitt873ad0e2015-01-20 09:08:51 -0800300 const GrBatchTracker& bt = this->batchTracker();
joshualittabb52a12015-01-13 15:02:10 -0800301 fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, fGpu->glCaps()));
joshualitta5305a12014-10-10 17:47:00 -0700302
303 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
304 this->emitSamplers(gp, &samplers, fGeometryProcessor);
305
joshualittabb52a12015-01-13 15:02:10 -0800306 GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers,
307 fCoordTransforms, &fOutCoords);
joshualittc369e7c2014-10-22 10:56:26 -0700308 fGeometryProcessor->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700309
310 // We have to check that effects and the code they emit are consistent, ie if an effect
311 // asks for dst color, then the emit code needs to follow suit
312 verify(gp);
joshualitt30ba4362014-08-21 20:18:45 -0700313}
314
egdanielc2304142014-12-11 13:15:13 -0800315void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
316 const GrGLSLExpr4& colorIn,
317 const GrGLSLExpr4& coverageIn) {
318 // Program builders have a bit of state we need to clear with each effect
319 AutoStageAdvance adv(this);
320
321 SkASSERT(!fXferProcessor);
322 fXferProcessor = SkNEW(GrGLInstalledXferProc);
323
324 fXferProcessor->fGLProc.reset(xp.createGLInstance());
325
326 // Enable dual source secondary output if we have one
327 if (xp.hasSecondaryOutput()) {
328 fFS.enableSecondaryOutput();
329 }
330
331 // On any post 1.10 GLSL supporting GPU, we declare custom output
332 if (k110_GrGLSLGeneration != fFS.fProgramBuilder->gpu()->glslGeneration()) {
333 fFS.enableCustomOutput();
334 }
335
336 SkString openBrace;
337 openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
338 fFS.codeAppend(openBrace.c_str());
339
340 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(xp.numTextures());
341 this->emitSamplers(xp, &samplers, fXferProcessor);
342
343 GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(),
344 fFS.getPrimaryColorOutputName(),
345 fFS.getSecondaryColorOutputName(), samplers);
346 fXferProcessor->fGLProc->emitCode(args);
347
348 // We have to check that effects and the code they emit are consistent, ie if an effect
349 // asks for dst color, then the emit code needs to follow suit
350 verify(xp);
351 fFS.codeAppend("}");
352}
353
joshualitt9b989322014-12-15 14:16:27 -0800354void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
joshualitt47bb3822014-10-07 16:43:25 -0700355 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
joshualittfe1233c2014-10-07 12:16:35 -0700356}
357
egdanielc2304142014-12-11 13:15:13 -0800358void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
egdaniel71e236c2015-01-20 06:34:51 -0800359 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
egdanielc2304142014-12-11 13:15:13 -0800360}
361
joshualitt47bb3822014-10-07 16:43:25 -0700362void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
363 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
joshualitt47bb3822014-10-07 16:43:25 -0700364}
365
joshualittabb52a12015-01-13 15:02:10 -0800366template <class Proc>
joshualitt47bb3822014-10-07 16:43:25 -0700367void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
368 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualittabb52a12015-01-13 15:02:10 -0800369 GrGLInstalledProc<Proc>* ip) {
joshualitt47bb3822014-10-07 16:43:25 -0700370 int numTextures = processor.numTextures();
joshualitta5305a12014-10-10 17:47:00 -0700371 ip->fSamplers.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700372 SkString name;
373 for (int t = 0; t < numTextures; ++t) {
374 name.printf("Sampler%d", t);
joshualitta5305a12014-10-10 17:47:00 -0700375 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800376 kSampler2D_GrSLType, kDefault_GrSLPrecision,
joshualitta5305a12014-10-10 17:47:00 -0700377 name.c_str());
joshualittb0a8a372014-09-23 09:50:21 -0700378 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
joshualitta5305a12014-10-10 17:47:00 -0700379 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700380 }
381}
382
joshualitt47bb3822014-10-07 16:43:25 -0700383GrGLProgram* GrGLProgramBuilder::finalize() {
384 // verify we can get a program id
385 GrGLuint programID;
386 GL_CALL_RET(programID, CreateProgram());
387 if (0 == programID) {
388 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700389 }
390
joshualitt47bb3822014-10-07 16:43:25 -0700391 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700392 SkTDArray<GrGLuint> shadersToDelete;
joshualitt71c92602015-01-14 08:12:47 -0800393
394 // Legacy nvpr will not compile with a vertex shader, but newer nvpr requires a dummy vertex
395 // shader
joshualitt17e73142015-01-21 11:52:36 -0800396 bool useNvpr = primitiveProcessor().isPathRendering();
joshualitt71c92602015-01-14 08:12:47 -0800397 if (!(useNvpr && fGpu->glCaps().nvprSupport() == GrGLCaps::kLegacy_NvprSupport)) {
joshualitt47bb3822014-10-07 16:43:25 -0700398 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
399 this->cleanupProgram(programID, shadersToDelete);
400 return NULL;
401 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800402
403 // Non fixed function NVPR actually requires a vertex shader to compile
joshualitt71c92602015-01-14 08:12:47 -0800404 if (!useNvpr) {
joshualitt2dd1ae02014-12-03 06:24:10 -0800405 fVS.bindVertexAttributes(programID);
406 }
joshualitt47bb3822014-10-07 16:43:25 -0700407 }
joshualitt9b989322014-12-15 14:16:27 -0800408
409 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
410 this->cleanupProgram(programID, shadersToDelete);
411 return NULL;
412 }
413
joshualitt47bb3822014-10-07 16:43:25 -0700414 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
415 if (usingBindUniform) {
416 this->bindUniformLocations(programID);
417 }
418 fFS.bindFragmentShaderLocations(programID);
419 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700420
421 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
422 bool checkLinked = !fGpu->ctxInfo().isChromium();
423#ifdef SK_DEBUG
424 checkLinked = true;
425#endif
426 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700427 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700428 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700429 if (!usingBindUniform) {
joshualitt47bb3822014-10-07 16:43:25 -0700430 this->resolveUniformLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700431 }
432
joshualitt47bb3822014-10-07 16:43:25 -0700433 this->cleanupShaders(shadersToDelete);
434
435 return this->createProgram(programID);
436}
437
438void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
439 int count = fUniforms.count();
440 for (int i = 0; i < count; ++i) {
441 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
442 fUniforms[i].fLocation = i;
443 }
444}
445
446bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
447 GrGLint linked = GR_GL_INIT_ZERO;
448 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
449 if (!linked) {
450 GrGLint infoLen = GR_GL_INIT_ZERO;
451 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
452 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
453 if (infoLen > 0) {
454 // retrieve length even though we don't need it to workaround
455 // bug in chrome cmd buffer param validation.
456 GrGLsizei length = GR_GL_INIT_ZERO;
457 GL_CALL(GetProgramInfoLog(programID,
458 infoLen+1,
459 &length,
460 (char*)log.get()));
tfarina38406c82014-10-31 07:11:12 -0700461 SkDebugf((char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700462 }
463 SkDEBUGFAIL("Error linking program");
464 GL_CALL(DeleteProgram(programID));
465 programID = 0;
466 }
467 return SkToBool(linked);
468}
469
470void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
471 int count = fUniforms.count();
kkinnunenec56e452014-08-25 22:21:16 -0700472 for (int i = 0; i < count; ++i) {
473 GrGLint location;
joshualitt47bb3822014-10-07 16:43:25 -0700474 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
475 fUniforms[i].fLocation = location;
kkinnunenec56e452014-08-25 22:21:16 -0700476 }
joshualitt30ba4362014-08-21 20:18:45 -0700477}
478
joshualitt47bb3822014-10-07 16:43:25 -0700479void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
480 GL_CALL(DeleteProgram(programID));
481 cleanupShaders(shaderIDs);
482}
483void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
484 for (int i = 0; i < shaderIDs.count(); ++i) {
485 GL_CALL(DeleteShader(shaderIDs[i]));
486 }
487}
488
489GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
joshualitt873ad0e2015-01-20 09:08:51 -0800490 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, programID, fUniforms,
egdanielc2304142014-12-11 13:15:13 -0800491 fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700492}
493
joshualitta5305a12014-10-10 17:47:00 -0700494///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700495
joshualitta5305a12014-10-10 17:47:00 -0700496GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
497 int numProcs = fProcs.count();
498 for (int e = 0; e < numProcs; ++e) {
499 SkDELETE(fProcs[e]);
joshualitt47bb3822014-10-07 16:43:25 -0700500 }
joshualitt30ba4362014-08-21 20:18:45 -0700501}