blob: 6f3214f23a8368856dafed2a6283cfb16aa5ac3e [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"
joshualittdb0d3ca2014-10-07 12:42:26 -070013#include "../GrGpuGL.h"
joshualitt47bb3822014-10-07 16:43:25 -070014#include "GrCoordTransform.h"
15#include "GrGLLegacyNvprProgramBuilder.h"
16#include "GrGLNvprProgramBuilder.h"
joshualitt30ba4362014-08-21 20:18:45 -070017#include "GrGLProgramBuilder.h"
18#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070019#include "SkRTConf.h"
20#include "SkTraceEvent.h"
21
joshualitt30ba4362014-08-21 20:18:45 -070022#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
23#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
24
joshualitt30ba4362014-08-21 20:18:45 -070025//////////////////////////////////////////////////////////////////////////////
26
joshualitt47bb3822014-10-07 16:43:25 -070027const int GrGLProgramBuilder::kVarsPerBlock = 8;
28
bsalomon861e1032014-12-16 07:33:49 -080029GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, GrGLGpu* gpu) {
joshualitt47bb3822014-10-07 16:43:25 -070030 // create a builder. This will be handed off to effects so they can use it to add
31 // uniforms, varyings, textures, etc
joshualitt79f8fae2014-10-28 17:59:26 -070032 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(optState,
joshualitta5305a12014-10-10 17:47:00 -070033 optState.hasGeometryProcessor(),
joshualitt47bb3822014-10-07 16:43:25 -070034 gpu));
35
36 GrGLProgramBuilder* pb = builder.get();
joshualitt79f8fae2014-10-28 17:59:26 -070037 const GrGLProgramDescBuilder::GLKeyHeader& header = GrGLProgramDescBuilder::GetHeader(pb->desc());
joshualitt47bb3822014-10-07 16:43:25 -070038
39 // emit code to read the dst copy texture, if necessary
joshualitt9b989322014-12-15 14:16:27 -080040 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey &&
41 !gpu->glCaps().fbFetchSupport()) {
joshualitt47bb3822014-10-07 16:43:25 -070042 pb->fFS.emitCodeToReadDstTexture();
43 }
44
egdaniel37b4d862014-11-03 10:07:07 -080045 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
joshualitt9b989322014-12-15 14:16:27 -080046 // seed correctly here
47 GrGLSLExpr4 inputColor;
48 GrGLSLExpr4 inputCoverage;
egdaniel37b4d862014-11-03 10:07:07 -080049
joshualitt9b989322014-12-15 14:16:27 -080050 pb->emitAndInstallProcs(&inputColor, &inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -070051
joshualitt47bb3822014-10-07 16:43:25 -070052 return pb->finalize();
53}
54
egdanielc2304142014-12-11 13:15:13 -080055GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState,
56 bool hasGeometryProcessor,
bsalomon861e1032014-12-16 07:33:49 -080057 GrGLGpu* gpu) {
joshualitt79f8fae2014-10-28 17:59:26 -070058 const GrProgramDesc& desc = optState.programDesc();
59 if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) {
joshualitt47bb3822014-10-07 16:43:25 -070060 SkASSERT(gpu->glCaps().pathRenderingSupport());
joshualitt47bb3822014-10-07 16:43:25 -070061 SkASSERT(!hasGeometryProcessor);
joshualitt0e602822014-10-28 10:27:44 -070062 if (gpu->glPathRendering()->texturingMode() ==
63 GrGLPathRendering::FixedFunction_TexturingMode) {
joshualitt79f8fae2014-10-28 17:59:26 -070064 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState));
joshualitt0e602822014-10-28 10:27:44 -070065 } else {
joshualitt79f8fae2014-10-28 17:59:26 -070066 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState));
joshualitt0e602822014-10-28 10:27:44 -070067 }
joshualitt47bb3822014-10-07 16:43:25 -070068 } else {
joshualitt79f8fae2014-10-28 17:59:26 -070069 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState));
joshualitt47bb3822014-10-07 16:43:25 -070070 }
71}
72
73/////////////////////////////////////////////////////////////////////////////
74
bsalomon861e1032014-12-16 07:33:49 -080075GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const GrOptDrawState& optState)
joshualitt47bb3822014-10-07 16:43:25 -070076 : fVS(this)
77 , fGS(this)
joshualitt79f8fae2014-10-28 17:59:26 -070078 , fFS(this, optState.programDesc().header().fFragPosKey)
joshualitt47bb3822014-10-07 16:43:25 -070079 , fOutOfStage(true)
80 , fStageIndex(-1)
joshualitta5305a12014-10-10 17:47:00 -070081 , fGeometryProcessor(NULL)
egdanielc2304142014-12-11 13:15:13 -080082 , fXferProcessor(NULL)
egdaniel307796b2014-10-06 12:13:54 -070083 , fOptState(optState)
joshualitt79f8fae2014-10-28 17:59:26 -070084 , fDesc(optState.programDesc())
joshualitt30ba4362014-08-21 20:18:45 -070085 , fGpu(gpu)
86 , fUniforms(kVarsPerBlock) {
87}
88
joshualitt74077b92014-10-24 11:26:03 -070089void GrGLProgramBuilder::addVarying(const char* name,
90 GrGLVarying* varying,
bsalomonc0bd6482014-12-09 10:04:14 -080091 GrSLPrecision fsPrecision) {
joshualitt74077b92014-10-24 11:26:03 -070092 SkASSERT(varying);
93 if (varying->vsVarying()) {
94 fVS.addVarying(name, varying);
95 }
96 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->willUseGeoShader()) {
97 fGS.addVarying(name, varying);
98 }
99 if (varying->fsVarying()) {
100 fFS.addVarying(varying, fsPrecision);
101 }
joshualitt47bb3822014-10-07 16:43:25 -0700102}
103
joshualitt2dd1ae02014-12-03 06:24:10 -0800104void GrGLProgramBuilder::addPassThroughAttribute(const GrGeometryProcessor::GrAttribute* input,
105 const char* output) {
106 GrSLType type = GrVertexAttribTypeToSLType(input->fType);
107 GrGLVertToFrag v(type);
108 this->addVarying(input->fName, &v);
109 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
110 fFS.codeAppendf("%s = %s;", output, v.fsIn());
111}
112
joshualitt30ba4362014-08-21 20:18:45 -0700113void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
114 if ('\0' == prefix) {
115 *out = name;
116 } else {
117 out->printf("%c%s", prefix, name);
118 }
joshualitt47bb3822014-10-07 16:43:25 -0700119 if (!fOutOfStage) {
joshualitt30ba4362014-08-21 20:18:45 -0700120 if (out->endsWith('_')) {
121 // Names containing "__" are reserved.
122 out->append("x");
123 }
joshualitt47bb3822014-10-07 16:43:25 -0700124 out->appendf("_Stage%d", fStageIndex);
joshualitt30ba4362014-08-21 20:18:45 -0700125 }
126}
127
bsalomon422f56f2014-12-09 10:18:12 -0800128GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(
129 uint32_t visibility,
130 GrSLType type,
131 GrSLPrecision precision,
132 const char* name,
133 int count,
134 const char** outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700135 SkASSERT(name && strlen(name));
136 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
137 SkASSERT(0 == (~kVisibilityMask & visibility));
138 SkASSERT(0 != visibility);
bsalomon422f56f2014-12-09 10:18:12 -0800139 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type));
joshualitt30ba4362014-08-21 20:18:45 -0700140
141 UniformInfo& uni = fUniforms.push_back();
142 uni.fVariable.setType(type);
143 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
joshualitt4973d9d2014-11-08 09:24:25 -0800144 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use
145 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
146 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then
147 // the names will mismatch. I think the correct solution is to have all GPs which need the
148 // uniform view matrix, they should upload the view matrix in their setData along with regular
149 // uniforms.
150 char prefix = 'u';
151 if ('u' == name[0]) {
152 prefix = '\0';
153 }
154 this->nameVariable(uni.fVariable.accessName(), prefix, name);
joshualitt30ba4362014-08-21 20:18:45 -0700155 uni.fVariable.setArrayCount(count);
156 uni.fVisibility = visibility;
bsalomon422f56f2014-12-09 10:18:12 -0800157 uni.fVariable.setPrecision(precision);
joshualitt30ba4362014-08-21 20:18:45 -0700158
bsalomon49f085d2014-09-05 13:34:00 -0700159 if (outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700160 *outName = uni.fVariable.c_str();
161 }
162 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
163}
164
joshualitt30ba4362014-08-21 20:18:45 -0700165void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
166 SkString* out) const {
167 for (int i = 0; i < fUniforms.count(); ++i) {
168 if (fUniforms[i].fVisibility & visibility) {
169 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
170 out->append(";\n");
171 }
172 }
173}
174
joshualitt47bb3822014-10-07 16:43:25 -0700175const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
176 return fGpu->ctxInfo();
177}
178
joshualitt2dd1ae02014-12-03 06:24:10 -0800179void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
180 if (fOptState.hasGeometryProcessor()) {
181 fVS.setupUniformViewMatrix();
182
joshualittdafa4d02014-12-04 08:59:10 -0800183 fVS.codeAppend("gl_PointSize = 1.0;");
joshualitt2dd1ae02014-12-03 06:24:10 -0800184
185 // Setup position
186 // TODO it'd be possible to remove these from the vertexshader builder and have them
187 // be outputs from the emit call. We don't do this because emitargs is constant. It would
188 // be easy to change this though
189 fVS.codeAppendf("vec3 %s;", fVS.glPosition());
190 fVS.codeAppendf("vec2 %s;", fVS.positionCoords());
191 fVS.codeAppendf("vec2 %s;", fVS.localCoords());
192
193 const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor();
194 fVS.emitAttributes(gp);
joshualitt2dd1ae02014-12-03 06:24:10 -0800195 }
196
joshualitt9b989322014-12-15 14:16:27 -0800197 const GrPrimitiveProcessor& primProc = *fOptState.getPrimitiveProcessor();
198 this->emitAndInstallProc(primProc, inputColor, inputCoverage);
199
joshualitta5305a12014-10-10 17:47:00 -0700200 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
joshualitt4973d9d2014-11-08 09:24:25 -0800201 int numProcs = fOptState.numFragmentStages();
202 this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor);
joshualitt4973d9d2014-11-08 09:24:25 -0800203 this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, inputCoverage);
joshualitt2dd1ae02014-12-03 06:24:10 -0800204
205 if (fOptState.hasGeometryProcessor()) {
206 fVS.transformToNormalizedDeviceSpace();
207 }
egdanielc2304142014-12-11 13:15:13 -0800208
209 this->emitAndInstallXferProc(*fOptState.getXferProcessor(), *inputColor, *inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700210}
211
joshualitt2dd1ae02014-12-03 06:24:10 -0800212void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
213 int numProcs,
214 GrGLSLExpr4* inOut) {
joshualitta5305a12014-10-10 17:47:00 -0700215 for (int e = procOffset; e < numProcs; ++e) {
216 GrGLSLExpr4 output;
bsalomonae59b772014-11-19 08:23:49 -0800217 const GrPendingFragmentStage& stage = fOptState.getFragmentStage(e);
joshualitt2dd1ae02014-12-03 06:24:10 -0800218 this->emitAndInstallProc(stage, e, *inOut, &output);
joshualitta5305a12014-10-10 17:47:00 -0700219 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700220 }
joshualitta5305a12014-10-10 17:47:00 -0700221}
joshualitt30ba4362014-08-21 20:18:45 -0700222
joshualitt2dd1ae02014-12-03 06:24:10 -0800223void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
224 // create var to hold stage result. If we already have a valid output name, just use that
225 // otherwise create a new mangled one. This name is only valid if we are reordering stages
226 // and have to tell stage exactly where to put its output.
227 SkString outName;
228 if (output->isValid()) {
229 outName = output->c_str();
230 } else {
231 this->nameVariable(&outName, '\0', baseName);
232 }
233 fFS.codeAppendf("vec4 %s;", outName.c_str());
234 *output = outName;
235}
236
joshualitta5305a12014-10-10 17:47:00 -0700237// TODO Processors cannot output zeros because an empty string is all 1s
238// the fix is to allow effects to take the GrGLSLExpr4 directly
joshualitt2dd1ae02014-12-03 06:24:10 -0800239void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc,
joshualitta5305a12014-10-10 17:47:00 -0700240 int index,
joshualitta5305a12014-10-10 17:47:00 -0700241 const GrGLSLExpr4& input,
242 GrGLSLExpr4* output) {
243 // Program builders have a bit of state we need to clear with each effect
244 AutoStageAdvance adv(this);
joshualitt2dd1ae02014-12-03 06:24:10 -0800245 this->nameExpression(output, "output");
joshualitta5305a12014-10-10 17:47:00 -0700246
247 // Enclose custom code in a block to avoid namespace conflicts
248 SkString openBrace;
egdanielec03a462014-11-19 06:22:39 -0800249 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
joshualitta5305a12014-10-10 17:47:00 -0700250 fFS.codeAppend(openBrace.c_str());
251
joshualitt267ce482014-11-25 14:52:21 -0800252 this->emitAndInstallProc(proc, output->c_str(), input.isOnes() ? NULL : input.c_str());
joshualitta5305a12014-10-10 17:47:00 -0700253
254 fFS.codeAppend("}");
255}
256
joshualitt9b989322014-12-15 14:16:27 -0800257void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
joshualitt2dd1ae02014-12-03 06:24:10 -0800258 GrGLSLExpr4* outputColor,
259 GrGLSLExpr4* outputCoverage) {
260 // Program builders have a bit of state we need to clear with each effect
261 AutoStageAdvance adv(this);
262 this->nameExpression(outputColor, "outputColor");
263 this->nameExpression(outputCoverage, "outputCoverage");
264
265 // Enclose custom code in a block to avoid namespace conflicts
266 SkString openBrace;
267 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
268 fFS.codeAppend(openBrace.c_str());
269
270 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
271
272 fFS.codeAppend("}");
273}
274
bsalomonae59b772014-11-19 08:23:49 -0800275void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
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
280 const GrFragmentProcessor& fp = *fs.getProcessor();
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
286 // Fragment processors can have coord transforms
287 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms());
288 this->emitTransforms(fs, &coords, ifp);
289
joshualitt267ce482014-11-25 14:52:21 -0800290 ifp->fGLProc->emitCode(this, fp, outColor, inColor, coords, 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
joshualitt87f48d92014-12-04 10:41:40 -0800304 const GrBatchTracker& bt = fOptState.getBatchTracker();
joshualitteb2a6762014-12-04 11:35:33 -0800305 fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt));
joshualitta5305a12014-10-10 17:47:00 -0700306
307 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
308 this->emitSamplers(gp, &samplers, fGeometryProcessor);
309
joshualitt87f48d92014-12-04 10:41:40 -0800310 GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers);
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) {
362 // TODO: Once will readDst is only xp enable this assert and remove it from the
363 // FragmentProcessor verify()
364 //SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
365}
366
joshualitt47bb3822014-10-07 16:43:25 -0700367void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
368 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
369 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
370}
371
bsalomonae59b772014-11-19 08:23:49 -0800372void GrGLProgramBuilder::emitTransforms(const GrPendingFragmentStage& stage,
joshualitt47bb3822014-10-07 16:43:25 -0700373 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700374 GrGLInstalledFragProc* ifp) {
bsalomonae59b772014-11-19 08:23:49 -0800375 const GrFragmentProcessor* processor = stage.getProcessor();
376 int numTransforms = processor->numTransforms();
joshualitta5305a12014-10-10 17:47:00 -0700377 ifp->fTransforms.push_back_n(numTransforms);
joshualitt47bb3822014-10-07 16:43:25 -0700378
379 for (int t = 0; t < numTransforms; t++) {
380 const char* uniName = "StageMatrix";
bsalomonae59b772014-11-19 08:23:49 -0800381 GrSLType varyingType = stage.isPerspectiveCoordTransform(t) ? kVec3f_GrSLType :
382 kVec2f_GrSLType;
bsalomon54a57f52014-12-09 10:38:57 -0800383 GrSLPrecision precision = processor->coordTransform(t).precision();
384
joshualitt47bb3822014-10-07 16:43:25 -0700385 SkString suffixedUniName;
386 if (0 != t) {
387 suffixedUniName.append(uniName);
388 suffixedUniName.appendf("_%i", t);
389 uniName = suffixedUniName.c_str();
390 }
joshualitta5305a12014-10-10 17:47:00 -0700391 ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
bsalomon54a57f52014-12-09 10:38:57 -0800392 kMat33f_GrSLType, precision,
joshualitta5305a12014-10-10 17:47:00 -0700393 uniName,
394 &uniName).toShaderBuilderIndex();
joshualitt47bb3822014-10-07 16:43:25 -0700395
396 const char* varyingName = "MatrixCoord";
397 SkString suffixedVaryingName;
398 if (0 != t) {
399 suffixedVaryingName.append(varyingName);
400 suffixedVaryingName.appendf("_%i", t);
401 varyingName = suffixedVaryingName.c_str();
402 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800403
404 bool useLocalCoords = kLocal_GrCoordSet == processor->coordTransform(t).sourceCoords();
405 const char* coords = useLocalCoords ? fVS.localCoords() : fVS.positionCoords();
406
joshualitt74077b92014-10-24 11:26:03 -0700407 GrGLVertToFrag v(varyingType);
bsalomon54a57f52014-12-09 10:38:57 -0800408 this->addVarying(varyingName, &v, precision);
bsalomon17168df2014-12-09 09:00:49 -0800409 fCoordVaryings.push_back(TransformVarying(v, uniName, coords));
joshualitt47bb3822014-10-07 16:43:25 -0700410
joshualitt47bb3822014-10-07 16:43:25 -0700411 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
joshualitt47bb3822014-10-07 16:43:25 -0700412 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
joshualitt74077b92014-10-24 11:26:03 -0700413 (SkString(v.fsIn()), varyingType));
joshualitt47bb3822014-10-07 16:43:25 -0700414 }
415}
416
417void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
418 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700419 GrGLInstalledProc* ip) {
joshualitt47bb3822014-10-07 16:43:25 -0700420 int numTextures = processor.numTextures();
joshualitta5305a12014-10-10 17:47:00 -0700421 ip->fSamplers.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700422 SkString name;
423 for (int t = 0; t < numTextures; ++t) {
424 name.printf("Sampler%d", t);
joshualitta5305a12014-10-10 17:47:00 -0700425 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800426 kSampler2D_GrSLType, kDefault_GrSLPrecision,
joshualitta5305a12014-10-10 17:47:00 -0700427 name.c_str());
joshualittb0a8a372014-09-23 09:50:21 -0700428 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
joshualitta5305a12014-10-10 17:47:00 -0700429 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700430 }
431}
432
joshualitt47bb3822014-10-07 16:43:25 -0700433GrGLProgram* GrGLProgramBuilder::finalize() {
434 // verify we can get a program id
435 GrGLuint programID;
436 GL_CALL_RET(programID, CreateProgram());
437 if (0 == programID) {
438 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700439 }
440
joshualitt47bb3822014-10-07 16:43:25 -0700441 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700442 SkTDArray<GrGLuint> shadersToDelete;
joshualitt79f8fae2014-10-28 17:59:26 -0700443 if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr &&
joshualitt0e602822014-10-28 10:27:44 -0700444 fGpu->glPathRendering()->texturingMode() ==
445 GrGLPathRendering::FixedFunction_TexturingMode)) {
joshualitt47bb3822014-10-07 16:43:25 -0700446 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
447 this->cleanupProgram(programID, shadersToDelete);
448 return NULL;
449 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800450
451 // Non fixed function NVPR actually requires a vertex shader to compile
452 if (fOptState.hasGeometryProcessor()) {
453 fVS.bindVertexAttributes(programID);
454 }
joshualitt47bb3822014-10-07 16:43:25 -0700455 }
joshualitt9b989322014-12-15 14:16:27 -0800456
457 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
458 this->cleanupProgram(programID, shadersToDelete);
459 return NULL;
460 }
461
joshualitt47bb3822014-10-07 16:43:25 -0700462 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
463 if (usingBindUniform) {
464 this->bindUniformLocations(programID);
465 }
466 fFS.bindFragmentShaderLocations(programID);
467 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700468
469 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
470 bool checkLinked = !fGpu->ctxInfo().isChromium();
471#ifdef SK_DEBUG
472 checkLinked = true;
473#endif
474 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700475 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700476 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700477 if (!usingBindUniform) {
joshualitt47bb3822014-10-07 16:43:25 -0700478 this->resolveUniformLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700479 }
480
joshualitt47bb3822014-10-07 16:43:25 -0700481 this->cleanupShaders(shadersToDelete);
482
483 return this->createProgram(programID);
484}
485
486void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
487 int count = fUniforms.count();
488 for (int i = 0; i < count; ++i) {
489 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
490 fUniforms[i].fLocation = i;
491 }
492}
493
494bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
495 GrGLint linked = GR_GL_INIT_ZERO;
496 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
497 if (!linked) {
498 GrGLint infoLen = GR_GL_INIT_ZERO;
499 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
500 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
501 if (infoLen > 0) {
502 // retrieve length even though we don't need it to workaround
503 // bug in chrome cmd buffer param validation.
504 GrGLsizei length = GR_GL_INIT_ZERO;
505 GL_CALL(GetProgramInfoLog(programID,
506 infoLen+1,
507 &length,
508 (char*)log.get()));
tfarina38406c82014-10-31 07:11:12 -0700509 SkDebugf((char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700510 }
511 SkDEBUGFAIL("Error linking program");
512 GL_CALL(DeleteProgram(programID));
513 programID = 0;
514 }
515 return SkToBool(linked);
516}
517
518void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
519 int count = fUniforms.count();
kkinnunenec56e452014-08-25 22:21:16 -0700520 for (int i = 0; i < count; ++i) {
521 GrGLint location;
joshualitt47bb3822014-10-07 16:43:25 -0700522 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
523 fUniforms[i].fLocation = location;
kkinnunenec56e452014-08-25 22:21:16 -0700524 }
joshualitt30ba4362014-08-21 20:18:45 -0700525}
526
joshualitt47bb3822014-10-07 16:43:25 -0700527void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
528 GL_CALL(DeleteProgram(programID));
529 cleanupShaders(shaderIDs);
530}
531void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
532 for (int i = 0; i < shaderIDs.count(); ++i) {
533 GL_CALL(DeleteShader(shaderIDs[i]));
534 }
535}
536
537GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
538 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
egdanielc2304142014-12-11 13:15:13 -0800539 fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700540}
541
joshualitta5305a12014-10-10 17:47:00 -0700542///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700543
joshualitta5305a12014-10-10 17:47:00 -0700544GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
545 int numProcs = fProcs.count();
546 for (int e = 0; e < numProcs; ++e) {
547 SkDELETE(fProcs[e]);
joshualitt47bb3822014-10-07 16:43:25 -0700548 }
joshualitt30ba4362014-08-21 20:18:45 -0700549}