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 #include "gl/GrGLProgram.h" | 9 #include "gl/GrGLProgram.h" |
10 #include "gl/GrGLSLPrettyPrint.h" | 10 #include "gl/GrGLSLPrettyPrint.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 // get the initial color and coverage to feed into the first effect in each
effect chain | 50 // get the initial color and coverage to feed into the first effect in each
effect chain |
51 GrGLSLExpr4 inputColor; | 51 GrGLSLExpr4 inputColor; |
52 GrGLSLExpr1 inputCoverage; | 52 GrGLSLExpr1 inputCoverage; |
53 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); | 53 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); |
54 | 54 |
55 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES)
, then we may have | 55 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES)
, then we may have |
56 // to setup a few more things like builtin vertex attributes | 56 // to setup a few more things like builtin vertex attributes |
57 bool hasVertexShader = !(header.fUseNvpr && | 57 bool hasVertexShader = !(header.fUseNvpr && |
58 gpu->glPathRendering()->texturingMode() == | 58 gpu->glPathRendering()->texturingMode() == |
59 GrGLPathRendering::FixedFunction_TexturingMode); | 59 GrGLPathRendering::FixedFunction_TexturingMode); |
60 | |
61 if (hasVertexShader) { | 60 if (hasVertexShader) { |
62 pb->fVS.setupUniformViewMatrix(); | 61 pb->fVS.setupLocalCoords(); |
63 pb->fVS.setupPositionAndLocalCoords(); | 62 pb->fVS.transformGLToSkiaCoords(); |
64 | |
65 if (header.fEmitsPointSize) { | 63 if (header.fEmitsPointSize) { |
66 pb->fVS.codeAppend("gl_PointSize = 1.0;"); | 64 pb->fVS.codeAppend("gl_PointSize = 1.0;"); |
67 } | 65 } |
68 if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { | 66 if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { |
69 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); | 67 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); |
70 } | 68 } |
71 if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { | 69 if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { |
72 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); | 70 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); |
73 } | 71 } |
74 } | 72 } |
75 | 73 |
76 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can | 74 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can |
77 // remove this cast to a vec4. | 75 // remove this cast to a vec4. |
78 GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); | 76 GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); |
79 | 77 |
80 pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4); | 78 pb->emitAndInstallProcs(optState, &inputColor, &inputCoverageVec4); |
81 | 79 |
82 if (hasVertexShader) { | 80 if (hasVertexShader) { |
83 pb->fVS.transformToNormalizedDeviceSpace(); | 81 pb->fVS.transformSkiaToGLCoords(); |
84 } | 82 } |
85 | 83 |
86 // write the secondary color output if necessary | 84 // write the secondary color output if necessary |
87 if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType)
{ | 85 if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType)
{ |
88 pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4); | 86 pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4); |
89 } | 87 } |
90 | 88 |
91 pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4); | 89 pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4); |
92 | 90 |
93 return pb->finalize(); | 91 return pb->finalize(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 int co
unt, | 164 int co
unt, |
167 const
char** outName) { | 165 const
char** outName) { |
168 SkASSERT(name && strlen(name)); | 166 SkASSERT(name && strlen(name)); |
169 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); | 167 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); |
170 SkASSERT(0 == (~kVisibilityMask & visibility)); | 168 SkASSERT(0 == (~kVisibilityMask & visibility)); |
171 SkASSERT(0 != visibility); | 169 SkASSERT(0 != visibility); |
172 | 170 |
173 UniformInfo& uni = fUniforms.push_back(); | 171 UniformInfo& uni = fUniforms.push_back(); |
174 uni.fVariable.setType(type); | 172 uni.fVariable.setType(type); |
175 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); | 173 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); |
176 // TODO this is a bit hacky, lets think of a better way. Basically we need
to be able to use | 174 this->nameVariable(uni.fVariable.accessName(), 'u', name); |
177 // the uniform view matrix name in the GP, and the GP is immutable so it has
to tell the PB | |
178 // exactly what name it wants to use for the uniform view matrix. If we pre
fix anythings, then | |
179 // the names will mismatch. I think the correct solution is to have all GPs
which need the | |
180 // uniform view matrix, they should upload the view matrix in their setData
along with regular | |
181 // uniforms. | |
182 char prefix = 'u'; | |
183 if ('u' == name[0]) { | |
184 prefix = '\0'; | |
185 } | |
186 this->nameVariable(uni.fVariable.accessName(), prefix, name); | |
187 uni.fVariable.setArrayCount(count); | 175 uni.fVariable.setArrayCount(count); |
188 uni.fVisibility = visibility; | 176 uni.fVisibility = visibility; |
189 | 177 |
190 // If it is visible in both the VS and FS, the precision must match. | 178 // If it is visible in both the VS and FS, the precision must match. |
191 // We declare a default FS precision, but not a default VS. So set the var | 179 // We declare a default FS precision, but not a default VS. So set the var |
192 // to use the default FS precision. | 180 // to use the default FS precision. |
193 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { | 181 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { |
194 // the fragment and vertex precisions must match | 182 // the fragment and vertex precisions must match |
195 uni.fVariable.setPrecision(kDefaultFragmentPrecision); | 183 uni.fVariable.setPrecision(kDefaultFragmentPrecision); |
196 } | 184 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, | 223 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
236 kFloat_GrSLType, | 224 kFloat_GrSLType, |
237 "Coverage", | 225 "Coverage", |
238 &name); | 226 &name); |
239 *inputCoverage = GrGLSLExpr1(name); | 227 *inputCoverage = GrGLSLExpr1(name); |
240 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { | 228 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { |
241 *inputCoverage = GrGLSLExpr1(1); | 229 *inputCoverage = GrGLSLExpr1(1); |
242 } | 230 } |
243 } | 231 } |
244 | 232 |
245 void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, | 233 void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState, |
| 234 GrGLSLExpr4* inputColor, |
246 GrGLSLExpr4* inputCoverage) { | 235 GrGLSLExpr4* inputCoverage) { |
247 // We need to collect all of the transforms to thread them through the GP in
the case of GPs | |
248 // which use additional shader stages between the VS and the FS. To do this
we emit a dummy | |
249 // input coverage | |
250 GrGLSLExpr4 coverageInput = *inputCoverage; | |
251 if (fOptState.hasGeometryProcessor()) { | |
252 AutoStageAdvance adv(this); | |
253 SkString outColorName; | |
254 this->nameVariable(&outColorName, '\0', "gpOutput"); | |
255 coverageInput = outColorName; | |
256 } | |
257 GrGLSLExpr4 gpOutput = coverageInput; | |
258 | |
259 // Emit fragment processors | |
260 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); | 236 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); |
261 int numProcs = fOptState.numFragmentStages(); | 237 int numProcs = optState.numFragmentStages(); |
262 this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); | 238 this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor); |
263 this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, &covera
geInput); | 239 if (optState.hasGeometryProcessor()) { |
264 | 240 const GrGeometryProcessor& gp = *optState.getGeometryProcessor(); |
265 // We have to save the existing code stack, and then append it to the fragme
nt shader code | |
266 // after emiting the GP | |
267 if (fOptState.hasGeometryProcessor()) { | |
268 SkString existingCode(fFS.fCode); | |
269 fFS.fCode.reset(); | |
270 const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); | |
271 fVS.emitAttributes(gp); | 241 fVS.emitAttributes(gp); |
272 ProcKeyProvider keyProvider(&fDesc, | 242 ProcKeyProvider keyProvider(&fDesc, |
273 ProcKeyProvider::kGeometry_ProcessorType, | 243 ProcKeyProvider::kGeometry_ProcessorType, |
274 GrGLProgramDescBuilder::kProcessorKeyOffsets
AndLengthOffset); | 244 GrGLProgramDescBuilder::kProcessorKeyOffsets
AndLengthOffset); |
275 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *input
Coverage, &gpOutput); | 245 GrGLSLExpr4 output; |
276 fFS.fCode.append(existingCode); | 246 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *input
Coverage, &output); |
| 247 *inputCoverage = output; |
277 } | 248 } |
278 *inputCoverage = coverageInput; | 249 this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCov
erage); |
279 } | 250 } |
280 | 251 |
281 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, G
rGLSLExpr4* inOut) { | 252 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, G
rGLSLExpr4* inOut) { |
282 ProcKeyProvider keyProvider(&fDesc, | 253 ProcKeyProvider keyProvider(&fDesc, |
283 ProcKeyProvider::kFragment_ProcessorType, | 254 ProcKeyProvider::kFragment_ProcessorType, |
284 GrGLProgramDescBuilder::kProcessorKeyOffsetsAndL
engthOffset); | 255 GrGLProgramDescBuilder::kProcessorKeyOffsetsAndL
engthOffset); |
285 for (int e = procOffset; e < numProcs; ++e) { | 256 for (int e = procOffset; e < numProcs; ++e) { |
286 GrGLSLExpr4 output; | 257 GrGLSLExpr4 output; |
287 const GrFragmentStage& stage = fOptState.getFragmentStage(e); | 258 const GrFragmentStage& stage = fOptState.getFragmentStage(e); |
288 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut,
&output); | 259 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut,
&output); |
289 *inOut = output; | 260 *inOut = output; |
290 } | 261 } |
291 } | 262 } |
292 | 263 |
293 // TODO Processors cannot output zeros because an empty string is all 1s | 264 // TODO Processors cannot output zeros because an empty string is all 1s |
294 // the fix is to allow effects to take the GrGLSLExpr4 directly | 265 // the fix is to allow effects to take the GrGLSLExpr4 directly |
295 template <class Proc> | 266 template <class Proc> |
296 void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, | 267 void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, |
297 int index, | 268 int index, |
298 const ProcKeyProvider& keyProvider, | 269 const ProcKeyProvider& keyProvider, |
299 const GrGLSLExpr4& input, | 270 const GrGLSLExpr4& input, |
300 GrGLSLExpr4* output) { | 271 GrGLSLExpr4* output) { |
301 // Program builders have a bit of state we need to clear with each effect | 272 // Program builders have a bit of state we need to clear with each effect |
302 AutoStageAdvance adv(this); | 273 AutoStageAdvance adv(this); |
303 | 274 |
304 // create var to hold stage result. If we already have a valid output name,
just use that | 275 // create var to hold stage result |
305 // otherwise create a new mangled one. | |
306 SkString outColorName; | 276 SkString outColorName; |
307 if (output->isValid()) { | 277 this->nameVariable(&outColorName, '\0', "output"); |
308 outColorName = output->c_str(); | |
309 } else { | |
310 this->nameVariable(&outColorName, '\0', "output"); | |
311 } | |
312 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); | 278 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); |
313 *output = outColorName; | 279 *output = outColorName; |
314 | 280 |
315 // Enclose custom code in a block to avoid namespace conflicts | 281 // Enclose custom code in a block to avoid namespace conflicts |
316 SkString openBrace; | 282 SkString openBrace; |
317 openBrace.printf("{ // Stage %d\n", fStageIndex); | 283 openBrace.printf("{ // Stage %d\n", fStageIndex); |
318 fFS.codeAppend(openBrace.c_str()); | 284 fFS.codeAppend(openBrace.c_str()); |
319 | 285 |
320 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(), | 286 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(), |
321 input.isOnes() ? NULL : input.c_str()); | 287 input.isOnes() ? NULL : input.c_str()); |
(...skipping 20 matching lines...) Expand all Loading... |
342 ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers); | 308 ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers); |
343 | 309 |
344 // We have to check that effects and the code they emit are consistent, ie i
f an effect | 310 // We have to check that effects and the code they emit are consistent, ie i
f an effect |
345 // asks for dst color, then the emit code needs to follow suit | 311 // asks for dst color, then the emit code needs to follow suit |
346 verify(fp); | 312 verify(fp); |
347 fFragmentProcessors->fProcs.push_back(ifp); | 313 fFragmentProcessors->fProcs.push_back(ifp); |
348 } | 314 } |
349 | 315 |
350 void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, | 316 void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, |
351 const GrProcessorKey& key, | 317 const GrProcessorKey& key, |
352 const char* outCoverage, | 318 const char* outColor, |
353 const char* inCoverage) { | 319 const char* inColor) { |
354 SkASSERT(!fGeometryProcessor); | 320 SkASSERT(!fGeometryProcessor); |
355 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); | 321 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); |
356 | 322 |
357 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp)); | 323 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp)); |
358 | 324 |
359 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); | 325 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); |
360 this->emitSamplers(gp, &samplers, fGeometryProcessor); | 326 this->emitSamplers(gp, &samplers, fGeometryProcessor); |
361 | 327 |
362 GrGLGeometryProcessor::EmitArgs args(this, gp, key, outCoverage, inCoverage,
samplers); | 328 GrGLGeometryProcessor::EmitArgs args(this, gp, key, outColor, inColor, sampl
ers); |
363 fGeometryProcessor->fGLProc->emitCode(args); | 329 fGeometryProcessor->fGLProc->emitCode(args); |
364 | 330 |
365 // We have to check that effects and the code they emit are consistent, ie i
f an effect | 331 // We have to check that effects and the code they emit are consistent, ie i
f an effect |
366 // asks for dst color, then the emit code needs to follow suit | 332 // asks for dst color, then the emit code needs to follow suit |
367 verify(gp); | 333 verify(gp); |
368 } | 334 } |
369 | 335 |
370 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { | 336 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { |
371 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); | 337 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); |
372 } | 338 } |
(...skipping 28 matching lines...) Expand all Loading... |
401 uniName, | 367 uniName, |
402 &uniName).toShaderBuilder
Index(); | 368 &uniName).toShaderBuilder
Index(); |
403 | 369 |
404 const char* varyingName = "MatrixCoord"; | 370 const char* varyingName = "MatrixCoord"; |
405 SkString suffixedVaryingName; | 371 SkString suffixedVaryingName; |
406 if (0 != t) { | 372 if (0 != t) { |
407 suffixedVaryingName.append(varyingName); | 373 suffixedVaryingName.append(varyingName); |
408 suffixedVaryingName.appendf("_%i", t); | 374 suffixedVaryingName.appendf("_%i", t); |
409 varyingName = suffixedVaryingName.c_str(); | 375 varyingName = suffixedVaryingName.c_str(); |
410 } | 376 } |
411 const char* coords = kPosition_GrCoordSet == effect->coordTransform(t).s
ourceCoords() ? | |
412 fVS.positionAttribute().c_s
tr() : | |
413 fVS.localCoordsAttribute().
c_str(); | |
414 GrGLVertToFrag v(varyingType); | 377 GrGLVertToFrag v(varyingType); |
415 this->addCoordVarying(varyingName, &v, uniName, coords); | 378 this->addVarying(varyingName, &v); |
416 | 379 |
| 380 const GrGLShaderVar& coords = |
| 381 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords()
? |
| 382 fVS.positionAttribute() : |
| 383 fVS.localCoordsAttribute(); |
| 384 |
| 385 // varying = matrix * coords (logically) |
417 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); | 386 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); |
| 387 if (kVec2f_GrSLType == varyingType) { |
| 388 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;", |
| 389 v.vsOut(), uniName, coords.c_str()); |
| 390 } else { |
| 391 fVS.codeAppendf("%s = %s * vec3(%s, 1);", |
| 392 v.vsOut(), uniName, coords.c_str()); |
| 393 } |
418 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, | 394 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, |
419 (SkString(v.fsIn()), varyingType)); | 395 (SkString(v.fsIn()), varyingType)); |
420 } | 396 } |
421 } | 397 } |
422 | 398 |
423 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | 399 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
424 GrGLProcessor::TextureSamplerArray* outSam
plers, | 400 GrGLProcessor::TextureSamplerArray* outSam
plers, |
425 GrGLInstalledProc* ip) { | 401 GrGLInstalledProc* ip) { |
426 int numTextures = processor.numTextures(); | 402 int numTextures = processor.numTextures(); |
427 ip->fSamplers.push_back_n(numTextures); | 403 ip->fSamplers.push_back_n(numTextures); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 } | 516 } |
541 | 517 |
542 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 518 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
543 | 519 |
544 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 520 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
545 int numProcs = fProcs.count(); | 521 int numProcs = fProcs.count(); |
546 for (int e = 0; e < numProcs; ++e) { | 522 for (int e = 0; e < numProcs; ++e) { |
547 SkDELETE(fProcs[e]); | 523 SkDELETE(fProcs[e]); |
548 } | 524 } |
549 } | 525 } |
OLD | NEW |