| 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" |
| 9 #include "gl/GrGLGeometryProcessor.h" |
| 8 #include "gl/GrGLProgram.h" | 10 #include "gl/GrGLProgram.h" |
| 9 #include "gl/GrGLSLPrettyPrint.h" | 11 #include "gl/GrGLSLPrettyPrint.h" |
| 10 #include "gl/GrGLUniformHandle.h" | 12 #include "gl/GrGLUniformHandle.h" |
| 13 #include "../GrGpuGL.h" |
| 11 #include "GrCoordTransform.h" | 14 #include "GrCoordTransform.h" |
| 12 #include "../GrGpuGL.h" | 15 #include "GrGLLegacyNvprProgramBuilder.h" |
| 13 #include "GrGLFragmentShaderBuilder.h" | 16 #include "GrGLNvprProgramBuilder.h" |
| 14 #include "GrGLProgramBuilder.h" | 17 #include "GrGLProgramBuilder.h" |
| 15 #include "GrTexture.h" | 18 #include "GrTexture.h" |
| 16 #include "GrGLVertexShaderBuilder.h" | |
| 17 #include "SkRTConf.h" | 19 #include "SkRTConf.h" |
| 18 #include "SkTraceEvent.h" | 20 #include "SkTraceEvent.h" |
| 19 | 21 |
| 20 namespace { | |
| 21 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 22 #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 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
| 23 | 24 |
| 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 | 25 // ES2 FS only guarantees mediump and lowp support |
| 28 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
:kMedium_Precision; | 26 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 | 27 |
| 83 ////////////////////////////////////////////////////////////////////////////// | 28 ////////////////////////////////////////////////////////////////////////////// |
| 84 | 29 |
| 30 const int GrGLProgramBuilder::kVarsPerBlock = 8; |
| 31 |
| 32 GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, |
| 33 const GrGLProgramDesc& desc, |
| 34 GrGpu::DrawType drawType, |
| 35 const GrGeometryStage* geometryPr
ocessor, |
| 36 const GrFragmentStage* colorStage
s[], |
| 37 const GrFragmentStage* coverageSt
ages[], |
| 38 GrGpuGL* gpu) { |
| 39 // create a builder. This will be handed off to effects so they can use it
to add |
| 40 // uniforms, varyings, textures, etc |
| 41 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc, |
| 42 optState, |
| 43 drawType, |
| 44 SkToBool(geom
etryProcessor), |
| 45 gpu)); |
| 46 |
| 47 GrGLProgramBuilder* pb = builder.get(); |
| 48 const GrGLProgramDesc::KeyHeader& header = pb->header(); |
| 49 |
| 50 // emit code to read the dst copy texture, if necessary |
| 51 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey |
| 52 && !gpu->glCaps().fbFetchSupport()) { |
| 53 pb->fFS.emitCodeToReadDstTexture(); |
| 54 } |
| 55 |
| 56 // get the initial color and coverage to feed into the first effect in each
effect chain |
| 57 GrGLSLExpr4 inputColor, inputCoverage; |
| 58 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); |
| 59 |
| 60 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES)
, then we may have |
| 61 // to setup a few more things like builtin vertex attributes |
| 62 bool hasVertexShader = !header.fUseFragShaderOnly; |
| 63 if (hasVertexShader) { |
| 64 pb->fVS.setupLocalCoords(); |
| 65 pb->fVS.transformGLToSkiaCoords(); |
| 66 if (header.fEmitsPointSize) { |
| 67 pb->fVS.codeAppend("gl_PointSize = 1.0;"); |
| 68 } |
| 69 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { |
| 70 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); |
| 71 } |
| 72 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { |
| 73 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); |
| 74 } |
| 75 } |
| 76 |
| 77 pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages,
&inputColor, |
| 78 &inputCoverage); |
| 79 |
| 80 if (hasVertexShader) { |
| 81 pb->fVS.transformSkiaToGLCoords(); |
| 82 } |
| 83 |
| 84 // write the secondary color output if necessary |
| 85 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType
) { |
| 86 pb->fFS.enableSecondaryOutput(inputColor, inputCoverage); |
| 87 } |
| 88 |
| 89 pb->fFS.combineColorAndCoverage(inputColor, inputCoverage); |
| 90 |
| 91 return pb->finalize(); |
| 92 } |
| 93 |
| 94 GrGLProgramBuilder* |
| 95 GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc, |
| 96 const GrOptDrawState& optState, |
| 97 GrGpu::DrawType drawType, |
| 98 bool hasGeometryProcessor, |
| 99 GrGpuGL* gpu) { |
| 100 if (desc.getHeader().fUseFragShaderOnly) { |
| 101 SkASSERT(gpu->glCaps().pathRenderingSupport()); |
| 102 SkASSERT(gpu->glPathRendering()->texturingMode() == |
| 103 GrGLPathRendering::FixedFunction_TexturingMode); |
| 104 SkASSERT(!hasGeometryProcessor); |
| 105 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc)); |
| 106 } else if (GrGpu::IsPathRenderingDrawType(drawType)) { |
| 107 SkASSERT(gpu->glCaps().pathRenderingSupport()); |
| 108 SkASSERT(gpu->glPathRendering()->texturingMode() == |
| 109 GrGLPathRendering::SeparableShaders_TexturingMode); |
| 110 SkASSERT(!hasGeometryProcessor); |
| 111 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc)); |
| 112 } else { |
| 113 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc)); |
| 114 } |
| 115 } |
| 116 |
| 117 ///////////////////////////////////////////////////////////////////////////// |
| 118 |
| 85 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optSt
ate, | 119 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optSt
ate, |
| 86 const GrGLProgramDesc& desc) | 120 const GrGLProgramDesc& desc) |
| 87 : fEffectEmitter(NULL) | 121 : fVS(this) |
| 88 , fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly)) | 122 , fGS(this) |
| 89 , fTexCoordSetCnt(0) | |
| 90 , fProgramID(0) | |
| 91 , fFS(this, desc) | 123 , fFS(this, desc) |
| 92 , fSeparableVaryingInfos(kVarsPerBlock) | 124 , fOutOfStage(true) |
| 93 , fGrProcessorEmitter(this) | 125 , fStageIndex(-1) |
| 94 , fOptState(optState) | 126 , fOptState(optState) |
| 95 , fDesc(desc) | 127 , fDesc(desc) |
| 96 , fGpu(gpu) | 128 , fGpu(gpu) |
| 97 , fUniforms(kVarsPerBlock) { | 129 , fUniforms(kVarsPerBlock) { |
| 98 } | 130 } |
| 99 | 131 |
| 132 void GrGLProgramBuilder::addVarying(GrSLType type, |
| 133 const char* name, |
| 134 const char** vsOutName, |
| 135 const char** fsInName, |
| 136 GrGLShaderVar::Precision fsPrecision) { |
| 137 SkString* fsInputName = fVS.addVarying(type, name, vsOutName); |
| 138 fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision); |
| 139 } |
| 140 |
| 100 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { | 141 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { |
| 101 if ('\0' == prefix) { | 142 if ('\0' == prefix) { |
| 102 *out = name; | 143 *out = name; |
| 103 } else { | 144 } else { |
| 104 out->printf("%c%s", prefix, name); | 145 out->printf("%c%s", prefix, name); |
| 105 } | 146 } |
| 106 if (fCodeStage.inStageCode()) { | 147 if (!fOutOfStage) { |
| 107 if (out->endsWith('_')) { | 148 if (out->endsWith('_')) { |
| 108 // Names containing "__" are reserved. | 149 // Names containing "__" are reserved. |
| 109 out->append("x"); | 150 out->append("x"); |
| 110 } | 151 } |
| 111 out->appendf("_Stage%d", fCodeStage.stageIndex()); | 152 out->appendf("_Stage%d", fStageIndex); |
| 112 } | 153 } |
| 113 } | 154 } |
| 114 | 155 |
| 115 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
_t visibility, | 156 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
_t visibility, |
| 116 GrSLTy
pe type, | 157 GrSLTy
pe type, |
| 117 const
char* name, | 158 const
char* name, |
| 118 int co
unt, | 159 int co
unt, |
| 119 const
char** outName) { | 160 const
char** outName) { |
| 120 SkASSERT(name && strlen(name)); | 161 SkASSERT(name && strlen(name)); |
| 121 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); | 162 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 136 // the fragment and vertex precisions must match | 177 // the fragment and vertex precisions must match |
| 137 uni.fVariable.setPrecision(kDefaultFragmentPrecision); | 178 uni.fVariable.setPrecision(kDefaultFragmentPrecision); |
| 138 } | 179 } |
| 139 | 180 |
| 140 if (outName) { | 181 if (outName) { |
| 141 *outName = uni.fVariable.c_str(); | 182 *outName = uni.fVariable.c_str(); |
| 142 } | 183 } |
| 143 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor
ms.count() - 1); | 184 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor
ms.count() - 1); |
| 144 } | 185 } |
| 145 | 186 |
| 146 void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const
{ | |
| 147 for (int i = 0; i < vars.count(); ++i) { | |
| 148 vars[i].appendDecl(this->ctxInfo(), out); | |
| 149 out->append(";\n"); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, | 187 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, |
| 154 SkString* out) const { | 188 SkString* out) const { |
| 155 for (int i = 0; i < fUniforms.count(); ++i) { | 189 for (int i = 0; i < fUniforms.count(); ++i) { |
| 156 if (fUniforms[i].fVisibility & visibility) { | 190 if (fUniforms[i].fVisibility & visibility) { |
| 157 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); | 191 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); |
| 158 out->append(";\n"); | 192 out->append(";\n"); |
| 159 } | 193 } |
| 160 } | 194 } |
| 161 } | 195 } |
| 162 | 196 |
| 163 void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStage
s[], | 197 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { |
| 164 int effectCnt, | 198 return fGpu->ctxInfo(); |
| 165 const GrGLProgramDesc::EffectKeyPr
ovider& keyProvider, | 199 } |
| 166 GrGLSLExpr4* fsInOutColor) { | 200 |
| 201 void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input
Color, |
| 202 GrGLSLExpr4* input
Coverage) { |
| 203 const GrGLProgramDesc::KeyHeader& header = this->header(); |
| 204 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { |
| 205 const char* name; |
| 206 fUniformHandles.fColorUni = |
| 207 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
| 208 kVec4f_GrSLType, |
| 209 "Color", |
| 210 &name); |
| 211 *inputColor = GrGLSLExpr4(name); |
| 212 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) { |
| 213 *inputColor = GrGLSLExpr4(1); |
| 214 } |
| 215 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { |
| 216 const char* name; |
| 217 fUniformHandles.fCoverageUni = |
| 218 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
| 219 kVec4f_GrSLType, |
| 220 "Coverage", |
| 221 &name); |
| 222 *inputCoverage = GrGLSLExpr4(name); |
| 223 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { |
| 224 *inputCoverage = GrGLSLExpr4(1); |
| 225 } |
| 226 } |
| 227 |
| 228 void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometry
Processor, |
| 229 const GrFragmentStage* colorSta
ges[], |
| 230 const GrFragmentStage* coverage
Stages[], |
| 231 GrGLSLExpr4* inputColor, |
| 232 GrGLSLExpr4* inputCoverage) { |
| 233 bool useLocalCoords = fVS.hasExplicitLocalCoords(); |
| 234 |
| 235 EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectT
ype); |
| 236 int numColorEffects = fDesc.numColorEffects(); |
| 237 GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorE
ffects, |
| 238 useLocalC
oords)); |
| 239 this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects,
colorKeyProvider, |
| 240 inputColor, ip); |
| 241 fColorEffects.reset(ip); |
| 242 |
| 243 if (geometryProcessor) { |
| 244 fVS.emitAttributes(*geometryProcessor->getProcessor()); |
| 245 EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProc
essor_EffectType); |
| 246 ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords)); |
| 247 this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gp
KeyProvider, |
| 248 inputCoverage, ip); |
| 249 fGeometryProcessor.reset(ip); |
| 250 } |
| 251 |
| 252 EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_E
ffectType); |
| 253 int numCoverageEffects = fDesc.numCoverageEffects(); |
| 254 ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords
)); |
| 255 this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEf
fects, |
| 256 coverageKeyProvider, inputCov
erage, ip); |
| 257 fCoverageEffects.reset(ip); |
| 258 } |
| 259 |
| 260 template <class ProcessorStage> |
| 261 void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processSt
ages[], |
| 262 int effectCnt, |
| 263 const EffectKeyProvider& keyPro
vider, |
| 264 GrGLSLExpr4* fsInOutColor, |
| 265 GrGLInstalledProcessors* instal
ledProcessors) { |
| 167 bool effectEmitted = false; | 266 bool effectEmitted = false; |
| 168 | 267 |
| 169 GrGLSLExpr4 inColor = *fsInOutColor; | 268 GrGLSLExpr4 inColor = *fsInOutColor; |
| 170 GrGLSLExpr4 outColor; | 269 GrGLSLExpr4 outColor; |
| 171 | 270 |
| 172 for (int e = 0; e < effectCnt; ++e) { | 271 for (int e = 0; e < effectCnt; ++e) { |
| 173 fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor()); | 272 // Program builders have a bit of state we need to clear with each effec
t |
| 174 fEffectEmitter = &fGrProcessorEmitter; | 273 AutoStageAdvance adv(this); |
| 175 // calls into the subclass to emit the actual effect into the program ef
fect object | 274 const ProcessorStage& stage = *processStages[e]; |
| 176 this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor); | 275 SkASSERT(stage.getProcessor()); |
| 276 |
| 277 if (inColor.isZeros()) { |
| 278 SkString inColorName; |
| 279 |
| 280 // Effects have no way to communicate zeros, they treat an empty str
ing as ones. |
| 281 this->nameVariable(&inColorName, '\0', "input"); |
| 282 fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str(
)); |
| 283 inColor = inColorName; |
| 284 } |
| 285 |
| 286 // create var to hold stage result |
| 287 SkString outColorName; |
| 288 this->nameVariable(&outColorName, '\0', "output"); |
| 289 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); |
| 290 outColor = outColorName; |
| 291 |
| 292 SkASSERT(installedProcessors); |
| 293 const typename ProcessorStage::Processor& processor = *stage.getProcesso
r(); |
| 294 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTrans
forms()); |
| 295 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextur
es()); |
| 296 |
| 297 this->emitTransforms(stage, &coords, installedProcessors); |
| 298 this->emitSamplers(processor, &samplers, installedProcessors); |
| 299 |
| 300 typename ProcessorStage::GLProcessor* glEffect = |
| 301 processor.getFactory().createGLInstance(processor); |
| 302 installedProcessors->addEffect(glEffect); |
| 303 |
| 304 // Enclose custom code in a block to avoid namespace conflicts |
| 305 SkString openBrace; |
| 306 openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name()); |
| 307 fFS.codeAppend(openBrace.c_str()); |
| 308 fVS.codeAppend(openBrace.c_str()); |
| 309 |
| 310 glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str()
, |
| 311 inColor.isOnes() ? NULL : inColor.c_str(), coords, sa
mplers); |
| 312 |
| 313 // We have to check that effects and the code they emit are consistent,
ie if an effect |
| 314 // asks for dst color, then the emit code needs to follow suit |
| 315 verify(processor); |
| 316 fFS.codeAppend("}"); |
| 317 fVS.codeAppend("}"); |
| 318 |
| 319 inColor = outColor; |
| 177 effectEmitted = true; | 320 effectEmitted = true; |
| 178 } | 321 } |
| 179 | 322 |
| 180 if (effectEmitted) { | 323 if (effectEmitted) { |
| 181 *fsInOutColor = outColor; | 324 *fsInOutColor = outColor; |
| 182 } | 325 } |
| 183 } | 326 } |
| 184 | 327 |
| 185 void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage, | 328 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { |
| 186 int effectIndex, | 329 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); |
| 187 const GrGLProgramDesc::EffectKeyProvider& ke
yProvider, | |
| 188 GrGLSLExpr4* inColor, | |
| 189 GrGLSLExpr4* outColor) { | |
| 190 SkASSERT(effectStage.getProcessor()); | |
| 191 CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage); | |
| 192 | |
| 193 if (inColor->isZeros()) { | |
| 194 SkString inColorName; | |
| 195 | |
| 196 // Effects have no way to communicate zeros, they treat an empty string
as ones. | |
| 197 this->nameVariable(&inColorName, '\0', "input"); | |
| 198 fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str
()); | |
| 199 *inColor = inColorName; | |
| 200 } | |
| 201 | |
| 202 // create var to hold stage result | |
| 203 SkString outColorName; | |
| 204 this->nameVariable(&outColorName, '\0', "output"); | |
| 205 fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str()); | |
| 206 *outColor = outColorName; | |
| 207 | |
| 208 this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(
), | |
| 209 inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.sta
geIndex()); | |
| 210 | |
| 211 *inColor = *outColor; | |
| 212 } | 330 } |
| 213 | 331 |
| 214 void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect, | 332 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { |
| 215 GrGLProcessor::TextureSamplerArray* outSam
plers) { | 333 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); |
| 216 SkTArray<GrGLProgramEffects::Sampler, true>& samplers = | 334 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor()); |
| 217 this->getProgramEffects()->addSamplers(); | 335 } |
| 218 int numTextures = effect.numTextures(); | 336 |
| 337 void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage, |
| 338 GrGLProcessor::TransformedCoordsArray* o
utCoords, |
| 339 GrGLInstalledProcessors* installedProces
sors) { |
| 340 SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = |
| 341 installedProcessors->addTransforms(); |
| 342 const GrProcessor* effect = effectStage.getProcessor(); |
| 343 int numTransforms = effect->numTransforms(); |
| 344 transforms.push_back_n(numTransforms); |
| 345 |
| 346 for (int t = 0; t < numTransforms; t++) { |
| 347 const char* uniName = "StageMatrix"; |
| 348 GrSLType varyingType = |
| 349 effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalC
oords()) ? |
| 350 kVec3f_GrSLType : |
| 351 kVec2f_GrSLType; |
| 352 |
| 353 SkString suffixedUniName; |
| 354 if (0 != t) { |
| 355 suffixedUniName.append(uniName); |
| 356 suffixedUniName.appendf("_%i", t); |
| 357 uniName = suffixedUniName.c_str(); |
| 358 } |
| 359 transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Vis
ibility, |
| 360 kMat33f_GrSLType, |
| 361 uniName, |
| 362 &uniName).toShaderBuilderIndex(
); |
| 363 |
| 364 const char* varyingName = "MatrixCoord"; |
| 365 SkString suffixedVaryingName; |
| 366 if (0 != t) { |
| 367 suffixedVaryingName.append(varyingName); |
| 368 suffixedVaryingName.appendf("_%i", t); |
| 369 varyingName = suffixedVaryingName.c_str(); |
| 370 } |
| 371 const char* vsVaryingName; |
| 372 const char* fsVaryingName; |
| 373 this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingNam
e); |
| 374 |
| 375 const GrGLShaderVar& coords = |
| 376 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords()
? |
| 377 fVS.positionAttribute() : |
| 378 fVS.localCoordsAttribute(); |
| 379 |
| 380 // varying = matrix * coords (logically) |
| 381 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); |
| 382 if (kVec2f_GrSLType == varyingType) { |
| 383 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;", |
| 384 vsVaryingName, uniName, coords.c_str()); |
| 385 } else { |
| 386 fVS.codeAppendf("%s = %s * vec3(%s, 1);", |
| 387 vsVaryingName, uniName, coords.c_str()); |
| 388 } |
| 389 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, |
| 390 (SkString(fsVaryingName), varyingType)); |
| 391 } |
| 392 } |
| 393 |
| 394 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
| 395 GrGLProcessor::TextureSamplerArray* outSam
plers, |
| 396 GrGLInstalledProcessors* installedProcesso
rs) { |
| 397 SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProces
sors->addSamplers(); |
| 398 int numTextures = processor.numTextures(); |
| 219 samplers.push_back_n(numTextures); | 399 samplers.push_back_n(numTextures); |
| 220 SkString name; | 400 SkString name; |
| 221 for (int t = 0; t < numTextures; ++t) { | 401 for (int t = 0; t < numTextures; ++t) { |
| 222 name.printf("Sampler%d", t); | 402 name.printf("Sampler%d", t); |
| 223 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Vi
sibility, | 403 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Vi
sibility, |
| 224 kSampler2D_GrSLType, | 404 kSampler2D_GrSLType, |
| 225 name.c_str()); | 405 name.c_str()); |
| 226 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, | 406 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, |
| 227 (samplers[t].fUniform, effect.textureAccess(t))); | 407 (samplers[t].fUniform, processor.textureAccess(t)
)); |
| 228 } | 408 } |
| 229 } | 409 } |
| 230 | 410 |
| 231 bool GrGLProgramBuilder::finish() { | 411 GrGLProgram* GrGLProgramBuilder::finalize() { |
| 232 SkASSERT(0 == fProgramID); | 412 // verify we can get a program id |
| 233 GL_CALL_RET(fProgramID, CreateProgram()); | 413 GrGLuint programID; |
| 234 if (!fProgramID) { | 414 GL_CALL_RET(programID, CreateProgram()); |
| 235 return false; | 415 if (0 == programID) { |
| 416 return NULL; |
| 236 } | 417 } |
| 237 | 418 |
| 419 // compile shaders and bind attributes / uniforms |
| 238 SkTDArray<GrGLuint> shadersToDelete; | 420 SkTDArray<GrGLuint> shadersToDelete; |
| 239 | 421 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { |
| 240 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { | 422 this->cleanupProgram(programID, shadersToDelete); |
| 241 GL_CALL(DeleteProgram(fProgramID)); | 423 return NULL; |
| 242 return false; | |
| 243 } | 424 } |
| 244 | 425 if (!this->header().fUseFragShaderOnly) { |
| 245 this->bindProgramLocations(fProgramID); | 426 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { |
| 246 | 427 this->cleanupProgram(programID, shadersToDelete); |
| 247 GL_CALL(LinkProgram(fProgramID)); | 428 return NULL; |
| 429 } |
| 430 fVS.bindVertexAttributes(programID); |
| 431 } |
| 432 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; |
| 433 if (usingBindUniform) { |
| 434 this->bindUniformLocations(programID); |
| 435 } |
| 436 fFS.bindFragmentShaderLocations(programID); |
| 437 GL_CALL(LinkProgram(programID)); |
| 248 | 438 |
| 249 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. | 439 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. |
| 250 bool checkLinked = !fGpu->ctxInfo().isChromium(); | 440 bool checkLinked = !fGpu->ctxInfo().isChromium(); |
| 251 #ifdef SK_DEBUG | 441 #ifdef SK_DEBUG |
| 252 checkLinked = true; | 442 checkLinked = true; |
| 253 #endif | 443 #endif |
| 254 if (checkLinked) { | 444 if (checkLinked) { |
| 255 GrGLint linked = GR_GL_INIT_ZERO; | 445 checkLinkStatus(programID); |
| 256 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); | 446 } |
| 257 if (!linked) { | 447 if (!usingBindUniform) { |
| 258 GrGLint infoLen = GR_GL_INIT_ZERO; | 448 this->resolveUniformLocations(programID); |
| 259 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); | |
| 260 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debug
ger | |
| 261 if (infoLen > 0) { | |
| 262 // retrieve length even though we don't need it to workaround | |
| 263 // bug in chrome cmd buffer param validation. | |
| 264 GrGLsizei length = GR_GL_INIT_ZERO; | |
| 265 GL_CALL(GetProgramInfoLog(fProgramID, | |
| 266 infoLen+1, | |
| 267 &length, | |
| 268 (char*)log.get())); | |
| 269 GrPrintf((char*)log.get()); | |
| 270 } | |
| 271 SkDEBUGFAIL("Error linking program"); | |
| 272 GL_CALL(DeleteProgram(fProgramID)); | |
| 273 fProgramID = 0; | |
| 274 return false; | |
| 275 } | |
| 276 } | 449 } |
| 277 | 450 |
| 278 this->resolveProgramLocations(fProgramID); | 451 this->cleanupShaders(shadersToDelete); |
| 279 | 452 |
| 280 for (int i = 0; i < shadersToDelete.count(); ++i) { | 453 return this->createProgram(programID); |
| 281 GL_CALL(DeleteShader(shadersToDelete[i])); | |
| 282 } | |
| 283 | |
| 284 return true; | |
| 285 } | 454 } |
| 286 | 455 |
| 287 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, | 456 void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) { |
| 288 SkTDArray<GrGLuint>* shaderIds)
const { | 457 int count = fUniforms.count(); |
| 289 return fFS.compileAndAttachShaders(programId, shaderIds); | 458 for (int i = 0; i < count; ++i) { |
| 290 } | 459 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()
)); |
| 291 | 460 fUniforms[i].fLocation = i; |
| 292 void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) { | |
| 293 fFS.bindProgramLocations(programId); | |
| 294 | |
| 295 // skbug.com/2056 | |
| 296 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | |
| 297 if (usingBindUniform) { | |
| 298 int count = fUniforms.count(); | |
| 299 for (int i = 0; i < count; ++i) { | |
| 300 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_s
tr())); | |
| 301 fUniforms[i].fLocation = i; | |
| 302 } | |
| 303 } | 461 } |
| 304 } | 462 } |
| 305 | 463 |
| 306 void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { | 464 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { |
| 307 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | 465 GrGLint linked = GR_GL_INIT_ZERO; |
| 308 if (!usingBindUniform) { | 466 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); |
| 309 int count = fUniforms.count(); | 467 if (!linked) { |
| 310 for (int i = 0; i < count; ++i) { | 468 GrGLint infoLen = GR_GL_INIT_ZERO; |
| 311 GrGLint location; | 469 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
| 312 GL_CALL_RET(location, | 470 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
| 313 GetUniformLocation(programId, fUniforms[i].fVariable.c_s
tr())); | 471 if (infoLen > 0) { |
| 314 fUniforms[i].fLocation = location; | 472 // retrieve length even though we don't need it to workaround |
| 473 // bug in chrome cmd buffer param validation. |
| 474 GrGLsizei length = GR_GL_INIT_ZERO; |
| 475 GL_CALL(GetProgramInfoLog(programID, |
| 476 infoLen+1, |
| 477 &length, |
| 478 (char*)log.get())); |
| 479 GrPrintf((char*)log.get()); |
| 315 } | 480 } |
| 481 SkDEBUGFAIL("Error linking program"); |
| 482 GL_CALL(DeleteProgram(programID)); |
| 483 programID = 0; |
| 316 } | 484 } |
| 485 return SkToBool(linked); |
| 486 } |
| 317 | 487 |
| 318 int count = fSeparableVaryingInfos.count(); | 488 void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) { |
| 489 int count = fUniforms.count(); |
| 319 for (int i = 0; i < count; ++i) { | 490 for (int i = 0; i < count; ++i) { |
| 320 GrGLint location; | 491 GrGLint location; |
| 321 GL_CALL_RET(location, | 492 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariab
le.c_str())); |
| 322 GetProgramResourceLocation(programId, | 493 fUniforms[i].fLocation = location; |
| 323 GR_GL_FRAGMENT_INPUT, | |
| 324 fSeparableVaryingInfos[i].fVariab
le.c_str())); | |
| 325 fSeparableVaryingInfos[i].fLocation = location; | |
| 326 } | 494 } |
| 327 } | 495 } |
| 328 | 496 |
| 329 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { | 497 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL
uint>& shaderIDs) { |
| 330 return fGpu->ctxInfo(); | 498 GL_CALL(DeleteProgram(programID)); |
| 499 cleanupShaders(shaderIDs); |
| 331 } | 500 } |
| 501 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { |
| 502 for (int i = 0; i < shaderIDs.count(); ++i) { |
| 503 GL_CALL(DeleteShader(shaderIDs[i])); |
| 504 } |
| 505 } |
| 506 |
| 507 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
| 508 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUn
iforms, |
| 509 fGeometryProcessor, fColorEffects, fCoverage
Effects)); |
| 510 } |
| 511 |
| 512 //////////////////////////////////////////////////////////////////////////////// |
| 513 |
| 514 GrGLInstalledProcessors::~GrGLInstalledProcessors() { |
| 515 int numEffects = fGLProcessors.count(); |
| 516 for (int e = 0; e < numEffects; ++e) { |
| 517 SkDELETE(fGLProcessors[e]); |
| 518 } |
| 519 } |
| OLD | NEW |