joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "gl/GrGLProgram.h" |
| 9 | #include "gl/GrGLSLPrettyPrint.h" |
| 10 | #include "gl/GrGLUniformHandle.h" |
| 11 | #include "GrCoordTransform.h" |
| 12 | #include "GrDrawEffect.h" |
| 13 | #include "../GrGpuGL.h" |
| 14 | #include "GrGLFragmentShaderBuilder.h" |
| 15 | #include "GrGLProgramBuilder.h" |
| 16 | #include "GrTexture.h" |
| 17 | #include "GrGLVertexShaderBuilder.h" |
| 18 | #include "SkRTConf.h" |
| 19 | #include "SkTraceEvent.h" |
| 20 | |
| 21 | namespace { |
| 22 | #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) |
| 23 | #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
| 24 | |
| 25 | // number of each input/output type in a single allocation block |
| 26 | static const int kVarsPerBlock = 8; |
| 27 | |
| 28 | // ES2 FS only guarantees mediump and lowp support |
| 29 | static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; |
| 30 | } |
| 31 | |
| 32 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 33 | |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 34 | bool GrGLProgramBuilder::genProgram(const GrEffectStage* geometryProcessor, |
| 35 | const GrEffectStage* colorStages[], |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 36 | const GrEffectStage* coverageStages[]) { |
| 37 | const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); |
| 38 | |
| 39 | fFS.emitCodeBeforeEffects(); |
| 40 | |
| 41 | /////////////////////////////////////////////////////////////////////////// |
| 42 | // get the initial color and coverage to feed into the first effect in each effect chain |
| 43 | |
| 44 | GrGLSLExpr4 inputColor; |
| 45 | GrGLSLExpr4 inputCoverage; |
| 46 | |
| 47 | if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { |
| 48 | const char* name; |
| 49 | fUniformHandles.fColorUni = |
| 50 | this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
| 51 | kVec4f_GrSLType, |
| 52 | "Color", |
| 53 | &name); |
| 54 | inputColor = GrGLSLExpr4(name); |
egdaniel | 842b086 | 2014-09-02 10:01:30 -0700 | [diff] [blame] | 55 | } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) { |
| 56 | inputColor = GrGLSLExpr4(1); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { |
| 60 | const char* name; |
| 61 | fUniformHandles.fCoverageUni = |
| 62 | this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
| 63 | kVec4f_GrSLType, |
| 64 | "Coverage", |
| 65 | &name); |
| 66 | inputCoverage = GrGLSLExpr4(name); |
egdaniel | 842b086 | 2014-09-02 10:01:30 -0700 | [diff] [blame] | 67 | } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 68 | inputCoverage = GrGLSLExpr4(1); |
| 69 | } |
| 70 | |
| 71 | this->emitCodeBeforeEffects(&inputColor, &inputCoverage); |
| 72 | |
| 73 | /////////////////////////////////////////////////////////////////////////// |
| 74 | // emit the per-effect code for both color and coverage effects |
| 75 | |
| 76 | GrGLProgramDesc::EffectKeyProvider colorKeyProvider( |
| 77 | &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType); |
| 78 | fColorEffects.reset(this->createAndEmitEffects(colorStages, |
| 79 | this->desc().numColorEffects(), |
| 80 | colorKeyProvider, |
| 81 | &inputColor)); |
| 82 | |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 83 | this->emitGeometryProcessor(geometryProcessor, &inputCoverage); |
| 84 | |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 85 | GrGLProgramDesc::EffectKeyProvider coverageKeyProvider( |
| 86 | &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType); |
| 87 | fCoverageEffects.reset(this->createAndEmitEffects(coverageStages, |
| 88 | this->desc().numCoverageEffects(), |
| 89 | coverageKeyProvider, |
| 90 | &inputCoverage)); |
| 91 | |
| 92 | this->emitCodeAfterEffects(); |
| 93 | |
| 94 | fFS.emitCodeAfterEffects(inputColor, inputCoverage); |
| 95 | |
| 96 | if (!this->finish()) { |
| 97 | return false; |
| 98 | } |
| 99 | |
| 100 | return true; |
| 101 | } |
| 102 | |
| 103 | ////////////////////////////////////////////////////////////////////////////// |
| 104 | |
| 105 | GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, |
| 106 | const GrGLProgramDesc& desc) |
kkinnunen | ec56e45 | 2014-08-25 22:21:16 -0700 | [diff] [blame] | 107 | : fFragOnly(!desc.getHeader().fRequiresVertexShader && |
| 108 | gpu->glCaps().pathRenderingSupport() && |
| 109 | gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 110 | , fTexCoordSetCnt(0) |
| 111 | , fProgramID(0) |
| 112 | , fFS(this, desc) |
kkinnunen | ec56e45 | 2014-08-25 22:21:16 -0700 | [diff] [blame] | 113 | , fSeparableVaryingInfos(kVarsPerBlock) |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 114 | , fDesc(desc) |
| 115 | , fGpu(gpu) |
| 116 | , fUniforms(kVarsPerBlock) { |
| 117 | } |
| 118 | |
| 119 | void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) { |
| 120 | if ('\0' == prefix) { |
| 121 | *out = name; |
| 122 | } else { |
| 123 | out->printf("%c%s", prefix, name); |
| 124 | } |
| 125 | if (fCodeStage.inStageCode()) { |
| 126 | if (out->endsWith('_')) { |
| 127 | // Names containing "__" are reserved. |
| 128 | out->append("x"); |
| 129 | } |
| 130 | out->appendf("_Stage%d", fCodeStage.stageIndex()); |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility, |
| 135 | GrSLType type, |
| 136 | const char* name, |
| 137 | int count, |
| 138 | const char** outName) { |
| 139 | SkASSERT(name && strlen(name)); |
| 140 | SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); |
| 141 | SkASSERT(0 == (~kVisibilityMask & visibility)); |
| 142 | SkASSERT(0 != visibility); |
| 143 | |
| 144 | UniformInfo& uni = fUniforms.push_back(); |
| 145 | uni.fVariable.setType(type); |
| 146 | uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); |
| 147 | this->nameVariable(uni.fVariable.accessName(), 'u', name); |
| 148 | uni.fVariable.setArrayCount(count); |
| 149 | uni.fVisibility = visibility; |
| 150 | |
| 151 | // If it is visible in both the VS and FS, the precision must match. |
| 152 | // We declare a default FS precision, but not a default VS. So set the var |
| 153 | // to use the default FS precision. |
| 154 | if ((kVertex_Visibility | kFragment_Visibility) == visibility) { |
| 155 | // the fragment and vertex precisions must match |
| 156 | uni.fVariable.setPrecision(kDefaultFragmentPrecision); |
| 157 | } |
| 158 | |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame^] | 159 | if (outName) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 160 | *outName = uni.fVariable.c_str(); |
| 161 | } |
| 162 | return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); |
| 163 | } |
| 164 | |
| 165 | void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const { |
| 166 | for (int i = 0; i < vars.count(); ++i) { |
| 167 | vars[i].appendDecl(this->ctxInfo(), out); |
| 168 | out->append(";\n"); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, |
| 173 | SkString* out) const { |
| 174 | for (int i = 0; i < fUniforms.count(); ++i) { |
| 175 | if (fUniforms[i].fVisibility & visibility) { |
| 176 | fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); |
| 177 | out->append(";\n"); |
| 178 | } |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, |
| 183 | const GrEffectStage* effectStages[], |
| 184 | int effectCnt, |
| 185 | const GrGLProgramDesc::EffectKeyProvider& keyProvider, |
| 186 | GrGLSLExpr4* fsInOutColor) { |
| 187 | bool effectEmitted = false; |
| 188 | |
| 189 | GrGLSLExpr4 inColor = *fsInOutColor; |
| 190 | GrGLSLExpr4 outColor; |
| 191 | |
| 192 | for (int e = 0; e < effectCnt; ++e) { |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame^] | 193 | SkASSERT(effectStages[e] && effectStages[e]->getEffect()); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 194 | const GrEffectStage& stage = *effectStages[e]; |
| 195 | |
| 196 | CodeStage::AutoStageRestore csar(&fCodeStage, &stage); |
| 197 | |
| 198 | if (inColor.isZeros()) { |
| 199 | SkString inColorName; |
| 200 | |
| 201 | // Effects have no way to communicate zeros, they treat an empty string as ones. |
| 202 | this->nameVariable(&inColorName, '\0', "input"); |
| 203 | fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); |
| 204 | inColor = inColorName; |
| 205 | } |
| 206 | |
| 207 | // create var to hold stage result |
| 208 | SkString outColorName; |
| 209 | this->nameVariable(&outColorName, '\0', "output"); |
| 210 | fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str()); |
| 211 | outColor = outColorName; |
| 212 | |
| 213 | |
| 214 | programEffectsBuilder->emitEffect(stage, |
| 215 | keyProvider.get(e), |
| 216 | outColor.c_str(), |
| 217 | inColor.isOnes() ? NULL : inColor.c_str(), |
| 218 | fCodeStage.stageIndex()); |
| 219 | |
| 220 | inColor = outColor; |
| 221 | effectEmitted = true; |
| 222 | } |
| 223 | |
| 224 | if (effectEmitted) { |
| 225 | *fsInOutColor = outColor; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | bool GrGLProgramBuilder::finish() { |
| 230 | SkASSERT(0 == fProgramID); |
| 231 | GL_CALL_RET(fProgramID, CreateProgram()); |
| 232 | if (!fProgramID) { |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | SkTDArray<GrGLuint> shadersToDelete; |
| 237 | |
| 238 | if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { |
| 239 | GL_CALL(DeleteProgram(fProgramID)); |
| 240 | return false; |
| 241 | } |
| 242 | |
| 243 | this->bindProgramLocations(fProgramID); |
| 244 | |
| 245 | GL_CALL(LinkProgram(fProgramID)); |
| 246 | |
| 247 | // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. |
| 248 | bool checkLinked = !fGpu->ctxInfo().isChromium(); |
| 249 | #ifdef SK_DEBUG |
| 250 | checkLinked = true; |
| 251 | #endif |
| 252 | if (checkLinked) { |
| 253 | GrGLint linked = GR_GL_INIT_ZERO; |
| 254 | GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); |
| 255 | if (!linked) { |
| 256 | GrGLint infoLen = GR_GL_INIT_ZERO; |
| 257 | GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
| 258 | SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
| 259 | if (infoLen > 0) { |
| 260 | // retrieve length even though we don't need it to workaround |
| 261 | // bug in chrome cmd buffer param validation. |
| 262 | GrGLsizei length = GR_GL_INIT_ZERO; |
| 263 | GL_CALL(GetProgramInfoLog(fProgramID, |
| 264 | infoLen+1, |
| 265 | &length, |
| 266 | (char*)log.get())); |
| 267 | GrPrintf((char*)log.get()); |
| 268 | } |
| 269 | SkDEBUGFAIL("Error linking program"); |
| 270 | GL_CALL(DeleteProgram(fProgramID)); |
| 271 | fProgramID = 0; |
| 272 | return false; |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | this->resolveProgramLocations(fProgramID); |
| 277 | |
| 278 | for (int i = 0; i < shadersToDelete.count(); ++i) { |
| 279 | GL_CALL(DeleteShader(shadersToDelete[i])); |
| 280 | } |
| 281 | |
| 282 | return true; |
| 283 | } |
| 284 | |
| 285 | bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, |
| 286 | SkTDArray<GrGLuint>* shaderIds) const { |
| 287 | return fFS.compileAndAttachShaders(programId, shaderIds); |
| 288 | } |
| 289 | |
| 290 | void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) { |
| 291 | fFS.bindProgramLocations(programId); |
| 292 | |
| 293 | // skbug.com/2056 |
| 294 | bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; |
| 295 | if (usingBindUniform) { |
| 296 | int count = fUniforms.count(); |
| 297 | for (int i = 0; i < count; ++i) { |
| 298 | GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str())); |
| 299 | fUniforms[i].fLocation = i; |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { |
| 305 | bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; |
| 306 | if (!usingBindUniform) { |
| 307 | int count = fUniforms.count(); |
| 308 | for (int i = 0; i < count; ++i) { |
| 309 | GrGLint location; |
| 310 | GL_CALL_RET(location, |
| 311 | GetUniformLocation(programId, fUniforms[i].fVariable.c_str())); |
| 312 | fUniforms[i].fLocation = location; |
| 313 | } |
| 314 | } |
kkinnunen | ec56e45 | 2014-08-25 22:21:16 -0700 | [diff] [blame] | 315 | |
| 316 | int count = fSeparableVaryingInfos.count(); |
| 317 | for (int i = 0; i < count; ++i) { |
| 318 | GrGLint location; |
| 319 | GL_CALL_RET(location, |
| 320 | GetProgramResourceLocation(programId, |
| 321 | GR_GL_FRAGMENT_INPUT, |
| 322 | fSeparableVaryingInfos[i].fVariable.c_str())); |
| 323 | fSeparableVaryingInfos[i].fLocation = location; |
| 324 | } |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { |
| 328 | return fGpu->ctxInfo(); |
| 329 | } |
| 330 | |
| 331 | //////////////////////////////////////////////////////////////////////////////// |
| 332 | |
| 333 | GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu, |
| 334 | const GrGLProgramDesc& desc) |
| 335 | : INHERITED(gpu, desc) |
| 336 | , fGS(this) |
| 337 | , fVS(this) { |
| 338 | } |
| 339 | |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 340 | void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, |
| 341 | GrGLSLExpr4* coverage) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 342 | fVS.emitCodeBeforeEffects(color, coverage); |
| 343 | } |
| 344 | |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 345 | void GrGLFullProgramBuilder::emitGeometryProcessor(const GrEffectStage* geometryProcessor, |
| 346 | GrGLSLExpr4* coverage) { |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame^] | 347 | if (geometryProcessor) { |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 348 | GrGLProgramDesc::EffectKeyProvider geometryProcessorKeyProvider( |
| 349 | &this->desc(), GrGLProgramDesc::EffectKeyProvider::kGeometryProcessor_EffectType); |
| 350 | fGeometryProcessor.reset(this->createAndEmitEffect( |
| 351 | geometryProcessor, |
| 352 | geometryProcessorKeyProvider, |
| 353 | coverage)); |
| 354 | } |
| 355 | } |
| 356 | |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 357 | void GrGLFullProgramBuilder::emitCodeAfterEffects() { |
| 358 | fVS.emitCodeAfterEffects(); |
| 359 | } |
| 360 | |
| 361 | void GrGLFullProgramBuilder::addVarying(GrSLType type, |
| 362 | const char* name, |
| 363 | const char** vsOutName, |
egdaniel | 6db9128 | 2014-09-02 08:02:38 -0700 | [diff] [blame] | 364 | const char** fsInName, |
| 365 | GrGLShaderVar::Precision fsPrecision) { |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 366 | fVS.addVarying(type, name, vsOutName); |
| 367 | |
| 368 | SkString* fsInputName = fVS.fOutputs.back().accessName(); |
| 369 | |
| 370 | #if GR_GL_EXPERIMENTAL_GS |
| 371 | if (desc().getHeader().fExperimentalGS) { |
| 372 | // TODO let the caller use these names |
| 373 | fGS.addVarying(type, fsInputName->c_str(), NULL); |
| 374 | fsInputName = fGS.fOutputs.back().accessName(); |
| 375 | } |
| 376 | #endif |
egdaniel | 6db9128 | 2014-09-02 08:02:38 -0700 | [diff] [blame] | 377 | fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 378 | } |
| 379 | |
kkinnunen | ec56e45 | 2014-08-25 22:21:16 -0700 | [diff] [blame] | 380 | GrGLFullProgramBuilder::VaryingHandle |
| 381 | GrGLFullProgramBuilder::addSeparableVarying(GrSLType type, |
| 382 | const char* name, |
| 383 | const char** vsOutName, |
| 384 | const char** fsInName) { |
| 385 | addVarying(type, name, vsOutName, fsInName); |
| 386 | SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back(); |
| 387 | varying.fVariable = fFS.fInputs.back(); |
| 388 | return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1); |
| 389 | } |
| 390 | |
| 391 | |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 392 | GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects( |
| 393 | const GrEffectStage* effectStages[], |
| 394 | int effectCnt, |
| 395 | const GrGLProgramDesc::EffectKeyProvider& keyProvider, |
| 396 | GrGLSLExpr4* inOutFSColor) { |
| 397 | |
| 398 | GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); |
| 399 | this->INHERITED::createAndEmitEffects(&programEffectsBuilder, |
| 400 | effectStages, |
| 401 | effectCnt, |
| 402 | keyProvider, |
| 403 | inOutFSColor); |
| 404 | return programEffectsBuilder.finish(); |
| 405 | } |
| 406 | |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 407 | void GrGLFullProgramBuilder::createAndEmitEffect(GrGLProgramEffectsBuilder* programEffectsBuilder, |
| 408 | const GrEffectStage* effectStages, |
| 409 | const GrGLProgramDesc::EffectKeyProvider& keyProvider, |
| 410 | GrGLSLExpr4* fsInOutColor) { |
| 411 | GrGLSLExpr4 inColor = *fsInOutColor; |
| 412 | GrGLSLExpr4 outColor; |
| 413 | |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame^] | 414 | SkASSERT(effectStages && effectStages->getEffect()); |
joshualitt | bd769d0 | 2014-09-04 08:56:46 -0700 | [diff] [blame] | 415 | const GrEffectStage& stage = *effectStages; |
| 416 | |
| 417 | // Using scope to force ASR destructor to be triggered |
| 418 | { |
| 419 | CodeStage::AutoStageRestore csar(&fCodeStage, &stage); |
| 420 | |
| 421 | if (inColor.isZeros()) { |
| 422 | SkString inColorName; |
| 423 | |
| 424 | // Effects have no way to communicate zeros, they treat an empty string as ones. |
| 425 | this->nameVariable(&inColorName, '\0', "input"); |
| 426 | fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str()); |
| 427 | inColor = inColorName; |
| 428 | } |
| 429 | |
| 430 | // create var to hold stage result |
| 431 | SkString outColorName; |
| 432 | this->nameVariable(&outColorName, '\0', "output"); |
| 433 | fFS.codeAppendf("vec4 %s;", outColorName.c_str()); |
| 434 | outColor = outColorName; |
| 435 | |
| 436 | |
| 437 | programEffectsBuilder->emitEffect(stage, |
| 438 | keyProvider.get(0), |
| 439 | outColor.c_str(), |
| 440 | inColor.isOnes() ? NULL : inColor.c_str(), |
| 441 | fCodeStage.stageIndex()); |
| 442 | } |
| 443 | |
| 444 | *fsInOutColor = outColor; |
| 445 | } |
| 446 | |
| 447 | GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffect( |
| 448 | const GrEffectStage* geometryProcessor, |
| 449 | const GrGLProgramDesc::EffectKeyProvider& keyProvider, |
| 450 | GrGLSLExpr4* inOutFSColor) { |
| 451 | |
| 452 | GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, 1); |
| 453 | this->createAndEmitEffect(&programEffectsBuilder, geometryProcessor, keyProvider, inOutFSColor); |
| 454 | return programEffectsBuilder.finish(); |
| 455 | } |
| 456 | |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 457 | bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId, |
| 458 | SkTDArray<GrGLuint>* shaderIds) const { |
| 459 | return INHERITED::compileAndAttachShaders(programId, shaderIds) |
| 460 | && fVS.compileAndAttachShaders(programId, shaderIds) |
| 461 | #if GR_GL_EXPERIMENTAL_GS |
| 462 | && (!desc().getHeader().fExperimentalGS |
| 463 | || fGS.compileAndAttachShaders(programId, shaderIds)) |
| 464 | #endif |
| 465 | ; |
| 466 | } |
| 467 | |
| 468 | void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) { |
| 469 | fVS.bindProgramLocations(programId); |
| 470 | INHERITED::bindProgramLocations(programId); |
| 471 | } |
| 472 | |
| 473 | //////////////////////////////////////////////////////////////////////////////// |
| 474 | |
| 475 | GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu, |
| 476 | const GrGLProgramDesc& desc) |
| 477 | : INHERITED(gpu, desc) { |
kkinnunen | ec56e45 | 2014-08-25 22:21:16 -0700 | [diff] [blame] | 478 | SkASSERT(!desc.getHeader().fRequiresVertexShader); |
joshualitt | 30ba436 | 2014-08-21 20:18:45 -0700 | [diff] [blame] | 479 | SkASSERT(gpu->glCaps().pathRenderingSupport()); |
| 480 | SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); |
| 481 | SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); |
| 482 | } |
| 483 | |
| 484 | int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) { |
| 485 | int firstFreeCoordSet = fTexCoordSetCnt; |
| 486 | fTexCoordSetCnt += count; |
| 487 | SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt); |
| 488 | return firstFreeCoordSet; |
| 489 | } |
| 490 | |
| 491 | GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects( |
| 492 | const GrEffectStage* effectStages[], int effectCnt, |
| 493 | const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) { |
| 494 | |
| 495 | GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this, |
| 496 | effectCnt); |
| 497 | this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder, |
| 498 | effectStages, |
| 499 | effectCnt, |
| 500 | keyProvider, |
| 501 | inOutFSColor); |
| 502 | return pathTexGenEffectsBuilder.finish(); |
| 503 | } |