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