blob: 3844a30f92ae3ff6aeb6f1389ade90dcc3404c5b [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
joshualittbd769d02014-09-04 08:56:46 -070034bool GrGLProgramBuilder::genProgram(const GrEffectStage* geometryProcessor,
35 const GrEffectStage* colorStages[],
joshualitt30ba4362014-08-21 20:18:45 -070036 const GrEffectStage* coverageStages[]) {
37 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
38
39 fFS.emitCodeBeforeEffects();
40
41 ///////////////////////////////////////////////////////////////////////////
42 // get the initial color and coverage to feed into the first effect in each effect chain
43
44 GrGLSLExpr4 inputColor;
45 GrGLSLExpr4 inputCoverage;
46
47 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
48 const char* name;
49 fUniformHandles.fColorUni =
50 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
51 kVec4f_GrSLType,
52 "Color",
53 &name);
54 inputColor = GrGLSLExpr4(name);
egdaniel842b0862014-09-02 10:01:30 -070055 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
56 inputColor = GrGLSLExpr4(1);
joshualitt30ba4362014-08-21 20:18:45 -070057 }
58
59 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
60 const char* name;
61 fUniformHandles.fCoverageUni =
62 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
63 kVec4f_GrSLType,
64 "Coverage",
65 &name);
66 inputCoverage = GrGLSLExpr4(name);
egdaniel842b0862014-09-02 10:01:30 -070067 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
joshualitt30ba4362014-08-21 20:18:45 -070068 inputCoverage = GrGLSLExpr4(1);
69 }
70
71 this->emitCodeBeforeEffects(&inputColor, &inputCoverage);
72
73 ///////////////////////////////////////////////////////////////////////////
74 // emit the per-effect code for both color and coverage effects
75
76 GrGLProgramDesc::EffectKeyProvider colorKeyProvider(
77 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType);
78 fColorEffects.reset(this->createAndEmitEffects(colorStages,
79 this->desc().numColorEffects(),
80 colorKeyProvider,
81 &inputColor));
82
joshualittbd769d02014-09-04 08:56:46 -070083 this->emitGeometryProcessor(geometryProcessor, &inputCoverage);
84
joshualitt30ba4362014-08-21 20:18:45 -070085 GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
86 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
87 fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
88 this->desc().numCoverageEffects(),
89 coverageKeyProvider,
90 &inputCoverage));
91
92 this->emitCodeAfterEffects();
93
94 fFS.emitCodeAfterEffects(inputColor, inputCoverage);
95
96 if (!this->finish()) {
97 return false;
98 }
99
100 return true;
101}
102
103//////////////////////////////////////////////////////////////////////////////
104
105GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
106 const GrGLProgramDesc& desc)
kkinnunenec56e452014-08-25 22:21:16 -0700107 : fFragOnly(!desc.getHeader().fRequiresVertexShader &&
108 gpu->glCaps().pathRenderingSupport() &&
109 gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode)
joshualitt30ba4362014-08-21 20:18:45 -0700110 , fTexCoordSetCnt(0)
111 , fProgramID(0)
112 , fFS(this, desc)
kkinnunenec56e452014-08-25 22:21:16 -0700113 , fSeparableVaryingInfos(kVarsPerBlock)
joshualitt30ba4362014-08-21 20:18:45 -0700114 , fDesc(desc)
115 , fGpu(gpu)
116 , fUniforms(kVarsPerBlock) {
117}
118
119void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
120 if ('\0' == prefix) {
121 *out = name;
122 } else {
123 out->printf("%c%s", prefix, name);
124 }
125 if (fCodeStage.inStageCode()) {
126 if (out->endsWith('_')) {
127 // Names containing "__" are reserved.
128 out->append("x");
129 }
130 out->appendf("_Stage%d", fCodeStage.stageIndex());
131 }
132}
133
134GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility,
135 GrSLType type,
136 const char* name,
137 int count,
138 const char** outName) {
139 SkASSERT(name && strlen(name));
140 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
141 SkASSERT(0 == (~kVisibilityMask & visibility));
142 SkASSERT(0 != visibility);
143
144 UniformInfo& uni = fUniforms.push_back();
145 uni.fVariable.setType(type);
146 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
147 this->nameVariable(uni.fVariable.accessName(), 'u', name);
148 uni.fVariable.setArrayCount(count);
149 uni.fVisibility = visibility;
150
151 // If it is visible in both the VS and FS, the precision must match.
152 // We declare a default FS precision, but not a default VS. So set the var
153 // to use the default FS precision.
154 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
155 // the fragment and vertex precisions must match
156 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
157 }
158
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
165void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
166 for (int i = 0; i < vars.count(); ++i) {
167 vars[i].appendDecl(this->ctxInfo(), out);
168 out->append(";\n");
169 }
170}
171
172void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
173 SkString* out) const {
174 for (int i = 0; i < fUniforms.count(); ++i) {
175 if (fUniforms[i].fVisibility & visibility) {
176 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
177 out->append(";\n");
178 }
179 }
180}
181
182void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
183 const GrEffectStage* effectStages[],
184 int effectCnt,
185 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
186 GrGLSLExpr4* fsInOutColor) {
187 bool effectEmitted = false;
188
189 GrGLSLExpr4 inColor = *fsInOutColor;
190 GrGLSLExpr4 outColor;
191
192 for (int e = 0; e < effectCnt; ++e) {
bsalomon49f085d2014-09-05 13:34:00 -0700193 SkASSERT(effectStages[e] && effectStages[e]->getEffect());
joshualitt30ba4362014-08-21 20:18:45 -0700194 const GrEffectStage& stage = *effectStages[e];
195
196 CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
197
198 if (inColor.isZeros()) {
199 SkString inColorName;
200
201 // Effects have no way to communicate zeros, they treat an empty string as ones.
202 this->nameVariable(&inColorName, '\0', "input");
203 fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
204 inColor = inColorName;
205 }
206
207 // create var to hold stage result
208 SkString outColorName;
209 this->nameVariable(&outColorName, '\0', "output");
210 fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
211 outColor = outColorName;
212
213
214 programEffectsBuilder->emitEffect(stage,
215 keyProvider.get(e),
216 outColor.c_str(),
217 inColor.isOnes() ? NULL : inColor.c_str(),
218 fCodeStage.stageIndex());
219
220 inColor = outColor;
221 effectEmitted = true;
222 }
223
224 if (effectEmitted) {
225 *fsInOutColor = outColor;
226 }
227}
228
229bool GrGLProgramBuilder::finish() {
230 SkASSERT(0 == fProgramID);
231 GL_CALL_RET(fProgramID, CreateProgram());
232 if (!fProgramID) {
233 return false;
234 }
235
236 SkTDArray<GrGLuint> shadersToDelete;
237
238 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
239 GL_CALL(DeleteProgram(fProgramID));
240 return false;
241 }
242
243 this->bindProgramLocations(fProgramID);
244
245 GL_CALL(LinkProgram(fProgramID));
246
247 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
248 bool checkLinked = !fGpu->ctxInfo().isChromium();
249#ifdef SK_DEBUG
250 checkLinked = true;
251#endif
252 if (checkLinked) {
253 GrGLint linked = GR_GL_INIT_ZERO;
254 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
255 if (!linked) {
256 GrGLint infoLen = GR_GL_INIT_ZERO;
257 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
258 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
259 if (infoLen > 0) {
260 // retrieve length even though we don't need it to workaround
261 // bug in chrome cmd buffer param validation.
262 GrGLsizei length = GR_GL_INIT_ZERO;
263 GL_CALL(GetProgramInfoLog(fProgramID,
264 infoLen+1,
265 &length,
266 (char*)log.get()));
267 GrPrintf((char*)log.get());
268 }
269 SkDEBUGFAIL("Error linking program");
270 GL_CALL(DeleteProgram(fProgramID));
271 fProgramID = 0;
272 return false;
273 }
274 }
275
276 this->resolveProgramLocations(fProgramID);
277
278 for (int i = 0; i < shadersToDelete.count(); ++i) {
279 GL_CALL(DeleteShader(shadersToDelete[i]));
280 }
281
282 return true;
283}
284
285bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId,
286 SkTDArray<GrGLuint>* shaderIds) const {
287 return fFS.compileAndAttachShaders(programId, shaderIds);
288}
289
290void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
291 fFS.bindProgramLocations(programId);
292
293 // skbug.com/2056
294 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
295 if (usingBindUniform) {
296 int count = fUniforms.count();
297 for (int i = 0; i < count; ++i) {
298 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str()));
299 fUniforms[i].fLocation = i;
300 }
301 }
302}
303
304void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
305 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
306 if (!usingBindUniform) {
307 int count = fUniforms.count();
308 for (int i = 0; i < count; ++i) {
309 GrGLint location;
310 GL_CALL_RET(location,
311 GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
312 fUniforms[i].fLocation = location;
313 }
314 }
kkinnunenec56e452014-08-25 22:21:16 -0700315
316 int count = fSeparableVaryingInfos.count();
317 for (int i = 0; i < count; ++i) {
318 GrGLint location;
319 GL_CALL_RET(location,
320 GetProgramResourceLocation(programId,
321 GR_GL_FRAGMENT_INPUT,
322 fSeparableVaryingInfos[i].fVariable.c_str()));
323 fSeparableVaryingInfos[i].fLocation = location;
324 }
joshualitt30ba4362014-08-21 20:18:45 -0700325}
326
327const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
328 return fGpu->ctxInfo();
329}
330
331////////////////////////////////////////////////////////////////////////////////
332
333GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
334 const GrGLProgramDesc& desc)
335 : INHERITED(gpu, desc)
336 , fGS(this)
337 , fVS(this) {
338}
339
joshualittbd769d02014-09-04 08:56:46 -0700340void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color,
341 GrGLSLExpr4* coverage) {
joshualitt30ba4362014-08-21 20:18:45 -0700342 fVS.emitCodeBeforeEffects(color, coverage);
343}
344
joshualittbd769d02014-09-04 08:56:46 -0700345void GrGLFullProgramBuilder::emitGeometryProcessor(const GrEffectStage* geometryProcessor,
346 GrGLSLExpr4* coverage) {
bsalomon49f085d2014-09-05 13:34:00 -0700347 if (geometryProcessor) {
joshualittbd769d02014-09-04 08:56:46 -0700348 GrGLProgramDesc::EffectKeyProvider geometryProcessorKeyProvider(
349 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kGeometryProcessor_EffectType);
350 fGeometryProcessor.reset(this->createAndEmitEffect(
351 geometryProcessor,
352 geometryProcessorKeyProvider,
353 coverage));
354 }
355}
356
joshualitt30ba4362014-08-21 20:18:45 -0700357void GrGLFullProgramBuilder::emitCodeAfterEffects() {
358 fVS.emitCodeAfterEffects();
359}
360
361void GrGLFullProgramBuilder::addVarying(GrSLType type,
362 const char* name,
363 const char** vsOutName,
egdaniel6db91282014-09-02 08:02:38 -0700364 const char** fsInName,
365 GrGLShaderVar::Precision fsPrecision) {
joshualitt30ba4362014-08-21 20:18:45 -0700366 fVS.addVarying(type, name, vsOutName);
367
368 SkString* fsInputName = fVS.fOutputs.back().accessName();
369
370#if GR_GL_EXPERIMENTAL_GS
371 if (desc().getHeader().fExperimentalGS) {
372 // TODO let the caller use these names
373 fGS.addVarying(type, fsInputName->c_str(), NULL);
374 fsInputName = fGS.fOutputs.back().accessName();
375 }
376#endif
egdaniel6db91282014-09-02 08:02:38 -0700377 fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
joshualitt30ba4362014-08-21 20:18:45 -0700378}
379
kkinnunenec56e452014-08-25 22:21:16 -0700380GrGLFullProgramBuilder::VaryingHandle
381GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
382 const char* name,
383 const char** vsOutName,
384 const char** fsInName) {
385 addVarying(type, name, vsOutName, fsInName);
386 SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
387 varying.fVariable = fFS.fInputs.back();
388 return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
389}
390
391
joshualitt30ba4362014-08-21 20:18:45 -0700392GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
393 const GrEffectStage* effectStages[],
394 int effectCnt,
395 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
396 GrGLSLExpr4* inOutFSColor) {
397
398 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
399 this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
400 effectStages,
401 effectCnt,
402 keyProvider,
403 inOutFSColor);
404 return programEffectsBuilder.finish();
405}
406
joshualittbd769d02014-09-04 08:56:46 -0700407void GrGLFullProgramBuilder::createAndEmitEffect(GrGLProgramEffectsBuilder* programEffectsBuilder,
408 const GrEffectStage* effectStages,
409 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
410 GrGLSLExpr4* fsInOutColor) {
411 GrGLSLExpr4 inColor = *fsInOutColor;
412 GrGLSLExpr4 outColor;
413
bsalomon49f085d2014-09-05 13:34:00 -0700414 SkASSERT(effectStages && effectStages->getEffect());
joshualittbd769d02014-09-04 08:56:46 -0700415 const GrEffectStage& stage = *effectStages;
416
417 // Using scope to force ASR destructor to be triggered
418 {
419 CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
420
421 if (inColor.isZeros()) {
422 SkString inColorName;
423
424 // Effects have no way to communicate zeros, they treat an empty string as ones.
425 this->nameVariable(&inColorName, '\0', "input");
426 fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
427 inColor = inColorName;
428 }
429
430 // create var to hold stage result
431 SkString outColorName;
432 this->nameVariable(&outColorName, '\0', "output");
433 fFS.codeAppendf("vec4 %s;", outColorName.c_str());
434 outColor = outColorName;
435
436
437 programEffectsBuilder->emitEffect(stage,
438 keyProvider.get(0),
439 outColor.c_str(),
440 inColor.isOnes() ? NULL : inColor.c_str(),
441 fCodeStage.stageIndex());
442 }
443
444 *fsInOutColor = outColor;
445}
446
447GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffect(
448 const GrEffectStage* geometryProcessor,
449 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
450 GrGLSLExpr4* inOutFSColor) {
451
452 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, 1);
453 this->createAndEmitEffect(&programEffectsBuilder, geometryProcessor, keyProvider, inOutFSColor);
454 return programEffectsBuilder.finish();
455}
456
joshualitt30ba4362014-08-21 20:18:45 -0700457bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
458 SkTDArray<GrGLuint>* shaderIds) const {
459 return INHERITED::compileAndAttachShaders(programId, shaderIds)
460 && fVS.compileAndAttachShaders(programId, shaderIds)
461#if GR_GL_EXPERIMENTAL_GS
462 && (!desc().getHeader().fExperimentalGS
463 || fGS.compileAndAttachShaders(programId, shaderIds))
464#endif
465 ;
466}
467
468void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
469 fVS.bindProgramLocations(programId);
470 INHERITED::bindProgramLocations(programId);
471}
472
473////////////////////////////////////////////////////////////////////////////////
474
475GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
476 const GrGLProgramDesc& desc)
477 : INHERITED(gpu, desc) {
kkinnunenec56e452014-08-25 22:21:16 -0700478 SkASSERT(!desc.getHeader().fRequiresVertexShader);
joshualitt30ba4362014-08-21 20:18:45 -0700479 SkASSERT(gpu->glCaps().pathRenderingSupport());
480 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
481 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
482}
483
484int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
485 int firstFreeCoordSet = fTexCoordSetCnt;
486 fTexCoordSetCnt += count;
487 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
488 return firstFreeCoordSet;
489}
490
491GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(
492 const GrEffectStage* effectStages[], int effectCnt,
493 const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
494
495 GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
496 effectCnt);
497 this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
498 effectStages,
499 effectCnt,
500 keyProvider,
501 inOutFSColor);
502 return pathTexGenEffectsBuilder.finish();
503}