| 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 "gl/GrGLGeometryProcessor.h" | 10 #include "gl/GrGLGeometryProcessor.h" |
| 11 #include "gl/GrGLGpu.h" | 11 #include "gl/GrGLGpu.h" |
| 12 #include "gl/GrGLPathProcessor.h" | 12 #include "gl/GrGLPathProcessor.h" |
| 13 #include "gl/GrGLProgram.h" | 13 #include "gl/GrGLProgram.h" |
| 14 #include "gl/GrGLSLPrettyPrint.h" | 14 #include "gl/GrGLSLPrettyPrint.h" |
| 15 #include "gl/GrGLUniformHandle.h" | 15 #include "gl/GrGLUniformHandle.h" |
| 16 #include "gl/GrGLXferProcessor.h" | 16 #include "gl/GrGLXferProcessor.h" |
| 17 #include "glsl/GrGLSLCaps.h" | 17 #include "glsl/GrGLSLCaps.h" |
| 18 #include "GrAutoLocaleSetter.h" | 18 #include "GrAutoLocaleSetter.h" |
| 19 #include "GrCoordTransform.h" | 19 #include "GrCoordTransform.h" |
| 20 #include "GrGLPathProgramBuilder.h" |
| 20 #include "GrGLProgramBuilder.h" | 21 #include "GrGLProgramBuilder.h" |
| 21 #include "GrTexture.h" | 22 #include "GrTexture.h" |
| 22 #include "SkRTConf.h" | 23 #include "SkRTConf.h" |
| 23 #include "SkTraceEvent.h" | 24 #include "SkTraceEvent.h" |
| 24 | 25 |
| 25 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 26 #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) | 27 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
| 27 | 28 |
| 28 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 29 | |
| 30 class GrGLNvprProgramBuilder : public GrGLProgramBuilder { | |
| 31 public: | |
| 32 GrGLNvprProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | |
| 33 : INHERITED(gpu, args) {} | |
| 34 | |
| 35 GrGLProgram* createProgram(GrGLuint programID) override { | |
| 36 // this is just for nvpr es, which has separable varyings that are plugg
ed in after | |
| 37 // building | |
| 38 GrGLPathProcessor* pathProc = | |
| 39 static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get(
)); | |
| 40 pathProc->resolveSeparableVaryings(fGpu, programID); | |
| 41 return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles,
programID, | |
| 42 fUniforms, fGeometryProcessor, fXfer
Processor, | |
| 43 fFragmentProcessors.get(), &fSampler
Uniforms)); | |
| 44 } | |
| 45 | |
| 46 private: | |
| 47 typedef GrGLProgramBuilder INHERITED; | |
| 48 }; | |
| 49 | |
| 50 | |
| 51 | |
| 52 ////////////////////////////////////////////////////////////////////////////// | |
| 53 | |
| 54 const int GrGLProgramBuilder::kVarsPerBlock = 8; | 29 const int GrGLProgramBuilder::kVarsPerBlock = 8; |
| 55 | 30 |
| 56 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
u) { | 31 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
u) { |
| 57 GrAutoLocaleSetter als("C"); | 32 GrAutoLocaleSetter als("C"); |
| 58 | 33 |
| 59 // create a builder. This will be handed off to effects so they can use it
to add | 34 // create a builder. This will be handed off to effects so they can use it
to add |
| 60 // uniforms, varyings, textures, etc | 35 // uniforms, varyings, textures, etc |
| 61 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu)); | 36 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu)); |
| 62 | 37 |
| 63 GrGLProgramBuilder* pb = builder.get(); | 38 GrGLProgramBuilder* pb = builder.get(); |
| 64 | 39 |
| 65 // 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 |
| 66 // seed correctly here | 41 // seed correctly here |
| 67 GrGLSLExpr4 inputColor; | 42 GrGLSLExpr4 inputColor; |
| 68 GrGLSLExpr4 inputCoverage; | 43 GrGLSLExpr4 inputCoverage; |
| 69 | 44 |
| 70 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { | 45 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { |
| 71 return NULL; | 46 return NULL; |
| 72 } | 47 } |
| 73 | 48 |
| 74 return pb->finalize(); | 49 return pb->finalize(); |
| 75 } | 50 } |
| 76 | 51 |
| 77 GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& arg
s, | 52 GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& arg
s, |
| 78 GrGLGpu* gpu) { | 53 GrGLGpu* gpu) { |
| 79 if (args.fPrimitiveProcessor->isPathRendering()) { | 54 if (args.fPrimitiveProcessor->isPathRendering()) { |
| 80 SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() && | 55 SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() && |
| 81 !args.fPrimitiveProcessor->willUseGeoShader() && | 56 !args.fPrimitiveProcessor->willUseGeoShader() && |
| 82 args.fPrimitiveProcessor->numAttribs() == 0); | 57 args.fPrimitiveProcessor->numAttribs() == 0); |
| 83 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args)); | 58 return SkNEW_ARGS(GrGLPathProgramBuilder, (gpu, args)); |
| 84 } else { | 59 } else { |
| 85 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args)); | 60 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args)); |
| 86 } | 61 } |
| 87 } | 62 } |
| 88 | 63 |
| 89 ///////////////////////////////////////////////////////////////////////////// | 64 ///////////////////////////////////////////////////////////////////////////// |
| 90 | 65 |
| 91 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | 66 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
| 92 : fVS(this) | 67 : fVS(this) |
| 93 , fGS(this) | 68 , fGS(this) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 119 | 94 |
| 120 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
ribute* input, | 95 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
ribute* input, |
| 121 const char* output) { | 96 const char* output) { |
| 122 GrSLType type = GrVertexAttribTypeToSLType(input->fType); | 97 GrSLType type = GrVertexAttribTypeToSLType(input->fType); |
| 123 GrGLVertToFrag v(type); | 98 GrGLVertToFrag v(type); |
| 124 this->addVarying(input->fName, &v); | 99 this->addVarying(input->fName, &v); |
| 125 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); | 100 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); |
| 126 fFS.codeAppendf("%s = %s;", output, v.fsIn()); | 101 fFS.codeAppendf("%s = %s;", output, v.fsIn()); |
| 127 } | 102 } |
| 128 | 103 |
| 104 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVaryi
ng(const char*, |
| 105
GrGLVertToFrag*, |
| 106
GrSLPrecision) { |
| 107 // This call is not used for non-NVPR backends. However, the polymorphism be
tween |
| 108 // GrPrimitiveProcessor, GrGLPrimitiveProcessor and GrGLProgramBuilder does
not allow for |
| 109 // a system where GrGLPathProcessor would be able to refer to a primitive-sp
ecific builder |
| 110 // that would understand separable varyings. Thus separable varyings need to
be present |
| 111 // early in the inheritance chain of builders. |
| 112 SkASSERT(false); |
| 113 return SeparableVaryingHandle(); |
| 114 } |
| 115 |
| 129 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { | 116 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { |
| 130 if ('\0' == prefix) { | 117 if ('\0' == prefix) { |
| 131 *out = name; | 118 *out = name; |
| 132 } else { | 119 } else { |
| 133 out->printf("%c%s", prefix, name); | 120 out->printf("%c%s", prefix, name); |
| 134 } | 121 } |
| 135 if (!fOutOfStage) { | 122 if (!fOutOfStage) { |
| 136 if (out->endsWith('_')) { | 123 if (out->endsWith('_')) { |
| 137 // Names containing "__" are reserved. | 124 // Names containing "__" are reserved. |
| 138 out->append("x"); | 125 out->append("x"); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 bool useNvpr = primitiveProcessor().isPathRendering(); | 403 bool useNvpr = primitiveProcessor().isPathRendering(); |
| 417 if (!useNvpr) { | 404 if (!useNvpr) { |
| 418 fVS.bindVertexAttributes(programID); | 405 fVS.bindVertexAttributes(programID); |
| 419 } | 406 } |
| 420 | 407 |
| 421 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { | 408 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { |
| 422 this->cleanupProgram(programID, shadersToDelete); | 409 this->cleanupProgram(programID, shadersToDelete); |
| 423 return NULL; | 410 return NULL; |
| 424 } | 411 } |
| 425 | 412 |
| 426 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | 413 this->bindProgramResourceLocations(programID); |
| 427 if (usingBindUniform) { | 414 |
| 428 this->bindUniformLocations(programID); | |
| 429 } | |
| 430 fFS.bindFragmentShaderLocations(programID); | |
| 431 GL_CALL(LinkProgram(programID)); | 415 GL_CALL(LinkProgram(programID)); |
| 432 | 416 |
| 433 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. | 417 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. |
| 434 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); | 418 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); |
| 435 #ifdef SK_DEBUG | 419 #ifdef SK_DEBUG |
| 436 checkLinked = true; | 420 checkLinked = true; |
| 437 #endif | 421 #endif |
| 438 if (checkLinked) { | 422 if (checkLinked) { |
| 439 checkLinkStatus(programID); | 423 checkLinkStatus(programID); |
| 440 } | 424 } |
| 441 if (!usingBindUniform) { | 425 this->resolveProgramResourceLocations(programID); |
| 442 this->resolveUniformLocations(programID); | |
| 443 } | |
| 444 | 426 |
| 445 this->cleanupShaders(shadersToDelete); | 427 this->cleanupShaders(shadersToDelete); |
| 446 | 428 |
| 447 return this->createProgram(programID); | 429 return this->createProgram(programID); |
| 448 } | 430 } |
| 449 | 431 |
| 450 void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) { | 432 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) { |
| 451 int count = fUniforms.count(); | 433 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; |
| 452 for (int i = 0; i < count; ++i) { | 434 if (usingBindUniform) { |
| 453 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()
)); | 435 int count = fUniforms.count(); |
| 454 fUniforms[i].fLocation = i; | 436 for (int i = 0; i < count; ++i) { |
| 437 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_s
tr())); |
| 438 fUniforms[i].fLocation = i; |
| 439 } |
| 455 } | 440 } |
| 441 |
| 442 fFS.bindFragmentShaderLocations(programID); |
| 456 } | 443 } |
| 457 | 444 |
| 458 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { | 445 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { |
| 459 GrGLint linked = GR_GL_INIT_ZERO; | 446 GrGLint linked = GR_GL_INIT_ZERO; |
| 460 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); | 447 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); |
| 461 if (!linked) { | 448 if (!linked) { |
| 462 GrGLint infoLen = GR_GL_INIT_ZERO; | 449 GrGLint infoLen = GR_GL_INIT_ZERO; |
| 463 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); | 450 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
| 464 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger | 451 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
| 465 if (infoLen > 0) { | 452 if (infoLen > 0) { |
| 466 // retrieve length even though we don't need it to workaround | 453 // retrieve length even though we don't need it to workaround |
| 467 // bug in chrome cmd buffer param validation. | 454 // bug in chrome cmd buffer param validation. |
| 468 GrGLsizei length = GR_GL_INIT_ZERO; | 455 GrGLsizei length = GR_GL_INIT_ZERO; |
| 469 GL_CALL(GetProgramInfoLog(programID, | 456 GL_CALL(GetProgramInfoLog(programID, |
| 470 infoLen+1, | 457 infoLen+1, |
| 471 &length, | 458 &length, |
| 472 (char*)log.get())); | 459 (char*)log.get())); |
| 473 SkDebugf("%s", (char*)log.get()); | 460 SkDebugf("%s", (char*)log.get()); |
| 474 } | 461 } |
| 475 SkDEBUGFAIL("Error linking program"); | 462 SkDEBUGFAIL("Error linking program"); |
| 476 GL_CALL(DeleteProgram(programID)); | 463 GL_CALL(DeleteProgram(programID)); |
| 477 programID = 0; | 464 programID = 0; |
| 478 } | 465 } |
| 479 return SkToBool(linked); | 466 return SkToBool(linked); |
| 480 } | 467 } |
| 481 | 468 |
| 482 void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) { | 469 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { |
| 483 int count = fUniforms.count(); | 470 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; |
| 484 for (int i = 0; i < count; ++i) { | 471 if (!usingBindUniform) { |
| 485 GrGLint location; | 472 int count = fUniforms.count(); |
| 486 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariab
le.c_str())); | 473 for (int i = 0; i < count; ++i) { |
| 487 fUniforms[i].fLocation = location; | 474 GrGLint location; |
| 475 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVa
riable.c_str())); |
| 476 fUniforms[i].fLocation = location; |
| 477 } |
| 488 } | 478 } |
| 489 } | 479 } |
| 490 | 480 |
| 491 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL
uint>& shaderIDs) { | 481 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL
uint>& shaderIDs) { |
| 492 GL_CALL(DeleteProgram(programID)); | 482 GL_CALL(DeleteProgram(programID)); |
| 493 cleanupShaders(shaderIDs); | 483 cleanupShaders(shaderIDs); |
| 494 } | 484 } |
| 495 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { | 485 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { |
| 496 for (int i = 0; i < shaderIDs.count(); ++i) { | 486 for (int i = 0; i < shaderIDs.count(); ++i) { |
| 497 GL_CALL(DeleteShader(shaderIDs[i])); | 487 GL_CALL(DeleteShader(shaderIDs[i])); |
| 498 } | 488 } |
| 499 } | 489 } |
| 500 | 490 |
| 501 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { | 491 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
| 502 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, program
ID, fUniforms, | 492 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, program
ID, fUniforms, |
| 503 fGeometryProcessor, fXferProcessor, fFragmen
tProcessors.get(), | 493 fGeometryProcessor, fXferProcessor, fFragmen
tProcessors.get(), |
| 504 &fSamplerUniforms)); | 494 &fSamplerUniforms)); |
| 505 } | 495 } |
| 506 | 496 |
| 507 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 497 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 508 | 498 |
| 509 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 499 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
| 510 int numProcs = fProcs.count(); | 500 int numProcs = fProcs.count(); |
| 511 for (int e = 0; e < numProcs; ++e) { | 501 for (int e = 0; e < numProcs; ++e) { |
| 512 SkDELETE(fProcs[e]); | 502 SkDELETE(fProcs[e]); |
| 513 } | 503 } |
| 514 } | 504 } |
| OLD | NEW |