OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
| 8 #include "gl/builders/GrGLProgramBuilder.h" |
8 #include "GrRRectEffect.h" | 9 #include "GrRRectEffect.h" |
9 | 10 |
10 #include "gl/GrGLEffect.h" | 11 #include "gl/GrGLEffect.h" |
11 #include "gl/GrGLShaderBuilder.h" | |
12 #include "gl/GrGLSL.h" | 12 #include "gl/GrGLSL.h" |
13 #include "GrConvexPolyEffect.h" | 13 #include "GrConvexPolyEffect.h" |
14 #include "GrOvalEffect.h" | 14 #include "GrOvalEffect.h" |
15 #include "GrTBackendEffectFactory.h" | 15 #include "GrTBackendEffectFactory.h" |
16 | 16 |
17 #include "SkRRect.h" | 17 #include "SkRRect.h" |
18 | 18 |
19 // The effects defined here only handle rrect radii >= kRadiusMin. | 19 // The effects defined here only handle rrect radii >= kRadiusMin. |
20 static const SkScalar kRadiusMin = SK_ScalarHalf; | 20 static const SkScalar kRadiusMin = SK_ScalarHalf; |
21 | 21 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 } while (NULL == effect); | 127 } while (NULL == effect); |
128 return effect; | 128 return effect; |
129 } | 129 } |
130 | 130 |
131 ////////////////////////////////////////////////////////////////////////////// | 131 ////////////////////////////////////////////////////////////////////////////// |
132 | 132 |
133 class GLCircularRRectEffect : public GrGLEffect { | 133 class GLCircularRRectEffect : public GrGLEffect { |
134 public: | 134 public: |
135 GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 135 GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
136 | 136 |
137 virtual void emitCode(GrGLShaderBuilder* builder, | 137 virtual void emitCode(GrGLProgramBuilder* builder, |
138 const GrDrawEffect& drawEffect, | 138 const GrDrawEffect& drawEffect, |
139 const GrEffectKey& key, | 139 const GrEffectKey& key, |
140 const char* outputColor, | 140 const char* outputColor, |
141 const char* inputColor, | 141 const char* inputColor, |
142 const TransformedCoordsArray&, | 142 const TransformedCoordsArray&, |
143 const TextureSamplerArray&) SK_OVERRIDE; | 143 const TextureSamplerArray&) SK_OVERRIDE; |
144 | 144 |
145 static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyB
uilder*); | 145 static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyB
uilder*); |
146 | 146 |
147 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_
OVERRIDE; | 147 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_
OVERRIDE; |
148 | 148 |
149 private: | 149 private: |
150 GrGLProgramDataManager::UniformHandle fInnerRectUniform; | 150 GrGLProgramDataManager::UniformHandle fInnerRectUniform; |
151 GrGLProgramDataManager::UniformHandle fRadiusPlusHalfUniform; | 151 GrGLProgramDataManager::UniformHandle fRadiusPlusHalfUniform; |
152 SkRRect fPrevRRect; | 152 SkRRect fPrevRRect; |
153 typedef GrGLEffect INHERITED; | 153 typedef GrGLEffect INHERITED; |
154 }; | 154 }; |
155 | 155 |
156 GLCircularRRectEffect::GLCircularRRectEffect(const GrBackendEffectFactory& facto
ry, | 156 GLCircularRRectEffect::GLCircularRRectEffect(const GrBackendEffectFactory& facto
ry, |
157 const GrDrawEffect& drawEffect) | 157 const GrDrawEffect& drawEffect) |
158 : INHERITED (factory) { | 158 : INHERITED (factory) { |
159 fPrevRRect.setEmpty(); | 159 fPrevRRect.setEmpty(); |
160 } | 160 } |
161 | 161 |
162 void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder, | 162 void GLCircularRRectEffect::emitCode(GrGLProgramBuilder* builder, |
163 const GrDrawEffect& drawEffect, | 163 const GrDrawEffect& drawEffect, |
164 const GrEffectKey& key, | 164 const GrEffectKey& key, |
165 const char* outputColor, | 165 const char* outputColor, |
166 const char* inputColor, | 166 const char* inputColor, |
167 const TransformedCoordsArray&, | 167 const TransformedCoordsArray&, |
168 const TextureSamplerArray& samplers) { | 168 const TextureSamplerArray& samplers) { |
169 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>
(); | 169 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>
(); |
170 const char *rectName; | 170 const char *rectName; |
171 const char *radiusPlusHalfName; | 171 const char *radiusPlusHalfName; |
172 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri
ght, and bottom | 172 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri
ght, and bottom |
173 // edges correspond to components x, y, z, and w, respectively. When a side
of the rrect has | 173 // edges correspond to components x, y, z, and w, respectively. When a side
of the rrect has |
174 // only rectangular corners, that side's value corresponds to the rect edge'
s value outset by | 174 // only rectangular corners, that side's value corresponds to the rect edge'
s value outset by |
175 // half a pixel. | 175 // half a pixel. |
176 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil
ity, | 176 fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, |
177 kVec4f_GrSLType, | 177 kVec4f_GrSLType, |
178 "innerRect", | 178 "innerRect", |
179 &rectName); | 179 &rectName); |
180 fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Vi
sibility, | 180 fRadiusPlusHalfUniform = builder->addUniform(GrGLProgramBuilder::kFragment_V
isibility, |
181 kFloat_GrSLType, | 181 kFloat_GrSLType, |
182 "radiusPlusHalf", | 182 "radiusPlusHalf", |
183 &radiusPlusHalfName); | 183 &radiusPlusHalfName); |
184 const char* fragmentPos = builder->fragmentPosition(); | 184 |
| 185 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
| 186 const char* fragmentPos = fsBuilder->fragmentPosition(); |
185 // At each quarter-circle corner we compute a vector that is the offset of t
he fragment position | 187 // At each quarter-circle corner we compute a vector that is the offset of t
he fragment position |
186 // from the circle center. The vector is pinned in x and y to be in the quar
ter-plane relevant | 188 // from the circle center. The vector is pinned in x and y to be in the quar
ter-plane relevant |
187 // to that corner. This means that points near the interior near the rrect t
op edge will have | 189 // to that corner. This means that points near the interior near the rrect t
op edge will have |
188 // a vector that points straight up for both the TL left and TR corners. Com
puting an | 190 // a vector that points straight up for both the TL left and TR corners. Com
puting an |
189 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, | 191 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, |
190 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of | 192 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of |
191 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will | 193 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will |
192 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. | 194 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. |
193 // The code below is a simplified version of the above that performs maxs on
the vector | 195 // The code below is a simplified version of the above that performs maxs on
the vector |
194 // components before computing distances and alpha values so that only one d
istance computation | 196 // components before computing distances and alpha values so that only one d
istance computation |
195 // need be computed to determine the min alpha. | 197 // need be computed to determine the min alpha. |
196 // | 198 // |
197 // For the cases where one half of the rrect is rectangular we drop one of t
he x or y | 199 // For the cases where one half of the rrect is rectangular we drop one of t
he x or y |
198 // computations, compute a separate rect edge alpha for the rect side, and m
ul the two computed | 200 // computations, compute a separate rect edge alpha for the rect side, and m
ul the two computed |
199 // alphas together. | 201 // alphas together. |
200 switch (crre.getCircularCornerFlags()) { | 202 switch (crre.getCircularCornerFlags()) { |
201 case CircularRRectEffect::kAll_CornerFlags: | 203 case CircularRRectEffect::kAll_CornerFlags: |
202 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 204 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
203 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 205 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
204 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; | 206 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; |
205 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.
0, 1.0);\n", | 207 fsBuilder->codeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.
0, 1.0);\n", |
206 radiusPlusHalfName); | 208 radiusPlusHalfName); |
207 break; | 209 break; |
208 case CircularRRectEffect::kTopLeft_CornerFlag: | 210 case CircularRRectEffect::kTopLeft_CornerFlag: |
209 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", | 211 fsBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", |
210 rectName, fragmentPos); | 212 rectName, fragmentPos); |
211 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", | 213 fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", |
212 rectName, fragmentPos); | 214 rectName, fragmentPos); |
213 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", | 215 fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", |
214 rectName, fragmentPos); | 216 rectName, fragmentPos); |
215 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha *
clamp(%s - length(dxy), 0.0, 1.0);\n", | 217 fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha *
clamp(%s - length(dxy), 0.0, 1.0);\n", |
216 radiusPlusHalfName); | 218 radiusPlusHalfName); |
217 break; | 219 break; |
218 case CircularRRectEffect::kTopRight_CornerFlag: | 220 case CircularRRectEffect::kTopRight_CornerFlag: |
219 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y -
%s.y), 0.0);\n", | 221 fsBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y -
%s.y), 0.0);\n", |
220 fragmentPos, rectName, rectName, fragmentPos)
; | 222 fragmentPos, rectName, rectName, fragmentPos)
; |
221 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", | 223 fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", |
222 fragmentPos, rectName); | 224 fragmentPos, rectName); |
223 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", | 225 fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", |
224 rectName, fragmentPos); | 226 rectName, fragmentPos); |
225 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha *
clamp(%s - length(dxy), 0.0, 1.0);\n", | 227 fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha *
clamp(%s - length(dxy), 0.0, 1.0);\n", |
226 radiusPlusHalfName); | 228 radiusPlusHalfName); |
227 break; | 229 break; |
228 case CircularRRectEffect::kBottomRight_CornerFlag: | 230 case CircularRRectEffect::kBottomRight_CornerFlag: |
229 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", | 231 fsBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", |
230 fragmentPos, rectName); | 232 fragmentPos, rectName); |
231 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", | 233 fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", |
232 fragmentPos, rectName); | 234 fragmentPos, rectName); |
233 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", | 235 fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", |
234 fragmentPos, rectName); | 236 fragmentPos, rectName); |
235 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * cla
mp(%s - length(dxy), 0.0, 1.0);\n", | 237 fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * cla
mp(%s - length(dxy), 0.0, 1.0);\n", |
236 radiusPlusHalfName); | 238 radiusPlusHalfName); |
237 break; | 239 break; |
238 case CircularRRectEffect::kBottomLeft_CornerFlag: | 240 case CircularRRectEffect::kBottomLeft_CornerFlag: |
239 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y -
%s.w), 0.0);\n", | 241 fsBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y -
%s.w), 0.0);\n", |
240 rectName, fragmentPos, fragmentPos, rectName)
; | 242 rectName, fragmentPos, fragmentPos, rectName)
; |
241 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", | 243 fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", |
242 rectName, fragmentPos); | 244 rectName, fragmentPos); |
243 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", | 245 fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", |
244 fragmentPos, rectName); | 246 fragmentPos, rectName); |
245 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * cl
amp(%s - length(dxy), 0.0, 1.0);\n", | 247 fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * cl
amp(%s - length(dxy), 0.0, 1.0);\n", |
246 radiusPlusHalfName); | 248 radiusPlusHalfName); |
247 break; | 249 break; |
248 case CircularRRectEffect::kLeft_CornerFlags: | 250 case CircularRRectEffect::kLeft_CornerFlags: |
249 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 251 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
250 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos
, rectName); | 252 fsBuilder->codeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos
, rectName); |
251 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d
y1)), 0.0);\n"); | 253 fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d
y1)), 0.0);\n"); |
252 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", | 254 fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", |
253 rectName, fragmentPos); | 255 rectName, fragmentPos); |
254 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", | 256 fsBuilder->codeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", |
255 radiusPlusHalfName); | 257 radiusPlusHalfName); |
256 break; | 258 break; |
257 case CircularRRectEffect::kTop_CornerFlags: | 259 case CircularRRectEffect::kTop_CornerFlags: |
258 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 260 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
259 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos
, rectName); | 261 fsBuilder->codeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos
, rectName); |
260 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy
0.y), 0.0);\n"); | 262 fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy
0.y), 0.0);\n"); |
261 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", | 263 fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", |
262 rectName, fragmentPos); | 264 rectName, fragmentPos); |
263 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", | 265 fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", |
264 radiusPlusHalfName); | 266 radiusPlusHalfName); |
265 break; | 267 break; |
266 case CircularRRectEffect::kRight_CornerFlags: | 268 case CircularRRectEffect::kRight_CornerFlags: |
267 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f
ragmentPos); | 269 fsBuilder->codeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f
ragmentPos); |
268 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 270 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
269 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1
.y)), 0.0);\n"); | 271 fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1
.y)), 0.0);\n"); |
270 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", | 272 fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", |
271 fragmentPos, rectName); | 273 fragmentPos, rectName); |
272 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", | 274 fsBuilder->codeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", |
273 radiusPlusHalfName); | 275 radiusPlusHalfName); |
274 break; | 276 break; |
275 case CircularRRectEffect::kBottom_CornerFlags: | 277 case CircularRRectEffect::kBottom_CornerFlags: |
276 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f
ragmentPos); | 278 fsBuilder->codeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f
ragmentPos); |
277 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 279 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
278 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy
1.y), 0.0);\n"); | 280 fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy
1.y), 0.0);\n"); |
279 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", | 281 fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", |
280 fragmentPos, rectName); | 282 fragmentPos, rectName); |
281 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", | 283 fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", |
282 radiusPlusHalfName); | 284 radiusPlusHalfName); |
283 break; | 285 break; |
284 } | 286 } |
285 | 287 |
286 if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) { | 288 if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) { |
287 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); | 289 fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n"); |
288 } | 290 } |
289 | 291 |
290 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 292 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, |
291 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); | 293 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); |
292 } | 294 } |
293 | 295 |
294 void GLCircularRRectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCap
s&, | 296 void GLCircularRRectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCap
s&, |
295 GrEffectKeyBuilder* b) { | 297 GrEffectKeyBuilder* b) { |
296 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>
(); | 298 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>
(); |
297 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); | 299 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); |
298 b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType()); | 300 b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType()); |
299 } | 301 } |
300 | 302 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 } while (NULL == effect); | 481 } while (NULL == effect); |
480 return effect; | 482 return effect; |
481 } | 483 } |
482 | 484 |
483 ////////////////////////////////////////////////////////////////////////////// | 485 ////////////////////////////////////////////////////////////////////////////// |
484 | 486 |
485 class GLEllipticalRRectEffect : public GrGLEffect { | 487 class GLEllipticalRRectEffect : public GrGLEffect { |
486 public: | 488 public: |
487 GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 489 GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
488 | 490 |
489 virtual void emitCode(GrGLShaderBuilder* builder, | 491 virtual void emitCode(GrGLProgramBuilder* builder, |
490 const GrDrawEffect& drawEffect, | 492 const GrDrawEffect& drawEffect, |
491 const GrEffectKey& key, | 493 const GrEffectKey& key, |
492 const char* outputColor, | 494 const char* outputColor, |
493 const char* inputColor, | 495 const char* inputColor, |
494 const TransformedCoordsArray&, | 496 const TransformedCoordsArray&, |
495 const TextureSamplerArray&) SK_OVERRIDE; | 497 const TextureSamplerArray&) SK_OVERRIDE; |
496 | 498 |
497 static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyB
uilder*); | 499 static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyB
uilder*); |
498 | 500 |
499 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_
OVERRIDE; | 501 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_
OVERRIDE; |
500 | 502 |
501 private: | 503 private: |
502 GrGLProgramDataManager::UniformHandle fInnerRectUniform; | 504 GrGLProgramDataManager::UniformHandle fInnerRectUniform; |
503 GrGLProgramDataManager::UniformHandle fInvRadiiSqdUniform; | 505 GrGLProgramDataManager::UniformHandle fInvRadiiSqdUniform; |
504 SkRRect fPrevRRect; | 506 SkRRect fPrevRRect; |
505 typedef GrGLEffect INHERITED; | 507 typedef GrGLEffect INHERITED; |
506 }; | 508 }; |
507 | 509 |
508 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f
actory, | 510 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f
actory, |
509 const GrDrawEffect& drawEffect) | 511 const GrDrawEffect& drawEffect) |
510 : INHERITED (factory) { | 512 : INHERITED (factory) { |
511 fPrevRRect.setEmpty(); | 513 fPrevRRect.setEmpty(); |
512 } | 514 } |
513 | 515 |
514 void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, | 516 void GLEllipticalRRectEffect::emitCode(GrGLProgramBuilder* builder, |
515 const GrDrawEffect& drawEffect, | 517 const GrDrawEffect& drawEffect, |
516 const GrEffectKey& key, | 518 const GrEffectKey& key, |
517 const char* outputColor, | 519 const char* outputColor, |
518 const char* inputColor, | 520 const char* inputColor, |
519 const TransformedCoordsArray&, | 521 const TransformedCoordsArray&, |
520 const TextureSamplerArray& samplers) { | 522 const TextureSamplerArray& samplers) { |
521 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff
ect>(); | 523 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff
ect>(); |
522 const char *rectName; | 524 const char *rectName; |
523 // The inner rect is the rrect bounds inset by the x/y radii | 525 // The inner rect is the rrect bounds inset by the x/y radii |
524 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil
ity, | 526 fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, |
525 kVec4f_GrSLType, | 527 kVec4f_GrSLType, |
526 "innerRect", | 528 "innerRect", |
527 &rectName); | 529 &rectName); |
528 const char* fragmentPos = builder->fragmentPosition(); | 530 |
| 531 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
| 532 const char* fragmentPos = fsBuilder->fragmentPosition(); |
529 // At each quarter-ellipse corner we compute a vector that is the offset of
the fragment pos | 533 // At each quarter-ellipse corner we compute a vector that is the offset of
the fragment pos |
530 // to the ellipse center. The vector is pinned in x and y to be in the quart
er-plane relevant | 534 // to the ellipse center. The vector is pinned in x and y to be in the quart
er-plane relevant |
531 // to that corner. This means that points near the interior near the rrect t
op edge will have | 535 // to that corner. This means that points near the interior near the rrect t
op edge will have |
532 // a vector that points straight up for both the TL left and TR corners. Com
puting an | 536 // a vector that points straight up for both the TL left and TR corners. Com
puting an |
533 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, | 537 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, |
534 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of | 538 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of |
535 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dii > 0.5 they will | 539 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dii > 0.5 they will |
536 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. | 540 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. |
537 // The code below is a simplified version of the above that performs maxs on
the vector | 541 // The code below is a simplified version of the above that performs maxs on
the vector |
538 // components before computing distances and alpha values so that only one d
istance computation | 542 // components before computing distances and alpha values so that only one d
istance computation |
539 // need be computed to determine the min alpha. | 543 // need be computed to determine the min alpha. |
540 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen
tPos); | 544 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen
tPos); |
541 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect
Name); | 545 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect
Name); |
542 switch (erre.getRRect().getType()) { | 546 switch (erre.getRRect().getType()) { |
543 case SkRRect::kSimple_Type: { | 547 case SkRRect::kSimple_Type: { |
544 const char *invRadiiXYSqdName; | 548 const char *invRadiiXYSqdName; |
545 fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragme
nt_Visibility, | 549 fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragm
ent_Visibility, |
546 kVec2f_GrSLType, | 550 kVec2f_GrSLType, |
547 "invRadiiXY", | 551 "invRadiiXY", |
548 &invRadiiXYSqdName); | 552 &invRadiiXYSqdName); |
549 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; | 553 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; |
550 // Z is the x/y offsets divided by squared radii. | 554 // Z is the x/y offsets divided by squared radii. |
551 builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName
); | 555 fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName
); |
552 break; | 556 break; |
553 } | 557 } |
554 case SkRRect::kNinePatch_Type: { | 558 case SkRRect::kNinePatch_Type: { |
555 const char *invRadiiLTRBSqdName; | 559 const char *invRadiiLTRBSqdName; |
556 fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragme
nt_Visibility, | 560 fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragm
ent_Visibility, |
557 kVec4f_GrSLType, | 561 kVec4f_GrSLType, |
558 "invRadiiLTRB", | 562 "invRadiiLTRB", |
559 &invRadiiLTRBSqdName); | 563 &invRadiiLTRBSqdName); |
560 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; | 564 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; |
561 // Z is the x/y offsets divided by squared radii. We only care about
the (at most) one | 565 // Z is the x/y offsets divided by squared radii. We only care about
the (at most) one |
562 // corner where both the x and y offsets are positive, hence the max
es. (The inverse | 566 // corner where both the x and y offsets are positive, hence the max
es. (The inverse |
563 // squared radii will always be positive.) | 567 // squared radii will always be positive.) |
564 builder->fsCodeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s
.zw), 0.0);\n", | 568 fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s
.zw), 0.0);\n", |
565 invRadiiLTRBSqdName, invRadiiLTRBSqdName); | 569 invRadiiLTRBSqdName, invRadiiLTRBSqdName); |
566 break; | 570 break; |
567 } | 571 } |
568 default: | 572 default: |
569 SkFAIL("RRect should always be simple or nine-patch."); | 573 SkFAIL("RRect should always be simple or nine-patch."); |
570 } | 574 } |
571 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. | 575 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. |
572 builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); | 576 fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); |
573 // grad_dot is the squared length of the gradient of the implicit. | 577 // grad_dot is the squared length of the gradient of the implicit. |
574 builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); | 578 fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); |
575 // avoid calling inversesqrt on zero. | 579 // avoid calling inversesqrt on zero. |
576 builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); | 580 fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); |
577 builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_
dot);\n"); | 581 fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_
dot);\n"); |
578 | 582 |
579 if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) { | 583 if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) { |
580 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1
.0);\n"); | 584 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1
.0);\n"); |
581 } else { | 585 } else { |
582 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1
.0);\n"); | 586 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1
.0);\n"); |
583 } | 587 } |
584 | 588 |
585 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 589 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, |
586 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); | 590 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); |
587 } | 591 } |
588 | 592 |
589 void GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLC
aps&, | 593 void GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLC
aps&, |
590 GrEffectKeyBuilder* b) { | 594 GrEffectKeyBuilder* b) { |
591 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff
ect>(); | 595 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff
ect>(); |
592 GR_STATIC_ASSERT(kLast_GrEffectEdgeType < (1 << 3)); | 596 GR_STATIC_ASSERT(kLast_GrEffectEdgeType < (1 << 3)); |
593 b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3); | 597 b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3); |
594 } | 598 } |
595 | 599 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 if (rrect.isNinePatch()) { | 725 if (rrect.isNinePatch()) { |
722 return EllipticalRRectEffect::Create(edgeType, rrect); | 726 return EllipticalRRectEffect::Create(edgeType, rrect); |
723 } | 727 } |
724 return NULL; | 728 return NULL; |
725 } | 729 } |
726 } | 730 } |
727 } | 731 } |
728 | 732 |
729 return NULL; | 733 return NULL; |
730 } | 734 } |
OLD | NEW |