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