diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/batches/GrAADistanceFieldPathRenderer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/batches/GrAtlasTextBatch.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldGeoProc.cpp | 95 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldGeoProc.h | 9 |
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, }; |