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
15typedef GrGLProgramEffects::EffectKey EffectKey;
16typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
17typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
18typedef GrGLProgramEffects::TextureSampler TextureSampler;
19typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
20
21/**
22 * We specialize the vertex code for each of these matrix types.
23 */
24enum 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 */
35enum {
36    kMatrixTypeKeyBits   = 2,
37    kMatrixTypeKeyMask   = (1 << kMatrixTypeKeyBits) - 1,
38    kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
39    kTransformKeyBits    = kMatrixTypeKeyBits + 1,
40};
41
42namespace {
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 */
49inline 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 */
74MatrixType 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 */
84GrCoordSet 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 */
94void 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 */
117SkMatrix 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
143EffectKey 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
156EffectKey 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
196EffectKey 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
209GrGLProgramEffects::~GrGLProgramEffects() {
210    int numEffects = fGLEffects.count();
211    for (int e = 0; e < numEffects; ++e) {
212        SkDELETE(fGLEffects[e]);
213    }
214}
215
216void 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
233void 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
247void 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
262void 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
297void 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
311void 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                SkFAIL("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                SkFAIL("Unexpected uniform type.");
397        }
398        SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
399                               (SkString(fsVaryingName), varyingType));
400    }
401}
402
403void 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
417void 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                break;
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                SkFAIL("Unexpected uniform type.");
450        }
451    }
452}
453
454GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
455                                                                 int reserveCount)
456    : fBuilder(builder)
457    , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
458                                 (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
459}
460
461void 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
472void GrGLPathTexGenProgramEffects::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->setupPathTexGen(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
501void GrGLPathTexGenProgramEffects::setupPathTexGen(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
519void GrGLPathTexGenProgramEffects::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->setPathTexGenState(gpu, drawEffect, e);
529        this->bindTextures(gpu, *drawEffect.effect(), e);
530    }
531}
532
533void GrGLPathTexGenProgramEffects::setPathTexGenState(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->enablePathTexGen(texCoordIndex++,
546                                      GrGpuGL::kST_PathTexGenComponents,
547                                      identity);
548                break;
549            }
550            case kTrans_MatrixType: {
551                GrGLfloat tx, ty;
552                get_transform_translation(drawEffect, t, &tx, &ty);
553                GrGLfloat translate[] = {1, 0, tx,
554                                         0, 1, ty};
555                gpu->enablePathTexGen(texCoordIndex++,
556                                      GrGpuGL::kST_PathTexGenComponents,
557                                      translate);
558                break;
559            }
560            case kNoPersp_MatrixType: {
561                const SkMatrix& transform = get_transform_matrix(drawEffect, t);
562                gpu->enablePathTexGen(texCoordIndex++,
563                                      GrGpuGL::kST_PathTexGenComponents,
564                                      transform);
565                break;
566            }
567            case kGeneral_MatrixType: {
568                const SkMatrix& transform = get_transform_matrix(drawEffect, t);
569                gpu->enablePathTexGen(texCoordIndex++,
570                                      GrGpuGL::kSTR_PathTexGenComponents,
571                                      transform);
572                break;
573            }
574            default:
575                SkFAIL("Unexpected matrixs type.");
576        }
577    }
578}
579
580GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
581        GrGLFragmentOnlyShaderBuilder* builder,
582        int reserveCount)
583    : fBuilder(builder)
584    , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
585}
586
587void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
588                                                     GrGLProgramEffects::EffectKey key,
589                                                     const char* outColor,
590                                                     const char* inColor,
591                                                     int stageIndex) {
592    SkASSERT(NULL != fProgramEffects.get());
593    fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
594}
595