Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2012 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 "GrGLEffectMatrix.h"
      9 #include "GrDrawEffect.h"
     10 #include "GrTexture.h"
     11 
     12 GrGLEffect::EffectKey GrGLEffectMatrix::GenKey(const SkMatrix& effectMatrix,
     13                                                const GrDrawEffect& drawEffect,
     14                                                CoordsType coordsType,
     15                                                const GrTexture* texture) {
     16     EffectKey key = 0;
     17     SkMatrix::TypeMask type0 = effectMatrix.getType();
     18     SkMatrix::TypeMask type1;
     19     if (GrEffect::kLocal_CoordsType == coordsType) {
     20         type1 = drawEffect.getCoordChangeMatrix().getType();
     21     } else {
     22         if (drawEffect.programHasExplicitLocalCoords()) {
     23             // We only make the key indicate that device coords are referenced when the local coords
     24             // are not actually determined by positions.
     25             key |= kPositionCoords_Flag;
     26         }
     27         type1 = SkMatrix::kIdentity_Mask;
     28     }
     29 
     30     int combinedTypes = type0 | type1;
     31 
     32     bool reverseY = (NULL != texture) && kBottomLeft_GrSurfaceOrigin == texture->origin();
     33 
     34     if (SkMatrix::kPerspective_Mask & combinedTypes) {
     35         key |= kGeneral_MatrixType;
     36     } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) {
     37         key |= kNoPersp_MatrixType;
     38     } else if (SkMatrix::kTranslate_Mask & combinedTypes) {
     39         key |= kTrans_MatrixType;
     40     } else {
     41         key |= kIdentity_MatrixType;
     42     }
     43     return key;
     44 }
     45 
     46 GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder,
     47                                     EffectKey key,
     48                                     const char** fsCoordName,
     49                                     const char** vsCoordName,
     50                                     const char* suffix) {
     51     GrSLType varyingType = kVoid_GrSLType;
     52     const char* uniName;
     53     key &= kKeyMask;
     54     switch (key & kMatrixTypeKeyMask) {
     55         case kIdentity_MatrixType:
     56             fUniType = kVoid_GrSLType;
     57             varyingType = kVec2f_GrSLType;
     58             break;
     59         case kTrans_MatrixType:
     60             fUniType = kVec2f_GrSLType;
     61             uniName = "StageTranslate";
     62             varyingType = kVec2f_GrSLType;
     63             break;
     64         case kNoPersp_MatrixType:
     65             fUniType = kMat33f_GrSLType;
     66             uniName = "StageMatrix";
     67             varyingType = kVec2f_GrSLType;
     68             break;
     69         case kGeneral_MatrixType:
     70             fUniType = kMat33f_GrSLType;
     71             uniName = "StageMatrix";
     72             varyingType = kVec3f_GrSLType;
     73             break;
     74         default:
     75             GrCrash("Unexpected key.");
     76     }
     77     SkString suffixedUniName;
     78     if (NULL != suffix) {
     79         suffixedUniName.append(uniName);
     80         suffixedUniName.append(suffix);
     81         uniName = suffixedUniName.c_str();
     82     }
     83     if (kVoid_GrSLType != fUniType) {
     84         fUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
     85                                    fUniType,
     86                                    uniName,
     87                                    &uniName);
     88     }
     89 
     90     const char* varyingName = "MatrixCoord";
     91     SkString suffixedVaryingName;
     92     if (NULL != suffix) {
     93         suffixedVaryingName.append(varyingName);
     94         suffixedVaryingName.append(suffix);
     95         varyingName = suffixedVaryingName.c_str();
     96     }
     97     const char* vsVaryingName;
     98     const char* fsVaryingName;
     99     builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
    100 
    101     const GrGLShaderVar* coords;
    102     switch (fCoordsType) {
    103         case GrEffect::kLocal_CoordsType:
    104             GrAssert(!(kPositionCoords_Flag & key));
    105             coords = &builder->localCoordsAttribute();
    106             break;
    107         case GrEffect::kPosition_CoordsType:
    108             GrAssert((kPositionCoords_Flag & key) || !builder->hasExplicitLocalCoords());
    109             coords = &builder->positionAttribute();
    110             break;
    111         default:
    112             coords = NULL; // prevents warning
    113             GrCrash("Unexpected coords type.");
    114     }
    115     // varying = matrix * coords (logically)
    116     switch (fUniType) {
    117         case kVoid_GrSLType:
    118             GrAssert(kVec2f_GrSLType == varyingType);
    119             builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords->c_str());
    120             break;
    121         case kVec2f_GrSLType:
    122             GrAssert(kVec2f_GrSLType == varyingType);
    123             builder->vsCodeAppendf("\t%s = %s + %s;\n",
    124                                    vsVaryingName, uniName, coords->c_str());
    125             break;
    126         case kMat33f_GrSLType: {
    127             GrAssert(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
    128             if (kVec2f_GrSLType == varyingType) {
    129                 builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
    130                                        vsVaryingName, uniName, coords->c_str());
    131             } else {
    132                 builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
    133                                        vsVaryingName, uniName, coords->c_str());
    134             }
    135             break;
    136         }
    137         default:
    138             GrCrash("Unexpected uniform type.");
    139     }
    140     if (NULL != vsCoordName) {
    141         *vsCoordName = vsVaryingName;
    142     }
    143     if (NULL != fsCoordName) {
    144         *fsCoordName = fsVaryingName;
    145     }
    146     return varyingType;
    147 }
    148 
    149 /**
    150     * This is similar to emitCode except that it performs perspective division in the FS if the
    151     * texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f.
    152     */
    153 void GrGLEffectMatrix::emitCodeMakeFSCoords2D(GrGLShaderBuilder* builder,
    154                                               EffectKey key,
    155                                               const char** fsCoordName,
    156                                               const char** vsVaryingName,
    157                                               GrSLType* vsVaryingType,
    158                                               const char* suffix) {
    159     const char* fsVaryingName;
    160 
    161     GrSLType varyingType = this->emitCode(builder,
    162                                           key,
    163                                           &fsVaryingName,
    164                                           vsVaryingName,
    165                                           suffix);
    166     if (kVec3f_GrSLType == varyingType) {
    167 
    168         const char* coordName = "coords2D";
    169         SkString suffixedCoordName;
    170         if (NULL != suffix) {
    171             suffixedCoordName.append(coordName);
    172             suffixedCoordName.append(suffix);
    173             coordName = suffixedCoordName.c_str();
    174         }
    175         builder->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;",
    176                                coordName, fsVaryingName, fsVaryingName);
    177         if (NULL != fsCoordName) {
    178             *fsCoordName = coordName;
    179         }
    180     } else if(NULL != fsCoordName) {
    181         *fsCoordName = fsVaryingName;
    182     }
    183     if (NULL != vsVaryingType) {
    184         *vsVaryingType = varyingType;
    185     }
    186 }
    187 
    188 void GrGLEffectMatrix::setData(const GrGLUniformManager& uniformManager,
    189                                const SkMatrix& matrix,
    190                                const GrDrawEffect& drawEffect,
    191                                const GrTexture* texture) {
    192     GrAssert((GrGLUniformManager::kInvalidUniformHandle == fUni) ==
    193              (kVoid_GrSLType == fUniType));
    194     const SkMatrix& coordChangeMatrix = GrEffect::kLocal_CoordsType == fCoordsType ?
    195                                             drawEffect.getCoordChangeMatrix() :
    196                                             SkMatrix::I();
    197     switch (fUniType) {
    198         case kVoid_GrSLType:
    199             GrAssert(matrix.isIdentity());
    200             GrAssert(coordChangeMatrix.isIdentity());
    201             GrAssert(NULL == texture || kTopLeft_GrSurfaceOrigin == texture->origin());
    202             return;
    203         case kVec2f_GrSLType: {
    204             GrAssert(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
    205             GrAssert(NULL == texture || kTopLeft_GrSurfaceOrigin == texture->origin());
    206             SkScalar tx = matrix[SkMatrix::kMTransX] + (coordChangeMatrix)[SkMatrix::kMTransX];
    207             SkScalar ty = matrix[SkMatrix::kMTransY] + (coordChangeMatrix)[SkMatrix::kMTransY];
    208             if (fPrevMatrix.get(SkMatrix::kMTransX) != tx ||
    209                 fPrevMatrix.get(SkMatrix::kMTransY) != ty) {
    210                 uniformManager.set2f(fUni, tx, ty);
    211                 fPrevMatrix.set(SkMatrix::kMTransX, tx);
    212                 fPrevMatrix.set(SkMatrix::kMTransY, ty);
    213             }
    214             break;
    215         }
    216         case kMat33f_GrSLType: {
    217             SkMatrix combined;
    218             combined.setConcat(matrix, coordChangeMatrix);
    219             if (NULL != texture && kBottomLeft_GrSurfaceOrigin == texture->origin()) {
    220                 // combined.postScale(1,-1);
    221                 // combined.postTranslate(0,1);
    222                 combined.set(SkMatrix::kMSkewY,
    223                     combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
    224                 combined.set(SkMatrix::kMScaleY,
    225                     combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
    226                 combined.set(SkMatrix::kMTransY,
    227                     combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
    228             }
    229             if (!fPrevMatrix.cheapEqualTo(combined)) {
    230                 uniformManager.setSkMatrix(fUni, combined);
    231                 fPrevMatrix = combined;
    232             }
    233             break;
    234         }
    235         default:
    236             GrCrash("Unexpected uniform type.");
    237     }
    238 }
    239