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 "../GrGpuGL.h" 13 #include "GrGLFragmentShaderBuilder.h" 14 #include "GrGLProgramBuilder.h" 15 #include "GrTexture.h" 16 #include "GrGLVertexShaderBuilder.h" 17 #include "SkRTConf.h" 18 #include "SkTraceEvent.h" 19 20 namespace { 21 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) 22 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) 23 24 // number of each input/output type in a single allocation block 25 static const int kVarsPerBlock = 8; 26 27 // ES2 FS only guarantees mediump and lowp support 28 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 29 } 30 31 /////////////////////////////////////////////////////////////////////////////////////////////////// 32 33 bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor, 34 const GrFragmentStage* colorStages[], 35 const GrFragmentStage* coverageStages[]) { 36 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); 37 38 fFS.emitCodeBeforeEffects(); 39 40 /////////////////////////////////////////////////////////////////////////// 41 // get the initial color and coverage to feed into the first effect in each effect chain 42 43 GrGLSLExpr4 inputColor; 44 GrGLSLExpr4 inputCoverage; 45 46 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { 47 const char* name; 48 fUniformHandles.fColorUni = 49 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, 50 kVec4f_GrSLType, 51 "Color", 52 &name); 53 inputColor = GrGLSLExpr4(name); 54 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) { 55 inputColor = GrGLSLExpr4(1); 56 } 57 58 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { 59 const char* name; 60 fUniformHandles.fCoverageUni = 61 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, 62 kVec4f_GrSLType, 63 "Coverage", 64 &name); 65 inputCoverage = GrGLSLExpr4(name); 66 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { 67 inputCoverage = GrGLSLExpr4(1); 68 } 69 70 // Subclasses drive effect emitting 71 this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &inputColor, 72 &inputCoverage); 73 74 fFS.emitCodeAfterEffects(inputColor, inputCoverage); 75 76 if (!this->finish()) { 77 return false; 78 } 79 80 return true; 81 } 82 83 ////////////////////////////////////////////////////////////////////////////// 84 85 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, 86 const GrGLProgramDesc& desc) 87 : fEffectEmitter(NULL) 88 , fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly)) 89 , fTexCoordSetCnt(0) 90 , fProgramID(0) 91 , fFS(this, desc) 92 , fSeparableVaryingInfos(kVarsPerBlock) 93 , fGrProcessorEmitter(this) 94 , fDesc(desc) 95 , fGpu(gpu) 96 , fUniforms(kVarsPerBlock) { 97 } 98 99 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) { 100 if ('\0' == prefix) { 101 *out = name; 102 } else { 103 out->printf("%c%s", prefix, name); 104 } 105 if (fCodeStage.inStageCode()) { 106 if (out->endsWith('_')) { 107 // Names containing "__" are reserved. 108 out->append("x"); 109 } 110 out->appendf("_Stage%d", fCodeStage.stageIndex()); 111 } 112 } 113 114 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility, 115 GrSLType type, 116 const char* name, 117 int count, 118 const char** outName) { 119 SkASSERT(name && strlen(name)); 120 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); 121 SkASSERT(0 == (~kVisibilityMask & visibility)); 122 SkASSERT(0 != visibility); 123 124 UniformInfo& uni = fUniforms.push_back(); 125 uni.fVariable.setType(type); 126 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 127 this->nameVariable(uni.fVariable.accessName(), 'u', name); 128 uni.fVariable.setArrayCount(count); 129 uni.fVisibility = visibility; 130 131 // If it is visible in both the VS and FS, the precision must match. 132 // We declare a default FS precision, but not a default VS. So set the var 133 // to use the default FS precision. 134 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { 135 // the fragment and vertex precisions must match 136 uni.fVariable.setPrecision(kDefaultFragmentPrecision); 137 } 138 139 if (outName) { 140 *outName = uni.fVariable.c_str(); 141 } 142 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); 143 } 144 145 void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const { 146 for (int i = 0; i < vars.count(); ++i) { 147 vars[i].appendDecl(this->ctxInfo(), out); 148 out->append(";\n"); 149 } 150 } 151 152 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, 153 SkString* out) const { 154 for (int i = 0; i < fUniforms.count(); ++i) { 155 if (fUniforms[i].fVisibility & visibility) { 156 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); 157 out->append(";\n"); 158 } 159 } 160 } 161 162 void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStages[], 163 int effectCnt, 164 const GrGLProgramDesc::EffectKeyProvider& keyProvider, 165 GrGLSLExpr4* fsInOutColor) { 166 bool effectEmitted = false; 167 168 GrGLSLExpr4 inColor = *fsInOutColor; 169 GrGLSLExpr4 outColor; 170 171 for (int e = 0; e < effectCnt; ++e) { 172 fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor()); 173 fEffectEmitter = &fGrProcessorEmitter; 174 // calls into the subclass to emit the actual effect into the program effect object 175 this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor); 176 effectEmitted = true; 177 } 178 179 if (effectEmitted) { 180 *fsInOutColor = outColor; 181 } 182 } 183 184 void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage, 185 int effectIndex, 186 const GrGLProgramDesc::EffectKeyProvider& keyProvider, 187 GrGLSLExpr4* inColor, 188 GrGLSLExpr4* outColor) { 189 SkASSERT(effectStage.getProcessor()); 190 CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage); 191 192 if (inColor->isZeros()) { 193 SkString inColorName; 194 195 // Effects have no way to communicate zeros, they treat an empty string as ones. 196 this->nameVariable(&inColorName, '\0', "input"); 197 fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str()); 198 *inColor = inColorName; 199 } 200 201 // create var to hold stage result 202 SkString outColorName; 203 this->nameVariable(&outColorName, '\0', "output"); 204 fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str()); 205 *outColor = outColorName; 206 207 this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(), 208 inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.stageIndex()); 209 210 *inColor = *outColor; 211 } 212 213 void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect, 214 GrGLProcessor::TextureSamplerArray* outSamplers) { 215 SkTArray<GrGLProgramEffects::Sampler, true>& samplers = 216 this->getProgramEffects()->addSamplers(); 217 int numTextures = effect.numTextures(); 218 samplers.push_back_n(numTextures); 219 SkString name; 220 for (int t = 0; t < numTextures; ++t) { 221 name.printf("Sampler%d", t); 222 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility, 223 kSampler2D_GrSLType, 224 name.c_str()); 225 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, 226 (samplers[t].fUniform, effect.textureAccess(t))); 227 } 228 } 229 230 bool GrGLProgramBuilder::finish() { 231 SkASSERT(0 == fProgramID); 232 GL_CALL_RET(fProgramID, CreateProgram()); 233 if (!fProgramID) { 234 return false; 235 } 236 237 SkTDArray<GrGLuint> shadersToDelete; 238 239 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { 240 GL_CALL(DeleteProgram(fProgramID)); 241 return false; 242 } 243 244 this->bindProgramLocations(fProgramID); 245 246 GL_CALL(LinkProgram(fProgramID)); 247 248 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. 249 bool checkLinked = !fGpu->ctxInfo().isChromium(); 250 #ifdef SK_DEBUG 251 checkLinked = true; 252 #endif 253 if (checkLinked) { 254 GrGLint linked = GR_GL_INIT_ZERO; 255 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); 256 if (!linked) { 257 GrGLint infoLen = GR_GL_INIT_ZERO; 258 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 259 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 260 if (infoLen > 0) { 261 // retrieve length even though we don't need it to workaround 262 // bug in chrome cmd buffer param validation. 263 GrGLsizei length = GR_GL_INIT_ZERO; 264 GL_CALL(GetProgramInfoLog(fProgramID, 265 infoLen+1, 266 &length, 267 (char*)log.get())); 268 GrPrintf((char*)log.get()); 269 } 270 SkDEBUGFAIL("Error linking program"); 271 GL_CALL(DeleteProgram(fProgramID)); 272 fProgramID = 0; 273 return false; 274 } 275 } 276 277 this->resolveProgramLocations(fProgramID); 278 279 for (int i = 0; i < shadersToDelete.count(); ++i) { 280 GL_CALL(DeleteShader(shadersToDelete[i])); 281 } 282 283 return true; 284 } 285 286 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, 287 SkTDArray<GrGLuint>* shaderIds) const { 288 return fFS.compileAndAttachShaders(programId, shaderIds); 289 } 290 291 void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) { 292 fFS.bindProgramLocations(programId); 293 294 // skbug.com/2056 295 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; 296 if (usingBindUniform) { 297 int count = fUniforms.count(); 298 for (int i = 0; i < count; ++i) { 299 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str())); 300 fUniforms[i].fLocation = i; 301 } 302 } 303 } 304 305 void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { 306 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; 307 if (!usingBindUniform) { 308 int count = fUniforms.count(); 309 for (int i = 0; i < count; ++i) { 310 GrGLint location; 311 GL_CALL_RET(location, 312 GetUniformLocation(programId, fUniforms[i].fVariable.c_str())); 313 fUniforms[i].fLocation = location; 314 } 315 } 316 317 int count = fSeparableVaryingInfos.count(); 318 for (int i = 0; i < count; ++i) { 319 GrGLint location; 320 GL_CALL_RET(location, 321 GetProgramResourceLocation(programId, 322 GR_GL_FRAGMENT_INPUT, 323 fSeparableVaryingInfos[i].fVariable.c_str())); 324 fSeparableVaryingInfos[i].fLocation = location; 325 } 326 } 327 328 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { 329 return fGpu->ctxInfo(); 330 } 331