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" | 8 #include "GrGLProgramBuilder.h" |
9 | 9 |
10 #include "GrAutoLocaleSetter.h" | 10 #include "GrAutoLocaleSetter.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 // uniforms, varyings, textures, etc | 35 // uniforms, varyings, textures, etc |
36 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args)) ; | 36 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args)) ; |
37 | 37 |
38 GrGLProgramBuilder* pb = builder.get(); | 38 GrGLProgramBuilder* pb = builder.get(); |
39 | 39 |
40 // TODO: Once all stages can handle taking a float or vec4 and correctly han dling them we can | 40 // TODO: Once all stages can handle taking a float or vec4 and correctly han dling them we can |
41 // seed correctly here | 41 // seed correctly here |
42 GrGLSLExpr4 inputColor; | 42 GrGLSLExpr4 inputColor; |
43 GrGLSLExpr4 inputCoverage; | 43 GrGLSLExpr4 inputCoverage; |
44 | 44 |
45 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { | 45 if (!pb->emitAndInstallProcs(&inputColor, |
46 &inputCoverage, | |
47 gpu->glCaps().maxFragmentTextureUnits())) { | |
46 return nullptr; | 48 return nullptr; |
47 } | 49 } |
48 | 50 |
49 return pb->finalize(); | 51 return pb->finalize(); |
50 } | 52 } |
51 | 53 |
52 ///////////////////////////////////////////////////////////////////////////// | 54 ///////////////////////////////////////////////////////////////////////////// |
53 | 55 |
54 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | 56 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
55 : INHERITED(args) | 57 : INHERITED(args) |
56 , fGeometryProcessor(nullptr) | |
57 , fXferProcessor(nullptr) | |
58 , fGpu(gpu) | 58 , fGpu(gpu) |
59 , fSamplerUniforms(4) | 59 , fSamplerUniforms(4) |
60 , fVaryingHandler(this) | 60 , fVaryingHandler(this) |
61 , fUniformHandler(this) { | 61 , fUniformHandler(this) { |
62 } | 62 } |
63 | 63 |
64 const GrCaps* GrGLProgramBuilder::caps() const { | |
65 return fGpu->caps(); | |
66 } | |
64 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { | 67 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { |
bsalomon
2016/01/13 17:49:19
\n
egdaniel
2016/01/13 19:59:49
Done.
| |
65 return this->fGpu->ctxInfo().caps()->glslCaps(); | 68 return fGpu->ctxInfo().caps()->glslCaps(); |
66 } | |
67 | |
68 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr 4* inputCoverage) { | |
69 // First we loop over all of the installed processors and collect coord tran sforms. These will | |
70 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function | |
71 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); | |
72 int totalTextures = primProc.numTextures(); | |
73 const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); | |
74 | |
75 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { | |
76 const GrFragmentProcessor& processor = this->pipeline().getFragmentProce ssor(i); | |
77 | |
78 if (!primProc.hasTransformedLocalCoords()) { | |
79 SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransfor ms.push_back(); | |
80 processor.gatherCoordTransforms(&procCoords); | |
81 } | |
82 | |
83 totalTextures += processor.numTextures(); | |
84 if (totalTextures >= maxTextureUnits) { | |
85 GrCapsDebugf(fGpu->caps(), "Program would use too many texture units \n"); | |
86 return false; | |
87 } | |
88 } | |
89 | |
90 this->emitAndInstallProc(primProc, inputColor, inputCoverage); | |
91 | |
92 fFragmentProcessors.reset(new GrGLInstalledFragProcs); | |
93 int numProcs = this->pipeline().numFragmentProcessors(); | |
94 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors (), inputColor); | |
95 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, | |
96 inputCoverage); | |
97 this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColo r, *inputCoverage, | |
98 this->pipeline().ignoresCoverage()); | |
99 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOu tput()); | |
100 return true; | |
101 } | |
102 | |
103 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, | |
104 int numProcs, | |
105 GrGLSLExpr4* inOut) { | |
106 for (int i = procOffset; i < numProcs; ++i) { | |
107 GrGLSLExpr4 output; | |
108 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i) ; | |
109 this->emitAndInstallProc(fp, i, *inOut, &output); | |
110 *inOut = output; | |
111 } | |
112 } | |
113 | |
114 void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseNam e) { | |
115 // create var to hold stage result. If we already have a valid output name, just use that | |
116 // otherwise create a new mangled one. This name is only valid if we are re ordering stages | |
117 // and have to tell stage exactly where to put its output. | |
118 SkString outName; | |
119 if (output->isValid()) { | |
120 outName = output->c_str(); | |
121 } else { | |
122 this->nameVariable(&outName, '\0', baseName); | |
123 } | |
124 fFS.codeAppendf("vec4 %s;", outName.c_str()); | |
125 *output = outName; | |
126 } | |
127 | |
128 // TODO Processors cannot output zeros because an empty string is all 1s | |
129 // the fix is to allow effects to take the GrGLSLExpr4 directly | |
130 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, | |
131 int index, | |
132 const GrGLSLExpr4& input, | |
133 GrGLSLExpr4* output) { | |
134 // Program builders have a bit of state we need to clear with each effect | |
135 AutoStageAdvance adv(this); | |
136 this->nameExpression(output, "output"); | |
137 | |
138 // Enclose custom code in a block to avoid namespace conflicts | |
139 SkString openBrace; | |
140 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); | |
141 fFS.codeAppend(openBrace.c_str()); | |
142 | |
143 this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullpt r : input.c_str()); | |
144 | |
145 fFS.codeAppend("}"); | |
146 } | |
147 | |
148 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, | |
149 GrGLSLExpr4* outputColor, | |
150 GrGLSLExpr4* outputCoverage) { | |
151 // Program builders have a bit of state we need to clear with each effect | |
152 AutoStageAdvance adv(this); | |
153 this->nameExpression(outputColor, "outputColor"); | |
154 this->nameExpression(outputCoverage, "outputCoverage"); | |
155 | |
156 // Enclose custom code in a block to avoid namespace conflicts | |
157 SkString openBrace; | |
158 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); | |
159 fFS.codeAppend(openBrace.c_str()); | |
160 fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); | |
161 | |
162 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str() ); | |
163 | |
164 fFS.codeAppend("}"); | |
165 } | |
166 | |
167 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, | |
168 int index, | |
169 const char* outColor, | |
170 const char* inColor) { | |
171 GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc; | |
172 | |
173 ifp->fGLProc.reset(fp.createGLSLInstance()); | |
174 | |
175 SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures()); | |
176 this->emitSamplers(fp, &samplers, ifp); | |
177 | |
178 GrGLSLFragmentProcessor::EmitArgs args(&fFS, | |
179 &fUniformHandler, | |
180 this->glslCaps(), | |
181 fp, | |
182 outColor, | |
183 inColor, | |
184 fOutCoords[index], | |
185 samplers); | |
186 ifp->fGLProc->emitCode(args); | |
187 | |
188 // We have to check that effects and the code they emit are consistent, ie i f an effect | |
189 // asks for dst color, then the emit code needs to follow suit | |
190 verify(fp); | |
191 fFragmentProcessors->fProcs.push_back(ifp); | |
192 } | |
193 | |
194 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, | |
195 const char* outColor, | |
196 const char* outCoverage) { | |
197 SkASSERT(!fGeometryProcessor); | |
198 fGeometryProcessor = new GrGLInstalledGeoProc; | |
199 | |
200 fGeometryProcessor->fGLProc.reset(gp.createGLSLInstance(*fGpu->glCaps().glsl Caps())); | |
201 | |
202 SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures()); | |
203 this->emitSamplers(gp, &samplers, fGeometryProcessor); | |
204 | |
205 GrGLSLGeometryProcessor::EmitArgs args(&fVS, | |
206 &fFS, | |
207 &fVaryingHandler, | |
208 &fUniformHandler, | |
209 this->glslCaps(), | |
210 gp, | |
211 outColor, | |
212 outCoverage, | |
213 samplers, | |
214 fCoordTransforms, | |
215 &fOutCoords); | |
216 fGeometryProcessor->fGLProc->emitCode(args); | |
217 | |
218 // We have to check that effects and the code they emit are consistent, ie i f an effect | |
219 // asks for dst color, then the emit code needs to follow suit | |
220 verify(gp); | |
221 } | |
222 | |
223 void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp, | |
224 const GrGLSLExpr4& colorIn, | |
225 const GrGLSLExpr4& coverageIn, | |
226 bool ignoresCoverage) { | |
227 // Program builders have a bit of state we need to clear with each effect | |
228 AutoStageAdvance adv(this); | |
229 | |
230 SkASSERT(!fXferProcessor); | |
231 fXferProcessor = new GrGLInstalledXferProc; | |
232 | |
233 fXferProcessor->fGLProc.reset(xp.createGLSLInstance()); | |
234 | |
235 // Enable dual source secondary output if we have one | |
236 if (xp.hasSecondaryOutput()) { | |
237 fFS.enableSecondaryOutput(); | |
238 } | |
239 | |
240 if (this->glslCaps()->mustDeclareFragmentShaderOutput()) { | |
241 fFS.enableCustomOutput(); | |
242 } | |
243 | |
244 SkString openBrace; | |
245 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); | |
246 fFS.codeAppend(openBrace.c_str()); | |
247 | |
248 SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); | |
249 this->emitSamplers(xp, &samplers, fXferProcessor); | |
250 | |
251 GrGLSLXferProcessor::EmitArgs args(&fFS, | |
252 &fUniformHandler, | |
253 this->glslCaps(), | |
254 xp, colorIn.c_str(), | |
255 ignoresCoverage ? nullptr : coverageIn.c_ str(), | |
256 fFS.getPrimaryColorOutputName(), | |
257 fFS.getSecondaryColorOutputName(), | |
258 samplers); | |
259 fXferProcessor->fGLProc->emitCode(args); | |
260 | |
261 // We have to check that effects and the code they emit are consistent, ie i f an effect | |
262 // asks for dst color, then the emit code needs to follow suit | |
263 verify(xp); | |
264 fFS.codeAppend("}"); | |
265 } | |
266 | |
267 void GrGLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { | |
268 // Swizzle the fragment shader outputs if necessary. | |
269 GrSwizzle swizzle; | |
270 swizzle.setFromKey(this->desc().header().fOutputSwizzle); | |
271 if (swizzle != GrSwizzle::RGBA()) { | |
272 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), | |
273 fFS.getPrimaryColorOutputName(), | |
274 swizzle.c_str()); | |
275 if (hasSecondaryOutput) { | |
276 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), | |
277 fFS.getSecondaryColorOutputName(), | |
278 swizzle.c_str()); | |
279 } | |
280 } | |
281 } | |
282 | |
283 void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { | |
284 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); | |
285 } | |
286 | |
287 void GrGLProgramBuilder::verify(const GrXferProcessor& xp) { | |
288 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); | |
289 } | |
290 | |
291 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { | |
292 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); | |
293 } | 69 } |
294 | 70 |
295 static GrSLType get_sampler_type(const GrTextureAccess& access) { | 71 static GrSLType get_sampler_type(const GrTextureAccess& access) { |
296 GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture()); | 72 GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture()); |
297 if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) { | 73 if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) { |
298 return kSamplerExternal_GrSLType; | 74 return kSamplerExternal_GrSLType; |
299 } else { | 75 } else { |
300 SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D); | 76 SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D); |
301 return kSampler2D_GrSLType; | 77 return kSampler2D_GrSLType; |
302 } | 78 } |
303 } | 79 } |
304 | 80 |
305 template <class Proc> | |
306 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | 81 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
307 GrGLSLTextureSampler::TextureSamplerArray* outSamplers, | 82 GrGLSLTextureSampler::TextureSamplerArra y* outSamplers) { |
bsalomon
2016/01/13 17:49:19
rm two spaces?
egdaniel
2016/01/13 19:59:49
Done.
| |
308 GrGLInstalledProc<Proc>* ip) { | |
309 SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();) | |
310 int numTextures = processor.numTextures(); | 83 int numTextures = processor.numTextures(); |
311 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextur es); | 84 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextur es); |
312 SkString name; | 85 SkString name; |
313 for (int t = 0; t < numTextures; ++t) { | 86 for (int t = 0; t < numTextures; ++t) { |
314 name.printf("Sampler%d", t); | 87 name.printf("Sampler%d", t); |
315 GrSLType samplerType = get_sampler_type(processor.textureAccess(t)); | 88 GrSLType samplerType = get_sampler_type(processor.textureAccess(t)); |
316 localSamplerUniforms[t] = | 89 localSamplerUniforms[t] = |
317 fUniformHandler.addUniform(GrGLSLUniformHandler::kFragment_Visibilit y, | 90 fUniformHandler.addUniform(GrGLSLUniformHandler::kFragment_Visibilit y, |
318 samplerType, kDefault_GrSLPrecision, | 91 samplerType, kDefault_GrSLPrecision, |
319 name.c_str()); | 92 name.c_str()); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
484 | 257 |
485 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { | 258 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
486 return new GrGLProgram(fGpu, | 259 return new GrGLProgram(fGpu, |
487 this->desc(), | 260 this->desc(), |
488 fUniformHandles, | 261 fUniformHandles, |
489 programID, | 262 programID, |
490 fUniformHandler.fUniforms, | 263 fUniformHandler.fUniforms, |
491 fVaryingHandler.fPathProcVaryingInfos, | 264 fVaryingHandler.fPathProcVaryingInfos, |
492 fGeometryProcessor, | 265 fGeometryProcessor, |
493 fXferProcessor, | 266 fXferProcessor, |
494 fFragmentProcessors.get(), | 267 fFragmentProcessors, |
495 &fSamplerUniforms); | 268 &fSamplerUniforms); |
496 } | 269 } |
497 | 270 |
498 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
499 | |
500 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | |
501 int numProcs = fProcs.count(); | |
502 for (int i = 0; i < numProcs; ++i) { | |
503 delete fProcs[i]; | |
504 } | |
505 } | |
OLD | NEW |