• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GenKey(const SkMatrix & effectMatrix,const SkMatrix & coordChangeMatrix,const GrTexture * texture)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 
emitCode(GrGLShaderBuilder * builder,EffectKey key,const char * vertexCoords,const char ** fsCoordName,const char ** vsCoordName,const char * suffix)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     */
emitCodeMakeFSCoords2D(GrGLShaderBuilder * builder,EffectKey key,const char * vertexCoords,const char ** fsCoordName,const char ** vsVaryingName,GrSLType * vsVaryingType,const char * suffix)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 
setData(const GrGLUniformManager & uniformManager,const SkMatrix & matrix,const SkMatrix & coordChangeMatrix,const GrTexture * texture)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