Index: src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
index d44c193260dac3f674c62a52db885206b2486a13..b6cc463baccb15003f74e362666a9698ec1c5e51 100755 |
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp |
@@ -51,16 +51,6 @@ public: |
// emit attributes |
vsBuilder->emitAttributes(dfTexEffect); |
- GrGLVertToFrag st(kVec2f_GrSLType); |
- args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); |
- vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); |
- |
- GrGLVertToFrag uv(kVec2f_GrSLType); |
- args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
- // this is only used with text, so our texture bounds always match the glyph atlas |
- vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " |
- GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), |
- dfTexEffect.inTextureCoords()->fName); |
#ifdef SK_GAMMA_APPLY_TO_A8 |
// adjust based on gamma |
const char* distanceAdjustUniName = NULL; |
@@ -78,9 +68,35 @@ public: |
this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); |
// emit transforms |
+ const SkMatrix& localMatrix = dfTexEffect.localMatrix(); |
this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, |
- dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut); |
+ localMatrix, args.fTransformsIn, args.fTransformsOut); |
+ // add varyings |
+ GrGLVertToFrag recipScale(kFloat_GrSLType); |
+ GrGLVertToFrag st(kVec2f_GrSLType); |
+ bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); |
+ const char* viewMatrixName = this->uViewM(); |
+ // view matrix name is NULL if identity matrix |
+ bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName; |
+ if (isSimilarity && useInverseScale) { |
+ args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision); |
+ vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);", |
+ viewMatrixName, viewMatrixName); |
+ vsBuilder->codeAppend("float tx2 = dot(tx, tx);"); |
+ vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut()); |
+ } else { |
+ args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); |
+ vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); |
+ } |
+ |
+ GrGLVertToFrag uv(kVec2f_GrSLType); |
+ args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
+ // this is only used with text, so our texture bounds always match the glyph atlas |
+ vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " |
+ GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), |
+ dfTexEffect.inTextureCoords()->fName); |
+ |
// Use highp to work around aliasing issues |
fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, |
pb->ctxInfo().standard())); |
@@ -98,17 +114,21 @@ public: |
fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); |
#endif |
- fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, |
- pb->ctxInfo().standard())); |
- fsBuilder->codeAppendf("vec2 st = %s;", st.fsIn()); |
fsBuilder->codeAppend("float afwidth;"); |
- if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { |
+ if (isSimilarity) { |
// For uniform scale, we adjust for the effect of the transformation on the distance |
+ // either by using the inverse scale in the view matrix, or (if there is no view matrix) |
// 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. |
+ // with the latter to ensure we're mapping 1:1 from texel space to pixel space. |
// this gives us a smooth step across approximately one fragment |
- fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));"); |
+ if (useInverseScale) { |
+ fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*%s);", |
+ recipScale.fsIn()); |
+ } else { |
+ fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));", |
+ st.fsIn()); |
+ } |
} 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 |
@@ -123,8 +143,8 @@ public: |
fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); |
fsBuilder->codeAppend("}"); |
- fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); |
- fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); |
+ fsBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn()); |
+ fsBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn()); |
fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); |
fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); |
@@ -170,6 +190,7 @@ public: |
key |= local.fInputColorType << 16; |
key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0; |
key |= ComputePosKey(gp.viewMatrix()) << 25; |
+ key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0; |
b->add32(key); |
} |
@@ -188,13 +209,14 @@ private: |
GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrColor color, |
const SkMatrix& viewMatrix, |
+ const SkMatrix& localMatrix, |
GrTexture* texture, |
const GrTextureParams& params, |
#ifdef SK_GAMMA_APPLY_TO_A8 |
float distanceAdjust, |
#endif |
uint32_t flags, bool opaqueVertexColors) |
- : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors) |
+ : INHERITED(color, viewMatrix, localMatrix, opaqueVertexColors) |
, fTextureAccess(texture, params) |
#ifdef SK_GAMMA_APPLY_TO_A8 |
, fDistanceAdjust(distanceAdjust) |
@@ -281,6 +303,7 @@ GrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random, |
return GrDistanceFieldTextureEffect::Create(GrRandomColor(random), |
GrProcessorUnitTest::TestMatrix(random), |
+ GrProcessorUnitTest::TestMatrix(random), |
textures[texIdx], params, |
#ifdef SK_GAMMA_APPLY_TO_A8 |
random->nextF(), |
@@ -564,17 +587,6 @@ public: |
// emit attributes |
vsBuilder->emitAttributes(dfTexEffect); |
- GrGLVertToFrag st(kVec2f_GrSLType); |
- args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); |
- vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); |
- |
- GrGLVertToFrag uv(kVec2f_GrSLType); |
- args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
- // this is only used with text, so our texture bounds always match the glyph atlas |
- vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " |
- GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), |
- dfTexEffect.inTextureCoords()->fName); |
- |
// setup pass through color |
this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, |
&fColorUniform); |
@@ -583,9 +595,36 @@ public: |
this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); |
// emit transforms |
+ const SkMatrix& localMatrix = dfTexEffect.localMatrix(); |
this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, |
- dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut); |
+ localMatrix, args.fTransformsIn, args.fTransformsOut); |
+ // set up varyings |
+ bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); |
+ GrGLVertToFrag recipScale(kFloat_GrSLType); |
+ GrGLVertToFrag st(kVec2f_GrSLType); |
+ const char* viewMatrixName = this->uViewM(); |
+ // view matrix name is NULL if identity matrix |
+ bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName; |
+ if (isUniformScale && useInverseScale) { |
+ args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision); |
+ vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);", |
+ viewMatrixName, viewMatrixName); |
+ vsBuilder->codeAppend("float tx2 = dot(tx, tx);"); |
+ vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut()); |
+ } else { |
+ args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); |
+ vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); |
+ } |
+ |
+ GrGLVertToFrag uv(kVec2f_GrSLType); |
+ args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
+ // this is only used with text, so our texture bounds always match the glyph atlas |
+ vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " |
+ GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), |
+ dfTexEffect.inTextureCoords()->fName); |
+ |
+ // add frag shader code |
GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
SkAssertResult(fsBuilder->enableFeature( |
@@ -598,21 +637,24 @@ public: |
fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); |
fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, |
pb->ctxInfo().standard())); |
- fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); |
- bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); |
- |
if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { |
fsBuilder->codeAppend("float delta = -" GR_FONT_ATLAS_LCD_DELTA ";\n"); |
} else { |
fsBuilder->codeAppend("float delta = " GR_FONT_ATLAS_LCD_DELTA ";\n"); |
} |
if (isUniformScale) { |
- fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n"); |
- fsBuilder->codeAppend("\tvec2 offset = vec2(dx*delta, 0.0);\n"); |
+ if (useInverseScale) { |
+ fsBuilder->codeAppendf("float dx = %s;", recipScale.fsIn()); |
+ } else { |
+ fsBuilder->codeAppendf("float dx = dFdx(%s.x);", st.fsIn()); |
+ } |
+ fsBuilder->codeAppend("vec2 offset = vec2(dx*delta, 0.0);"); |
} else { |
- fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); |
- fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); |
- fsBuilder->codeAppend("\tvec2 offset = delta*Jdx;\n"); |
+ fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); |
+ |
+ fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); |
+ fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); |
+ fsBuilder->codeAppend("vec2 offset = delta*Jdx;"); |
} |
// green is distance to uv center |
@@ -721,6 +763,7 @@ public: |
key |= local.fInputColorType << 16; |
key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0; |
key |= ComputePosKey(gp.viewMatrix()) << 25; |
+ key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0; |
b->add32(key); |
} |
@@ -737,10 +780,11 @@ private: |
GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect( |
GrColor color, const SkMatrix& viewMatrix, |
+ const SkMatrix& localMatrix, |
GrTexture* texture, const GrTextureParams& params, |
DistanceAdjust distanceAdjust, |
uint32_t flags) |
- : INHERITED(color, viewMatrix, SkMatrix::I()) |
+ : INHERITED(color, viewMatrix, localMatrix) |
, fTextureAccess(texture, params) |
, fDistanceAdjust(distanceAdjust) |
, fFlags(flags & kLCD_DistanceFieldEffectMask){ |
@@ -821,6 +865,7 @@ GrGeometryProcessor* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* rando |
flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; |
return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), |
GrProcessorUnitTest::TestMatrix(random), |
+ GrProcessorUnitTest::TestMatrix(random), |
textures[texIdx], params, |
wa, |
flags); |