blob: 7664bab90f87aa248c493d99842e83fb478a2c2b [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
8#include "gl/GrGLProgram.h"
9#include "gl/GrGLSLPrettyPrint.h"
10#include "gl/GrGLUniformHandle.h"
11#include "GrCoordTransform.h"
12#include "GrDrawEffect.h"
13#include "../GrGpuGL.h"
14#include "GrGLFragmentShaderBuilder.h"
15#include "GrGLProgramBuilder.h"
16#include "GrTexture.h"
17#include "GrGLVertexShaderBuilder.h"
18#include "SkRTConf.h"
19#include "SkTraceEvent.h"
20
21namespace {
22#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
25// number of each input/output type in a single allocation block
26static const int kVarsPerBlock = 8;
27
28// ES2 FS only guarantees mediump and lowp support
29static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
30}
31
32///////////////////////////////////////////////////////////////////////////////////////////////////
33
34bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
35 const GrEffectStage* coverageStages[]) {
36 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
37
38 fFS.emitCodeBeforeEffects();
39
40 ///////////////////////////////////////////////////////////////////////////
41 // get the initial color and coverage to feed into the first effect in each effect chain
42
43 GrGLSLExpr4 inputColor;
44 GrGLSLExpr4 inputCoverage;
45
46 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
47 const char* name;
48 fUniformHandles.fColorUni =
49 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
50 kVec4f_GrSLType,
51 "Color",
52 &name);
53 inputColor = GrGLSLExpr4(name);
egdaniel842b0862014-09-02 10:01:30 -070054 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
55 inputColor = GrGLSLExpr4(1);
joshualitt30ba4362014-08-21 20:18:45 -070056 }
57
58 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
59 const char* name;
60 fUniformHandles.fCoverageUni =
61 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
62 kVec4f_GrSLType,
63 "Coverage",
64 &name);
65 inputCoverage = GrGLSLExpr4(name);
egdaniel842b0862014-09-02 10:01:30 -070066 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
joshualitt30ba4362014-08-21 20:18:45 -070067 inputCoverage = GrGLSLExpr4(1);
68 }
69
70 this->emitCodeBeforeEffects(&inputColor, &inputCoverage);
71
72 ///////////////////////////////////////////////////////////////////////////
73 // emit the per-effect code for both color and coverage effects
74
75 GrGLProgramDesc::EffectKeyProvider colorKeyProvider(
76 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType);
77 fColorEffects.reset(this->createAndEmitEffects(colorStages,
78 this->desc().numColorEffects(),
79 colorKeyProvider,
80 &inputColor));
81
82 GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
83 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
84 fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
85 this->desc().numCoverageEffects(),
86 coverageKeyProvider,
87 &inputCoverage));
88
89 this->emitCodeAfterEffects();
90
91 fFS.emitCodeAfterEffects(inputColor, inputCoverage);
92
93 if (!this->finish()) {
94 return false;
95 }
96
97 return true;
98}
99
100//////////////////////////////////////////////////////////////////////////////
101
102GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
103 const GrGLProgramDesc& desc)
kkinnunenec56e452014-08-25 22:21:16 -0700104 : fFragOnly(!desc.getHeader().fRequiresVertexShader &&
105 gpu->glCaps().pathRenderingSupport() &&
106 gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode)
joshualitt30ba4362014-08-21 20:18:45 -0700107 , fTexCoordSetCnt(0)
108 , fProgramID(0)
109 , fFS(this, desc)
kkinnunenec56e452014-08-25 22:21:16 -0700110 , fSeparableVaryingInfos(kVarsPerBlock)
joshualitt30ba4362014-08-21 20:18:45 -0700111 , fDesc(desc)
112 , fGpu(gpu)
113 , fUniforms(kVarsPerBlock) {
114}
115
116void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
117 if ('\0' == prefix) {
118 *out = name;
119 } else {
120 out->printf("%c%s", prefix, name);
121 }
122 if (fCodeStage.inStageCode()) {
123 if (out->endsWith('_')) {
124 // Names containing "__" are reserved.
125 out->append("x");
126 }
127 out->appendf("_Stage%d", fCodeStage.stageIndex());
128 }
129}
130
131GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility,
132 GrSLType type,
133 const char* name,
134 int count,
135 const char** outName) {
136 SkASSERT(name && strlen(name));
137 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
138 SkASSERT(0 == (~kVisibilityMask & visibility));
139 SkASSERT(0 != visibility);
140
141 UniformInfo& uni = fUniforms.push_back();
142 uni.fVariable.setType(type);
143 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
144 this->nameVariable(uni.fVariable.accessName(), 'u', name);
145 uni.fVariable.setArrayCount(count);
146 uni.fVisibility = visibility;
147
148 // If it is visible in both the VS and FS, the precision must match.
149 // We declare a default FS precision, but not a default VS. So set the var
150 // to use the default FS precision.
151 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
152 // the fragment and vertex precisions must match
153 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
154 }
155
156 if (NULL != outName) {
157 *outName = uni.fVariable.c_str();
158 }
159 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
160}
161
162void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
163 for (int i = 0; i < vars.count(); ++i) {
164 vars[i].appendDecl(this->ctxInfo(), out);
165 out->append(";\n");
166 }
167}
168
169void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
170 SkString* out) const {
171 for (int i = 0; i < fUniforms.count(); ++i) {
172 if (fUniforms[i].fVisibility & visibility) {
173 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
174 out->append(";\n");
175 }
176 }
177}
178
179void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
180 const GrEffectStage* effectStages[],
181 int effectCnt,
182 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
183 GrGLSLExpr4* fsInOutColor) {
184 bool effectEmitted = false;
185
186 GrGLSLExpr4 inColor = *fsInOutColor;
187 GrGLSLExpr4 outColor;
188
189 for (int e = 0; e < effectCnt; ++e) {
190 SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
191 const GrEffectStage& stage = *effectStages[e];
192
193 CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
194
195 if (inColor.isZeros()) {
196 SkString inColorName;
197
198 // Effects have no way to communicate zeros, they treat an empty string as ones.
199 this->nameVariable(&inColorName, '\0', "input");
200 fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
201 inColor = inColorName;
202 }
203
204 // create var to hold stage result
205 SkString outColorName;
206 this->nameVariable(&outColorName, '\0', "output");
207 fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
208 outColor = outColorName;
209
210
211 programEffectsBuilder->emitEffect(stage,
212 keyProvider.get(e),
213 outColor.c_str(),
214 inColor.isOnes() ? NULL : inColor.c_str(),
215 fCodeStage.stageIndex());
216
217 inColor = outColor;
218 effectEmitted = true;
219 }
220
221 if (effectEmitted) {
222 *fsInOutColor = outColor;
223 }
224}
225
226bool GrGLProgramBuilder::finish() {
227 SkASSERT(0 == fProgramID);
228 GL_CALL_RET(fProgramID, CreateProgram());
229 if (!fProgramID) {
230 return false;
231 }
232
233 SkTDArray<GrGLuint> shadersToDelete;
234
235 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
236 GL_CALL(DeleteProgram(fProgramID));
237 return false;
238 }
239
240 this->bindProgramLocations(fProgramID);
241
242 GL_CALL(LinkProgram(fProgramID));
243
244 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
245 bool checkLinked = !fGpu->ctxInfo().isChromium();
246#ifdef SK_DEBUG
247 checkLinked = true;
248#endif
249 if (checkLinked) {
250 GrGLint linked = GR_GL_INIT_ZERO;
251 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
252 if (!linked) {
253 GrGLint infoLen = GR_GL_INIT_ZERO;
254 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
255 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
256 if (infoLen > 0) {
257 // retrieve length even though we don't need it to workaround
258 // bug in chrome cmd buffer param validation.
259 GrGLsizei length = GR_GL_INIT_ZERO;
260 GL_CALL(GetProgramInfoLog(fProgramID,
261 infoLen+1,
262 &length,
263 (char*)log.get()));
264 GrPrintf((char*)log.get());
265 }
266 SkDEBUGFAIL("Error linking program");
267 GL_CALL(DeleteProgram(fProgramID));
268 fProgramID = 0;
269 return false;
270 }
271 }
272
273 this->resolveProgramLocations(fProgramID);
274
275 for (int i = 0; i < shadersToDelete.count(); ++i) {
276 GL_CALL(DeleteShader(shadersToDelete[i]));
277 }
278
279 return true;
280}
281
282bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId,
283 SkTDArray<GrGLuint>* shaderIds) const {
284 return fFS.compileAndAttachShaders(programId, shaderIds);
285}
286
287void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
288 fFS.bindProgramLocations(programId);
289
290 // skbug.com/2056
291 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
292 if (usingBindUniform) {
293 int count = fUniforms.count();
294 for (int i = 0; i < count; ++i) {
295 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str()));
296 fUniforms[i].fLocation = i;
297 }
298 }
299}
300
301void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
302 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
303 if (!usingBindUniform) {
304 int count = fUniforms.count();
305 for (int i = 0; i < count; ++i) {
306 GrGLint location;
307 GL_CALL_RET(location,
308 GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
309 fUniforms[i].fLocation = location;
310 }
311 }
kkinnunenec56e452014-08-25 22:21:16 -0700312
313 int count = fSeparableVaryingInfos.count();
314 for (int i = 0; i < count; ++i) {
315 GrGLint location;
316 GL_CALL_RET(location,
317 GetProgramResourceLocation(programId,
318 GR_GL_FRAGMENT_INPUT,
319 fSeparableVaryingInfos[i].fVariable.c_str()));
320 fSeparableVaryingInfos[i].fLocation = location;
321 }
joshualitt30ba4362014-08-21 20:18:45 -0700322}
323
324const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
325 return fGpu->ctxInfo();
326}
327
328////////////////////////////////////////////////////////////////////////////////
329
330GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
331 const GrGLProgramDesc& desc)
332 : INHERITED(gpu, desc)
333 , fGS(this)
334 , fVS(this) {
335}
336
337void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
338 fVS.emitCodeBeforeEffects(color, coverage);
339}
340
341void GrGLFullProgramBuilder::emitCodeAfterEffects() {
342 fVS.emitCodeAfterEffects();
343}
344
345void GrGLFullProgramBuilder::addVarying(GrSLType type,
346 const char* name,
347 const char** vsOutName,
egdaniel6db91282014-09-02 08:02:38 -0700348 const char** fsInName,
349 GrGLShaderVar::Precision fsPrecision) {
joshualitt30ba4362014-08-21 20:18:45 -0700350 fVS.addVarying(type, name, vsOutName);
351
352 SkString* fsInputName = fVS.fOutputs.back().accessName();
353
354#if GR_GL_EXPERIMENTAL_GS
355 if (desc().getHeader().fExperimentalGS) {
356 // TODO let the caller use these names
357 fGS.addVarying(type, fsInputName->c_str(), NULL);
358 fsInputName = fGS.fOutputs.back().accessName();
359 }
360#endif
egdaniel6db91282014-09-02 08:02:38 -0700361 fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
joshualitt30ba4362014-08-21 20:18:45 -0700362}
363
kkinnunenec56e452014-08-25 22:21:16 -0700364GrGLFullProgramBuilder::VaryingHandle
365GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
366 const char* name,
367 const char** vsOutName,
368 const char** fsInName) {
369 addVarying(type, name, vsOutName, fsInName);
370 SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
371 varying.fVariable = fFS.fInputs.back();
372 return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
373}
374
375
joshualitt30ba4362014-08-21 20:18:45 -0700376GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
377 const GrEffectStage* effectStages[],
378 int effectCnt,
379 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
380 GrGLSLExpr4* inOutFSColor) {
381
382 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
383 this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
384 effectStages,
385 effectCnt,
386 keyProvider,
387 inOutFSColor);
388 return programEffectsBuilder.finish();
389}
390
391bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
392 SkTDArray<GrGLuint>* shaderIds) const {
393 return INHERITED::compileAndAttachShaders(programId, shaderIds)
394 && fVS.compileAndAttachShaders(programId, shaderIds)
395#if GR_GL_EXPERIMENTAL_GS
396 && (!desc().getHeader().fExperimentalGS
397 || fGS.compileAndAttachShaders(programId, shaderIds))
398#endif
399 ;
400}
401
402void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
403 fVS.bindProgramLocations(programId);
404 INHERITED::bindProgramLocations(programId);
405}
406
407////////////////////////////////////////////////////////////////////////////////
408
409GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
410 const GrGLProgramDesc& desc)
411 : INHERITED(gpu, desc) {
kkinnunenec56e452014-08-25 22:21:16 -0700412 SkASSERT(!desc.getHeader().fRequiresVertexShader);
joshualitt30ba4362014-08-21 20:18:45 -0700413 SkASSERT(gpu->glCaps().pathRenderingSupport());
414 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
415 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
416}
417
418int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
419 int firstFreeCoordSet = fTexCoordSetCnt;
420 fTexCoordSetCnt += count;
421 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
422 return firstFreeCoordSet;
423}
424
425GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(
426 const GrEffectStage* effectStages[], int effectCnt,
427 const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
428
429 GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
430 effectCnt);
431 this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
432 effectStages,
433 effectCnt,
434 keyProvider,
435 inOutFSColor);
436 return pathTexGenEffectsBuilder.finish();
437}