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" |
11 #include "GrCoordTransform.h" | 11 #include "GrCoordTransform.h" |
12 #include "GrGLPathProgramBuilder.h" | |
13 #include "GrGLProgramBuilder.h" | 12 #include "GrGLProgramBuilder.h" |
14 #include "GrTexture.h" | 13 #include "GrTexture.h" |
15 #include "SkRTConf.h" | 14 #include "SkRTConf.h" |
16 #include "SkTraceEvent.h" | 15 #include "SkTraceEvent.h" |
17 #include "gl/GrGLGeometryProcessor.h" | 16 #include "gl/GrGLGeometryProcessor.h" |
18 #include "gl/GrGLGpu.h" | 17 #include "gl/GrGLGpu.h" |
19 #include "gl/GrGLPathProcessor.h" | 18 #include "gl/GrGLPathProcessor.h" |
20 #include "gl/GrGLProgram.h" | 19 #include "gl/GrGLProgram.h" |
21 #include "gl/GrGLSLPrettyPrint.h" | 20 #include "gl/GrGLSLPrettyPrint.h" |
22 #include "gl/GrGLXferProcessor.h" | 21 #include "gl/GrGLXferProcessor.h" |
23 #include "glsl/GrGLSLCaps.h" | 22 #include "glsl/GrGLSLCaps.h" |
24 | 23 |
25 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 24 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) |
26 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) | 25 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
27 | 26 |
28 const int GrGLProgramBuilder::kVarsPerBlock = 8; | 27 const int GrGLProgramBuilder::kVarsPerBlock = 8; |
29 | 28 |
30 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
u) { | 29 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
u) { |
31 GrAutoLocaleSetter als("C"); | 30 GrAutoLocaleSetter als("C"); |
32 | 31 |
33 // create a builder. This will be handed off to effects so they can use it
to add | 32 // create a builder. This will be handed off to effects so they can use it
to add |
34 // uniforms, varyings, textures, etc | 33 // uniforms, varyings, textures, etc |
35 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu)); | 34 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args))
; |
36 | 35 |
37 GrGLProgramBuilder* pb = builder.get(); | 36 GrGLProgramBuilder* pb = builder.get(); |
38 | 37 |
39 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can | 38 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can |
40 // seed correctly here | 39 // seed correctly here |
41 GrGLSLExpr4 inputColor; | 40 GrGLSLExpr4 inputColor; |
42 GrGLSLExpr4 inputCoverage; | 41 GrGLSLExpr4 inputCoverage; |
43 | 42 |
44 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { | 43 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { |
45 return nullptr; | 44 return nullptr; |
46 } | 45 } |
47 | 46 |
48 return pb->finalize(); | 47 return pb->finalize(); |
49 } | 48 } |
50 | 49 |
51 GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& arg
s, | |
52 GrGLGpu* gpu) { | |
53 if (args.fPrimitiveProcessor->isPathRendering()) { | |
54 SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() && | |
55 !args.fPrimitiveProcessor->willUseGeoShader() && | |
56 args.fPrimitiveProcessor->numAttribs() == 0); | |
57 return new GrGLPathProgramBuilder(gpu, args); | |
58 } else { | |
59 return new GrGLProgramBuilder(gpu, args); | |
60 } | |
61 } | |
62 | |
63 ///////////////////////////////////////////////////////////////////////////// | 50 ///////////////////////////////////////////////////////////////////////////// |
64 | 51 |
65 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | 52 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
66 : fVS(this) | 53 : fVS(this) |
67 , fGS(this) | 54 , fGS(this) |
68 , fFS(this, args.fDesc->header().fFragPosKey) | 55 , fFS(this, args.fDesc->header().fFragPosKey) |
69 , fOutOfStage(true) | 56 , fOutOfStage(true) |
70 , fStageIndex(-1) | 57 , fStageIndex(-1) |
71 , fGeometryProcessor(nullptr) | 58 , fGeometryProcessor(nullptr) |
72 , fXferProcessor(nullptr) | 59 , fXferProcessor(nullptr) |
73 , fArgs(args) | 60 , fArgs(args) |
74 , fGpu(gpu) | 61 , fGpu(gpu) |
75 , fUniforms(kVarsPerBlock) | 62 , fUniforms(kVarsPerBlock) |
76 , fSamplerUniforms(4) { | 63 , fSamplerUniforms(4) |
| 64 , fSeparableVaryingInfos(kVarsPerBlock) { |
77 } | 65 } |
78 | 66 |
79 void GrGLProgramBuilder::addVarying(const char* name, | 67 void GrGLProgramBuilder::addVarying(const char* name, |
80 GrGLVarying* varying, | 68 GrGLVarying* varying, |
81 GrSLPrecision fsPrecision) { | 69 GrSLPrecision fsPrecision) { |
82 SkASSERT(varying); | 70 SkASSERT(varying); |
83 if (varying->vsVarying()) { | 71 if (varying->vsVarying()) { |
84 fVS.addVarying(name, varying); | 72 fVS.addVarying(name, varying); |
85 } | 73 } |
86 if (this->primitiveProcessor().willUseGeoShader()) { | 74 if (this->primitiveProcessor().willUseGeoShader()) { |
87 fGS.addVarying(name, varying); | 75 fGS.addVarying(name, varying); |
88 } | 76 } |
89 if (varying->fsVarying()) { | 77 if (varying->fsVarying()) { |
90 fFS.addVarying(varying, fsPrecision); | 78 fFS.addVarying(varying, fsPrecision); |
91 } | 79 } |
92 } | 80 } |
93 | 81 |
94 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
ribute* input, | 82 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
ribute* input, |
95 const char* output) { | 83 const char* output) { |
96 GrSLType type = GrVertexAttribTypeToSLType(input->fType); | 84 GrSLType type = GrVertexAttribTypeToSLType(input->fType); |
97 GrGLVertToFrag v(type); | 85 GrGLVertToFrag v(type); |
98 this->addVarying(input->fName, &v); | 86 this->addVarying(input->fName, &v); |
99 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); | 87 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); |
100 fFS.codeAppendf("%s = %s;", output, v.fsIn()); | 88 fFS.codeAppendf("%s = %s;", output, v.fsIn()); |
101 } | 89 } |
102 | 90 |
103 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVaryi
ng(const char*, | 91 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVaryi
ng( |
104
GrGLVertToFrag*, | 92 const ch
ar* name, |
105
GrSLPrecision) { | 93 GrGLVert
ToFrag* v, |
106 // This call is not used for non-NVPR backends. However, the polymorphism be
tween | 94 GrSLPrec
ision fsPrecision) { |
107 // GrPrimitiveProcessor, GrGLPrimitiveProcessor and GrGLProgramBuilder does
not allow for | 95 // This call is not used for non-NVPR backends. |
108 // a system where GrGLPathProcessor would be able to refer to a primitive-sp
ecific builder | 96 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() && |
109 // that would understand separable varyings. Thus separable varyings need to
be present | 97 fArgs.fPrimitiveProcessor->isPathRendering() && |
110 // early in the inheritance chain of builders. | 98 !fArgs.fPrimitiveProcessor->willUseGeoShader() && |
111 SkASSERT(false); | 99 fArgs.fPrimitiveProcessor->numAttribs() == 0); |
112 return SeparableVaryingHandle(); | 100 this->addVarying(name, v, fsPrecision); |
| 101 SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back(); |
| 102 varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back(); |
| 103 varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1; |
| 104 return SeparableVaryingHandle(varyingInfo.fLocation); |
113 } | 105 } |
114 | 106 |
115 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { | 107 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { |
116 if ('\0' == prefix) { | 108 if ('\0' == prefix) { |
117 *out = name; | 109 *out = name; |
118 } else { | 110 } else { |
119 out->printf("%c%s", prefix, name); | 111 out->printf("%c%s", prefix, name); |
120 } | 112 } |
121 if (!fOutOfStage) { | 113 if (!fOutOfStage) { |
122 if (out->endsWith('_')) { | 114 if (out->endsWith('_')) { |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= nullptr; | 425 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= nullptr; |
434 if (usingBindUniform) { | 426 if (usingBindUniform) { |
435 int count = fUniforms.count(); | 427 int count = fUniforms.count(); |
436 for (int i = 0; i < count; ++i) { | 428 for (int i = 0; i < count; ++i) { |
437 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_s
tr())); | 429 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_s
tr())); |
438 fUniforms[i].fLocation = i; | 430 fUniforms[i].fLocation = i; |
439 } | 431 } |
440 } | 432 } |
441 | 433 |
442 fFS.bindFragmentShaderLocations(programID); | 434 fFS.bindFragmentShaderLocations(programID); |
| 435 |
| 436 // handle NVPR separable varyings |
| 437 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() || |
| 438 !fGpu->glPathRendering()->shouldBindFragmentInputs()) { |
| 439 return; |
| 440 } |
| 441 int count = fSeparableVaryingInfos.count(); |
| 442 for (int i = 0; i < count; ++i) { |
| 443 GL_CALL(BindFragmentInputLocation(programID, |
| 444 i, |
| 445 fSeparableVaryingInfos[i].fVariable.c_
str())); |
| 446 fSeparableVaryingInfos[i].fLocation = i; |
| 447 } |
443 } | 448 } |
444 | 449 |
445 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { | 450 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { |
446 GrGLint linked = GR_GL_INIT_ZERO; | 451 GrGLint linked = GR_GL_INIT_ZERO; |
447 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); | 452 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); |
448 if (!linked) { | 453 if (!linked) { |
449 GrGLint infoLen = GR_GL_INIT_ZERO; | 454 GrGLint infoLen = GR_GL_INIT_ZERO; |
450 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); | 455 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
451 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger | 456 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
452 if (infoLen > 0) { | 457 if (infoLen > 0) { |
(...skipping 16 matching lines...) Expand all Loading... |
469 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { | 474 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { |
470 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= nullptr; | 475 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= nullptr; |
471 if (!usingBindUniform) { | 476 if (!usingBindUniform) { |
472 int count = fUniforms.count(); | 477 int count = fUniforms.count(); |
473 for (int i = 0; i < count; ++i) { | 478 for (int i = 0; i < count; ++i) { |
474 GrGLint location; | 479 GrGLint location; |
475 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVa
riable.c_str())); | 480 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVa
riable.c_str())); |
476 fUniforms[i].fLocation = location; | 481 fUniforms[i].fLocation = location; |
477 } | 482 } |
478 } | 483 } |
| 484 |
| 485 // handle NVPR separable varyings |
| 486 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() || |
| 487 !fGpu->glPathRendering()->shouldBindFragmentInputs()) { |
| 488 return; |
| 489 } |
| 490 int count = fSeparableVaryingInfos.count(); |
| 491 for (int i = 0; i < count; ++i) { |
| 492 GrGLint location; |
| 493 GL_CALL_RET(location, |
| 494 GetProgramResourceLocation(programID, |
| 495 GR_GL_FRAGMENT_INPUT, |
| 496 fSeparableVaryingInfos[i].fVariab
le.c_str())); |
| 497 fSeparableVaryingInfos[i].fLocation = location; |
| 498 } |
479 } | 499 } |
480 | 500 |
481 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL
uint>& shaderIDs) { | 501 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL
uint>& shaderIDs) { |
482 GL_CALL(DeleteProgram(programID)); | 502 GL_CALL(DeleteProgram(programID)); |
483 cleanupShaders(shaderIDs); | 503 cleanupShaders(shaderIDs); |
484 } | 504 } |
485 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { | 505 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { |
486 for (int i = 0; i < shaderIDs.count(); ++i) { | 506 for (int i = 0; i < shaderIDs.count(); ++i) { |
487 GL_CALL(DeleteShader(shaderIDs[i])); | 507 GL_CALL(DeleteShader(shaderIDs[i])); |
488 } | 508 } |
489 } | 509 } |
490 | 510 |
491 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { | 511 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
492 return new GrGLProgram(fGpu, this->desc(), fUniformHandles, programID, fUnif
orms, | 512 return new GrGLProgram(fGpu, this->desc(), fUniformHandles, programID, fUnif
orms, |
| 513 fSeparableVaryingInfos, |
493 fGeometryProcessor, fXferProcessor, fFragmentProcesso
rs.get(), | 514 fGeometryProcessor, fXferProcessor, fFragmentProcesso
rs.get(), |
494 &fSamplerUniforms); | 515 &fSamplerUniforms); |
495 } | 516 } |
496 | 517 |
497 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 518 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
498 | 519 |
499 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 520 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
500 int numProcs = fProcs.count(); | 521 int numProcs = fProcs.count(); |
501 for (int i = 0; i < numProcs; ++i) { | 522 for (int i = 0; i < numProcs; ++i) { |
502 delete fProcs[i]; | 523 delete fProcs[i]; |
503 } | 524 } |
504 } | 525 } |
OLD | NEW |