blob: 8fc60201211e0a85c7189dfd717bca5ea7b9657f [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"
joshualittdb0d3ca2014-10-07 12:42:26 -070012#include "../GrGpuGL.h"
joshualitt47bb3822014-10-07 16:43:25 -070013#include "GrCoordTransform.h"
14#include "GrGLLegacyNvprProgramBuilder.h"
15#include "GrGLNvprProgramBuilder.h"
joshualitt30ba4362014-08-21 20:18:45 -070016#include "GrGLProgramBuilder.h"
17#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070018#include "SkRTConf.h"
19#include "SkTraceEvent.h"
20
joshualitt30ba4362014-08-21 20:18:45 -070021#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
22#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
23
joshualitt30ba4362014-08-21 20:18:45 -070024// ES2 FS only guarantees mediump and lowp support
25static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
joshualitt30ba4362014-08-21 20:18:45 -070026
27//////////////////////////////////////////////////////////////////////////////
28
joshualitt47bb3822014-10-07 16:43:25 -070029const int GrGLProgramBuilder::kVarsPerBlock = 8;
30
31GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
joshualitt47bb3822014-10-07 16:43:25 -070032 GrGpu::DrawType drawType,
joshualitt47bb3822014-10-07 16:43:25 -070033 GrGpuGL* gpu) {
34 // create a builder. This will be handed off to effects so they can use it to add
35 // uniforms, varyings, textures, etc
joshualitt79f8fae2014-10-28 17:59:26 -070036 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(optState,
joshualitt47bb3822014-10-07 16:43:25 -070037 drawType,
joshualitta5305a12014-10-10 17:47:00 -070038 optState.hasGeometryProcessor(),
joshualitt47bb3822014-10-07 16:43:25 -070039 gpu));
40
41 GrGLProgramBuilder* pb = builder.get();
joshualitt79f8fae2014-10-28 17:59:26 -070042 const GrGLProgramDescBuilder::GLKeyHeader& header = GrGLProgramDescBuilder::GetHeader(pb->desc());
joshualitt47bb3822014-10-07 16:43:25 -070043
44 // emit code to read the dst copy texture, if necessary
45 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
46 && !gpu->glCaps().fbFetchSupport()) {
47 pb->fFS.emitCodeToReadDstTexture();
48 }
49
50 // get the initial color and coverage to feed into the first effect in each effect chain
egdaniel37b4d862014-11-03 10:07:07 -080051 GrGLSLExpr4 inputColor;
52 GrGLSLExpr1 inputCoverage;
joshualitt47bb3822014-10-07 16:43:25 -070053 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
54
55 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
56 // to setup a few more things like builtin vertex attributes
joshualitt0e602822014-10-28 10:27:44 -070057 bool hasVertexShader = !(header.fUseNvpr &&
58 gpu->glPathRendering()->texturingMode() ==
59 GrGLPathRendering::FixedFunction_TexturingMode);
joshualitt47bb3822014-10-07 16:43:25 -070060 if (hasVertexShader) {
61 pb->fVS.setupLocalCoords();
62 pb->fVS.transformGLToSkiaCoords();
63 if (header.fEmitsPointSize) {
64 pb->fVS.codeAppend("gl_PointSize = 1.0;");
65 }
joshualitt79f8fae2014-10-28 17:59:26 -070066 if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) {
joshualitt47bb3822014-10-07 16:43:25 -070067 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
68 }
joshualitt79f8fae2014-10-28 17:59:26 -070069 if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
joshualitt47bb3822014-10-07 16:43:25 -070070 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
71 }
72 }
73
egdaniel37b4d862014-11-03 10:07:07 -080074 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
75 // remove this cast to a vec4.
76 GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage);
77
78 pb->emitAndInstallProcs(optState, &inputColor, &inputCoverageVec4);
joshualitt47bb3822014-10-07 16:43:25 -070079
80 if (hasVertexShader) {
81 pb->fVS.transformSkiaToGLCoords();
82 }
83
84 // write the secondary color output if necessary
joshualitt79f8fae2014-10-28 17:59:26 -070085 if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
egdaniel37b4d862014-11-03 10:07:07 -080086 pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4);
joshualitt47bb3822014-10-07 16:43:25 -070087 }
88
egdaniel37b4d862014-11-03 10:07:07 -080089 pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4);
joshualitt47bb3822014-10-07 16:43:25 -070090
91 return pb->finalize();
92}
93
94GrGLProgramBuilder*
joshualitt79f8fae2014-10-28 17:59:26 -070095GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState,
joshualitt47bb3822014-10-07 16:43:25 -070096 GrGpu::DrawType drawType,
97 bool hasGeometryProcessor,
98 GrGpuGL* gpu) {
joshualitt79f8fae2014-10-28 17:59:26 -070099 const GrProgramDesc& desc = optState.programDesc();
100 if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) {
joshualitt47bb3822014-10-07 16:43:25 -0700101 SkASSERT(gpu->glCaps().pathRenderingSupport());
joshualitt79f8fae2014-10-28 17:59:26 -0700102 SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fColorInput);
103 SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fCoverageInput);
joshualitt47bb3822014-10-07 16:43:25 -0700104 SkASSERT(!hasGeometryProcessor);
joshualitt0e602822014-10-28 10:27:44 -0700105 if (gpu->glPathRendering()->texturingMode() ==
106 GrGLPathRendering::FixedFunction_TexturingMode) {
joshualitt79f8fae2014-10-28 17:59:26 -0700107 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState));
joshualitt0e602822014-10-28 10:27:44 -0700108 } else {
joshualitt79f8fae2014-10-28 17:59:26 -0700109 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState));
joshualitt0e602822014-10-28 10:27:44 -0700110 }
joshualitt47bb3822014-10-07 16:43:25 -0700111 } else {
joshualitt79f8fae2014-10-28 17:59:26 -0700112 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState));
joshualitt47bb3822014-10-07 16:43:25 -0700113 }
114}
115
116/////////////////////////////////////////////////////////////////////////////
117
joshualitt79f8fae2014-10-28 17:59:26 -0700118GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState)
joshualitt47bb3822014-10-07 16:43:25 -0700119 : fVS(this)
120 , fGS(this)
joshualitt79f8fae2014-10-28 17:59:26 -0700121 , fFS(this, optState.programDesc().header().fFragPosKey)
joshualitt47bb3822014-10-07 16:43:25 -0700122 , fOutOfStage(true)
123 , fStageIndex(-1)
joshualitta5305a12014-10-10 17:47:00 -0700124 , fGeometryProcessor(NULL)
egdaniel307796b2014-10-06 12:13:54 -0700125 , fOptState(optState)
joshualitt79f8fae2014-10-28 17:59:26 -0700126 , fDesc(optState.programDesc())
joshualitt30ba4362014-08-21 20:18:45 -0700127 , fGpu(gpu)
128 , fUniforms(kVarsPerBlock) {
129}
130
joshualitt74077b92014-10-24 11:26:03 -0700131void GrGLProgramBuilder::addVarying(const char* name,
132 GrGLVarying* varying,
joshualitt47bb3822014-10-07 16:43:25 -0700133 GrGLShaderVar::Precision fsPrecision) {
joshualitt74077b92014-10-24 11:26:03 -0700134 SkASSERT(varying);
135 if (varying->vsVarying()) {
136 fVS.addVarying(name, varying);
137 }
138 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->willUseGeoShader()) {
139 fGS.addVarying(name, varying);
140 }
141 if (varying->fsVarying()) {
142 fFS.addVarying(varying, fsPrecision);
143 }
joshualitt47bb3822014-10-07 16:43:25 -0700144}
145
joshualitt30ba4362014-08-21 20:18:45 -0700146void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
147 if ('\0' == prefix) {
148 *out = name;
149 } else {
150 out->printf("%c%s", prefix, name);
151 }
joshualitt47bb3822014-10-07 16:43:25 -0700152 if (!fOutOfStage) {
joshualitt30ba4362014-08-21 20:18:45 -0700153 if (out->endsWith('_')) {
154 // Names containing "__" are reserved.
155 out->append("x");
156 }
joshualitt47bb3822014-10-07 16:43:25 -0700157 out->appendf("_Stage%d", fStageIndex);
joshualitt30ba4362014-08-21 20:18:45 -0700158 }
159}
160
161GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility,
162 GrSLType type,
163 const char* name,
164 int count,
165 const char** outName) {
166 SkASSERT(name && strlen(name));
167 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
168 SkASSERT(0 == (~kVisibilityMask & visibility));
169 SkASSERT(0 != visibility);
170
171 UniformInfo& uni = fUniforms.push_back();
172 uni.fVariable.setType(type);
173 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
174 this->nameVariable(uni.fVariable.accessName(), 'u', name);
175 uni.fVariable.setArrayCount(count);
176 uni.fVisibility = visibility;
177
178 // If it is visible in both the VS and FS, the precision must match.
179 // We declare a default FS precision, but not a default VS. So set the var
180 // to use the default FS precision.
181 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
182 // the fragment and vertex precisions must match
183 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
184 }
185
bsalomon49f085d2014-09-05 13:34:00 -0700186 if (outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700187 *outName = uni.fVariable.c_str();
188 }
189 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
190}
191
joshualitt30ba4362014-08-21 20:18:45 -0700192void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
193 SkString* out) const {
194 for (int i = 0; i < fUniforms.count(); ++i) {
195 if (fUniforms[i].fVisibility & visibility) {
196 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
197 out->append(";\n");
198 }
199 }
200}
201
joshualitt47bb3822014-10-07 16:43:25 -0700202const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
203 return fGpu->ctxInfo();
204}
205
206void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
egdaniel37b4d862014-11-03 10:07:07 -0800207 GrGLSLExpr1* inputCoverage) {
joshualitt79f8fae2014-10-28 17:59:26 -0700208 const GrProgramDesc::KeyHeader& header = this->header();
209 if (GrProgramDesc::kUniform_ColorInput == header.fColorInput) {
joshualitt47bb3822014-10-07 16:43:25 -0700210 const char* name;
211 fUniformHandles.fColorUni =
212 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
213 kVec4f_GrSLType,
214 "Color",
215 &name);
216 *inputColor = GrGLSLExpr4(name);
joshualitt79f8fae2014-10-28 17:59:26 -0700217 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
joshualitt47bb3822014-10-07 16:43:25 -0700218 *inputColor = GrGLSLExpr4(1);
219 }
joshualitt79f8fae2014-10-28 17:59:26 -0700220 if (GrProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
joshualitt47bb3822014-10-07 16:43:25 -0700221 const char* name;
222 fUniformHandles.fCoverageUni =
223 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
egdaniel37b4d862014-11-03 10:07:07 -0800224 kFloat_GrSLType,
joshualitt47bb3822014-10-07 16:43:25 -0700225 "Coverage",
226 &name);
egdaniel37b4d862014-11-03 10:07:07 -0800227 *inputCoverage = GrGLSLExpr1(name);
joshualitt79f8fae2014-10-28 17:59:26 -0700228 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
egdaniel37b4d862014-11-03 10:07:07 -0800229 *inputCoverage = GrGLSLExpr1(1);
joshualitt47bb3822014-10-07 16:43:25 -0700230 }
231}
232
joshualitta5305a12014-10-10 17:47:00 -0700233void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState,
234 GrGLSLExpr4* inputColor,
235 GrGLSLExpr4* inputCoverage) {
236 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
237 int numProcs = optState.numFragmentStages();
238 this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor);
239 if (optState.hasGeometryProcessor()) {
240 const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
241 fVS.emitAttributes(gp);
joshualitt79f8fae2014-10-28 17:59:26 -0700242 ProcKeyProvider keyProvider(&fDesc,
243 ProcKeyProvider::kGeometry_ProcessorType,
244 GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset);
joshualitta5305a12014-10-10 17:47:00 -0700245 GrGLSLExpr4 output;
246 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output);
247 *inputCoverage = output;
joshualitt47bb3822014-10-07 16:43:25 -0700248 }
joshualitta5305a12014-10-10 17:47:00 -0700249 this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700250}
251
joshualitta5305a12014-10-10 17:47:00 -0700252void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) {
joshualitt79f8fae2014-10-28 17:59:26 -0700253 ProcKeyProvider keyProvider(&fDesc,
254 ProcKeyProvider::kFragment_ProcessorType,
255 GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset);
joshualitta5305a12014-10-10 17:47:00 -0700256 for (int e = procOffset; e < numProcs; ++e) {
257 GrGLSLExpr4 output;
258 const GrFragmentStage& stage = fOptState.getFragmentStage(e);
259 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut, &output);
260 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700261 }
joshualitta5305a12014-10-10 17:47:00 -0700262}
joshualitt30ba4362014-08-21 20:18:45 -0700263
joshualitta5305a12014-10-10 17:47:00 -0700264// TODO Processors cannot output zeros because an empty string is all 1s
265// the fix is to allow effects to take the GrGLSLExpr4 directly
266template <class Proc>
267void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
268 int index,
joshualitt79f8fae2014-10-28 17:59:26 -0700269 const ProcKeyProvider& keyProvider,
joshualitta5305a12014-10-10 17:47:00 -0700270 const GrGLSLExpr4& input,
271 GrGLSLExpr4* output) {
272 // Program builders have a bit of state we need to clear with each effect
273 AutoStageAdvance adv(this);
274
275 // create var to hold stage result
276 SkString outColorName;
277 this->nameVariable(&outColorName, '\0', "output");
278 fFS.codeAppendf("vec4 %s;", outColorName.c_str());
279 *output = outColorName;
280
281 // Enclose custom code in a block to avoid namespace conflicts
282 SkString openBrace;
283 openBrace.printf("{ // Stage %d\n", fStageIndex);
284 fFS.codeAppend(openBrace.c_str());
285
286 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(),
287 input.isOnes() ? NULL : input.c_str());
288
289 fFS.codeAppend("}");
290}
291
292void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs,
293 const GrProcessorKey& key,
294 const char* outColor,
295 const char* inColor) {
296 GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
297
298 const GrFragmentProcessor& fp = *fs.getProcessor();
299 ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp));
300
301 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
302 this->emitSamplers(fp, &samplers, ifp);
303
304 // Fragment processors can have coord transforms
305 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms());
306 this->emitTransforms(fs, &coords, ifp);
307
308 ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers);
309
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(fp);
313 fFragmentProcessors->fProcs.push_back(ifp);
314}
315
316void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
317 const GrProcessorKey& key,
318 const char* outColor,
319 const char* inColor) {
320 SkASSERT(!fGeometryProcessor);
321 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
322
323 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp));
324
325 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
326 this->emitSamplers(gp, &samplers, fGeometryProcessor);
327
joshualittc369e7c2014-10-22 10:56:26 -0700328 GrGLGeometryProcessor::EmitArgs args(this, gp, key, outColor, inColor, samplers);
329 fGeometryProcessor->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700330
331 // We have to check that effects and the code they emit are consistent, ie if an effect
332 // asks for dst color, then the emit code needs to follow suit
333 verify(gp);
joshualitt30ba4362014-08-21 20:18:45 -0700334}
335
joshualitt47bb3822014-10-07 16:43:25 -0700336void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
337 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
joshualittfe1233c2014-10-07 12:16:35 -0700338}
339
joshualitt47bb3822014-10-07 16:43:25 -0700340void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
341 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
342 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
343}
344
joshualitta5305a12014-10-10 17:47:00 -0700345void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
joshualitt47bb3822014-10-07 16:43:25 -0700346 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700347 GrGLInstalledFragProc* ifp) {
348 const GrFragmentProcessor* effect = effectStage.getProcessor();
joshualitt47bb3822014-10-07 16:43:25 -0700349 int numTransforms = effect->numTransforms();
joshualitta5305a12014-10-10 17:47:00 -0700350 ifp->fTransforms.push_back_n(numTransforms);
joshualitt47bb3822014-10-07 16:43:25 -0700351
352 for (int t = 0; t < numTransforms; t++) {
353 const char* uniName = "StageMatrix";
354 GrSLType varyingType =
joshualitta5305a12014-10-10 17:47:00 -0700355 effectStage.isPerspectiveCoordTransform(t, fVS.hasLocalCoords()) ?
joshualitt47bb3822014-10-07 16:43:25 -0700356 kVec3f_GrSLType :
357 kVec2f_GrSLType;
358
359 SkString suffixedUniName;
360 if (0 != t) {
361 suffixedUniName.append(uniName);
362 suffixedUniName.appendf("_%i", t);
363 uniName = suffixedUniName.c_str();
364 }
joshualitta5305a12014-10-10 17:47:00 -0700365 ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
366 kMat33f_GrSLType,
367 uniName,
368 &uniName).toShaderBuilderIndex();
joshualitt47bb3822014-10-07 16:43:25 -0700369
370 const char* varyingName = "MatrixCoord";
371 SkString suffixedVaryingName;
372 if (0 != t) {
373 suffixedVaryingName.append(varyingName);
374 suffixedVaryingName.appendf("_%i", t);
375 varyingName = suffixedVaryingName.c_str();
376 }
joshualitt74077b92014-10-24 11:26:03 -0700377 GrGLVertToFrag v(varyingType);
378 this->addVarying(varyingName, &v);
joshualitt47bb3822014-10-07 16:43:25 -0700379
380 const GrGLShaderVar& coords =
381 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
382 fVS.positionAttribute() :
383 fVS.localCoordsAttribute();
384
385 // varying = matrix * coords (logically)
386 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
387 if (kVec2f_GrSLType == varyingType) {
388 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
joshualitt74077b92014-10-24 11:26:03 -0700389 v.vsOut(), uniName, coords.c_str());
joshualitt47bb3822014-10-07 16:43:25 -0700390 } else {
391 fVS.codeAppendf("%s = %s * vec3(%s, 1);",
joshualitt74077b92014-10-24 11:26:03 -0700392 v.vsOut(), uniName, coords.c_str());
joshualitt47bb3822014-10-07 16:43:25 -0700393 }
394 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
joshualitt74077b92014-10-24 11:26:03 -0700395 (SkString(v.fsIn()), varyingType));
joshualitt47bb3822014-10-07 16:43:25 -0700396 }
397}
398
399void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
400 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700401 GrGLInstalledProc* ip) {
joshualitt47bb3822014-10-07 16:43:25 -0700402 int numTextures = processor.numTextures();
joshualitta5305a12014-10-10 17:47:00 -0700403 ip->fSamplers.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700404 SkString name;
405 for (int t = 0; t < numTextures; ++t) {
406 name.printf("Sampler%d", t);
joshualitta5305a12014-10-10 17:47:00 -0700407 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
408 kSampler2D_GrSLType,
409 name.c_str());
joshualittb0a8a372014-09-23 09:50:21 -0700410 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
joshualitta5305a12014-10-10 17:47:00 -0700411 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700412 }
413}
414
joshualitt47bb3822014-10-07 16:43:25 -0700415GrGLProgram* GrGLProgramBuilder::finalize() {
416 // verify we can get a program id
417 GrGLuint programID;
418 GL_CALL_RET(programID, CreateProgram());
419 if (0 == programID) {
420 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700421 }
422
joshualitt47bb3822014-10-07 16:43:25 -0700423 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700424 SkTDArray<GrGLuint> shadersToDelete;
joshualitt47bb3822014-10-07 16:43:25 -0700425 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
426 this->cleanupProgram(programID, shadersToDelete);
427 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700428 }
joshualitt79f8fae2014-10-28 17:59:26 -0700429 if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr &&
joshualitt0e602822014-10-28 10:27:44 -0700430 fGpu->glPathRendering()->texturingMode() ==
431 GrGLPathRendering::FixedFunction_TexturingMode)) {
joshualitt47bb3822014-10-07 16:43:25 -0700432 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
433 this->cleanupProgram(programID, shadersToDelete);
434 return NULL;
435 }
436 fVS.bindVertexAttributes(programID);
437 }
438 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
439 if (usingBindUniform) {
440 this->bindUniformLocations(programID);
441 }
442 fFS.bindFragmentShaderLocations(programID);
443 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700444
445 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
446 bool checkLinked = !fGpu->ctxInfo().isChromium();
447#ifdef SK_DEBUG
448 checkLinked = true;
449#endif
450 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700451 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700452 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700453 if (!usingBindUniform) {
joshualitt47bb3822014-10-07 16:43:25 -0700454 this->resolveUniformLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700455 }
456
joshualitt47bb3822014-10-07 16:43:25 -0700457 this->cleanupShaders(shadersToDelete);
458
459 return this->createProgram(programID);
460}
461
462void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
463 int count = fUniforms.count();
464 for (int i = 0; i < count; ++i) {
465 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
466 fUniforms[i].fLocation = i;
467 }
468}
469
470bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
471 GrGLint linked = GR_GL_INIT_ZERO;
472 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
473 if (!linked) {
474 GrGLint infoLen = GR_GL_INIT_ZERO;
475 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
476 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
477 if (infoLen > 0) {
478 // retrieve length even though we don't need it to workaround
479 // bug in chrome cmd buffer param validation.
480 GrGLsizei length = GR_GL_INIT_ZERO;
481 GL_CALL(GetProgramInfoLog(programID,
482 infoLen+1,
483 &length,
484 (char*)log.get()));
tfarina38406c82014-10-31 07:11:12 -0700485 SkDebugf((char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700486 }
487 SkDEBUGFAIL("Error linking program");
488 GL_CALL(DeleteProgram(programID));
489 programID = 0;
490 }
491 return SkToBool(linked);
492}
493
494void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
495 int count = fUniforms.count();
kkinnunenec56e452014-08-25 22:21:16 -0700496 for (int i = 0; i < count; ++i) {
497 GrGLint location;
joshualitt47bb3822014-10-07 16:43:25 -0700498 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
499 fUniforms[i].fLocation = location;
kkinnunenec56e452014-08-25 22:21:16 -0700500 }
joshualitt30ba4362014-08-21 20:18:45 -0700501}
502
joshualitt47bb3822014-10-07 16:43:25 -0700503void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
504 GL_CALL(DeleteProgram(programID));
505 cleanupShaders(shaderIDs);
506}
507void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
508 for (int i = 0; i < shaderIDs.count(); ++i) {
509 GL_CALL(DeleteShader(shaderIDs[i]));
510 }
511}
512
513GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
514 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
joshualitta5305a12014-10-10 17:47:00 -0700515 fGeometryProcessor, fFragmentProcessors.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700516}
517
joshualitta5305a12014-10-10 17:47:00 -0700518///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700519
joshualitta5305a12014-10-10 17:47:00 -0700520GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
521 int numProcs = fProcs.count();
522 for (int e = 0; e < numProcs; ++e) {
523 SkDELETE(fProcs[e]);
joshualitt47bb3822014-10-07 16:43:25 -0700524 }
joshualitt30ba4362014-08-21 20:18:45 -0700525}