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