OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGLProgramBuilder.h" | |
9 #include "gl/GrGLGeometryProcessor.h" | |
10 #include "gl/GrGLProgram.h" | 8 #include "gl/GrGLProgram.h" |
11 #include "gl/GrGLSLPrettyPrint.h" | 9 #include "gl/GrGLSLPrettyPrint.h" |
12 #include "gl/GrGLUniformHandle.h" | 10 #include "gl/GrGLUniformHandle.h" |
| 11 #include "GrCoordTransform.h" |
13 #include "../GrGpuGL.h" | 12 #include "../GrGpuGL.h" |
14 #include "GrCoordTransform.h" | 13 #include "GrGLFragmentShaderBuilder.h" |
15 #include "GrGLLegacyNvprProgramBuilder.h" | |
16 #include "GrGLNvprProgramBuilder.h" | |
17 #include "GrGLProgramBuilder.h" | 14 #include "GrGLProgramBuilder.h" |
18 #include "GrTexture.h" | 15 #include "GrTexture.h" |
| 16 #include "GrGLVertexShaderBuilder.h" |
19 #include "SkRTConf.h" | 17 #include "SkRTConf.h" |
20 #include "SkTraceEvent.h" | 18 #include "SkTraceEvent.h" |
21 | 19 |
| 20 namespace { |
22 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 21 #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) | 22 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
24 | 23 |
| 24 // number of each input/output type in a single allocation block |
| 25 static const int kVarsPerBlock = 8; |
| 26 |
25 // ES2 FS only guarantees mediump and lowp support | 27 // ES2 FS only guarantees mediump and lowp support |
26 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
:kMedium_Precision; | 28 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
:kMedium_Precision; |
| 29 } |
| 30 |
| 31 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 32 |
| 33 bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor, |
| 34 const GrFragmentStage* colorStages[], |
| 35 const GrFragmentStage* 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 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) { |
| 55 inputColor = GrGLSLExpr4(1); |
| 56 } |
| 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); |
| 66 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { |
| 67 inputCoverage = GrGLSLExpr4(1); |
| 68 } |
| 69 |
| 70 // Subclasses drive effect emitting |
| 71 this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &
inputColor, |
| 72 &inputCoverage); |
| 73 |
| 74 fFS.emitCodeAfterEffects(inputColor, inputCoverage); |
| 75 |
| 76 if (!this->finish()) { |
| 77 return false; |
| 78 } |
| 79 |
| 80 return true; |
| 81 } |
27 | 82 |
28 ////////////////////////////////////////////////////////////////////////////// | 83 ////////////////////////////////////////////////////////////////////////////// |
29 | 84 |
30 const int GrGLProgramBuilder::kVarsPerBlock = 8; | |
31 | |
32 GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, | |
33 const GrGLProgramDesc& desc, | |
34 GrGpu::DrawType drawType, | |
35 const GrGeometryStage* geometryPr
ocessor, | |
36 const GrFragmentStage* colorStage
s[], | |
37 const GrFragmentStage* coverageSt
ages[], | |
38 GrGpuGL* gpu) { | |
39 // create a builder. This will be handed off to effects so they can use it
to add | |
40 // uniforms, varyings, textures, etc | |
41 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc, | |
42 optState, | |
43 drawType, | |
44 SkToBool(geom
etryProcessor), | |
45 gpu)); | |
46 | |
47 GrGLProgramBuilder* pb = builder.get(); | |
48 const GrGLProgramDesc::KeyHeader& header = pb->header(); | |
49 | |
50 // emit code to read the dst copy texture, if necessary | |
51 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey | |
52 && !gpu->glCaps().fbFetchSupport()) { | |
53 pb->fFS.emitCodeToReadDstTexture(); | |
54 } | |
55 | |
56 // get the initial color and coverage to feed into the first effect in each
effect chain | |
57 GrGLSLExpr4 inputColor, inputCoverage; | |
58 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); | |
59 | |
60 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES)
, then we may have | |
61 // to setup a few more things like builtin vertex attributes | |
62 bool hasVertexShader = !header.fUseFragShaderOnly; | |
63 if (hasVertexShader) { | |
64 pb->fVS.setupLocalCoords(); | |
65 pb->fVS.transformGLToSkiaCoords(); | |
66 if (header.fEmitsPointSize) { | |
67 pb->fVS.codeAppend("gl_PointSize = 1.0;"); | |
68 } | |
69 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { | |
70 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); | |
71 } | |
72 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { | |
73 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); | |
74 } | |
75 } | |
76 | |
77 pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages,
&inputColor, | |
78 &inputCoverage); | |
79 | |
80 if (hasVertexShader) { | |
81 pb->fVS.transformSkiaToGLCoords(); | |
82 } | |
83 | |
84 // write the secondary color output if necessary | |
85 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType
) { | |
86 pb->fFS.enableSecondaryOutput(inputColor, inputCoverage); | |
87 } | |
88 | |
89 pb->fFS.combineColorAndCoverage(inputColor, inputCoverage); | |
90 | |
91 return pb->finalize(); | |
92 } | |
93 | |
94 GrGLProgramBuilder* | |
95 GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc, | |
96 const GrOptDrawState& optState, | |
97 GrGpu::DrawType drawType, | |
98 bool hasGeometryProcessor, | |
99 GrGpuGL* gpu) { | |
100 if (desc.getHeader().fUseFragShaderOnly) { | |
101 SkASSERT(gpu->glCaps().pathRenderingSupport()); | |
102 SkASSERT(gpu->glPathRendering()->texturingMode() == | |
103 GrGLPathRendering::FixedFunction_TexturingMode); | |
104 SkASSERT(!hasGeometryProcessor); | |
105 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc)); | |
106 } else if (GrGpu::IsPathRenderingDrawType(drawType)) { | |
107 SkASSERT(gpu->glCaps().pathRenderingSupport()); | |
108 SkASSERT(gpu->glPathRendering()->texturingMode() == | |
109 GrGLPathRendering::SeparableShaders_TexturingMode); | |
110 SkASSERT(!hasGeometryProcessor); | |
111 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc)); | |
112 } else { | |
113 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc)); | |
114 } | |
115 } | |
116 | |
117 ///////////////////////////////////////////////////////////////////////////// | |
118 | |
119 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optSt
ate, | 85 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optSt
ate, |
120 const GrGLProgramDesc& desc) | 86 const GrGLProgramDesc& desc) |
121 : fVS(this) | 87 : fEffectEmitter(NULL) |
122 , fGS(this) | 88 , fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly)) |
| 89 , fTexCoordSetCnt(0) |
| 90 , fProgramID(0) |
123 , fFS(this, desc) | 91 , fFS(this, desc) |
124 , fOutOfStage(true) | 92 , fSeparableVaryingInfos(kVarsPerBlock) |
125 , fStageIndex(-1) | 93 , fGrProcessorEmitter(this) |
126 , fOptState(optState) | 94 , fOptState(optState) |
127 , fDesc(desc) | 95 , fDesc(desc) |
128 , fGpu(gpu) | 96 , fGpu(gpu) |
129 , fUniforms(kVarsPerBlock) { | 97 , fUniforms(kVarsPerBlock) { |
130 } | 98 } |
131 | 99 |
132 void GrGLProgramBuilder::addVarying(GrSLType type, | |
133 const char* name, | |
134 const char** vsOutName, | |
135 const char** fsInName, | |
136 GrGLShaderVar::Precision fsPrecision) { | |
137 SkString* fsInputName = fVS.addVarying(type, name, vsOutName); | |
138 fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision); | |
139 } | |
140 | |
141 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { | 100 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { |
142 if ('\0' == prefix) { | 101 if ('\0' == prefix) { |
143 *out = name; | 102 *out = name; |
144 } else { | 103 } else { |
145 out->printf("%c%s", prefix, name); | 104 out->printf("%c%s", prefix, name); |
146 } | 105 } |
147 if (!fOutOfStage) { | 106 if (fCodeStage.inStageCode()) { |
148 if (out->endsWith('_')) { | 107 if (out->endsWith('_')) { |
149 // Names containing "__" are reserved. | 108 // Names containing "__" are reserved. |
150 out->append("x"); | 109 out->append("x"); |
151 } | 110 } |
152 out->appendf("_Stage%d", fStageIndex); | 111 out->appendf("_Stage%d", fCodeStage.stageIndex()); |
153 } | 112 } |
154 } | 113 } |
155 | 114 |
156 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
_t visibility, | 115 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
_t visibility, |
157 GrSLTy
pe type, | 116 GrSLTy
pe type, |
158 const
char* name, | 117 const
char* name, |
159 int co
unt, | 118 int co
unt, |
160 const
char** outName) { | 119 const
char** outName) { |
161 SkASSERT(name && strlen(name)); | 120 SkASSERT(name && strlen(name)); |
162 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); | 121 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); |
(...skipping 14 matching lines...) Expand all Loading... |
177 // the fragment and vertex precisions must match | 136 // the fragment and vertex precisions must match |
178 uni.fVariable.setPrecision(kDefaultFragmentPrecision); | 137 uni.fVariable.setPrecision(kDefaultFragmentPrecision); |
179 } | 138 } |
180 | 139 |
181 if (outName) { | 140 if (outName) { |
182 *outName = uni.fVariable.c_str(); | 141 *outName = uni.fVariable.c_str(); |
183 } | 142 } |
184 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor
ms.count() - 1); | 143 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor
ms.count() - 1); |
185 } | 144 } |
186 | 145 |
| 146 void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const
{ |
| 147 for (int i = 0; i < vars.count(); ++i) { |
| 148 vars[i].appendDecl(this->ctxInfo(), out); |
| 149 out->append(";\n"); |
| 150 } |
| 151 } |
| 152 |
187 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, | 153 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, |
188 SkString* out) const { | 154 SkString* out) const { |
189 for (int i = 0; i < fUniforms.count(); ++i) { | 155 for (int i = 0; i < fUniforms.count(); ++i) { |
190 if (fUniforms[i].fVisibility & visibility) { | 156 if (fUniforms[i].fVisibility & visibility) { |
191 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); | 157 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); |
192 out->append(";\n"); | 158 out->append(";\n"); |
193 } | 159 } |
194 } | 160 } |
195 } | 161 } |
196 | 162 |
197 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { | 163 void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStage
s[], |
198 return fGpu->ctxInfo(); | 164 int effectCnt, |
199 } | 165 const GrGLProgramDesc::EffectKeyPr
ovider& keyProvider, |
200 | 166 GrGLSLExpr4* fsInOutColor) { |
201 void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input
Color, | |
202 GrGLSLExpr4* input
Coverage) { | |
203 const GrGLProgramDesc::KeyHeader& header = this->header(); | |
204 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { | |
205 const char* name; | |
206 fUniformHandles.fColorUni = | |
207 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
208 kVec4f_GrSLType, | |
209 "Color", | |
210 &name); | |
211 *inputColor = GrGLSLExpr4(name); | |
212 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) { | |
213 *inputColor = GrGLSLExpr4(1); | |
214 } | |
215 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { | |
216 const char* name; | |
217 fUniformHandles.fCoverageUni = | |
218 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
219 kVec4f_GrSLType, | |
220 "Coverage", | |
221 &name); | |
222 *inputCoverage = GrGLSLExpr4(name); | |
223 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { | |
224 *inputCoverage = GrGLSLExpr4(1); | |
225 } | |
226 } | |
227 | |
228 void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometry
Processor, | |
229 const GrFragmentStage* colorSta
ges[], | |
230 const GrFragmentStage* coverage
Stages[], | |
231 GrGLSLExpr4* inputColor, | |
232 GrGLSLExpr4* inputCoverage) { | |
233 bool useLocalCoords = fVS.hasExplicitLocalCoords(); | |
234 | |
235 EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectT
ype); | |
236 int numColorEffects = fDesc.numColorEffects(); | |
237 GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorE
ffects, | |
238 useLocalC
oords)); | |
239 this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects,
colorKeyProvider, | |
240 inputColor, ip); | |
241 fColorEffects.reset(ip); | |
242 | |
243 if (geometryProcessor) { | |
244 fVS.emitAttributes(*geometryProcessor->getProcessor()); | |
245 EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProc
essor_EffectType); | |
246 ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords)); | |
247 this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gp
KeyProvider, | |
248 inputCoverage, ip); | |
249 fGeometryProcessor.reset(ip); | |
250 } | |
251 | |
252 EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_E
ffectType); | |
253 int numCoverageEffects = fDesc.numCoverageEffects(); | |
254 ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords
)); | |
255 this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEf
fects, | |
256 coverageKeyProvider, inputCov
erage, ip); | |
257 fCoverageEffects.reset(ip); | |
258 } | |
259 | |
260 template <class ProcessorStage> | |
261 void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processSt
ages[], | |
262 int effectCnt, | |
263 const EffectKeyProvider& keyPro
vider, | |
264 GrGLSLExpr4* fsInOutColor, | |
265 GrGLInstalledProcessors* instal
ledProcessors) { | |
266 bool effectEmitted = false; | 167 bool effectEmitted = false; |
267 | 168 |
268 GrGLSLExpr4 inColor = *fsInOutColor; | 169 GrGLSLExpr4 inColor = *fsInOutColor; |
269 GrGLSLExpr4 outColor; | 170 GrGLSLExpr4 outColor; |
270 | 171 |
271 for (int e = 0; e < effectCnt; ++e) { | 172 for (int e = 0; e < effectCnt; ++e) { |
272 // Program builders have a bit of state we need to clear with each effec
t | 173 fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor()); |
273 this->reset(); | 174 fEffectEmitter = &fGrProcessorEmitter; |
274 const ProcessorStage& stage = *processStages[e]; | 175 // calls into the subclass to emit the actual effect into the program ef
fect object |
275 SkASSERT(stage.getProcessor()); | 176 this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor); |
276 | |
277 if (inColor.isZeros()) { | |
278 SkString inColorName; | |
279 | |
280 // Effects have no way to communicate zeros, they treat an empty str
ing as ones. | |
281 this->nameVariable(&inColorName, '\0', "input"); | |
282 fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str(
)); | |
283 inColor = inColorName; | |
284 } | |
285 | |
286 // create var to hold stage result | |
287 SkString outColorName; | |
288 this->nameVariable(&outColorName, '\0', "output"); | |
289 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); | |
290 outColor = outColorName; | |
291 | |
292 SkASSERT(installedProcessors); | |
293 const typename ProcessorStage::Processor& processor = *stage.getProcesso
r(); | |
294 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTrans
forms()); | |
295 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextur
es()); | |
296 | |
297 this->emitTransforms(stage, &coords, installedProcessors); | |
298 this->emitSamplers(processor, &samplers, installedProcessors); | |
299 | |
300 typename ProcessorStage::GLProcessor* glEffect = | |
301 processor.getFactory().createGLInstance(processor); | |
302 installedProcessors->addEffect(glEffect); | |
303 | |
304 // Enclose custom code in a block to avoid namespace conflicts | |
305 SkString openBrace; | |
306 openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name()); | |
307 fFS.codeAppend(openBrace.c_str()); | |
308 | |
309 glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str()
, inColor.c_str(), | |
310 coords, samplers); | |
311 | |
312 // We have to check that effects and the code they emit are consistent,
ie if an effect | |
313 // asks for dst color, then the emit code needs to follow suit | |
314 verify(processor); | |
315 fFS.codeAppend("}"); | |
316 | |
317 inColor = outColor; | |
318 effectEmitted = true; | 177 effectEmitted = true; |
319 } | 178 } |
320 | 179 |
321 if (effectEmitted) { | 180 if (effectEmitted) { |
322 *fsInOutColor = outColor; | 181 *fsInOutColor = outColor; |
323 } | 182 } |
324 } | 183 } |
325 | 184 |
326 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { | 185 void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage, |
327 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); | 186 int effectIndex, |
| 187 const GrGLProgramDesc::EffectKeyProvider& ke
yProvider, |
| 188 GrGLSLExpr4* inColor, |
| 189 GrGLSLExpr4* outColor) { |
| 190 SkASSERT(effectStage.getProcessor()); |
| 191 CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage); |
| 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 this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(
), |
| 209 inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.sta
geIndex()); |
| 210 |
| 211 *inColor = *outColor; |
328 } | 212 } |
329 | 213 |
330 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { | 214 void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect, |
331 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); | 215 GrGLProcessor::TextureSamplerArray* outSam
plers) { |
332 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor()); | 216 SkTArray<GrGLProgramEffects::Sampler, true>& samplers = |
333 } | 217 this->getProgramEffects()->addSamplers(); |
334 | 218 int numTextures = effect.numTextures(); |
335 void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage, | |
336 GrGLProcessor::TransformedCoordsArray* o
utCoords, | |
337 GrGLInstalledProcessors* installedProces
sors) { | |
338 SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = | |
339 installedProcessors->addTransforms(); | |
340 const GrProcessor* effect = effectStage.getProcessor(); | |
341 int numTransforms = effect->numTransforms(); | |
342 transforms.push_back_n(numTransforms); | |
343 | |
344 for (int t = 0; t < numTransforms; t++) { | |
345 const char* uniName = "StageMatrix"; | |
346 GrSLType varyingType = | |
347 effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalC
oords()) ? | |
348 kVec3f_GrSLType : | |
349 kVec2f_GrSLType; | |
350 | |
351 SkString suffixedUniName; | |
352 if (0 != t) { | |
353 suffixedUniName.append(uniName); | |
354 suffixedUniName.appendf("_%i", t); | |
355 uniName = suffixedUniName.c_str(); | |
356 } | |
357 transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Vis
ibility, | |
358 kMat33f_GrSLType, | |
359 uniName, | |
360 &uniName).toShaderBuilderIndex(
); | |
361 | |
362 const char* varyingName = "MatrixCoord"; | |
363 SkString suffixedVaryingName; | |
364 if (0 != t) { | |
365 suffixedVaryingName.append(varyingName); | |
366 suffixedVaryingName.appendf("_%i", t); | |
367 varyingName = suffixedVaryingName.c_str(); | |
368 } | |
369 const char* vsVaryingName; | |
370 const char* fsVaryingName; | |
371 this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingNam
e); | |
372 | |
373 const GrGLShaderVar& coords = | |
374 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords()
? | |
375 fVS.positionAttribute() : | |
376 fVS.localCoordsAttribute(); | |
377 | |
378 // varying = matrix * coords (logically) | |
379 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); | |
380 if (kVec2f_GrSLType == varyingType) { | |
381 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;", | |
382 vsVaryingName, uniName, coords.c_str()); | |
383 } else { | |
384 fVS.codeAppendf("%s = %s * vec3(%s, 1);", | |
385 vsVaryingName, uniName, coords.c_str()); | |
386 } | |
387 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, | |
388 (SkString(fsVaryingName), varyingType)); | |
389 } | |
390 } | |
391 | |
392 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | |
393 GrGLProcessor::TextureSamplerArray* outSam
plers, | |
394 GrGLInstalledProcessors* installedProcesso
rs) { | |
395 SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProces
sors->addSamplers(); | |
396 int numTextures = processor.numTextures(); | |
397 samplers.push_back_n(numTextures); | 219 samplers.push_back_n(numTextures); |
398 SkString name; | 220 SkString name; |
399 for (int t = 0; t < numTextures; ++t) { | 221 for (int t = 0; t < numTextures; ++t) { |
400 name.printf("Sampler%d", t); | 222 name.printf("Sampler%d", t); |
401 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Vi
sibility, | 223 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Vi
sibility, |
402 kSampler2D_GrSLType, | 224 kSampler2D_GrSLType, |
403 name.c_str()); | 225 name.c_str()); |
404 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, | 226 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, |
405 (samplers[t].fUniform, processor.textureAccess(t)
)); | 227 (samplers[t].fUniform, effect.textureAccess(t))); |
406 } | 228 } |
407 } | 229 } |
408 | 230 |
409 GrGLProgram* GrGLProgramBuilder::finalize() { | 231 bool GrGLProgramBuilder::finish() { |
410 // verify we can get a program id | 232 SkASSERT(0 == fProgramID); |
411 GrGLuint programID; | 233 GL_CALL_RET(fProgramID, CreateProgram()); |
412 GL_CALL_RET(programID, CreateProgram()); | 234 if (!fProgramID) { |
413 if (0 == programID) { | 235 return false; |
414 return NULL; | |
415 } | 236 } |
416 | 237 |
417 // compile shaders and bind attributes / uniforms | |
418 SkTDArray<GrGLuint> shadersToDelete; | 238 SkTDArray<GrGLuint> shadersToDelete; |
419 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { | 239 |
420 this->cleanupProgram(programID, shadersToDelete); | 240 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { |
421 return NULL; | 241 GL_CALL(DeleteProgram(fProgramID)); |
| 242 return false; |
422 } | 243 } |
423 if (!this->header().fUseFragShaderOnly) { | 244 |
424 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { | 245 this->bindProgramLocations(fProgramID); |
425 this->cleanupProgram(programID, shadersToDelete); | 246 |
426 return NULL; | 247 GL_CALL(LinkProgram(fProgramID)); |
427 } | |
428 fVS.bindVertexAttributes(programID); | |
429 } | |
430 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | |
431 if (usingBindUniform) { | |
432 this->bindUniformLocations(programID); | |
433 } | |
434 fFS.bindFragmentShaderLocations(programID); | |
435 GL_CALL(LinkProgram(programID)); | |
436 | 248 |
437 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. | 249 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. |
438 bool checkLinked = !fGpu->ctxInfo().isChromium(); | 250 bool checkLinked = !fGpu->ctxInfo().isChromium(); |
439 #ifdef SK_DEBUG | 251 #ifdef SK_DEBUG |
440 checkLinked = true; | 252 checkLinked = true; |
441 #endif | 253 #endif |
442 if (checkLinked) { | 254 if (checkLinked) { |
443 checkLinkStatus(programID); | 255 GrGLint linked = GR_GL_INIT_ZERO; |
444 } | 256 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); |
445 if (!usingBindUniform) { | 257 if (!linked) { |
446 this->resolveUniformLocations(programID); | 258 GrGLint infoLen = GR_GL_INIT_ZERO; |
| 259 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
| 260 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debug
ger |
| 261 if (infoLen > 0) { |
| 262 // retrieve length even though we don't need it to workaround |
| 263 // bug in chrome cmd buffer param validation. |
| 264 GrGLsizei length = GR_GL_INIT_ZERO; |
| 265 GL_CALL(GetProgramInfoLog(fProgramID, |
| 266 infoLen+1, |
| 267 &length, |
| 268 (char*)log.get())); |
| 269 GrPrintf((char*)log.get()); |
| 270 } |
| 271 SkDEBUGFAIL("Error linking program"); |
| 272 GL_CALL(DeleteProgram(fProgramID)); |
| 273 fProgramID = 0; |
| 274 return false; |
| 275 } |
447 } | 276 } |
448 | 277 |
449 this->cleanupShaders(shadersToDelete); | 278 this->resolveProgramLocations(fProgramID); |
450 | 279 |
451 return this->createProgram(programID); | 280 for (int i = 0; i < shadersToDelete.count(); ++i) { |
| 281 GL_CALL(DeleteShader(shadersToDelete[i])); |
| 282 } |
| 283 |
| 284 return true; |
452 } | 285 } |
453 | 286 |
454 void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) { | 287 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, |
455 int count = fUniforms.count(); | 288 SkTDArray<GrGLuint>* shaderIds)
const { |
456 for (int i = 0; i < count; ++i) { | 289 return fFS.compileAndAttachShaders(programId, shaderIds); |
457 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()
)); | 290 } |
458 fUniforms[i].fLocation = i; | 291 |
| 292 void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) { |
| 293 fFS.bindProgramLocations(programId); |
| 294 |
| 295 // skbug.com/2056 |
| 296 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; |
| 297 if (usingBindUniform) { |
| 298 int count = fUniforms.count(); |
| 299 for (int i = 0; i < count; ++i) { |
| 300 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_s
tr())); |
| 301 fUniforms[i].fLocation = i; |
| 302 } |
459 } | 303 } |
460 } | 304 } |
461 | 305 |
462 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { | 306 void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { |
463 GrGLint linked = GR_GL_INIT_ZERO; | 307 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; |
464 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); | 308 if (!usingBindUniform) { |
465 if (!linked) { | 309 int count = fUniforms.count(); |
466 GrGLint infoLen = GR_GL_INIT_ZERO; | 310 for (int i = 0; i < count; ++i) { |
467 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); | 311 GrGLint location; |
468 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger | 312 GL_CALL_RET(location, |
469 if (infoLen > 0) { | 313 GetUniformLocation(programId, fUniforms[i].fVariable.c_s
tr())); |
470 // retrieve length even though we don't need it to workaround | 314 fUniforms[i].fLocation = location; |
471 // bug in chrome cmd buffer param validation. | |
472 GrGLsizei length = GR_GL_INIT_ZERO; | |
473 GL_CALL(GetProgramInfoLog(programID, | |
474 infoLen+1, | |
475 &length, | |
476 (char*)log.get())); | |
477 GrPrintf((char*)log.get()); | |
478 } | 315 } |
479 SkDEBUGFAIL("Error linking program"); | |
480 GL_CALL(DeleteProgram(programID)); | |
481 programID = 0; | |
482 } | 316 } |
483 return SkToBool(linked); | |
484 } | |
485 | 317 |
486 void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) { | 318 int count = fSeparableVaryingInfos.count(); |
487 int count = fUniforms.count(); | |
488 for (int i = 0; i < count; ++i) { | 319 for (int i = 0; i < count; ++i) { |
489 GrGLint location; | 320 GrGLint location; |
490 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariab
le.c_str())); | 321 GL_CALL_RET(location, |
491 fUniforms[i].fLocation = location; | 322 GetProgramResourceLocation(programId, |
| 323 GR_GL_FRAGMENT_INPUT, |
| 324 fSeparableVaryingInfos[i].fVariab
le.c_str())); |
| 325 fSeparableVaryingInfos[i].fLocation = location; |
492 } | 326 } |
493 } | 327 } |
494 | 328 |
495 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL
uint>& shaderIDs) { | 329 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { |
496 GL_CALL(DeleteProgram(programID)); | 330 return fGpu->ctxInfo(); |
497 cleanupShaders(shaderIDs); | |
498 } | 331 } |
499 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { | |
500 for (int i = 0; i < shaderIDs.count(); ++i) { | |
501 GL_CALL(DeleteShader(shaderIDs[i])); | |
502 } | |
503 } | |
504 | |
505 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { | |
506 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUn
iforms, | |
507 fGeometryProcessor, fColorEffects, fCoverage
Effects)); | |
508 } | |
509 | |
510 //////////////////////////////////////////////////////////////////////////////// | |
511 | |
512 GrGLInstalledProcessors::~GrGLInstalledProcessors() { | |
513 int numEffects = fGLProcessors.count(); | |
514 for (int e = 0; e < numEffects; ++e) { | |
515 SkDELETE(fGLProcessors[e]); | |
516 } | |
517 } | |
OLD | NEW |