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