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