OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrDistanceFieldGeoProc.h" | 8 #include "GrDistanceFieldGeoProc.h" |
9 #include "GrInvariantOutput.h" | 9 #include "GrInvariantOutput.h" |
10 #include "GrTexture.h" | 10 #include "GrTexture.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 varyingHandler, | 72 varyingHandler, |
73 uniformHandler, | 73 uniformHandler, |
74 gpArgs->fPositionVar, | 74 gpArgs->fPositionVar, |
75 dfTexEffect.inPosition()->fName, | 75 dfTexEffect.inPosition()->fName, |
76 args.fTransformsIn, | 76 args.fTransformsIn, |
77 args.fTransformsOut); | 77 args.fTransformsOut); |
78 | 78 |
79 // add varyings | 79 // add varyings |
80 GrGLSLVertToFrag recipScale(kFloat_GrSLType); | 80 GrGLSLVertToFrag recipScale(kFloat_GrSLType); |
81 GrGLSLVertToFrag uv(kVec2f_GrSLType); | 81 GrGLSLVertToFrag uv(kVec2f_GrSLType); |
| 82 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFi
eldEffectMask) == |
| 83 kUniformScale_DistanceFieldEffectMask; |
82 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_Distan
ceFieldEffectFlag); | 84 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_Distan
ceFieldEffectFlag); |
83 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); | 85 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
84 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCo
ords()->fName); | 86 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCo
ords()->fName); |
85 | 87 |
86 // compute numbers to be hardcoded to convert texture coordinates from i
nt to float | 88 // compute numbers to be hardcoded to convert texture coordinates from f
loat to int |
87 SkASSERT(dfTexEffect.numTextures() == 1); | 89 SkASSERT(dfTexEffect.numTextures() == 1); |
88 GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); | 90 GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); |
89 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()))
; | 91 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()))
; |
90 | 92 |
91 GrGLSLVertToFrag st(kVec2f_GrSLType); | 93 GrGLSLVertToFrag st(kVec2f_GrSLType); |
92 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision)
; | 94 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision)
; |
93 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(), | 95 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(), |
94 atlas->width(), atlas->height(), | 96 atlas->width(), atlas->height(), |
95 dfTexEffect.inTextureCoords()->fName); | 97 dfTexEffect.inTextureCoords()->fName); |
96 | 98 |
97 // Use highp to work around aliasing issues | 99 // Use highp to work around aliasing issues |
98 fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, | 100 fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, |
99 kHigh_GrSLPreci
sion)); | 101 kHigh_GrSLPreci
sion)); |
100 fragBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); | 102 fragBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); |
101 | 103 |
102 fragBuilder->codeAppend("\tfloat texColor = "); | 104 fragBuilder->codeAppend("\tfloat texColor = "); |
103 fragBuilder->appendTextureLookup(args.fSamplers[0], | 105 fragBuilder->appendTextureLookup(args.fSamplers[0], |
104 "uv", | 106 "uv", |
105 kVec2f_GrSLType); | 107 kVec2f_GrSLType); |
106 fragBuilder->codeAppend(".r;\n"); | 108 fragBuilder->codeAppend(".r;\n"); |
107 fragBuilder->codeAppend("\tfloat distance = " | 109 fragBuilder->codeAppend("\tfloat distance = " |
108 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFie
ldThreshold ");"); | 110 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFie
ldThreshold ");"); |
109 #ifdef SK_GAMMA_APPLY_TO_A8 | 111 #ifdef SK_GAMMA_APPLY_TO_A8 |
110 // adjust width based on gamma | 112 // adjust width based on gamma |
111 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); | 113 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); |
112 #endif | 114 #endif |
113 | 115 |
114 fragBuilder->codeAppend("float afwidth;"); | 116 fragBuilder->codeAppend("float afwidth;"); |
115 if (isSimilarity) { | 117 if (isUniformScale) { |
116 // For uniform scale, we adjust for the effect of the transformation
on the distance | 118 // For uniform scale, we adjust for the effect of the transformation
on the distance |
| 119 // by using the length of the gradient of the t coordinate in the y
direction. |
| 120 // We use st coordinates to ensure we're mapping 1:1 from texel spac
e to pixel space. |
| 121 // We use the y gradient because there is a bug in the Mali 400 in t
he x direction. |
| 122 |
| 123 // this gives us a smooth step across approximately one fragment |
| 124 fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "
*dFdy(%s.y));", |
| 125 st.fsIn()); |
| 126 } else if (isSimilarity) { |
| 127 // For similarity transform, we adjust the effect of the transformat
ion on the distance |
117 // by using the length of the gradient of the texture coordinates. W
e use st coordinates | 128 // by using the length of the gradient of the texture coordinates. W
e use st coordinates |
118 // to ensure we're mapping 1:1 from texel space to pixel space. | 129 // to ensure we're mapping 1:1 from texel space to pixel space. |
| 130 // We use the y gradient because there is a bug in the Mali 400 in t
he x direction. |
119 | 131 |
120 // this gives us a smooth step across approximately one fragment | 132 // this gives us a smooth step across approximately one fragment |
121 // we use y to work around a Mali400 bug in the x direction | 133 fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st
.fsIn()); |
122 fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "
*dFdy(%s.y));", | 134 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*
st_grad_len);"); |
123 st.fsIn()); | |
124 } else { | 135 } else { |
125 // For general transforms, to determine the amount of correction we
multiply a unit | 136 // For general transforms, to determine the amount of correction we
multiply a unit |
126 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords | 137 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords |
127 // (which is the inverse transform for this fragment) and take the l
ength of the result. | 138 // (which is the inverse transform for this fragment) and take the l
ength of the result. |
128 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(
distance));"); | 139 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(
distance));"); |
129 // the length of the gradient may be 0, so we need to check for this | 140 // the length of the gradient may be 0, so we need to check for this |
130 // this also compensates for the Adreno, which likes to drop tiles o
n division by 0 | 141 // this also compensates for the Adreno, which likes to drop tiles o
n division by 0 |
131 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"
); | 142 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"
); |
132 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); | 143 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); |
133 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); | 144 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 SkShader::kRepeat_TileMode, | 258 SkShader::kRepeat_TileMode, |
248 SkShader::kMirror_TileMode, | 259 SkShader::kMirror_TileMode, |
249 }; | 260 }; |
250 SkShader::TileMode tileModes[] = { | 261 SkShader::TileMode tileModes[] = { |
251 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 262 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
252 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 263 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
253 }; | 264 }; |
254 GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::
kBilerp_FilterMode : | 265 GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::
kBilerp_FilterMode : |
255 GrTextureParams::kNon
e_FilterMode); | 266 GrTextureParams::kNon
e_FilterMode); |
256 | 267 |
| 268 uint32_t flags = 0; |
| 269 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; |
| 270 if (flags & kSimilarity_DistanceFieldEffectFlag) { |
| 271 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0
; |
| 272 } |
| 273 |
257 return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(d->fRandom), | 274 return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(d->fRandom), |
258 GrTest::TestMatrix(d->fRandom), | 275 GrTest::TestMatrix(d->fRandom), |
259 d->fTextures[texIdx], params, | 276 d->fTextures[texIdx], params, |
260 #ifdef SK_GAMMA_APPLY_TO_A8 | 277 #ifdef SK_GAMMA_APPLY_TO_A8 |
261 d->fRandom->nextF(), | 278 d->fRandom->nextF(), |
262 #endif | 279 #endif |
263 d->fRandom->nextBool() ? | 280 flags, |
264 kSimilarity_DistanceFieldEff
ectFlag : 0, | 281 d->fRandom->nextBool()); |
265 d->fRandom->nextBool()); | |
266 } | 282 } |
267 | 283 |
268 /////////////////////////////////////////////////////////////////////////////// | 284 /////////////////////////////////////////////////////////////////////////////// |
269 | 285 |
270 class GrGLDistanceFieldPathGeoProc : public GrGLSLGeometryProcessor { | 286 class GrGLDistanceFieldPathGeoProc : public GrGLSLGeometryProcessor { |
271 public: | 287 public: |
272 GrGLDistanceFieldPathGeoProc() | 288 GrGLDistanceFieldPathGeoProc() |
273 : fViewMatrix(SkMatrix::InvalidMatrix()) | 289 : fViewMatrix(SkMatrix::InvalidMatrix()) |
274 , fTextureSize(SkISize::Make(-1, -1)) {} | 290 , fTextureSize(SkISize::Make(-1, -1)) {} |
275 | 291 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 "uv", | 344 "uv", |
329 kVec2f_GrSLType); | 345 kVec2f_GrSLType); |
330 fragBuilder->codeAppend(".r;"); | 346 fragBuilder->codeAppend(".r;"); |
331 fragBuilder->codeAppend("float distance = " | 347 fragBuilder->codeAppend("float distance = " |
332 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold
");"); | 348 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold
");"); |
333 | 349 |
334 fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, | 350 fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, |
335 kHigh_GrSLPreci
sion)); | 351 kHigh_GrSLPreci
sion)); |
336 fragBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); | 352 fragBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); |
337 fragBuilder->codeAppend("float afwidth;"); | 353 fragBuilder->codeAppend("float afwidth;"); |
338 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { | 354 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFi
eldEffectMask) == |
| 355 kUniformScale_DistanceFieldEffectMask; |
| 356 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_Distan
ceFieldEffectFlag); |
| 357 if (isUniformScale) { |
339 // For uniform scale, we adjust for the effect of the transformation
on the distance | 358 // For uniform scale, we adjust for the effect of the transformation
on the distance |
340 // by using the length of the gradient of the texture coordinates. W
e use st coordinates | 359 // by using the length of the gradient of the t coordinate in the y
direction. |
341 // to ensure we're mapping 1:1 from texel space to pixel space. | 360 // We use st coordinates to ensure we're mapping 1:1 from texel spac
e to pixel space. |
| 361 // We use the y gradient because there is a bug in the Mali 400 in t
he x direction. |
342 | 362 |
343 // this gives us a smooth step across approximately one fragment | 363 // this gives us a smooth step across approximately one fragment |
344 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*
dFdy(st.y));"); | 364 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*
dFdy(st.y));"); |
| 365 |
| 366 } else if (isSimilarity) { |
| 367 // For similarity transform, we adjust the effect of the transformat
ion on the distance |
| 368 // by using the length of the gradient of the texture coordinates. W
e use st coordinates |
| 369 // to ensure we're mapping 1:1 from texel space to pixel space. |
| 370 // We use the y gradient because there is a bug in the Mali 400 in t
he x direction. |
| 371 |
| 372 // this gives us a smooth step across approximately one fragment |
| 373 fragBuilder->codeAppend("float st_grad_len = length(dFdy(st));"); |
| 374 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*
st_grad_len);"); |
345 } else { | 375 } else { |
346 // For general transforms, to determine the amount of correction we
multiply a unit | 376 // For general transforms, to determine the amount of correction we
multiply a unit |
347 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords | 377 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords |
348 // (which is the inverse transform for this fragment) and take the l
ength of the result. | 378 // (which is the inverse transform for this fragment) and take the l
ength of the result. |
349 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(
distance));"); | 379 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(
distance));"); |
350 // the length of the gradient may be 0, so we need to check for this | 380 // the length of the gradient may be 0, so we need to check for this |
351 // this also compensates for the Adreno, which likes to drop tiles o
n division by 0 | 381 // this also compensates for the Adreno, which likes to drop tiles o
n division by 0 |
352 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"
); | 382 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"
); |
353 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); | 383 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); |
354 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); | 384 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 SkShader::kRepeat_TileMode, | 487 SkShader::kRepeat_TileMode, |
458 SkShader::kMirror_TileMode, | 488 SkShader::kMirror_TileMode, |
459 }; | 489 }; |
460 SkShader::TileMode tileModes[] = { | 490 SkShader::TileMode tileModes[] = { |
461 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 491 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
462 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 492 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
463 }; | 493 }; |
464 GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::
kBilerp_FilterMode | 494 GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::
kBilerp_FilterMode |
465 : GrTextureParams::
kNone_FilterMode); | 495 : GrTextureParams::
kNone_FilterMode); |
466 | 496 |
| 497 uint32_t flags = 0; |
| 498 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; |
| 499 if (flags & kSimilarity_DistanceFieldEffectFlag) { |
| 500 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0
; |
| 501 } |
| 502 |
467 return GrDistanceFieldPathGeoProc::Create(GrRandomColor(d->fRandom), | 503 return GrDistanceFieldPathGeoProc::Create(GrRandomColor(d->fRandom), |
468 GrTest::TestMatrix(d->fRandom), | 504 GrTest::TestMatrix(d->fRandom), |
469 d->fTextures[texIdx], | 505 d->fTextures[texIdx], |
470 params, | 506 params, |
471 d->fRandom->nextBool() ? | 507 flags, |
472 kSimilarity_DistanceFieldE
ffectFlag : 0, | 508 d->fRandom->nextBool()); |
473 d->fRandom->nextBool()); | |
474 } | 509 } |
475 | 510 |
476 /////////////////////////////////////////////////////////////////////////////// | 511 /////////////////////////////////////////////////////////////////////////////// |
477 | 512 |
478 class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor { | 513 class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor { |
479 public: | 514 public: |
480 GrGLDistanceFieldLCDTextGeoProc() | 515 GrGLDistanceFieldLCDTextGeoProc() |
481 : fViewMatrix(SkMatrix::InvalidMatrix()) { | 516 : fViewMatrix(SkMatrix::InvalidMatrix()) { |
482 fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.
0f, 1.0f, 1.0f); | 517 fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.
0f, 1.0f, 1.0f); |
483 } | 518 } |
(...skipping 27 matching lines...) Expand all Loading... |
511 // emit transforms | 546 // emit transforms |
512 this->emitTransforms(vertBuilder, | 547 this->emitTransforms(vertBuilder, |
513 varyingHandler, | 548 varyingHandler, |
514 uniformHandler, | 549 uniformHandler, |
515 gpArgs->fPositionVar, | 550 gpArgs->fPositionVar, |
516 dfTexEffect.inPosition()->fName, | 551 dfTexEffect.inPosition()->fName, |
517 args.fTransformsIn, | 552 args.fTransformsIn, |
518 args.fTransformsOut); | 553 args.fTransformsOut); |
519 | 554 |
520 // set up varyings | 555 // set up varyings |
521 bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_Di
stanceFieldEffectMask); | 556 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFi
eldEffectMask) == |
| 557 kUniformScale_DistanceFieldEffectMask; |
| 558 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_Distan
ceFieldEffectFlag); |
522 GrGLSLVertToFrag recipScale(kFloat_GrSLType); | 559 GrGLSLVertToFrag recipScale(kFloat_GrSLType); |
523 GrGLSLVertToFrag uv(kVec2f_GrSLType); | 560 GrGLSLVertToFrag uv(kVec2f_GrSLType); |
524 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); | 561 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
525 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCo
ords()->fName); | 562 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCo
ords()->fName); |
526 | 563 |
527 // compute numbers to be hardcoded to convert texture coordinates from i
nt to float | 564 // compute numbers to be hardcoded to convert texture coordinates from f
loat to int |
528 SkASSERT(dfTexEffect.numTextures() == 1); | 565 SkASSERT(dfTexEffect.numTextures() == 1); |
529 GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); | 566 GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); |
530 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()))
; | 567 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()))
; |
531 | 568 |
532 GrGLSLVertToFrag st(kVec2f_GrSLType); | 569 GrGLSLVertToFrag st(kVec2f_GrSLType); |
533 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision)
; | 570 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision)
; |
534 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(), | 571 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(), |
535 atlas->width(), atlas->height(), | 572 atlas->width(), atlas->height(), |
536 dfTexEffect.inTextureCoords()->fName); | 573 dfTexEffect.inTextureCoords()->fName); |
537 | 574 |
(...skipping 10 matching lines...) Expand all Loading... |
548 fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, | 585 fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, |
549 kHigh_GrSLPreci
sion)); | 586 kHigh_GrSLPreci
sion)); |
550 | 587 |
551 SkScalar lcdDelta = 1.0f / (3.0f * atlas->width()); | 588 SkScalar lcdDelta = 1.0f / (3.0f * atlas->width()); |
552 if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { | 589 if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { |
553 fragBuilder->codeAppendf("float delta = -%.*f;\n", SK_FLT_DECIMAL_DI
G, lcdDelta); | 590 fragBuilder->codeAppendf("float delta = -%.*f;\n", SK_FLT_DECIMAL_DI
G, lcdDelta); |
554 } else { | 591 } else { |
555 fragBuilder->codeAppendf("float delta = %.*f;\n", SK_FLT_DECIMAL_DIG
, lcdDelta); | 592 fragBuilder->codeAppendf("float delta = %.*f;\n", SK_FLT_DECIMAL_DIG
, lcdDelta); |
556 } | 593 } |
557 if (isUniformScale) { | 594 if (isUniformScale) { |
558 fragBuilder->codeAppendf("float dy = abs(dFdy(%s.y));", st.fsIn()); | 595 fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.
fsIn()); |
559 fragBuilder->codeAppend("vec2 offset = vec2(dy*delta, 0.0);"); | 596 fragBuilder->codeAppend("vec2 offset = vec2(st_grad_len*delta, 0.0);
"); |
| 597 } else if (isSimilarity) { |
| 598 // For a similarity matrix with rotation, the gradient will not be a
ligned |
| 599 // with the texel coordinate axes, so we need to calculate it. |
| 600 // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to |
| 601 // get the gradient in the x direction. |
| 602 fragBuilder->codeAppendf("vec2 st_grad = dFdy(%s);", st.fsIn()); |
| 603 fragBuilder->codeAppend("float st_grad_len = length(st_grad);"); |
| 604 fragBuilder->codeAppend("vec2 offset = delta*vec2(st_grad.y, -st_gra
d.x);"); |
560 } else { | 605 } else { |
561 fragBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); | 606 fragBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); |
562 | 607 |
563 fragBuilder->codeAppend("vec2 Jdx = dFdx(st);"); | 608 fragBuilder->codeAppend("vec2 Jdx = dFdx(st);"); |
564 fragBuilder->codeAppend("vec2 Jdy = dFdy(st);"); | 609 fragBuilder->codeAppend("vec2 Jdy = dFdy(st);"); |
565 fragBuilder->codeAppend("vec2 offset = delta*Jdx;"); | 610 fragBuilder->codeAppend("vec2 offset = delta*Jdx;"); |
566 } | 611 } |
567 | 612 |
568 // green is distance to uv center | 613 // green is distance to uv center |
569 fragBuilder->codeAppend("\tvec4 texColor = "); | 614 fragBuilder->codeAppend("\tvec4 texColor = "); |
(...skipping 22 matching lines...) Expand all Loading... |
592 fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 637 fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
593 kVec3f_GrSLType, kDefaul
t_GrSLPrecision, | 638 kVec3f_GrSLType, kDefaul
t_GrSLPrecision, |
594 "DistanceAdjust", &dista
nceAdjustUniName); | 639 "DistanceAdjust", &dista
nceAdjustUniName); |
595 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); | 640 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); |
596 | 641 |
597 // To be strictly correct, we should compute the anti-aliasing factor se
parately | 642 // To be strictly correct, we should compute the anti-aliasing factor se
parately |
598 // for each color component. However, this is only important when using
perspective | 643 // for each color component. However, this is only important when using
perspective |
599 // transformations, and even then using a single factor seems like a rea
sonable | 644 // transformations, and even then using a single factor seems like a rea
sonable |
600 // trade-off between quality and speed. | 645 // trade-off between quality and speed. |
601 fragBuilder->codeAppend("float afwidth;"); | 646 fragBuilder->codeAppend("float afwidth;"); |
602 if (isUniformScale) { | 647 if (isSimilarity) { |
603 // For uniform scale, we adjust for the effect of the transformation
on the distance | 648 // For similarity transform (uniform scale-only is a subset of this)
, we adjust for the |
604 // by using the length of the gradient of the texture coordinates. W
e use st coordinates | 649 // effect of the transformation on the distance by using the length
of the gradient of |
605 // to ensure we're mapping 1:1 from texel space to pixel space. | 650 // the texture coordinates. We use st coordinates to ensure we're ma
pping 1:1 from texel |
| 651 // space to pixel space. |
606 | 652 |
607 // this gives us a smooth step across approximately one fragment | 653 // this gives us a smooth step across approximately one fragment |
608 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*dy;"
); | 654 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*st_g
rad_len;"); |
609 } else { | 655 } else { |
610 // For general transforms, to determine the amount of correction we
multiply a unit | 656 // For general transforms, to determine the amount of correction we
multiply a unit |
611 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords | 657 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords |
612 // (which is the inverse transform for this fragment) and take the l
ength of the result. | 658 // (which is the inverse transform for this fragment) and take the l
ength of the result. |
613 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFd
y(distance.r));"); | 659 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFd
y(distance.r));"); |
614 // the length of the gradient may be 0, so we need to check for this | 660 // the length of the gradient may be 0, so we need to check for this |
615 // this also compensates for the Adreno, which likes to drop tiles o
n division by 0 | 661 // this also compensates for the Adreno, which likes to drop tiles o
n division by 0 |
616 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"
); | 662 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"
); |
617 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); | 663 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); |
618 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); | 664 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 SkShader::kMirror_TileMode, | 776 SkShader::kMirror_TileMode, |
731 }; | 777 }; |
732 SkShader::TileMode tileModes[] = { | 778 SkShader::TileMode tileModes[] = { |
733 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 779 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
734 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 780 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
735 }; | 781 }; |
736 GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::
kBilerp_FilterMode : | 782 GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::
kBilerp_FilterMode : |
737 GrTextureParams::kNone_FilterMode); | 783 GrTextureParams::kNone_FilterMode); |
738 DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; | 784 DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; |
739 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; | 785 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; |
740 flags |= d->fRandom->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; | 786 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; |
| 787 if (flags & kSimilarity_DistanceFieldEffectFlag) { |
| 788 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0
; |
| 789 } |
741 flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; | 790 flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; |
742 return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), | 791 return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), |
743 GrTest::TestMatrix(d->fRandom), | 792 GrTest::TestMatrix(d->fRandom), |
744 d->fTextures[texIdx], params, | 793 d->fTextures[texIdx], params, |
745 wa, | 794 wa, |
746 flags, | 795 flags, |
747 d->fRandom->nextBool()); | 796 d->fRandom->nextBool()); |
748 } | 797 } |
OLD | NEW |