|
1 /* |
|
2 * Copyright 2013 Google Inc. |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #include "GrGLProgramEffects.h" |
|
9 #include "GrDrawEffect.h" |
|
10 #include "gl/GrGLEffect.h" |
|
11 #include "gl/GrGLShaderBuilder.h" |
|
12 #include "gl/GrGLVertexEffect.h" |
|
13 #include "gl/GrGpuGL.h" |
|
14 |
|
15 typedef GrGLProgramEffects::EffectKey EffectKey; |
|
16 typedef GrGLProgramEffects::TransformedCoords TransformedCoords; |
|
17 typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray; |
|
18 typedef GrGLProgramEffects::TextureSampler TextureSampler; |
|
19 typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray; |
|
20 |
|
21 /** |
|
22 * We specialize the vertex code for each of these matrix types. |
|
23 */ |
|
24 enum MatrixType { |
|
25 kIdentity_MatrixType = 0, |
|
26 kTrans_MatrixType = 1, |
|
27 kNoPersp_MatrixType = 2, |
|
28 kGeneral_MatrixType = 3, |
|
29 }; |
|
30 |
|
31 /** |
|
32 * The key for an individual coord transform is made up of a matrix type and a bit that |
|
33 * indicates the source of the input coords. |
|
34 */ |
|
35 enum { |
|
36 kMatrixTypeKeyBits = 2, |
|
37 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1, |
|
38 kPositionCoords_Flag = (1 << kMatrixTypeKeyBits), |
|
39 kTransformKeyBits = kMatrixTypeKeyBits + 1, |
|
40 }; |
|
41 |
|
42 namespace { |
|
43 |
|
44 /** |
|
45 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are |
|
46 * present in the texture's config. swizzleComponentMask indicates the channels present in the |
|
47 * shader swizzle. |
|
48 */ |
|
49 inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, |
|
50 uint32_t configComponentMask, |
|
51 uint32_t swizzleComponentMask) { |
|
52 if (caps.textureSwizzleSupport()) { |
|
53 // Any remapping is handled using texture swizzling not shader modifications. |
|
54 return false; |
|
55 } |
|
56 // check if the texture is alpha-only |
|
57 if (kA_GrColorComponentFlag == configComponentMask) { |
|
58 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) { |
|
59 // we must map the swizzle 'a's to 'r'. |
|
60 return true; |
|
61 } |
|
62 if (kRGB_GrColorComponentFlags & swizzleComponentMask) { |
|
63 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that |
|
64 // alpha-only textures smear alpha across all four channels when read. |
|
65 return true; |
|
66 } |
|
67 } |
|
68 return false; |
|
69 } |
|
70 |
|
71 /** |
|
72 * Retrieves the matrix type from transformKey for the transform at transformIdx. |
|
73 */ |
|
74 MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) { |
|
75 return static_cast<MatrixType>( |
|
76 (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask); |
|
77 } |
|
78 |
|
79 /** |
|
80 * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be |
|
81 * the same coordinate set as the original GrCoordTransform if the position and local coords are |
|
82 * identical for this program. |
|
83 */ |
|
84 GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) { |
|
85 return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ? |
|
86 kPosition_GrCoordSet : |
|
87 kLocal_GrCoordSet; |
|
88 } |
|
89 |
|
90 /** |
|
91 * Retrieves the final translation that a transform needs to apply to its source coords (and |
|
92 * verifies that a translation is all it needs). |
|
93 */ |
|
94 void get_transform_translation(const GrDrawEffect& drawEffect, |
|
95 int transformIdx, |
|
96 GrGLfloat* tx, |
|
97 GrGLfloat* ty) { |
|
98 const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx); |
|
99 SkASSERT(!coordTransform.reverseY()); |
|
100 const SkMatrix& matrix = coordTransform.getMatrix(); |
|
101 if (kLocal_GrCoordSet == coordTransform.sourceCoords() && |
|
102 !drawEffect.programHasExplicitLocalCoords()) { |
|
103 const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix(); |
|
104 SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType())); |
|
105 *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]); |
|
106 *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]); |
|
107 } else { |
|
108 SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType()); |
|
109 *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]); |
|
110 *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]); |
|
111 } |
|
112 } |
|
113 |
|
114 /** |
|
115 * Retrieves the final matrix that a transform needs to apply to its source coords. |
|
116 */ |
|
117 SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) { |
|
118 const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx); |
|
119 SkMatrix combined; |
|
120 if (kLocal_GrCoordSet == coordTransform.sourceCoords() && |
|
121 !drawEffect.programHasExplicitLocalCoords()) { |
|
122 combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix()); |
|
123 } else { |
|
124 combined = coordTransform.getMatrix(); |
|
125 } |
|
126 if (coordTransform.reverseY()) { |
|
127 // combined.postScale(1,-1); |
|
128 // combined.postTranslate(0,1); |
|
129 combined.set(SkMatrix::kMSkewY, |
|
130 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); |
|
131 combined.set(SkMatrix::kMScaleY, |
|
132 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); |
|
133 combined.set(SkMatrix::kMTransY, |
|
134 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); |
|
135 } |
|
136 return combined; |
|
137 } |
|
138 |
|
139 } |
|
140 |
|
141 //////////////////////////////////////////////////////////////////////////////// |
|
142 |
|
143 EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) { |
|
144 EffectKey key = 0; |
|
145 int numAttributes = drawEffect.getVertexAttribIndexCount(); |
|
146 SkASSERT(numAttributes <= 2); |
|
147 const int* attributeIndices = drawEffect.getVertexAttribIndices(); |
|
148 for (int a = 0; a < numAttributes; ++a) { |
|
149 EffectKey value = attributeIndices[a] << 3 * a; |
|
150 SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap |
|
151 key |= value; |
|
152 } |
|
153 return key; |
|
154 } |
|
155 |
|
156 EffectKey GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) { |
|
157 EffectKey totalKey = 0; |
|
158 int numTransforms = (*drawEffect.effect())->numTransforms(); |
|
159 for (int t = 0; t < numTransforms; ++t) { |
|
160 EffectKey key = 0; |
|
161 const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t); |
|
162 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType(); |
|
163 SkMatrix::TypeMask type1; |
|
164 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { |
|
165 type1 = drawEffect.getCoordChangeMatrix().getType(); |
|
166 } else { |
|
167 if (drawEffect.programHasExplicitLocalCoords()) { |
|
168 // We only make the key indicate that device coords are referenced when the local coords |
|
169 // are not actually determined by positions. Otherwise the local coords var and position |
|
170 // var are identical. |
|
171 key |= kPositionCoords_Flag; |
|
172 } |
|
173 type1 = SkMatrix::kIdentity_Mask; |
|
174 } |
|
175 |
|
176 int combinedTypes = type0 | type1; |
|
177 |
|
178 bool reverseY = coordTransform.reverseY(); |
|
179 |
|
180 if (SkMatrix::kPerspective_Mask & combinedTypes) { |
|
181 key |= kGeneral_MatrixType; |
|
182 } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) { |
|
183 key |= kNoPersp_MatrixType; |
|
184 } else if (SkMatrix::kTranslate_Mask & combinedTypes) { |
|
185 key |= kTrans_MatrixType; |
|
186 } else { |
|
187 key |= kIdentity_MatrixType; |
|
188 } |
|
189 key <<= kTransformKeyBits * t; |
|
190 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap |
|
191 totalKey |= key; |
|
192 } |
|
193 return totalKey; |
|
194 } |
|
195 |
|
196 EffectKey GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) { |
|
197 EffectKey key = 0; |
|
198 int numTextures = (*drawEffect.effect())->numTextures(); |
|
199 for (int t = 0; t < numTextures; ++t) { |
|
200 const GrTextureAccess& access = (*drawEffect.effect())->textureAccess(t); |
|
201 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); |
|
202 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { |
|
203 key |= 1 << t; |
|
204 } |
|
205 } |
|
206 return key; |
|
207 } |
|
208 |
|
209 GrGLProgramEffects::~GrGLProgramEffects() { |
|
210 int numEffects = fGLEffects.count(); |
|
211 for (int e = 0; e < numEffects; ++e) { |
|
212 SkDELETE(fGLEffects[e]); |
|
213 } |
|
214 } |
|
215 |
|
216 void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder, |
|
217 const GrEffectRef& effect, |
|
218 TextureSamplerArray* outSamplers) { |
|
219 SkTArray<Sampler, true>& samplers = fSamplers.push_back(); |
|
220 int numTextures = effect->numTextures(); |
|
221 samplers.push_back_n(numTextures); |
|
222 SkString name; |
|
223 for (int t = 0; t < numTextures; ++t) { |
|
224 name.printf("Sampler%d", t); |
|
225 samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
|
226 kSampler2D_GrSLType, |
|
227 name.c_str()); |
|
228 SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler, |
|
229 (samplers[t].fUniform, effect->textureAccess(t))); |
|
230 } |
|
231 } |
|
232 |
|
233 void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) { |
|
234 int numEffects = fGLEffects.count(); |
|
235 SkASSERT(numEffects == fSamplers.count()); |
|
236 for (int e = 0; e < numEffects; ++e) { |
|
237 SkTArray<Sampler, true>& samplers = fSamplers[e]; |
|
238 int numSamplers = samplers.count(); |
|
239 for (int s = 0; s < numSamplers; ++s) { |
|
240 SkASSERT(samplers[s].fUniform.isValid()); |
|
241 uniformManager.setSampler(samplers[s].fUniform, *texUnitIdx); |
|
242 samplers[s].fTextureUnit = (*texUnitIdx)++; |
|
243 } |
|
244 } |
|
245 } |
|
246 |
|
247 void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) { |
|
248 const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx]; |
|
249 int numSamplers = samplers.count(); |
|
250 SkASSERT(numSamplers == effect->numTextures()); |
|
251 for (int s = 0; s < numSamplers; ++s) { |
|
252 SkASSERT(samplers[s].fTextureUnit >= 0); |
|
253 const GrTextureAccess& textureAccess = effect->textureAccess(s); |
|
254 gpu->bindTexture(samplers[s].fTextureUnit, |
|
255 textureAccess.getParams(), |
|
256 static_cast<GrGLTexture*>(textureAccess.getTexture())); |
|
257 } |
|
258 } |
|
259 |
|
260 //////////////////////////////////////////////////////////////////////////////// |
|
261 |
|
262 void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder, |
|
263 const GrEffectStage& stage, |
|
264 EffectKey key, |
|
265 const char* outColor, |
|
266 const char* inColor, |
|
267 int stageIndex) { |
|
268 GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords); |
|
269 const GrEffectRef& effect = *stage.getEffect(); |
|
270 SkSTArray<2, TransformedCoords> coords(effect->numTransforms()); |
|
271 SkSTArray<4, TextureSampler> samplers(effect->numTextures()); |
|
272 |
|
273 this->emitAttributes(builder, stage); |
|
274 this->emitTransforms(builder, effect, key, &coords); |
|
275 this->emitSamplers(builder, effect, &samplers); |
|
276 |
|
277 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); |
|
278 fGLEffects.push_back(glEffect); |
|
279 |
|
280 // Enclose custom code in a block to avoid namespace conflicts |
|
281 SkString openBrace; |
|
282 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name()); |
|
283 builder->vsCodeAppend(openBrace.c_str()); |
|
284 builder->fsCodeAppend(openBrace.c_str()); |
|
285 |
|
286 if (glEffect->isVertexEffect()) { |
|
287 GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect); |
|
288 vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); |
|
289 } else { |
|
290 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); |
|
291 } |
|
292 |
|
293 builder->vsCodeAppend("\t}\n"); |
|
294 builder->fsCodeAppend("\t}\n"); |
|
295 } |
|
296 |
|
297 void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder, |
|
298 const GrEffectStage& stage) { |
|
299 int numAttributes = stage.getVertexAttribIndexCount(); |
|
300 const int* attributeIndices = stage.getVertexAttribIndices(); |
|
301 for (int a = 0; a < numAttributes; ++a) { |
|
302 // TODO: Make addAttribute mangle the name. |
|
303 SkString attributeName("aAttr"); |
|
304 attributeName.appendS32(attributeIndices[a]); |
|
305 builder->addEffectAttribute(attributeIndices[a], |
|
306 (*stage.getEffect())->vertexAttribType(a), |
|
307 attributeName); |
|
308 } |
|
309 } |
|
310 |
|
311 void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, |
|
312 const GrEffectRef& effect, |
|
313 EffectKey effectKey, |
|
314 TransformedCoordsArray* outCoords) { |
|
315 SkTArray<Transform, true>& transforms = fTransforms.push_back(); |
|
316 EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); |
|
317 int numTransforms = effect->numTransforms(); |
|
318 transforms.push_back_n(numTransforms); |
|
319 for (int t = 0; t < numTransforms; t++) { |
|
320 GrSLType varyingType = kVoid_GrSLType; |
|
321 const char* uniName; |
|
322 switch (get_matrix_type(totalKey, t)) { |
|
323 case kIdentity_MatrixType: |
|
324 transforms[t].fType = kVoid_GrSLType; |
|
325 uniName = NULL; |
|
326 varyingType = kVec2f_GrSLType; |
|
327 break; |
|
328 case kTrans_MatrixType: |
|
329 transforms[t].fType = kVec2f_GrSLType; |
|
330 uniName = "StageTranslate"; |
|
331 varyingType = kVec2f_GrSLType; |
|
332 break; |
|
333 case kNoPersp_MatrixType: |
|
334 transforms[t].fType = kMat33f_GrSLType; |
|
335 uniName = "StageMatrix"; |
|
336 varyingType = kVec2f_GrSLType; |
|
337 break; |
|
338 case kGeneral_MatrixType: |
|
339 transforms[t].fType = kMat33f_GrSLType; |
|
340 uniName = "StageMatrix"; |
|
341 varyingType = kVec3f_GrSLType; |
|
342 break; |
|
343 default: |
|
344 GrCrash("Unexpected key."); |
|
345 } |
|
346 SkString suffixedUniName; |
|
347 if (kVoid_GrSLType != transforms[t].fType) { |
|
348 if (0 != t) { |
|
349 suffixedUniName.append(uniName); |
|
350 suffixedUniName.appendf("_%i", t); |
|
351 uniName = suffixedUniName.c_str(); |
|
352 } |
|
353 transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility, |
|
354 transforms[t].fType, |
|
355 uniName, |
|
356 &uniName); |
|
357 } |
|
358 |
|
359 const char* varyingName = "MatrixCoord"; |
|
360 SkString suffixedVaryingName; |
|
361 if (0 != t) { |
|
362 suffixedVaryingName.append(varyingName); |
|
363 suffixedVaryingName.appendf("_%i", t); |
|
364 varyingName = suffixedVaryingName.c_str(); |
|
365 } |
|
366 const char* vsVaryingName; |
|
367 const char* fsVaryingName; |
|
368 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); |
|
369 |
|
370 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ? |
|
371 builder->positionAttribute() : |
|
372 builder->localCoordsAttribute(); |
|
373 // varying = matrix * coords (logically) |
|
374 switch (transforms[t].fType) { |
|
375 case kVoid_GrSLType: |
|
376 SkASSERT(kVec2f_GrSLType == varyingType); |
|
377 builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str()); |
|
378 break; |
|
379 case kVec2f_GrSLType: |
|
380 SkASSERT(kVec2f_GrSLType == varyingType); |
|
381 builder->vsCodeAppendf("\t%s = %s + %s;\n", |
|
382 vsVaryingName, uniName, coords.c_str()); |
|
383 break; |
|
384 case kMat33f_GrSLType: { |
|
385 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); |
|
386 if (kVec2f_GrSLType == varyingType) { |
|
387 builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", |
|
388 vsVaryingName, uniName, coords.c_str()); |
|
389 } else { |
|
390 builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", |
|
391 vsVaryingName, uniName, coords.c_str()); |
|
392 } |
|
393 break; |
|
394 } |
|
395 default: |
|
396 GrCrash("Unexpected uniform type."); |
|
397 } |
|
398 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, |
|
399 (SkString(fsVaryingName), varyingType)); |
|
400 } |
|
401 } |
|
402 |
|
403 void GrGLVertexProgramEffects::setData(GrGpuGL* gpu, |
|
404 const GrGLUniformManager& uniformManager, |
|
405 const GrEffectStage* effectStages[]) { |
|
406 int numEffects = fGLEffects.count(); |
|
407 SkASSERT(numEffects == fTransforms.count()); |
|
408 SkASSERT(numEffects == fSamplers.count()); |
|
409 for (int e = 0; e < numEffects; ++e) { |
|
410 GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords); |
|
411 fGLEffects[e]->setData(uniformManager, drawEffect); |
|
412 this->setTransformData(uniformManager, drawEffect, e); |
|
413 this->bindTextures(gpu, *drawEffect.effect(), e); |
|
414 } |
|
415 } |
|
416 |
|
417 void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager, |
|
418 const GrDrawEffect& drawEffect, |
|
419 int effectIdx) { |
|
420 SkTArray<Transform, true>& transforms = fTransforms[effectIdx]; |
|
421 int numTransforms = transforms.count(); |
|
422 SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms()); |
|
423 for (int t = 0; t < numTransforms; ++t) { |
|
424 SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType)); |
|
425 switch (transforms[t].fType) { |
|
426 case kVoid_GrSLType: |
|
427 SkASSERT(get_transform_matrix(drawEffect, t).isIdentity()); |
|
428 return; |
|
429 case kVec2f_GrSLType: { |
|
430 GrGLfloat tx, ty; |
|
431 get_transform_translation(drawEffect, t, &tx, &ty); |
|
432 if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx || |
|
433 transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) { |
|
434 uniformManager.set2f(transforms[t].fHandle, tx, ty); |
|
435 transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx); |
|
436 transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty); |
|
437 } |
|
438 break; |
|
439 } |
|
440 case kMat33f_GrSLType: { |
|
441 const SkMatrix& matrix = get_transform_matrix(drawEffect, t); |
|
442 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { |
|
443 uniformManager.setSkMatrix(transforms[t].fHandle, matrix); |
|
444 transforms[t].fCurrentValue = matrix; |
|
445 } |
|
446 break; |
|
447 } |
|
448 default: |
|
449 GrCrash("Unexpected uniform type."); |
|
450 } |
|
451 } |
|
452 } |
|
453 |
|
454 GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder, |
|
455 int reserveCount) |
|
456 : fBuilder(builder) |
|
457 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects, |
|
458 (reserveCount, fBuilder->hasExplicitLocalCoords()))) { |
|
459 } |
|
460 |
|
461 void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, |
|
462 GrGLProgramEffects::EffectKey key, |
|
463 const char* outColor, |
|
464 const char* inColor, |
|
465 int stageIndex) { |
|
466 SkASSERT(NULL != fProgramEffects.get()); |
|
467 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex); |
|
468 } |
|
469 |
|
470 //////////////////////////////////////////////////////////////////////////////// |
|
471 |
|
472 void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder, |
|
473 const GrEffectStage& stage, |
|
474 EffectKey key, |
|
475 const char* outColor, |
|
476 const char* inColor, |
|
477 int stageIndex) { |
|
478 GrDrawEffect drawEffect(stage, false); |
|
479 const GrEffectRef& effect = *stage.getEffect(); |
|
480 SkSTArray<2, TransformedCoords> coords(effect->numTransforms()); |
|
481 SkSTArray<4, TextureSampler> samplers(effect->numTextures()); |
|
482 |
|
483 SkASSERT(0 == stage.getVertexAttribIndexCount()); |
|
484 this->setupTexGen(builder, effect, key, &coords); |
|
485 this->emitSamplers(builder, effect, &samplers); |
|
486 |
|
487 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); |
|
488 fGLEffects.push_back(glEffect); |
|
489 |
|
490 // Enclose custom code in a block to avoid namespace conflicts |
|
491 SkString openBrace; |
|
492 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name()); |
|
493 builder->fsCodeAppend(openBrace.c_str()); |
|
494 |
|
495 SkASSERT(!glEffect->isVertexEffect()); |
|
496 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); |
|
497 |
|
498 builder->fsCodeAppend("\t}\n"); |
|
499 } |
|
500 |
|
501 void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder, |
|
502 const GrEffectRef& effect, |
|
503 EffectKey effectKey, |
|
504 TransformedCoordsArray* outCoords) { |
|
505 int numTransforms = effect->numTransforms(); |
|
506 EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); |
|
507 int texCoordIndex = builder->addTexCoordSets(numTransforms); |
|
508 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex)); |
|
509 SkString name; |
|
510 for (int t = 0; t < numTransforms; ++t) { |
|
511 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ? |
|
512 kVec3f_GrSLType : |
|
513 kVec2f_GrSLType; |
|
514 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++); |
|
515 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type)); |
|
516 } |
|
517 } |
|
518 |
|
519 void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu, |
|
520 const GrGLUniformManager& uniformManager, |
|
521 const GrEffectStage* effectStages[]) { |
|
522 int numEffects = fGLEffects.count(); |
|
523 SkASSERT(numEffects == fTransforms.count()); |
|
524 SkASSERT(numEffects == fSamplers.count()); |
|
525 for (int e = 0; e < numEffects; ++e) { |
|
526 GrDrawEffect drawEffect(*effectStages[e], false); |
|
527 fGLEffects[e]->setData(uniformManager, drawEffect); |
|
528 this->setTexGenState(gpu, drawEffect, e); |
|
529 this->bindTextures(gpu, *drawEffect.effect(), e); |
|
530 } |
|
531 } |
|
532 |
|
533 void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu, |
|
534 const GrDrawEffect& drawEffect, |
|
535 int effectIdx) { |
|
536 EffectKey totalKey = fTransforms[effectIdx].fTransformKey; |
|
537 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex; |
|
538 int numTransforms = (*drawEffect.effect())->numTransforms(); |
|
539 for (int t = 0; t < numTransforms; ++t) { |
|
540 switch (get_matrix_type(totalKey, t)) { |
|
541 case kIdentity_MatrixType: { |
|
542 SkASSERT(get_transform_matrix(drawEffect, t).isIdentity()); |
|
543 GrGLfloat identity[] = {1, 0, 0, |
|
544 0, 1, 0}; |
|
545 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity); |
|
546 break; |
|
547 } |
|
548 case kTrans_MatrixType: { |
|
549 GrGLfloat tx, ty; |
|
550 get_transform_translation(drawEffect, t, &tx, &ty); |
|
551 GrGLfloat translate[] = {1, 0, tx, |
|
552 0, 1, ty}; |
|
553 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate); |
|
554 break; |
|
555 } |
|
556 case kNoPersp_MatrixType: { |
|
557 const SkMatrix& transform = get_transform_matrix(drawEffect, t); |
|
558 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform); |
|
559 break; |
|
560 } |
|
561 case kGeneral_MatrixType: { |
|
562 const SkMatrix& transform = get_transform_matrix(drawEffect, t); |
|
563 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform); |
|
564 break; |
|
565 } |
|
566 default: |
|
567 GrCrash("Unexpected matrixs type."); |
|
568 } |
|
569 } |
|
570 } |
|
571 |
|
572 GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder( |
|
573 GrGLFragmentOnlyShaderBuilder* builder, |
|
574 int reserveCount) |
|
575 : fBuilder(builder) |
|
576 , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) { |
|
577 } |
|
578 |
|
579 void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, |
|
580 GrGLProgramEffects::EffectKey key, |
|
581 const char* outColor, |
|
582 const char* inColor, |
|
583 int stageIndex) { |
|
584 SkASSERT(NULL != fProgramEffects.get()); |
|
585 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex); |
|
586 } |