diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-03-26 19:49:03 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-03-26 19:49:03 +0000 |
commit | 4362a38563a958083aca2b456aaaa9f756f6f4e1 (patch) | |
tree | e3fddd2736de4bc5888d468a935e5f5cf42526d4 /src/gpu/effects | |
parent | f6394d91e53a0a7b13f5e2bbb097eea51392eef8 (diff) |
Distance field fixes for Android
- Expand glyph size by 2 on each side to compensate for bilerp lookup
- Correct for Adreno tendency to drop entire tile if any pixel has divide-by-0
- Fix blurriness on Adreno by using uv coords to compute gradient instead
of st coords
- Add faster version for uniform scale
BUG=skia:2173
Committed: http://code.google.com/p/skia/source/detail?r=13955
R=bsalomon@google.com
Author: jvanverth@google.com
Review URL: https://codereview.chromium.org/205343008
git-svn-id: http://skia.googlecode.com/svn/trunk@13958 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/effects')
-rwxr-xr-x | src/gpu/effects/GrDistanceFieldTextureEffect.cpp | 75 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldTextureEffect.h | 10 |
2 files changed, 57 insertions, 28 deletions
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index 9159a701e3..dd370b6d4e 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -23,7 +23,7 @@ public: GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect) : INHERITED (factory) - , fTextureSize(SkSize::Make(-1.f,-1.f)) {} + , fTextureSize(SkISize::Make(-1,-1)) {} virtual void emitCode(GrGLFullShaderBuilder* builder, const GrDrawEffect& drawEffect, @@ -35,6 +35,8 @@ public: SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numVertexAttribs()); SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); + const GrDistanceFieldTextureEffect& dfTexEffect = + drawEffect.castEffect<GrDistanceFieldTextureEffect>(); SkString fsCoordName; const char* vsCoordName; @@ -61,16 +63,37 @@ public: // 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. - builder->fsCodeAppendf("\tvec2 st = %s*%s;\n", fsCoordName.c_str(), textureSizeUniName); - builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); - builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); - builder->fsCodeAppend("\tvec2 st_grad = normalize(st);\n"); - builder->fsCodeAppend("\tvec2 grad = vec2(st_grad.x*Jdx.x + st_grad.y*Jdy.x,\n"); - builder->fsCodeAppend("\t st_grad.x*Jdx.y + st_grad.y*Jdy.y);\n"); - - // this gives us a smooth step across approximately one fragment - // (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2) - builder->fsCodeAppend("\tfloat afwidth = 0.7071*length(grad);\n"); + builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); + builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName); + builder->fsCodeAppend("\tfloat afwidth;\n"); + if (dfTexEffect.isUniformScale()) { + // this gives us a smooth step across approximately one fragment + // (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2) + builder->fsCodeAppend("\tafwidth = 0.7071*dFdx(st.x);\n"); + } else { + builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); + builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); + + builder->fsCodeAppend("\tvec2 uv_grad;\n"); + if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { + // this is to compensate for the Adreno, which likes to drop tiles on division by 0 + builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); + builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n"); + builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); + builder->fsCodeAppend("\t} else {\n"); + builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); + builder->fsCodeAppend("\t}\n"); + } else { + builder->fsCodeAppend("\tuv_grad = normalize(uv);\n"); + } + builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); + builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); + + // this gives us a smooth step across approximately one fragment + // (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2) + builder->fsCodeAppend("\tafwidth = 0.7071*length(grad);\n"); + } + builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n"); builder->fsCodeAppendf("\t%s = %s;\n", outputColor, @@ -80,20 +103,27 @@ public: virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE { SkASSERT(fTextureSizeUni.isValid()); - const GrDistanceFieldTextureEffect& distanceFieldEffect = - drawEffect.castEffect<GrDistanceFieldTextureEffect>(); - if (distanceFieldEffect.getSize().width() != fTextureSize.width() || - distanceFieldEffect.getSize().height() != fTextureSize.height()) { - fTextureSize = distanceFieldEffect.getSize(); + + GrTexture* texture = drawEffect.effect()->get()->texture(0); + if (texture->width() != fTextureSize.width() || + texture->height() != fTextureSize.height()) { + fTextureSize = SkISize::Make(texture->width(), texture->height()); uman.set2f(fTextureSizeUni, - distanceFieldEffect.getSize().width(), - distanceFieldEffect.getSize().height()); + SkIntToScalar(fTextureSize.width()), + SkIntToScalar(fTextureSize.height())); } } + static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { + const GrDistanceFieldTextureEffect& dfTexEffect = + drawEffect.castEffect<GrDistanceFieldTextureEffect>(); + + return dfTexEffect.isUniformScale() ? 0x1 : 0x0; + } + private: GrGLUniformManager::UniformHandle fTextureSizeUni; - SkSize fTextureSize; + SkISize fTextureSize; typedef GrGLVertexEffect INHERITED; }; @@ -102,9 +132,9 @@ private: GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params, - const SkISize& size) + bool uniformScale) : fTextureAccess(texture, params) - , fSize(SkSize::Make(SkIntToScalar(size.width()), SkIntToScalar(size.height()))) { + , fUniformScale(uniformScale) { this->addTextureAccess(&fTextureAccess); this->addVertexAttrib(kVec2f_GrSLType); } @@ -149,7 +179,6 @@ GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random, }; GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : GrTextureParams::kNone_FilterMode); - SkISize size = SkISize::Make(1024, 2048); - return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, size); + return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, random->nextBool()); } diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h index 1292c03221..212532e0a8 100644 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.h +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h @@ -21,8 +21,8 @@ class GrGLDistanceFieldTextureEffect; */ class GrDistanceFieldTextureEffect : public GrVertexEffect { public: - static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& p, const SkISize& s) { - AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, p, s))); + static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& para, bool uniformScale) { + AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, para, uniformScale))); return CreateEffectRef(effect); } @@ -31,7 +31,7 @@ public: static const char* Name() { return "DistanceFieldTexture"; } virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; - const SkSize& getSize() const { return fSize; } + bool isUniformScale() const { return fUniformScale; } typedef GrGLDistanceFieldTextureEffect GLEffect; @@ -39,12 +39,12 @@ public: private: GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params, - const SkISize& textureSize); + bool uniformScale); virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; GrTextureAccess fTextureAccess; - SkSize fSize; + bool fUniformScale; GR_DECLARE_EFFECT_TEST; |