gfx/skia/trunk/src/gpu/gl/GrGLProgramEffects.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLProgramEffects.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,586 @@
     1.4 +/*
     1.5 + * Copyright 2013 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#include "GrGLProgramEffects.h"
    1.12 +#include "GrDrawEffect.h"
    1.13 +#include "gl/GrGLEffect.h"
    1.14 +#include "gl/GrGLShaderBuilder.h"
    1.15 +#include "gl/GrGLVertexEffect.h"
    1.16 +#include "gl/GrGpuGL.h"
    1.17 +
    1.18 +typedef GrGLProgramEffects::EffectKey EffectKey;
    1.19 +typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
    1.20 +typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
    1.21 +typedef GrGLProgramEffects::TextureSampler TextureSampler;
    1.22 +typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
    1.23 +
    1.24 +/**
    1.25 + * We specialize the vertex code for each of these matrix types.
    1.26 + */
    1.27 +enum MatrixType {
    1.28 +    kIdentity_MatrixType = 0,
    1.29 +    kTrans_MatrixType    = 1,
    1.30 +    kNoPersp_MatrixType  = 2,
    1.31 +    kGeneral_MatrixType  = 3,
    1.32 +};
    1.33 +
    1.34 +/**
    1.35 + * The key for an individual coord transform is made up of a matrix type and a bit that
    1.36 + * indicates the source of the input coords.
    1.37 + */
    1.38 +enum {
    1.39 +    kMatrixTypeKeyBits   = 2,
    1.40 +    kMatrixTypeKeyMask   = (1 << kMatrixTypeKeyBits) - 1,
    1.41 +    kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
    1.42 +    kTransformKeyBits    = kMatrixTypeKeyBits + 1,
    1.43 +};
    1.44 +
    1.45 +namespace {
    1.46 +
    1.47 +/**
    1.48 + * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
    1.49 + * present in the texture's config. swizzleComponentMask indicates the channels present in the
    1.50 + * shader swizzle.
    1.51 + */
    1.52 +inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
    1.53 +                                             uint32_t configComponentMask,
    1.54 +                                             uint32_t swizzleComponentMask) {
    1.55 +    if (caps.textureSwizzleSupport()) {
    1.56 +        // Any remapping is handled using texture swizzling not shader modifications.
    1.57 +        return false;
    1.58 +    }
    1.59 +    // check if the texture is alpha-only
    1.60 +    if (kA_GrColorComponentFlag == configComponentMask) {
    1.61 +        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
    1.62 +            // we must map the swizzle 'a's to 'r'.
    1.63 +            return true;
    1.64 +        }
    1.65 +        if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
    1.66 +            // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
    1.67 +            // alpha-only textures smear alpha across all four channels when read.
    1.68 +            return true;
    1.69 +        }
    1.70 +    }
    1.71 +    return false;
    1.72 +}
    1.73 +
    1.74 +/**
    1.75 + * Retrieves the matrix type from transformKey for the transform at transformIdx.
    1.76 + */
    1.77 +MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) {
    1.78 +    return static_cast<MatrixType>(
    1.79 +               (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
    1.80 +}
    1.81 +
    1.82 +/**
    1.83 + * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
    1.84 + * the same coordinate set as the original GrCoordTransform if the position and local coords are
    1.85 + * identical for this program.
    1.86 + */
    1.87 +GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) {
    1.88 +    return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
    1.89 +               kPosition_GrCoordSet :
    1.90 +               kLocal_GrCoordSet;
    1.91 +}
    1.92 +
    1.93 +/**
    1.94 + * Retrieves the final translation that a transform needs to apply to its source coords (and
    1.95 + * verifies that a translation is all it needs).
    1.96 + */
    1.97 +void get_transform_translation(const GrDrawEffect& drawEffect,
    1.98 +                               int transformIdx,
    1.99 +                               GrGLfloat* tx,
   1.100 +                               GrGLfloat* ty) {
   1.101 +    const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
   1.102 +    SkASSERT(!coordTransform.reverseY());
   1.103 +    const SkMatrix& matrix = coordTransform.getMatrix();
   1.104 +    if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
   1.105 +        !drawEffect.programHasExplicitLocalCoords()) {
   1.106 +        const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix();
   1.107 +        SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
   1.108 +        *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]);
   1.109 +        *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]);
   1.110 +    } else {
   1.111 +        SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType());
   1.112 +        *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
   1.113 +        *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
   1.114 +    }
   1.115 +}
   1.116 +
   1.117 +/**
   1.118 + * Retrieves the final matrix that a transform needs to apply to its source coords.
   1.119 + */
   1.120 +SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
   1.121 +    const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
   1.122 +    SkMatrix combined;
   1.123 +    if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
   1.124 +        !drawEffect.programHasExplicitLocalCoords()) {
   1.125 +        combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
   1.126 +    } else {
   1.127 +        combined = coordTransform.getMatrix();
   1.128 +    }
   1.129 +    if (coordTransform.reverseY()) {
   1.130 +        // combined.postScale(1,-1);
   1.131 +        // combined.postTranslate(0,1);
   1.132 +        combined.set(SkMatrix::kMSkewY,
   1.133 +            combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
   1.134 +        combined.set(SkMatrix::kMScaleY,
   1.135 +            combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
   1.136 +        combined.set(SkMatrix::kMTransY,
   1.137 +            combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
   1.138 +    }
   1.139 +    return combined;
   1.140 +}
   1.141 +
   1.142 +}
   1.143 +
   1.144 +////////////////////////////////////////////////////////////////////////////////
   1.145 +
   1.146 +EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
   1.147 +    EffectKey key = 0;
   1.148 +    int numAttributes = drawEffect.getVertexAttribIndexCount();
   1.149 +    SkASSERT(numAttributes <= 2);
   1.150 +    const int* attributeIndices = drawEffect.getVertexAttribIndices();
   1.151 +    for (int a = 0; a < numAttributes; ++a) {
   1.152 +        EffectKey value = attributeIndices[a] << 3 * a;
   1.153 +        SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap
   1.154 +        key |= value;
   1.155 +    }
   1.156 +    return key;
   1.157 +}
   1.158 +
   1.159 +EffectKey GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) {
   1.160 +    EffectKey totalKey = 0;
   1.161 +    int numTransforms = (*drawEffect.effect())->numTransforms();
   1.162 +    for (int t = 0; t < numTransforms; ++t) {
   1.163 +        EffectKey key = 0;
   1.164 +        const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t);
   1.165 +        SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
   1.166 +        SkMatrix::TypeMask type1;
   1.167 +        if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
   1.168 +            type1 = drawEffect.getCoordChangeMatrix().getType();
   1.169 +        } else {
   1.170 +            if (drawEffect.programHasExplicitLocalCoords()) {
   1.171 +                // We only make the key indicate that device coords are referenced when the local coords
   1.172 +                // are not actually determined by positions. Otherwise the local coords var and position
   1.173 +                // var are identical.
   1.174 +                key |= kPositionCoords_Flag;
   1.175 +            }
   1.176 +            type1 = SkMatrix::kIdentity_Mask;
   1.177 +        }
   1.178 +
   1.179 +        int combinedTypes = type0 | type1;
   1.180 +
   1.181 +        bool reverseY = coordTransform.reverseY();
   1.182 +
   1.183 +        if (SkMatrix::kPerspective_Mask & combinedTypes) {
   1.184 +            key |= kGeneral_MatrixType;
   1.185 +        } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) {
   1.186 +            key |= kNoPersp_MatrixType;
   1.187 +        } else if (SkMatrix::kTranslate_Mask & combinedTypes) {
   1.188 +            key |= kTrans_MatrixType;
   1.189 +        } else {
   1.190 +            key |= kIdentity_MatrixType;
   1.191 +        }
   1.192 +        key <<= kTransformKeyBits * t;
   1.193 +        SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
   1.194 +        totalKey |= key;
   1.195 +    }
   1.196 +    return totalKey;
   1.197 +}
   1.198 +
   1.199 +EffectKey GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) {
   1.200 +    EffectKey key = 0;
   1.201 +    int numTextures = (*drawEffect.effect())->numTextures();
   1.202 +    for (int t = 0; t < numTextures; ++t) {
   1.203 +        const GrTextureAccess& access = (*drawEffect.effect())->textureAccess(t);
   1.204 +        uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
   1.205 +        if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
   1.206 +            key |= 1 << t;
   1.207 +        }
   1.208 +    }
   1.209 +    return key;
   1.210 +}
   1.211 +
   1.212 +GrGLProgramEffects::~GrGLProgramEffects() {
   1.213 +    int numEffects = fGLEffects.count();
   1.214 +    for (int e = 0; e < numEffects; ++e) {
   1.215 +        SkDELETE(fGLEffects[e]);
   1.216 +    }
   1.217 +}
   1.218 +
   1.219 +void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder,
   1.220 +                                      const GrEffectRef& effect,
   1.221 +                                      TextureSamplerArray* outSamplers) {
   1.222 +    SkTArray<Sampler, true>& samplers = fSamplers.push_back();
   1.223 +    int numTextures = effect->numTextures();
   1.224 +    samplers.push_back_n(numTextures);
   1.225 +    SkString name;
   1.226 +    for (int t = 0; t < numTextures; ++t) {
   1.227 +        name.printf("Sampler%d", t);
   1.228 +        samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   1.229 +                                                   kSampler2D_GrSLType,
   1.230 +                                                   name.c_str());
   1.231 +        SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
   1.232 +                               (samplers[t].fUniform, effect->textureAccess(t)));
   1.233 +    }
   1.234 +}
   1.235 +
   1.236 +void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) {
   1.237 +    int numEffects = fGLEffects.count();
   1.238 +    SkASSERT(numEffects == fSamplers.count());
   1.239 +    for (int e = 0; e < numEffects; ++e) {
   1.240 +        SkTArray<Sampler, true>& samplers = fSamplers[e];
   1.241 +        int numSamplers = samplers.count();
   1.242 +        for (int s = 0; s < numSamplers; ++s) {
   1.243 +            SkASSERT(samplers[s].fUniform.isValid());
   1.244 +            uniformManager.setSampler(samplers[s].fUniform, *texUnitIdx);
   1.245 +            samplers[s].fTextureUnit = (*texUnitIdx)++;
   1.246 +        }
   1.247 +    }
   1.248 +}
   1.249 +
   1.250 +void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) {
   1.251 +    const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
   1.252 +    int numSamplers = samplers.count();
   1.253 +    SkASSERT(numSamplers == effect->numTextures());
   1.254 +    for (int s = 0; s < numSamplers; ++s) {
   1.255 +        SkASSERT(samplers[s].fTextureUnit >= 0);
   1.256 +        const GrTextureAccess& textureAccess = effect->textureAccess(s);
   1.257 +        gpu->bindTexture(samplers[s].fTextureUnit,
   1.258 +                         textureAccess.getParams(),
   1.259 +                         static_cast<GrGLTexture*>(textureAccess.getTexture()));
   1.260 +    }
   1.261 +}
   1.262 +
   1.263 +////////////////////////////////////////////////////////////////////////////////
   1.264 +
   1.265 +void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
   1.266 +                                          const GrEffectStage& stage,
   1.267 +                                          EffectKey key,
   1.268 +                                          const char* outColor,
   1.269 +                                          const char* inColor,
   1.270 +                                          int stageIndex) {
   1.271 +    GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
   1.272 +    const GrEffectRef& effect = *stage.getEffect();
   1.273 +    SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
   1.274 +    SkSTArray<4, TextureSampler> samplers(effect->numTextures());
   1.275 +
   1.276 +    this->emitAttributes(builder, stage);
   1.277 +    this->emitTransforms(builder, effect, key, &coords);
   1.278 +    this->emitSamplers(builder, effect, &samplers);
   1.279 +
   1.280 +    GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
   1.281 +    fGLEffects.push_back(glEffect);
   1.282 +
   1.283 +    // Enclose custom code in a block to avoid namespace conflicts
   1.284 +    SkString openBrace;
   1.285 +    openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
   1.286 +    builder->vsCodeAppend(openBrace.c_str());
   1.287 +    builder->fsCodeAppend(openBrace.c_str());
   1.288 +
   1.289 +    if (glEffect->isVertexEffect()) {
   1.290 +        GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
   1.291 +        vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
   1.292 +    } else {
   1.293 +        glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
   1.294 +    }
   1.295 +
   1.296 +    builder->vsCodeAppend("\t}\n");
   1.297 +    builder->fsCodeAppend("\t}\n");
   1.298 +}
   1.299 +
   1.300 +void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
   1.301 +                                              const GrEffectStage& stage) {
   1.302 +    int numAttributes = stage.getVertexAttribIndexCount();
   1.303 +    const int* attributeIndices = stage.getVertexAttribIndices();
   1.304 +    for (int a = 0; a < numAttributes; ++a) {
   1.305 +        // TODO: Make addAttribute mangle the name.
   1.306 +        SkString attributeName("aAttr");
   1.307 +        attributeName.appendS32(attributeIndices[a]);
   1.308 +        builder->addEffectAttribute(attributeIndices[a],
   1.309 +                                    (*stage.getEffect())->vertexAttribType(a),
   1.310 +                                    attributeName);
   1.311 +    }
   1.312 +}
   1.313 +
   1.314 +void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
   1.315 +                                              const GrEffectRef& effect,
   1.316 +                                              EffectKey effectKey,
   1.317 +                                              TransformedCoordsArray* outCoords) {
   1.318 +    SkTArray<Transform, true>& transforms = fTransforms.push_back();
   1.319 +    EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
   1.320 +    int numTransforms = effect->numTransforms();
   1.321 +    transforms.push_back_n(numTransforms);
   1.322 +    for (int t = 0; t < numTransforms; t++) {
   1.323 +        GrSLType varyingType = kVoid_GrSLType;
   1.324 +        const char* uniName;
   1.325 +        switch (get_matrix_type(totalKey, t)) {
   1.326 +            case kIdentity_MatrixType:
   1.327 +                transforms[t].fType = kVoid_GrSLType;
   1.328 +                uniName = NULL;
   1.329 +                varyingType = kVec2f_GrSLType;
   1.330 +                break;
   1.331 +            case kTrans_MatrixType:
   1.332 +                transforms[t].fType = kVec2f_GrSLType;
   1.333 +                uniName = "StageTranslate";
   1.334 +                varyingType = kVec2f_GrSLType;
   1.335 +                break;
   1.336 +            case kNoPersp_MatrixType:
   1.337 +                transforms[t].fType = kMat33f_GrSLType;
   1.338 +                uniName = "StageMatrix";
   1.339 +                varyingType = kVec2f_GrSLType;
   1.340 +                break;
   1.341 +            case kGeneral_MatrixType:
   1.342 +                transforms[t].fType = kMat33f_GrSLType;
   1.343 +                uniName = "StageMatrix";
   1.344 +                varyingType = kVec3f_GrSLType;
   1.345 +                break;
   1.346 +            default:
   1.347 +                GrCrash("Unexpected key.");
   1.348 +        }
   1.349 +        SkString suffixedUniName;
   1.350 +        if (kVoid_GrSLType != transforms[t].fType) {
   1.351 +            if (0 != t) {
   1.352 +                suffixedUniName.append(uniName);
   1.353 +                suffixedUniName.appendf("_%i", t);
   1.354 +                uniName = suffixedUniName.c_str();
   1.355 +            }
   1.356 +            transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
   1.357 +                                                        transforms[t].fType,
   1.358 +                                                        uniName,
   1.359 +                                                        &uniName);
   1.360 +        }
   1.361 +
   1.362 +        const char* varyingName = "MatrixCoord";
   1.363 +        SkString suffixedVaryingName;
   1.364 +        if (0 != t) {
   1.365 +            suffixedVaryingName.append(varyingName);
   1.366 +            suffixedVaryingName.appendf("_%i", t);
   1.367 +            varyingName = suffixedVaryingName.c_str();
   1.368 +        }
   1.369 +        const char* vsVaryingName;
   1.370 +        const char* fsVaryingName;
   1.371 +        builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
   1.372 +
   1.373 +        const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
   1.374 +                                          builder->positionAttribute() :
   1.375 +                                          builder->localCoordsAttribute();
   1.376 +        // varying = matrix * coords (logically)
   1.377 +        switch (transforms[t].fType) {
   1.378 +            case kVoid_GrSLType:
   1.379 +                SkASSERT(kVec2f_GrSLType == varyingType);
   1.380 +                builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
   1.381 +                break;
   1.382 +            case kVec2f_GrSLType:
   1.383 +                SkASSERT(kVec2f_GrSLType == varyingType);
   1.384 +                builder->vsCodeAppendf("\t%s = %s + %s;\n",
   1.385 +                                       vsVaryingName, uniName, coords.c_str());
   1.386 +                break;
   1.387 +            case kMat33f_GrSLType: {
   1.388 +                SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
   1.389 +                if (kVec2f_GrSLType == varyingType) {
   1.390 +                    builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
   1.391 +                                           vsVaryingName, uniName, coords.c_str());
   1.392 +                } else {
   1.393 +                    builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
   1.394 +                                           vsVaryingName, uniName, coords.c_str());
   1.395 +                }
   1.396 +                break;
   1.397 +            }
   1.398 +            default:
   1.399 +                GrCrash("Unexpected uniform type.");
   1.400 +        }
   1.401 +        SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
   1.402 +                               (SkString(fsVaryingName), varyingType));
   1.403 +    }
   1.404 +}
   1.405 +
   1.406 +void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
   1.407 +                                       const GrGLUniformManager& uniformManager,
   1.408 +                                       const GrEffectStage* effectStages[]) {
   1.409 +    int numEffects = fGLEffects.count();
   1.410 +    SkASSERT(numEffects == fTransforms.count());
   1.411 +    SkASSERT(numEffects == fSamplers.count());
   1.412 +    for (int e = 0; e < numEffects; ++e) {
   1.413 +        GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
   1.414 +        fGLEffects[e]->setData(uniformManager, drawEffect);
   1.415 +        this->setTransformData(uniformManager, drawEffect, e);
   1.416 +        this->bindTextures(gpu, *drawEffect.effect(), e);
   1.417 +    }
   1.418 +}
   1.419 +
   1.420 +void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
   1.421 +                                                const GrDrawEffect& drawEffect,
   1.422 +                                                int effectIdx) {
   1.423 +    SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
   1.424 +    int numTransforms = transforms.count();
   1.425 +    SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
   1.426 +    for (int t = 0; t < numTransforms; ++t) {
   1.427 +        SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
   1.428 +        switch (transforms[t].fType) {
   1.429 +            case kVoid_GrSLType:
   1.430 +                SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
   1.431 +                return;
   1.432 +            case kVec2f_GrSLType: {
   1.433 +                GrGLfloat tx, ty;
   1.434 +                get_transform_translation(drawEffect, t, &tx, &ty);
   1.435 +                if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
   1.436 +                    transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
   1.437 +                    uniformManager.set2f(transforms[t].fHandle, tx, ty);
   1.438 +                    transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
   1.439 +                    transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
   1.440 +                }
   1.441 +                break;
   1.442 +            }
   1.443 +            case kMat33f_GrSLType: {
   1.444 +                const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
   1.445 +                if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
   1.446 +                    uniformManager.setSkMatrix(transforms[t].fHandle, matrix);
   1.447 +                    transforms[t].fCurrentValue = matrix;
   1.448 +                }
   1.449 +                break;
   1.450 +            }
   1.451 +            default:
   1.452 +                GrCrash("Unexpected uniform type.");
   1.453 +        }
   1.454 +    }
   1.455 +}
   1.456 +
   1.457 +GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
   1.458 +                                                                 int reserveCount)
   1.459 +    : fBuilder(builder)
   1.460 +    , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
   1.461 +                                 (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
   1.462 +}
   1.463 +
   1.464 +void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
   1.465 +                                                 GrGLProgramEffects::EffectKey key,
   1.466 +                                                 const char* outColor,
   1.467 +                                                 const char* inColor,
   1.468 +                                                 int stageIndex) {
   1.469 +    SkASSERT(NULL != fProgramEffects.get());
   1.470 +    fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
   1.471 +}
   1.472 +
   1.473 +////////////////////////////////////////////////////////////////////////////////
   1.474 +
   1.475 +void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
   1.476 +                                          const GrEffectStage& stage,
   1.477 +                                          EffectKey key,
   1.478 +                                          const char* outColor,
   1.479 +                                          const char* inColor,
   1.480 +                                          int stageIndex) {
   1.481 +    GrDrawEffect drawEffect(stage, false);
   1.482 +    const GrEffectRef& effect = *stage.getEffect();
   1.483 +    SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
   1.484 +    SkSTArray<4, TextureSampler> samplers(effect->numTextures());
   1.485 +
   1.486 +    SkASSERT(0 == stage.getVertexAttribIndexCount());
   1.487 +    this->setupTexGen(builder, effect, key, &coords);
   1.488 +    this->emitSamplers(builder, effect, &samplers);
   1.489 +
   1.490 +    GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
   1.491 +    fGLEffects.push_back(glEffect);
   1.492 +
   1.493 +    // Enclose custom code in a block to avoid namespace conflicts
   1.494 +    SkString openBrace;
   1.495 +    openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
   1.496 +    builder->fsCodeAppend(openBrace.c_str());
   1.497 +
   1.498 +    SkASSERT(!glEffect->isVertexEffect());
   1.499 +    glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
   1.500 +
   1.501 +    builder->fsCodeAppend("\t}\n");
   1.502 +}
   1.503 +
   1.504 +void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder,
   1.505 +                                           const GrEffectRef& effect,
   1.506 +                                           EffectKey effectKey,
   1.507 +                                           TransformedCoordsArray* outCoords) {
   1.508 +    int numTransforms = effect->numTransforms();
   1.509 +    EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
   1.510 +    int texCoordIndex = builder->addTexCoordSets(numTransforms);
   1.511 +    SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
   1.512 +    SkString name;
   1.513 +    for (int t = 0; t < numTransforms; ++t) {
   1.514 +        GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
   1.515 +                            kVec3f_GrSLType :
   1.516 +                            kVec2f_GrSLType;
   1.517 +        name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
   1.518 +        SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
   1.519 +    }
   1.520 +}
   1.521 +
   1.522 +void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
   1.523 +                                       const GrGLUniformManager& uniformManager,
   1.524 +                                       const GrEffectStage* effectStages[]) {
   1.525 +    int numEffects = fGLEffects.count();
   1.526 +    SkASSERT(numEffects == fTransforms.count());
   1.527 +    SkASSERT(numEffects == fSamplers.count());
   1.528 +    for (int e = 0; e < numEffects; ++e) {
   1.529 +        GrDrawEffect drawEffect(*effectStages[e], false);
   1.530 +        fGLEffects[e]->setData(uniformManager, drawEffect);
   1.531 +        this->setTexGenState(gpu, drawEffect, e);
   1.532 +        this->bindTextures(gpu, *drawEffect.effect(), e);
   1.533 +    }
   1.534 +}
   1.535 +
   1.536 +void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
   1.537 +                                              const GrDrawEffect& drawEffect,
   1.538 +                                              int effectIdx) {
   1.539 +    EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
   1.540 +    int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
   1.541 +    int numTransforms = (*drawEffect.effect())->numTransforms();
   1.542 +    for (int t = 0; t < numTransforms; ++t) {
   1.543 +        switch (get_matrix_type(totalKey, t)) {
   1.544 +            case kIdentity_MatrixType: {
   1.545 +                SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
   1.546 +                GrGLfloat identity[] = {1, 0, 0,
   1.547 +                                        0, 1, 0};
   1.548 +                gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity);
   1.549 +                break;
   1.550 +            }
   1.551 +            case kTrans_MatrixType: {
   1.552 +                GrGLfloat tx, ty;
   1.553 +                get_transform_translation(drawEffect, t, &tx, &ty);
   1.554 +                GrGLfloat translate[] = {1, 0, tx,
   1.555 +                                         0, 1, ty};
   1.556 +                gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate);
   1.557 +                break;
   1.558 +            }
   1.559 +            case kNoPersp_MatrixType: {
   1.560 +                const SkMatrix& transform = get_transform_matrix(drawEffect, t);
   1.561 +                gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform);
   1.562 +                break;
   1.563 +            }
   1.564 +            case kGeneral_MatrixType: {
   1.565 +                const SkMatrix& transform = get_transform_matrix(drawEffect, t);
   1.566 +                gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform);
   1.567 +                break;
   1.568 +            }
   1.569 +            default:
   1.570 +                GrCrash("Unexpected matrixs type.");
   1.571 +        }
   1.572 +    }
   1.573 +}
   1.574 +
   1.575 +GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder(
   1.576 +        GrGLFragmentOnlyShaderBuilder* builder,
   1.577 +        int reserveCount)
   1.578 +    : fBuilder(builder)
   1.579 +    , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) {
   1.580 +}
   1.581 +
   1.582 +void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
   1.583 +                                                 GrGLProgramEffects::EffectKey key,
   1.584 +                                                 const char* outColor,
   1.585 +                                                 const char* inColor,
   1.586 +                                                 int stageIndex) {
   1.587 +    SkASSERT(NULL != fProgramEffects.get());
   1.588 +    fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
   1.589 +}

mercurial