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 19 matching lines...) Expand all Loading... |
30 | 30 |
31 GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, | 31 GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, |
32 const GrGLProgramDesc& desc, | 32 const GrGLProgramDesc& desc, |
33 GrGpu::DrawType drawType, | 33 GrGpu::DrawType drawType, |
34 GrGpuGL* gpu) { | 34 GrGpuGL* gpu) { |
35 // create a builder. This will be handed off to effects so they can use it
to add | 35 // create a builder. This will be handed off to effects so they can use it
to add |
36 // uniforms, varyings, textures, etc | 36 // uniforms, varyings, textures, etc |
37 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc, | 37 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc, |
38 optState, | 38 optState, |
39 drawType, | 39 drawType, |
40 optState.hasG
eometryProcessor(), | |
41 gpu)); | 40 gpu)); |
42 | 41 return builder->create(); |
43 GrGLProgramBuilder* pb = builder.get(); | |
44 const GrGLProgramDesc::KeyHeader& header = pb->header(); | |
45 | |
46 // emit code to read the dst copy texture, if necessary | |
47 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey | |
48 && !gpu->glCaps().fbFetchSupport()) { | |
49 pb->fFS.emitCodeToReadDstTexture(); | |
50 } | |
51 | |
52 // get the initial color and coverage to feed into the first effect in each
effect chain | |
53 GrGLSLExpr4 inputColor, inputCoverage; | |
54 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); | |
55 | |
56 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES)
, then we may have | |
57 // to setup a few more things like builtin vertex attributes | |
58 bool hasVertexShader = !header.fUseFragShaderOnly; | |
59 if (hasVertexShader) { | |
60 pb->fVS.setupLocalCoords(); | |
61 pb->fVS.transformGLToSkiaCoords(); | |
62 if (header.fEmitsPointSize) { | |
63 pb->fVS.codeAppend("gl_PointSize = 1.0;"); | |
64 } | |
65 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { | |
66 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); | |
67 } | |
68 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { | |
69 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); | |
70 } | |
71 } | |
72 | |
73 pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage); | |
74 | |
75 if (hasVertexShader) { | |
76 pb->fVS.transformSkiaToGLCoords(); | |
77 } | |
78 | |
79 // write the secondary color output if necessary | |
80 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType
) { | |
81 pb->fFS.enableSecondaryOutput(inputColor, inputCoverage); | |
82 } | |
83 | |
84 pb->fFS.combineColorAndCoverage(inputColor, inputCoverage); | |
85 | |
86 return pb->finalize(); | |
87 } | 42 } |
88 | 43 |
89 GrGLProgramBuilder* | 44 GrGLProgramBuilder* |
90 GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc, | 45 GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc, |
91 const GrOptDrawState& optState, | 46 const GrOptDrawState& optState, |
92 GrGpu::DrawType drawType, | 47 GrGpu::DrawType drawType, |
93 bool hasGeometryProcessor, | |
94 GrGpuGL* gpu) { | 48 GrGpuGL* gpu) { |
| 49 // We always have a GP but it gets ignored for nvpr |
95 if (desc.getHeader().fUseFragShaderOnly) { | 50 if (desc.getHeader().fUseFragShaderOnly) { |
96 SkASSERT(gpu->glCaps().pathRenderingSupport()); | 51 SkASSERT(gpu->glCaps().pathRenderingSupport()); |
97 SkASSERT(gpu->glPathRendering()->texturingMode() == | 52 SkASSERT(gpu->glPathRendering()->texturingMode() == |
98 GrGLPathRendering::FixedFunction_TexturingMode); | 53 GrGLPathRendering::FixedFunction_TexturingMode); |
99 SkASSERT(!hasGeometryProcessor); | |
100 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc)); | 54 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc)); |
101 } else if (GrGpu::IsPathRenderingDrawType(drawType)) { | 55 } else if (GrGpu::IsPathRenderingDrawType(drawType)) { |
102 SkASSERT(gpu->glCaps().pathRenderingSupport()); | 56 SkASSERT(gpu->glCaps().pathRenderingSupport()); |
103 SkASSERT(gpu->glPathRendering()->texturingMode() == | 57 SkASSERT(gpu->glPathRendering()->texturingMode() == |
104 GrGLPathRendering::SeparableShaders_TexturingMode); | 58 GrGLPathRendering::SeparableShaders_TexturingMode); |
105 SkASSERT(!hasGeometryProcessor); | |
106 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc)); | 59 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc)); |
107 } else { | 60 } else { |
108 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc)); | 61 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc)); |
109 } | 62 } |
110 } | 63 } |
111 | 64 |
112 ///////////////////////////////////////////////////////////////////////////// | 65 ///////////////////////////////////////////////////////////////////////////// |
113 | 66 |
114 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, | 67 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, |
115 const GrOptDrawState& optState, | 68 const GrOptDrawState& optState, |
116 const GrGLProgramDesc& desc) | 69 const GrGLProgramDesc& desc) |
117 : fVS(this) | 70 : fVS(this) |
118 , fGS(this) | 71 , fGS(this) |
119 , fFS(this, desc) | 72 , fFS(this, desc) |
120 , fOutOfStage(true) | 73 , fOutOfStage(true) |
121 , fStageIndex(-1) | 74 , fStageIndex(-1) |
122 , fGeometryProcessor(NULL) | 75 , fGeometryProcessor(NULL) |
123 , fOptState(optState) | 76 , fOptState(optState) |
124 , fDesc(desc) | 77 , fDesc(desc) |
125 , fGpu(gpu) | 78 , fGpu(gpu) |
126 , fUniforms(kVarsPerBlock) { | 79 , fUniforms(kVarsPerBlock) { |
127 } | 80 } |
128 | 81 |
| 82 GrGLProgram* GrGLProgramBuilder::create() { |
| 83 const GrGLProgramDesc::KeyHeader& header = this->header(); |
| 84 |
| 85 // emit code to read the dst copy texture, if necessary |
| 86 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey |
| 87 && !fGpu->glCaps().fbFetchSupport()) { |
| 88 this->fFS.emitCodeToReadDstTexture(); |
| 89 } |
| 90 |
| 91 // get the initial color and coverage to feed into the first effect in each
effect chain |
| 92 GrGLSLExpr4 inputColor, inputCoverage; |
| 93 this->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); |
| 94 |
| 95 // We always have a vertex shader in our default program |
| 96 fVS.setupLocalCoords(); |
| 97 |
| 98 // Setup default view matrix |
| 99 this->fUniformHandles.fViewMatrixUni = |
| 100 this->addUniform(GrGLProgramBuilder::kVertex_Visibility, |
| 101 kMat33f_GrSLType, |
| 102 fOptState.getGeometryProcessor()->uViewM()); |
| 103 if (header.fEmitsPointSize) { |
| 104 this->fVS.codeAppend("gl_PointSize = 1.0;"); |
| 105 } |
| 106 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { |
| 107 this->fVS.setupBuiltinVertexAttribute("Color", &inputColor); |
| 108 } |
| 109 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { |
| 110 this->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); |
| 111 } |
| 112 |
| 113 this->emitAndInstallProcs(&inputColor, &inputCoverage); |
| 114 |
| 115 // write the secondary color output if necessary |
| 116 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType
) { |
| 117 fFS.enableSecondaryOutput(inputColor, inputCoverage); |
| 118 } |
| 119 |
| 120 fFS.combineColorAndCoverage(inputColor, inputCoverage); |
| 121 |
| 122 return this->finalize(); |
| 123 } |
| 124 |
129 void GrGLProgramBuilder::addVarying(const char* name, | 125 void GrGLProgramBuilder::addVarying(const char* name, |
130 GrGLVarying* varying, | 126 GrGLVarying* varying, |
131 GrGLShaderVar::Precision fsPrecision) { | 127 GrGLShaderVar::Precision fsPrecision) { |
132 SkASSERT(varying); | 128 SkASSERT(varying); |
133 if (varying->vsVarying()) { | 129 if (varying->vsVarying()) { |
134 fVS.addVarying(name, varying); | 130 fVS.addVarying(name, varying); |
135 } | 131 } |
136 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->wi
llUseGeoShader()) { | 132 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->wi
llUseGeoShader()) { |
137 fGS.addVarying(name, varying); | 133 fGS.addVarying(name, varying); |
138 } | 134 } |
(...skipping 23 matching lines...) Expand all Loading... |
162 int co
unt, | 158 int co
unt, |
163 const
char** outName) { | 159 const
char** outName) { |
164 SkASSERT(name && strlen(name)); | 160 SkASSERT(name && strlen(name)); |
165 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); | 161 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); |
166 SkASSERT(0 == (~kVisibilityMask & visibility)); | 162 SkASSERT(0 == (~kVisibilityMask & visibility)); |
167 SkASSERT(0 != visibility); | 163 SkASSERT(0 != visibility); |
168 | 164 |
169 UniformInfo& uni = fUniforms.push_back(); | 165 UniformInfo& uni = fUniforms.push_back(); |
170 uni.fVariable.setType(type); | 166 uni.fVariable.setType(type); |
171 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); | 167 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); |
172 this->nameVariable(uni.fVariable.accessName(), 'u', name); | 168 // TODO this is a bit hacky, lets think of a better way. Basically we need
to be able to use |
| 169 // the uniform view matrix name in the GP, and the GP is immutable so it has
to tell the PB |
| 170 // exactly what name it wants to use for the uniform view matrix. If we pre
fix anythings, then |
| 171 // the names will mismatch. I think the correct solution is to have all GPs
which need the |
| 172 // uniform view matrix, they should upload the view matrix in their setData
along with regular |
| 173 // uniforms. |
| 174 char prefix = 'u'; |
| 175 if ('u' == name[0]) { |
| 176 prefix = '\0'; |
| 177 } |
| 178 this->nameVariable(uni.fVariable.accessName(), prefix, name); |
173 uni.fVariable.setArrayCount(count); | 179 uni.fVariable.setArrayCount(count); |
174 uni.fVisibility = visibility; | 180 uni.fVisibility = visibility; |
175 | 181 |
176 // If it is visible in both the VS and FS, the precision must match. | 182 // If it is visible in both the VS and FS, the precision must match. |
177 // We declare a default FS precision, but not a default VS. So set the var | 183 // We declare a default FS precision, but not a default VS. So set the var |
178 // to use the default FS precision. | 184 // to use the default FS precision. |
179 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { | 185 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { |
180 // the fragment and vertex precisions must match | 186 // the fragment and vertex precisions must match |
181 uni.fVariable.setPrecision(kDefaultFragmentPrecision); | 187 uni.fVariable.setPrecision(kDefaultFragmentPrecision); |
182 } | 188 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, | 227 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
222 kVec4f_GrSLType, | 228 kVec4f_GrSLType, |
223 "Coverage", | 229 "Coverage", |
224 &name); | 230 &name); |
225 *inputCoverage = GrGLSLExpr4(name); | 231 *inputCoverage = GrGLSLExpr4(name); |
226 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { | 232 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { |
227 *inputCoverage = GrGLSLExpr4(1); | 233 *inputCoverage = GrGLSLExpr4(1); |
228 } | 234 } |
229 } | 235 } |
230 | 236 |
231 void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState, | 237 void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr
4* inputCoverage) { |
232 GrGLSLExpr4* inputColor, | 238 // We need to collect all of the transforms to thread them through the GP in
the case of GPs |
233 GrGLSLExpr4* inputCoverage) { | 239 // which use additional shader stages between the VS and the FS. To do this
we emit a dummy |
| 240 // input coverage |
| 241 AutoStageAdvance adv(this); |
| 242 SkString outColorName; |
| 243 this->nameVariable(&outColorName, '\0', "gpOutput"); |
| 244 GrGLSLExpr4 coverageInput = outColorName; |
| 245 GrGLSLExpr4 gpOutput = coverageInput; |
| 246 |
| 247 // Emit fragment processors |
234 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); | 248 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); |
235 int numProcs = optState.numFragmentStages(); | 249 int numProcs = fOptState.numFragmentStages(); |
236 this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor); | 250 this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); |
237 if (optState.hasGeometryProcessor()) { | 251 this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, &covera
geInput); |
238 const GrGeometryProcessor& gp = *optState.getGeometryProcessor(); | 252 |
239 fVS.emitAttributes(gp); | 253 // We have to save the existing code stack, and then append it to the fragme
nt shader code |
240 ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_Processor
Type); | 254 // after emiting the GP |
241 GrGLSLExpr4 output; | 255 SkString existingCode(fFS.fCode); |
242 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *input
Coverage, &output); | 256 fFS.fCode.reset(); |
243 *inputCoverage = output; | 257 const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); |
244 } | 258 fVS.emitAttributes(gp); |
245 this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCov
erage); | 259 ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType
); |
| 260 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCove
rage, &gpOutput); |
| 261 fFS.fCode.append(existingCode); |
| 262 *inputCoverage = coverageInput; |
246 } | 263 } |
247 | 264 |
248 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, G
rGLSLExpr4* inOut) { | 265 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, G
rGLSLExpr4* inOut) { |
249 ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kFragment_ProcessorType
); | 266 ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kFragment_ProcessorType
); |
250 for (int e = procOffset; e < numProcs; ++e) { | 267 for (int e = procOffset; e < numProcs; ++e) { |
251 GrGLSLExpr4 output; | 268 GrGLSLExpr4 output; |
252 const GrFragmentStage& stage = fOptState.getFragmentStage(e); | 269 const GrFragmentStage& stage = fOptState.getFragmentStage(e); |
253 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut,
&output); | 270 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut,
&output); |
254 *inOut = output; | 271 *inOut = output; |
255 } | 272 } |
256 } | 273 } |
257 | 274 |
258 // TODO Processors cannot output zeros because an empty string is all 1s | 275 // TODO Processors cannot output zeros because an empty string is all 1s |
259 // the fix is to allow effects to take the GrGLSLExpr4 directly | 276 // the fix is to allow effects to take the GrGLSLExpr4 directly |
260 template <class Proc> | 277 template <class Proc> |
261 void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, | 278 void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, |
262 int index, | 279 int index, |
263 const ProcKeyProvider keyProvider, | 280 const ProcKeyProvider keyProvider, |
264 const GrGLSLExpr4& input, | 281 const GrGLSLExpr4& input, |
265 GrGLSLExpr4* output) { | 282 GrGLSLExpr4* output) { |
266 // Program builders have a bit of state we need to clear with each effect | 283 // Program builders have a bit of state we need to clear with each effect |
267 AutoStageAdvance adv(this); | 284 AutoStageAdvance adv(this); |
268 | 285 |
269 // create var to hold stage result | 286 // create var to hold stage result. If we already have a valid output name,
just use that |
| 287 // otherwise create a new mangled one. |
270 SkString outColorName; | 288 SkString outColorName; |
271 this->nameVariable(&outColorName, '\0', "output"); | 289 if (output->isValid()) { |
| 290 outColorName = output->c_str(); |
| 291 } else { |
| 292 this->nameVariable(&outColorName, '\0', "output"); |
| 293 } |
272 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); | 294 fFS.codeAppendf("vec4 %s;", outColorName.c_str()); |
273 *output = outColorName; | 295 *output = outColorName; |
274 | 296 |
275 // Enclose custom code in a block to avoid namespace conflicts | 297 // Enclose custom code in a block to avoid namespace conflicts |
276 SkString openBrace; | 298 SkString openBrace; |
277 openBrace.printf("{ // Stage %d\n", fStageIndex); | 299 openBrace.printf("{ // Stage %d\n", fStageIndex); |
278 fFS.codeAppend(openBrace.c_str()); | 300 fFS.codeAppend(openBrace.c_str()); |
279 | 301 |
280 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(), | 302 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(), |
281 input.isOnes() ? NULL : input.c_str()); | 303 input.isOnes() ? NULL : input.c_str()); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 uniName, | 383 uniName, |
362 &uniName).toShaderBuilder
Index(); | 384 &uniName).toShaderBuilder
Index(); |
363 | 385 |
364 const char* varyingName = "MatrixCoord"; | 386 const char* varyingName = "MatrixCoord"; |
365 SkString suffixedVaryingName; | 387 SkString suffixedVaryingName; |
366 if (0 != t) { | 388 if (0 != t) { |
367 suffixedVaryingName.append(varyingName); | 389 suffixedVaryingName.append(varyingName); |
368 suffixedVaryingName.appendf("_%i", t); | 390 suffixedVaryingName.appendf("_%i", t); |
369 varyingName = suffixedVaryingName.c_str(); | 391 varyingName = suffixedVaryingName.c_str(); |
370 } | 392 } |
| 393 const char* coords = kPosition_GrCoordSet == effect->coordTransform(t).s
ourceCoords() ? |
| 394 fVS.positionAttribute().c_s
tr() : |
| 395 fVS.localCoordsAttribute().
c_str(); |
371 GrGLVertToFrag v(varyingType); | 396 GrGLVertToFrag v(varyingType); |
372 this->addVarying(varyingName, &v); | 397 this->addCoordVarying(varyingName, &v, uniName, coords); |
373 | 398 |
374 const GrGLShaderVar& coords = | |
375 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords()
? | |
376 fVS.positionAttribute() : | |
377 fVS.localCoordsAttribute(); | |
378 | |
379 // varying = matrix * coords (logically) | |
380 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); | 399 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp
e); |
381 if (kVec2f_GrSLType == varyingType) { | |
382 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;", | |
383 v.vsOut(), uniName, coords.c_str()); | |
384 } else { | |
385 fVS.codeAppendf("%s = %s * vec3(%s, 1);", | |
386 v.vsOut(), uniName, coords.c_str()); | |
387 } | |
388 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, | 400 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, |
389 (SkString(v.fsIn()), varyingType)); | 401 (SkString(v.fsIn()), varyingType)); |
390 } | 402 } |
391 } | 403 } |
392 | 404 |
393 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | 405 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
394 GrGLProcessor::TextureSamplerArray* outSam
plers, | 406 GrGLProcessor::TextureSamplerArray* outSam
plers, |
395 GrGLInstalledProc* ip) { | 407 GrGLInstalledProc* ip) { |
396 int numTextures = processor.numTextures(); | 408 int numTextures = processor.numTextures(); |
397 ip->fSamplers.push_back_n(numTextures); | 409 ip->fSamplers.push_back_n(numTextures); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 } | 520 } |
509 | 521 |
510 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 522 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
511 | 523 |
512 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 524 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
513 int numProcs = fProcs.count(); | 525 int numProcs = fProcs.count(); |
514 for (int e = 0; e < numProcs; ++e) { | 526 for (int e = 0; e < numProcs; ++e) { |
515 SkDELETE(fProcs[e]); | 527 SkDELETE(fProcs[e]); |
516 } | 528 } |
517 } | 529 } |
OLD | NEW |