Index: src/gpu/effects/GrDistanceFieldGeoProc.cpp |
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp |
index b77a1f5a5d21fce5660895dee26070a8c8b12254..2182a1175828be3ae2e35a8a172c88afb21b4e46 100644 |
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp |
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp |
@@ -79,11 +79,13 @@ public: |
// add varyings |
GrGLSLVertToFrag recipScale(kFloat_GrSLType); |
GrGLSLVertToFrag uv(kVec2f_GrSLType); |
+ bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) == |
+ kUniformScale_DistanceFieldEffectMask; |
bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); |
varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName); |
- // compute numbers to be hardcoded to convert texture coordinates from int to float |
+ // compute numbers to be hardcoded to convert texture coordinates from float to int |
SkASSERT(dfTexEffect.numTextures() == 1); |
GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); |
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height())); |
@@ -112,15 +114,24 @@ public: |
#endif |
fragBuilder->codeAppend("float afwidth;"); |
- if (isSimilarity) { |
+ if (isUniformScale) { |
// For uniform scale, we adjust for the effect of the transformation on the distance |
- // by using the length of the gradient of the texture coordinates. We use st coordinates |
- // to ensure we're mapping 1:1 from texel space to pixel space. |
+ // by using the length of the gradient of the t coordinate in the y direction. |
+ // We use st coordinates to ensure we're mapping 1:1 from texel space to pixel space. |
+ // We use the y gradient because there is a bug in the Mali 400 in the x direction. |
// this gives us a smooth step across approximately one fragment |
- // we use y to work around a Mali400 bug in the x direction |
fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));", |
st.fsIn()); |
+ } else if (isSimilarity) { |
+ // For similarity transform, we adjust the effect of the transformation on the distance |
+ // by using the length of the gradient of the texture coordinates. We use st coordinates |
+ // to ensure we're mapping 1:1 from texel space to pixel space. |
+ // We use the y gradient because there is a bug in the Mali 400 in the x direction. |
+ |
+ // this gives us a smooth step across approximately one fragment |
+ fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn()); |
+ fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);"); |
} else { |
// For general transforms, to determine the amount of correction we multiply a unit |
// vector pointing along the SDF gradient direction by the Jacobian of the st coords |
@@ -254,15 +265,20 @@ const GrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorT |
GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode : |
GrTextureParams::kNone_FilterMode); |
+ uint32_t flags = 0; |
+ flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; |
+ if (flags & kSimilarity_DistanceFieldEffectFlag) { |
+ flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0; |
+ } |
+ |
return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(d->fRandom), |
GrTest::TestMatrix(d->fRandom), |
d->fTextures[texIdx], params, |
#ifdef SK_GAMMA_APPLY_TO_A8 |
d->fRandom->nextF(), |
#endif |
- d->fRandom->nextBool() ? |
- kSimilarity_DistanceFieldEffectFlag : 0, |
- d->fRandom->nextBool()); |
+ flags, |
+ d->fRandom->nextBool()); |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -335,13 +351,27 @@ public: |
kHigh_GrSLPrecision)); |
fragBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); |
fragBuilder->codeAppend("float afwidth;"); |
- if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { |
+ bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) == |
+ kUniformScale_DistanceFieldEffectMask; |
+ bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); |
+ if (isUniformScale) { |
// For uniform scale, we adjust for the effect of the transformation on the distance |
+ // by using the length of the gradient of the t coordinate in the y direction. |
+ // We use st coordinates to ensure we're mapping 1:1 from texel space to pixel space. |
+ // We use the y gradient because there is a bug in the Mali 400 in the x direction. |
+ |
+ // this gives us a smooth step across approximately one fragment |
+ fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));"); |
+ |
+ } else if (isSimilarity) { |
+ // For similarity transform, we adjust the effect of the transformation on the distance |
// by using the length of the gradient of the texture coordinates. We use st coordinates |
// to ensure we're mapping 1:1 from texel space to pixel space. |
+ // We use the y gradient because there is a bug in the Mali 400 in the x direction. |
// this gives us a smooth step across approximately one fragment |
- fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));"); |
+ fragBuilder->codeAppend("float st_grad_len = length(dFdy(st));"); |
+ fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);"); |
} else { |
// For general transforms, to determine the amount of correction we multiply a unit |
// vector pointing along the SDF gradient direction by the Jacobian of the st coords |
@@ -464,13 +494,18 @@ const GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTes |
GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode |
: GrTextureParams::kNone_FilterMode); |
+ uint32_t flags = 0; |
+ flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; |
+ if (flags & kSimilarity_DistanceFieldEffectFlag) { |
+ flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0; |
+ } |
+ |
return GrDistanceFieldPathGeoProc::Create(GrRandomColor(d->fRandom), |
GrTest::TestMatrix(d->fRandom), |
d->fTextures[texIdx], |
params, |
- d->fRandom->nextBool() ? |
- kSimilarity_DistanceFieldEffectFlag : 0, |
- d->fRandom->nextBool()); |
+ flags, |
+ d->fRandom->nextBool()); |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -518,13 +553,15 @@ public: |
args.fTransformsOut); |
// set up varyings |
- bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); |
+ bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) == |
+ kUniformScale_DistanceFieldEffectMask; |
+ bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); |
GrGLSLVertToFrag recipScale(kFloat_GrSLType); |
GrGLSLVertToFrag uv(kVec2f_GrSLType); |
varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName); |
- // compute numbers to be hardcoded to convert texture coordinates from int to float |
+ // compute numbers to be hardcoded to convert texture coordinates from float to int |
SkASSERT(dfTexEffect.numTextures() == 1); |
GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); |
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height())); |
@@ -555,8 +592,16 @@ public: |
fragBuilder->codeAppendf("float delta = %.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta); |
} |
if (isUniformScale) { |
- fragBuilder->codeAppendf("float dy = abs(dFdy(%s.y));", st.fsIn()); |
- fragBuilder->codeAppend("vec2 offset = vec2(dy*delta, 0.0);"); |
+ fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.fsIn()); |
+ fragBuilder->codeAppend("vec2 offset = vec2(st_grad_len*delta, 0.0);"); |
+ } else if (isSimilarity) { |
+ // For a similarity matrix with rotation, the gradient will not be aligned |
+ // with the texel coordinate axes, so we need to calculate it. |
+ // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to |
+ // get the gradient in the x direction. |
+ fragBuilder->codeAppendf("vec2 st_grad = dFdy(%s);", st.fsIn()); |
+ fragBuilder->codeAppend("float st_grad_len = length(st_grad);"); |
+ fragBuilder->codeAppend("vec2 offset = delta*vec2(st_grad.y, -st_grad.x);"); |
} else { |
fragBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); |
@@ -599,13 +644,14 @@ public: |
// transformations, and even then using a single factor seems like a reasonable |
// trade-off between quality and speed. |
fragBuilder->codeAppend("float afwidth;"); |
- if (isUniformScale) { |
- // For uniform scale, we adjust for the effect of the transformation on the distance |
- // by using the length of the gradient of the texture coordinates. We use st coordinates |
- // to ensure we're mapping 1:1 from texel space to pixel space. |
+ if (isSimilarity) { |
+ // For similarity transform (uniform scale-only is a subset of this), we adjust for the |
+ // effect of the transformation on the distance by using the length of the gradient of |
+ // the texture coordinates. We use st coordinates to ensure we're mapping 1:1 from texel |
+ // space to pixel space. |
// this gives us a smooth step across approximately one fragment |
- fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*dy;"); |
+ fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*st_grad_len;"); |
} else { |
// For general transforms, to determine the amount of correction we multiply a unit |
// vector pointing along the SDF gradient direction by the Jacobian of the st coords |
@@ -737,7 +783,10 @@ const GrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessor |
GrTextureParams::kNone_FilterMode); |
DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; |
uint32_t flags = kUseLCD_DistanceFieldEffectFlag; |
- flags |= d->fRandom->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; |
+ flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; |
+ if (flags & kSimilarity_DistanceFieldEffectFlag) { |
+ flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0; |
+ } |
flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; |
return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), |
GrTest::TestMatrix(d->fRandom), |