Index: src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
index 6196cce3298461b6d577abca697b6e257469f5a7..29f0985107884e230d9f21a146c9f93305db22b5 100755 |
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
@@ -15,6 +15,19 @@ |
#include "SkDistanceFieldGen.h" |
+// To get optical sizes people don't complain about when we blit correctly, |
+// we need to slightly bold each glyph. On the Mac, we need a larger bold value. |
+#if defined(SK_BUILD_FOR_MAC) |
+#define SK_DistanceFieldLCDFactor "0.33" |
+#define SK_DistanceFieldNonLCDFactor "0.25" |
+#else |
+#define SK_DistanceFieldLCDFactor "0.05" |
+#define SK_DistanceFieldNonLCDFactor "0.05" |
+#endif |
+ |
+// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2 |
+#define SK_DistanceFieldAAFactor "0.7071" |
+ |
class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect { |
public: |
GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory, |
@@ -56,7 +69,8 @@ public: |
kVec2f_GrSLType); |
builder->fsCodeAppend(";\n"); |
builder->fsCodeAppend("\tfloat distance = " |
- SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n"); |
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ")" |
+ "+ " SK_DistanceFieldNonLCDFactor ";\n"); |
// 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 |
@@ -66,8 +80,7 @@ public: |
builder->fsCodeAppend("\tfloat afwidth;\n"); |
if (dfTexEffect.isSimilarity()) { |
// 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"); |
+ builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n"); |
} else { |
builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); |
builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); |
@@ -88,12 +101,25 @@ public: |
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("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); |
} |
- |
builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n"); |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ // adjust based on gamma |
+ const char* luminanceUniName = NULL; |
+ // width, height, 1/(3*width) |
+ fLuminanceUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
+ kFloat_GrSLType, "Luminance", |
+ &luminanceUniName); |
+ |
+ builder->fsCodeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); |
+ builder->fsCodeAppend("\tvec4 gammaColor = "); |
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); |
+ builder->fsCodeAppend(";\n"); |
+ builder->fsCodeAppend("\tval = gammaColor.r;\n"); |
+#endif |
+ |
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, |
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")).c_str()); |
} |
@@ -110,6 +136,15 @@ public: |
SkIntToScalar(fTextureSize.width()), |
SkIntToScalar(fTextureSize.height())); |
} |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ const GrDistanceFieldTextureEffect& dfTexEffect = |
+ drawEffect.castEffect<GrDistanceFieldTextureEffect>(); |
+ float luminance = dfTexEffect.getLuminance(); |
+ if (luminance != fLuminance) { |
+ uman.set1f(fLuminanceUni, luminance); |
+ fLuminance = luminance; |
+ } |
+#endif |
} |
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { |
@@ -122,6 +157,8 @@ public: |
private: |
GrGLUniformManager::UniformHandle fTextureSizeUni; |
SkISize fTextureSize; |
+ GrGLUniformManager::UniformHandle fLuminanceUni; |
+ float fLuminance; |
typedef GrGLVertexEffect INHERITED; |
}; |
@@ -130,10 +167,22 @@ private: |
GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture, |
const GrTextureParams& params, |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ GrTexture* gamma, |
+ const GrTextureParams& gammaParams, |
+ float luminance, |
+#endif |
bool similarity) |
: fTextureAccess(texture, params) |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ , fGammaTextureAccess(gamma, gammaParams) |
+ , fLuminance(luminance) |
+#endif |
, fIsSimilarity(similarity) { |
this->addTextureAccess(&fTextureAccess); |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ this->addTextureAccess(&fGammaTextureAccess); |
+#endif |
this->addVertexAttrib(kVec2f_GrSLType); |
} |
@@ -166,6 +215,10 @@ GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random, |
GrTexture* textures[]) { |
int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : |
GrEffectUnitTest::kAlphaTextureIdx; |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : |
+ GrEffectUnitTest::kAlphaTextureIdx; |
+#endif |
static const SkShader::TileMode kTileModes[] = { |
SkShader::kClamp_TileMode, |
SkShader::kRepeat_TileMode, |
@@ -177,8 +230,16 @@ GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random, |
}; |
GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : |
GrTextureParams::kNone_FilterMode); |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : |
+ GrTextureParams::kNone_FilterMode); |
+#endif |
return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, |
+#ifdef SK_GAMMA_APPLY_TO_A8 |
+ textures[texIdx2], params2, |
+ random->nextF(), |
+#endif |
random->nextBool()); |
} |
@@ -211,7 +272,7 @@ public: |
fsCoordName = fsCoordNamePtr; |
const char* attrName0 = |
- builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); |
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); |
builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0); |
const char* textureSizeUniName = NULL; |
@@ -237,22 +298,24 @@ public: |
builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType); |
builder->fsCodeAppend(";\n"); |
builder->fsCodeAppend("\tvec3 distance;\n"); |
- builder->fsCodeAppend("\tdistance.y = " |
- SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n"); |
+ builder->fsCodeAppend("\tdistance.y = texColor.r;\n"); |
// red is distance to left offset |
builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n"); |
builder->fsCodeAppend("\ttexColor = "); |
builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType); |
builder->fsCodeAppend(";\n"); |
- builder->fsCodeAppend("\tdistance.x = " |
- SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n"); |
+ builder->fsCodeAppend("\tdistance.x = texColor.r;\n"); |
// blue is distance to right offset |
builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n"); |
builder->fsCodeAppend("\ttexColor = "); |
builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType); |
builder->fsCodeAppend(";\n"); |
- builder->fsCodeAppend("\tdistance.z = " |
- SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n"); |
+ builder->fsCodeAppend("\tdistance.z = texColor.r;\n"); |
+ |
+ builder->fsCodeAppend("\tdistance = " |
+ "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"))" |
+ "+ vec3(" SK_DistanceFieldLCDFactor ");\n"); |
+ |
// 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. |
@@ -264,8 +327,7 @@ public: |
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*dx;\n"); |
+ builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n"); |
} else { |
builder->fsCodeAppend("\tvec2 uv_grad;\n"); |
if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
@@ -283,12 +345,36 @@ public: |
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("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); |
} |
builder->fsCodeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n"); |
+ // adjust based on gamma |
+ const char* textColorUniName = NULL; |
+ // width, height, 1/(3*width) |
+ fTextColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
+ kVec3f_GrSLType, "TextColor", |
+ &textColorUniName); |
+ |
+ builder->fsCodeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); |
+ builder->fsCodeAppend("\tvec4 gammaColor = "); |
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); |
+ builder->fsCodeAppend(";\n"); |
+ builder->fsCodeAppend("\tval.x = gammaColor.r;\n"); |
+ |
+ builder->fsCodeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName); |
+ builder->fsCodeAppend("\tgammaColor = "); |
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); |
+ builder->fsCodeAppend(";\n"); |
+ builder->fsCodeAppend("\tval.y = gammaColor.r;\n"); |
+ |
+ builder->fsCodeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName); |
+ builder->fsCodeAppend("\tgammaColor = "); |
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); |
+ builder->fsCodeAppend(";\n"); |
+ builder->fsCodeAppend("\tval.z = gammaColor.r;\n"); |
+ |
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, |
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_str()); |
} |
@@ -296,12 +382,13 @@ public: |
virtual void setData(const GrGLUniformManager& uman, |
const GrDrawEffect& drawEffect) SK_OVERRIDE { |
SkASSERT(fTextureSizeUni.isValid()); |
+ SkASSERT(fTextColorUni.isValid()); |
+ const GrDistanceFieldLCDTextureEffect& dfTexEffect = |
+ drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>(); |
GrTexture* texture = drawEffect.effect()->get()->texture(0); |
if (texture->width() != fTextureSize.width() || |
texture->height() != fTextureSize.height()) { |
- const GrDistanceFieldLCDTextureEffect& dfTexEffect = |
- drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>(); |
fTextureSize = SkISize::Make(texture->width(), texture->height()); |
float delta = 1.0f/(3.0f*texture->width()); |
if (dfTexEffect.useBGR()) { |
@@ -312,40 +399,55 @@ public: |
SkIntToScalar(fTextureSize.height()), |
delta); |
} |
+ |
+ GrColor textColor = dfTexEffect.getTextColor(); |
+ if (textColor != fTextColor) { |
+ static const float ONE_OVER_255 = 1.f / 255.f; |
+ uman.set3f(fTextColorUni, |
+ GrColorUnpackR(textColor) * ONE_OVER_255, |
+ GrColorUnpackG(textColor) * ONE_OVER_255, |
+ GrColorUnpackB(textColor) * ONE_OVER_255); |
+ fTextColor = textColor; |
+ } |
} |
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { |
const GrDistanceFieldLCDTextureEffect& dfTexEffect = |
drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>(); |
- int uniformScale = dfTexEffect.isUniformScale() ? 0x01 : 0x00; |
- int useBGR = dfTexEffect.useBGR() ? 0x10 : 0x00; |
- return uniformScale | useBGR; |
+ return dfTexEffect.isUniformScale() ? 0x01 : 0x00;; |
} |
private: |
GrGLUniformManager::UniformHandle fTextureSizeUni; |
SkISize fTextureSize; |
+ GrGLUniformManager::UniformHandle fTextColorUni; |
+ SkColor fTextColor; |
typedef GrGLVertexEffect INHERITED; |
}; |
/////////////////////////////////////////////////////////////////////////////// |
-GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(GrTexture* texture, |
- const GrTextureParams& params, |
- bool uniformScale, |
- bool useBGR) |
+GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect( |
+ GrTexture* texture, const GrTextureParams& params, |
+ GrTexture* gamma, const GrTextureParams& gParams, |
+ SkColor textColor, |
+ bool uniformScale, bool useBGR) |
: fTextureAccess(texture, params) |
+ , fGammaTextureAccess(gamma, gParams) |
+ , fTextColor(textColor) |
, fUniformScale(uniformScale) |
, fUseBGR(useBGR) { |
this->addTextureAccess(&fTextureAccess); |
+ this->addTextureAccess(&fGammaTextureAccess); |
this->addVertexAttrib(kVec2f_GrSLType); |
} |
bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrEffect& other) const { |
- const GrDistanceFieldLCDTextureEffect& cte = CastEffect<GrDistanceFieldLCDTextureEffect>(other); |
- return fTextureAccess == cte.fTextureAccess; |
+ const GrDistanceFieldLCDTextureEffect& cte = |
+ CastEffect<GrDistanceFieldLCDTextureEffect>(other); |
+ return (fTextureAccess == cte.fTextureAccess && fGammaTextureAccess == cte.fGammaTextureAccess); |
} |
void GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color, |
@@ -371,7 +473,9 @@ GrEffectRef* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random, |
const GrDrawTargetCaps&, |
GrTexture* textures[]) { |
int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : |
- GrEffectUnitTest::kAlphaTextureIdx; |
+ GrEffectUnitTest::kAlphaTextureIdx; |
+ int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : |
+ GrEffectUnitTest::kAlphaTextureIdx; |
static const SkShader::TileMode kTileModes[] = { |
SkShader::kClamp_TileMode, |
SkShader::kRepeat_TileMode, |
@@ -383,7 +487,14 @@ GrEffectRef* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random, |
}; |
GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : |
GrTextureParams::kNone_FilterMode); |
- |
+ GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : |
+ GrTextureParams::kNone_FilterMode); |
+ GrColor textColor = GrColorPackRGBA(random->nextULessThan(256), |
+ random->nextULessThan(256), |
+ random->nextULessThan(256), |
+ random->nextULessThan(256)); |
return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params, |
+ textures[texIdx2], params2, |
+ textColor, |
random->nextBool(), random->nextBool()); |
} |