OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGLProgramBuilder.h" | 8 #include "GrGLProgramBuilder.h" |
9 #include "gl/GrGLProgram.h" | 9 #include "gl/GrGLProgram.h" |
10 #include "gl/GrGLSLPrettyPrint.h" | 10 #include "gl/GrGLSLPrettyPrint.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey | 45 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey |
46 && !gpu->glCaps().fbFetchSupport()) { | 46 && !gpu->glCaps().fbFetchSupport()) { |
47 pb->fFS.emitCodeToReadDstTexture(); | 47 pb->fFS.emitCodeToReadDstTexture(); |
48 } | 48 } |
49 | 49 |
50 // get the initial color and coverage to feed into the first effect in each
effect chain | 50 // get the initial color and coverage to feed into the first effect in each
effect chain |
51 GrGLSLExpr4 inputColor; | 51 GrGLSLExpr4 inputColor; |
52 GrGLSLExpr1 inputCoverage; | 52 GrGLSLExpr1 inputCoverage; |
53 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); | 53 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); |
54 | 54 |
55 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES)
, then we may have | 55 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can |
56 // to setup a few more things like builtin vertex attributes | 56 // remove this cast to a vec4. |
57 bool hasVertexShader = !(header.fUseNvpr && | 57 GrGLSLExpr4 inputCoverageVec4; |
58 gpu->glPathRendering()->texturingMode() == | 58 if (inputCoverage.isValid()) { |
59 GrGLPathRendering::FixedFunction_TexturingMode); | 59 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); |
60 | |
61 if (hasVertexShader) { | |
62 pb->fVS.setupUniformViewMatrix(); | |
63 pb->fVS.setupPositionAndLocalCoords(); | |
64 | |
65 if (header.fEmitsPointSize) { | |
66 pb->fVS.codeAppend("gl_PointSize = 1.0;"); | |
67 } | |
68 if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { | |
69 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); | |
70 } | |
71 if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { | |
72 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); | |
73 } | |
74 } | 60 } |
75 | 61 |
76 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can | |
77 // remove this cast to a vec4. | |
78 GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); | |
79 | |
80 pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4); | 62 pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4); |
81 | 63 |
82 if (hasVertexShader) { | |
83 pb->fVS.transformToNormalizedDeviceSpace(); | |
84 } | |
85 | |
86 // write the secondary color output if necessary | 64 // write the secondary color output if necessary |
87 if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType)
{ | 65 if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType)
{ |
88 pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4); | 66 pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4); |
89 } | 67 } |
90 | 68 |
91 pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4); | 69 pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4); |
92 | 70 |
93 return pb->finalize(); | 71 return pb->finalize(); |
94 } | 72 } |
95 | 73 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 fVS.addVarying(name, varying); | 116 fVS.addVarying(name, varying); |
139 } | 117 } |
140 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->wi
llUseGeoShader()) { | 118 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->wi
llUseGeoShader()) { |
141 fGS.addVarying(name, varying); | 119 fGS.addVarying(name, varying); |
142 } | 120 } |
143 if (varying->fsVarying()) { | 121 if (varying->fsVarying()) { |
144 fFS.addVarying(varying, fsPrecision); | 122 fFS.addVarying(varying, fsPrecision); |
145 } | 123 } |
146 } | 124 } |
147 | 125 |
| 126 void GrGLProgramBuilder::addPassThroughAttribute(const GrGeometryProcessor::GrAt
tribute* input, |
| 127 const char* output) { |
| 128 GrSLType type = GrVertexAttribTypeToSLType(input->fType); |
| 129 GrGLVertToFrag v(type); |
| 130 this->addVarying(input->fName, &v); |
| 131 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); |
| 132 fFS.codeAppendf("%s = %s;", output, v.fsIn()); |
| 133 } |
| 134 |
148 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { | 135 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me) { |
149 if ('\0' == prefix) { | 136 if ('\0' == prefix) { |
150 *out = name; | 137 *out = name; |
151 } else { | 138 } else { |
152 out->printf("%c%s", prefix, name); | 139 out->printf("%c%s", prefix, name); |
153 } | 140 } |
154 if (!fOutOfStage) { | 141 if (!fOutOfStage) { |
155 if (out->endsWith('_')) { | 142 if (out->endsWith('_')) { |
156 // Names containing "__" are reserved. | 143 // Names containing "__" are reserved. |
157 out->append("x"); | 144 out->append("x"); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, | 222 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
236 kFloat_GrSLType, | 223 kFloat_GrSLType, |
237 "Coverage", | 224 "Coverage", |
238 &name); | 225 &name); |
239 *inputCoverage = GrGLSLExpr1(name); | 226 *inputCoverage = GrGLSLExpr1(name); |
240 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { | 227 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { |
241 *inputCoverage = GrGLSLExpr1(1); | 228 *inputCoverage = GrGLSLExpr1(1); |
242 } | 229 } |
243 } | 230 } |
244 | 231 |
245 void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, | 232 void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr
4* inputCoverage) { |
246 GrGLSLExpr4* inputCoverage) { | 233 if (fOptState.hasGeometryProcessor()) { |
| 234 fVS.setupUniformViewMatrix(); |
| 235 |
| 236 const GrProgramDesc::KeyHeader& header = this->header(); |
| 237 if (header.fEmitsPointSize) { |
| 238 fVS.codeAppend("gl_PointSize = 1.0;"); |
| 239 } |
| 240 |
| 241 // Setup position |
| 242 // TODO it'd be possible to remove these from the vertexshader builder a
nd have them |
| 243 // be outputs from the emit call. We don't do this because emitargs is
constant. It would |
| 244 // be easy to change this though |
| 245 fVS.codeAppendf("vec3 %s;", fVS.glPosition()); |
| 246 fVS.codeAppendf("vec2 %s;", fVS.positionCoords()); |
| 247 fVS.codeAppendf("vec2 %s;", fVS.localCoords()); |
| 248 |
| 249 const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); |
| 250 fVS.emitAttributes(gp); |
| 251 GrGLSLExpr4 outputColor; |
| 252 GrGLSLExpr4 outputCoverage; |
| 253 this->emitAndInstallProc(gp, &outputColor, &outputCoverage); |
| 254 |
| 255 // We may override color and coverage here if we have unform color or co
verage. This is |
| 256 // obviously not ideal. |
| 257 // TODO lets the GP itself do the override |
| 258 if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { |
| 259 *inputColor = outputColor; |
| 260 } |
| 261 if (GrProgramDesc::kUniform_ColorInput != header.fCoverageInput) { |
| 262 *inputCoverage = outputCoverage; |
| 263 } |
| 264 } |
| 265 |
247 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); | 266 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); |
248 int numProcs = fOptState.numFragmentStages(); | 267 int numProcs = fOptState.numFragmentStages(); |
249 this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); | 268 this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); |
| 269 this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, inputCo
verage); |
| 270 |
250 if (fOptState.hasGeometryProcessor()) { | 271 if (fOptState.hasGeometryProcessor()) { |
251 const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); | 272 fVS.transformToNormalizedDeviceSpace(); |
252 fVS.emitAttributes(gp); | |
253 GrGLSLExpr4 output; | |
254 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, *inputCoverage, &ou
tput); | |
255 *inputCoverage = output; | |
256 } | 273 } |
257 this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, inputCo
verage); | |
258 } | 274 } |
259 | 275 |
260 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, G
rGLSLExpr4* inOut) { | 276 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, |
| 277 int numProcs, |
| 278 GrGLSLExpr4* inOut) { |
261 for (int e = procOffset; e < numProcs; ++e) { | 279 for (int e = procOffset; e < numProcs; ++e) { |
262 GrGLSLExpr4 output; | 280 GrGLSLExpr4 output; |
263 const GrPendingFragmentStage& stage = fOptState.getFragmentStage(e); | 281 const GrPendingFragmentStage& stage = fOptState.getFragmentStage(e); |
264 this->emitAndInstallProc<GrPendingFragmentStage>(stage, e, *inOut, &outp
ut); | 282 this->emitAndInstallProc(stage, e, *inOut, &output); |
265 *inOut = output; | 283 *inOut = output; |
266 } | 284 } |
267 } | 285 } |
268 | 286 |
| 287 void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseNam
e) { |
| 288 // create var to hold stage result. If we already have a valid output name,
just use that |
| 289 // otherwise create a new mangled one. This name is only valid if we are re
ordering stages |
| 290 // and have to tell stage exactly where to put its output. |
| 291 SkString outName; |
| 292 if (output->isValid()) { |
| 293 outName = output->c_str(); |
| 294 } else { |
| 295 this->nameVariable(&outName, '\0', baseName); |
| 296 } |
| 297 fFS.codeAppendf("vec4 %s;", outName.c_str()); |
| 298 *output = outName; |
| 299 } |
| 300 |
269 // TODO Processors cannot output zeros because an empty string is all 1s | 301 // TODO Processors cannot output zeros because an empty string is all 1s |
270 // the fix is to allow effects to take the GrGLSLExpr4 directly | 302 // the fix is to allow effects to take the GrGLSLExpr4 directly |
271 template <class Proc> | 303 void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc, |
272 void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, | |
273 int index, | 304 int index, |
274 const GrGLSLExpr4& input, | 305 const GrGLSLExpr4& input, |
275 GrGLSLExpr4* output) { | 306 GrGLSLExpr4* output) { |
276 // Program builders have a bit of state we need to clear with each effect | 307 // Program builders have a bit of state we need to clear with each effect |
277 AutoStageAdvance adv(this); | 308 AutoStageAdvance adv(this); |
278 | 309 this->nameExpression(output, "output"); |
279 // create var to hold stage result. If we already have a valid output name,
just use that | |
280 // otherwise create a new mangled one. | |
281 SkString outColorName; | |
282 if (output->isValid()) { | |
283 outColorName = output->c_str(); | |
284 } else { | |
285 this->nameVariable(&outColorName, '\0', "output"); | |
286 } | |
287 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); | |
288 *output = outColorName; | |
289 | 310 |
290 // Enclose custom code in a block to avoid namespace conflicts | 311 // Enclose custom code in a block to avoid namespace conflicts |
291 SkString openBrace; | 312 SkString openBrace; |
292 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); | 313 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); |
293 fFS.codeAppend(openBrace.c_str()); | 314 fFS.codeAppend(openBrace.c_str()); |
294 | 315 |
295 this->emitAndInstallProc(proc, output->c_str(), input.isOnes() ? NULL : inpu
t.c_str()); | 316 this->emitAndInstallProc(proc, output->c_str(), input.isOnes() ? NULL : inpu
t.c_str()); |
296 | 317 |
297 fFS.codeAppend("}"); | 318 fFS.codeAppend("}"); |
298 } | 319 } |
299 | 320 |
| 321 void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& proc, |
| 322 GrGLSLExpr4* outputColor, |
| 323 GrGLSLExpr4* outputCoverage) { |
| 324 // Program builders have a bit of state we need to clear with each effect |
| 325 AutoStageAdvance adv(this); |
| 326 this->nameExpression(outputColor, "outputColor"); |
| 327 this->nameExpression(outputCoverage, "outputCoverage"); |
| 328 |
| 329 // Enclose custom code in a block to avoid namespace conflicts |
| 330 SkString openBrace; |
| 331 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); |
| 332 fFS.codeAppend(openBrace.c_str()); |
| 333 |
| 334 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()
); |
| 335 |
| 336 fFS.codeAppend("}"); |
| 337 } |
| 338 |
300 void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, | 339 void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, |
301 const char* outColor, | 340 const char* outColor, |
302 const char* inColor) { | 341 const char* inColor) { |
303 GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocal
Coords())); | 342 GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc); |
304 | 343 |
305 const GrFragmentProcessor& fp = *fs.getProcessor(); | 344 const GrFragmentProcessor& fp = *fs.getProcessor(); |
306 ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp)); | 345 ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp)); |
307 | 346 |
308 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures()); | 347 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures()); |
309 this->emitSamplers(fp, &samplers, ifp); | 348 this->emitSamplers(fp, &samplers, ifp); |
310 | 349 |
311 // Fragment processors can have coord transforms | 350 // Fragment processors can have coord transforms |
312 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms()); | 351 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms()); |
313 this->emitTransforms(fs, &coords, ifp); | 352 this->emitTransforms(fs, &coords, ifp); |
314 | 353 |
315 ifp->fGLProc->emitCode(this, fp, outColor, inColor, coords, samplers); | 354 ifp->fGLProc->emitCode(this, fp, outColor, inColor, coords, samplers); |
316 | 355 |
317 // We have to check that effects and the code they emit are consistent, ie i
f an effect | 356 // We have to check that effects and the code they emit are consistent, ie i
f an effect |
318 // asks for dst color, then the emit code needs to follow suit | 357 // asks for dst color, then the emit code needs to follow suit |
319 verify(fp); | 358 verify(fp); |
320 fFragmentProcessors->fProcs.push_back(ifp); | 359 fFragmentProcessors->fProcs.push_back(ifp); |
321 } | 360 } |
322 | 361 |
323 void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, | 362 void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, |
324 const char* outCoverage, | 363 const char* outColor, |
325 const char* inCoverage) { | 364 const char* outCoverage) { |
326 SkASSERT(!fGeometryProcessor); | 365 SkASSERT(!fGeometryProcessor); |
327 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); | 366 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); |
328 | 367 |
329 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp)); | 368 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp)); |
330 | 369 |
331 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); | 370 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); |
332 this->emitSamplers(gp, &samplers, fGeometryProcessor); | 371 this->emitSamplers(gp, &samplers, fGeometryProcessor); |
333 | 372 |
334 GrGLGeometryProcessor::EmitArgs args(this, gp, outCoverage, inCoverage, samp
lers); | 373 GrGLGeometryProcessor::EmitArgs args(this, gp, outColor, outCoverage, sample
rs); |
335 fGeometryProcessor->fGLProc->emitCode(args); | 374 fGeometryProcessor->fGLProc->emitCode(args); |
336 | 375 |
337 // We have to check that effects and the code they emit are consistent, ie i
f an effect | 376 // We have to check that effects and the code they emit are consistent, ie i
f an effect |
338 // asks for dst color, then the emit code needs to follow suit | 377 // asks for dst color, then the emit code needs to follow suit |
339 verify(gp); | 378 verify(gp); |
340 } | 379 } |
341 | 380 |
342 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { | 381 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) { |
343 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); | 382 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); |
344 } | 383 } |
(...skipping 25 matching lines...) Expand all Loading... |
370 uniName, | 409 uniName, |
371 &uniName).toShaderBuilder
Index(); | 410 &uniName).toShaderBuilder
Index(); |
372 | 411 |
373 const char* varyingName = "MatrixCoord"; | 412 const char* varyingName = "MatrixCoord"; |
374 SkString suffixedVaryingName; | 413 SkString suffixedVaryingName; |
375 if (0 != t) { | 414 if (0 != t) { |
376 suffixedVaryingName.append(varyingName); | 415 suffixedVaryingName.append(varyingName); |
377 suffixedVaryingName.appendf("_%i", t); | 416 suffixedVaryingName.appendf("_%i", t); |
378 varyingName = suffixedVaryingName.c_str(); | 417 varyingName = suffixedVaryingName.c_str(); |
379 } | 418 } |
380 const char* coords = kPosition_GrCoordSet == processor->coordTransform(t
).sourceCoords() ? | 419 |
381 fVS.positionAttribute().c_s
tr() : | 420 bool useLocalCoords = kLocal_GrCoordSet == processor->coordTransform(t).
sourceCoords(); |
382 fVS.localCoordsAttribute().
c_str(); | 421 const char* coords = useLocalCoords ? fVS.localCoords() : fVS.positionCo
ords(); |
| 422 |
383 GrGLVertToFrag v(varyingType); | 423 GrGLVertToFrag v(varyingType); |
384 this->addCoordVarying(varyingName, &v, uniName, coords); | 424 this->addCoordVarying(varyingName, &v, uniName, coords); |
385 | 425 |
386 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); | 426 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); |
387 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, | 427 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, |
388 (SkString(v.fsIn()), varyingType)); | 428 (SkString(v.fsIn()), varyingType)); |
389 } | 429 } |
390 } | 430 } |
391 | 431 |
392 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | 432 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
(...skipping 19 matching lines...) Expand all Loading... |
412 if (0 == programID) { | 452 if (0 == programID) { |
413 return NULL; | 453 return NULL; |
414 } | 454 } |
415 | 455 |
416 // compile shaders and bind attributes / uniforms | 456 // compile shaders and bind attributes / uniforms |
417 SkTDArray<GrGLuint> shadersToDelete; | 457 SkTDArray<GrGLuint> shadersToDelete; |
418 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { | 458 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { |
419 this->cleanupProgram(programID, shadersToDelete); | 459 this->cleanupProgram(programID, shadersToDelete); |
420 return NULL; | 460 return NULL; |
421 } | 461 } |
| 462 |
422 if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr && | 463 if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr && |
423 fGpu->glPathRendering()->texturingMode() == | 464 fGpu->glPathRendering()->texturingMode() == |
424 GrGLPathRendering::FixedFunction_TexturingMode)) { | 465 GrGLPathRendering::FixedFunction_TexturingMode)) { |
425 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { | 466 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { |
426 this->cleanupProgram(programID, shadersToDelete); | 467 this->cleanupProgram(programID, shadersToDelete); |
427 return NULL; | 468 return NULL; |
428 } | 469 } |
429 fVS.bindVertexAttributes(programID); | 470 |
| 471 // Non fixed function NVPR actually requires a vertex shader to compile |
| 472 if (fOptState.hasGeometryProcessor()) { |
| 473 fVS.bindVertexAttributes(programID); |
| 474 } |
430 } | 475 } |
431 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | 476 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; |
432 if (usingBindUniform) { | 477 if (usingBindUniform) { |
433 this->bindUniformLocations(programID); | 478 this->bindUniformLocations(programID); |
434 } | 479 } |
435 fFS.bindFragmentShaderLocations(programID); | 480 fFS.bindFragmentShaderLocations(programID); |
436 GL_CALL(LinkProgram(programID)); | 481 GL_CALL(LinkProgram(programID)); |
437 | 482 |
438 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. | 483 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. |
439 bool checkLinked = !fGpu->ctxInfo().isChromium(); | 484 bool checkLinked = !fGpu->ctxInfo().isChromium(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 } | 554 } |
510 | 555 |
511 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 556 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
512 | 557 |
513 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 558 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
514 int numProcs = fProcs.count(); | 559 int numProcs = fProcs.count(); |
515 for (int e = 0; e < numProcs; ++e) { | 560 for (int e = 0; e < numProcs; ++e) { |
516 SkDELETE(fProcs[e]); | 561 SkDELETE(fProcs[e]); |
517 } | 562 } |
518 } | 563 } |
OLD | NEW |