aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/batches/GrAADistanceFieldPathRenderer.cpp4
-rw-r--r--src/gpu/batches/GrAtlasTextBatch.cpp2
-rw-r--r--src/gpu/effects/GrDistanceFieldGeoProc.cpp95
-rw-r--r--src/gpu/effects/GrDistanceFieldGeoProc.h9
4 files changed, 81 insertions, 29 deletions
diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
index 8525eb2fde..b585de963a 100644
--- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
+++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
@@ -190,8 +190,10 @@ private:
return;
}
+ const SkMatrix& ctm = this->viewMatrix();
uint32_t flags = 0;
- flags |= this->viewMatrix().isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+ flags |= ctm.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0;
+ flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp
index 432322ff7a..1d8d7fe143 100644
--- a/src/gpu/batches/GrAtlasTextBatch.cpp
+++ b/src/gpu/batches/GrAtlasTextBatch.cpp
@@ -261,11 +261,11 @@ GrGeometryProcessor* GrAtlasTextBatch::setupDfProcessor(const SkMatrix& viewMatr
bool isLCD = this->isLCD();
// set up any flags
uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+ flags |= viewMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0;
// see if we need to create a new effect
if (isLCD) {
flags |= kUseLCD_DistanceFieldEffectFlag;
- flags |= viewMatrix.rectStaysRect() ? kRectToRect_DistanceFieldEffectFlag : 0;
flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0;
GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index b77a1f5a5d..2182a11758 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),
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h
index 46d39f0123..765a531c94 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.h
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.h
@@ -18,7 +18,7 @@ class GrInvariantOutput;
enum GrDistanceFieldEffectFlags {
kSimilarity_DistanceFieldEffectFlag = 0x01, // ctm is similarity matrix
- kRectToRect_DistanceFieldEffectFlag = 0x02, // ctm maps rects to rects
+ kScaleOnly_DistanceFieldEffectFlag = 0x02, // ctm has only scale and translate
kUseLCD_DistanceFieldEffectFlag = 0x04, // use lcd text
kBGR_DistanceFieldEffectFlag = 0x08, // lcd display has bgr order
kPortrait_DistanceFieldEffectFlag = 0x10, // lcd display is in portrait mode (not used yet)
@@ -26,12 +26,13 @@ enum GrDistanceFieldEffectFlags {
kInvalid_DistanceFieldEffectFlag = 0x80, // invalid state (for initialization)
kUniformScale_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
- kRectToRect_DistanceFieldEffectFlag,
+ kScaleOnly_DistanceFieldEffectFlag,
// The subset of the flags relevant to GrDistanceFieldA8TextGeoProc
- kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag,
+ kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
+ kScaleOnly_DistanceFieldEffectFlag,
// The subset of the flags relevant to GrDistanceFieldLCDTextGeoProc
kLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
- kRectToRect_DistanceFieldEffectFlag |
+ kScaleOnly_DistanceFieldEffectFlag |
kUseLCD_DistanceFieldEffectFlag |
kBGR_DistanceFieldEffectFlag,
};