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