| 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 |