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