aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2014-07-30 06:17:59 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-07-30 06:17:59 -0700
commit78f0718f4dac8bdcc0df43a3280cf8a89d8cf87a (patch)
treeb4607853b6cf4699f8d13e8ee9d6fdf0805ea1d2 /src/gpu
parent7510b224e52b9518a8ddf7418db0e9c258f79539 (diff)
Add effect caching to distance field text.
This also is a step towards unifying GrDistanceFieldTextureEffect and GrDistanceFieldLCDTextureEffect. Committed: https://skia.googlesource.com/skia/+/137bac067306c5446bc4f9797bedc3bbaf302822 R=robertphillips@google.com Author: jvanverth@google.com Review URL: https://codereview.chromium.org/424103002
Diffstat (limited to 'src/gpu')
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp101
-rw-r--r--src/gpu/GrDistanceFieldTextContext.h6
-rwxr-xr-xsrc/gpu/effects/GrDistanceFieldTextureEffect.cpp45
-rw-r--r--src/gpu/effects/GrDistanceFieldTextureEffect.h44
4 files changed, 131 insertions, 65 deletions
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 0ef596a27b..32d8f0c384 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -66,7 +66,10 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
fGammaTexture = NULL;
fCurrVertex = 0;
-
+ fEffectTextureUniqueID = SK_InvalidUniqueID;
+ fEffectColor = GrColor_ILLEGAL;
+ fEffectFlags = 0;
+
fVertices = NULL;
}
@@ -111,6 +114,58 @@ static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
return GrColorPackRGBA(r, g, b, 0xff);
}
+void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
+ GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
+ GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
+
+ GrTexture* currTexture = fStrike->getTexture();
+ SkASSERT(currTexture);
+ uint32_t textureUniqueID = currTexture->getUniqueID();
+
+ // set up any flags
+ uint32_t flags = 0;
+ flags |= fContext->getMatrix().isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+ flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
+ flags |= fUseLCDText && fContext->getMatrix().rectStaysRect() ?
+ kRectToRect_DistanceFieldEffectFlag : 0;
+ bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
+ fDeviceProperties.fGeometry.getLayout();
+ flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
+
+ // see if we need to create a new effect
+ if (textureUniqueID != fEffectTextureUniqueID ||
+ filteredColor != fEffectColor ||
+ flags != fEffectFlags) {
+ if (fUseLCDText) {
+ GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
+ fCachedEffect.reset(GrDistanceFieldLCDTextureEffect::Create(currTexture,
+ params,
+ fGammaTexture,
+ gammaParams,
+ colorNoPreMul,
+ flags));
+ } else {
+#ifdef SK_GAMMA_APPLY_TO_A8
+ U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.fGamma,
+ filteredColor);
+ fCachedEffect.reset(GrDistanceFieldTextureEffect::Create(currTexture,
+ params,
+ fGammaTexture,
+ gammaParams,
+ lum/255.f,
+ flags));
+#else
+ fCachedEffect.reset(GrDistanceFieldTextureEffect::Create(currTexture,
+ params, flags));
+#endif
+ }
+ fEffectTextureUniqueID = textureUniqueID;
+ fEffectColor = filteredColor;
+ fEffectFlags = flags;
+ }
+
+}
+
void GrDistanceFieldTextContext::flushGlyphs() {
if (NULL == fDrawTarget) {
return;
@@ -123,14 +178,8 @@ void GrDistanceFieldTextContext::flushGlyphs() {
if (fCurrVertex > 0) {
// setup our sampler state for our text texture/atlas
SkASSERT(SkIsAlign4(fCurrVertex));
- GrTexture* currTexture = fStrike->getTexture();
- SkASSERT(currTexture);
- GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
- GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
- // Effects could be stored with one of the cache objects (atlas?)
- int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
- kGlyphCoordsNoColorAttributeIndex;
+ // get our current color
SkColor filteredColor;
SkColorFilter* colorFilter = fSkPaint.getColorFilter();
if (NULL != colorFilter) {
@@ -138,21 +187,16 @@ void GrDistanceFieldTextContext::flushGlyphs() {
} else {
filteredColor = fSkPaint.getColor();
}
+ this->setupCoverageEffect(filteredColor);
+
+ // Effects could be stored with one of the cache objects (atlas?)
+ int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
+ kGlyphCoordsNoColorAttributeIndex;
+ drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
+
+ // Set draw state
if (fUseLCDText) {
GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
- bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
- fDeviceProperties.fGeometry.getLayout();
- drawState->addCoverageEffect(GrDistanceFieldLCDTextureEffect::Create(
- currTexture,
- params,
- fGammaTexture,
- gammaParams,
- colorNoPreMul,
- fContext->getMatrix().rectStaysRect() &&
- fContext->getMatrix().isSimilarity(),
- useBGR),
- coordsIdx)->unref();
-
if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
fPaint.numColorStages()) {
@@ -170,21 +214,6 @@ void GrDistanceFieldTextContext::flushGlyphs() {
drawState->setBlendConstant(colorNoPreMul);
drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
} else {
-#ifdef SK_GAMMA_APPLY_TO_A8
- U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.fGamma,
- filteredColor);
- drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
- currTexture, params,
- fGammaTexture, gammaParams,
- lum/255.f,
- fContext->getMatrix().isSimilarity()),
- coordsIdx)->unref();
-#else
- drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
- currTexture, params,
- fContext->getMatrix().isSimilarity()),
- coordsIdx)->unref();
-#endif
// set back to normal in case we took LCD path previously.
drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
//drawState->setColor(fPaint.getColor());
diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h
index 7676fc1648..672922d0d6 100644
--- a/src/gpu/GrDistanceFieldTextContext.h
+++ b/src/gpu/GrDistanceFieldTextContext.h
@@ -34,11 +34,17 @@ private:
SkScalar fTextRatio;
bool fUseLCDText;
bool fEnableDFRendering;
+ SkAutoTUnref<GrEffect> fCachedEffect;
+ // Used to check whether fCachedEffect is still valid.
+ uint32_t fEffectTextureUniqueID;
+ SkColor fEffectColor;
+ uint32_t fEffectFlags;
GrTexture* fGammaTexture;
void init(const GrPaint&, const SkPaint&);
void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
void flushGlyphs(); // automatically called by destructor
+ void setupCoverageEffect(const SkColor& filteredColor);
void finish();
enum {
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 510142e8fe..7ef1cbb2ba 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -79,7 +79,7 @@ public:
builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
builder->fsCodeAppend("\tfloat afwidth;\n");
- if (dfTexEffect.isSimilarity()) {
+ if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
// this gives us a smooth step across approximately one fragment
builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n");
} else {
@@ -153,7 +153,7 @@ public:
const GrDistanceFieldTextureEffect& dfTexEffect =
drawEffect.castEffect<GrDistanceFieldTextureEffect>();
- b->add32(dfTexEffect.isSimilarity());
+ b->add32(dfTexEffect.getFlags());
}
private:
@@ -174,13 +174,14 @@ GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
const GrTextureParams& gammaParams,
float luminance,
#endif
- bool similarity)
+ uint32_t flags)
: fTextureAccess(texture, params)
#ifdef SK_GAMMA_APPLY_TO_A8
, fGammaTextureAccess(gamma, gammaParams)
, fLuminance(luminance)
#endif
- , fIsSimilarity(similarity) {
+ , fFlags(flags & kNonLCD_DistanceFieldEffectMask) {
+ SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
this->addTextureAccess(&fTextureAccess);
#ifdef SK_GAMMA_APPLY_TO_A8
this->addTextureAccess(&fGammaTextureAccess);
@@ -190,7 +191,12 @@ GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
bool GrDistanceFieldTextureEffect::onIsEqual(const GrEffect& other) const {
const GrDistanceFieldTextureEffect& cte = CastEffect<GrDistanceFieldTextureEffect>(other);
- return fTextureAccess == cte.fTextureAccess;
+ return fTextureAccess == cte.fTextureAccess &&
+#ifdef SK_GAMMA_APPLY_TO_A8
+ fGammaTextureAccess == cte.fGammaTextureAccess &&
+ fLuminance == cte.fLuminance &&
+#endif
+ fFlags == cte.fFlags;
}
void GrDistanceFieldTextureEffect::getConstantColorComponents(GrColor* color,
@@ -242,7 +248,8 @@ GrEffect* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
textures[texIdx2], params2,
random->nextF(),
#endif
- random->nextBool());
+ random->nextBool() ?
+ kSimilarity_DistanceFieldEffectFlag : 0);
}
///////////////////////////////////////////////////////////////////////////////
@@ -286,7 +293,8 @@ public:
// create LCD offset adjusted by inverse of transform
builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
builder->fsCodeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
- if (dfTexEffect.isUniformScale()) {
+ bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
+ if (isUniformScale) {
builder->fsCodeAppend("\tfloat dx = dFdx(st.x);\n");
builder->fsCodeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
} else {
@@ -327,7 +335,7 @@ public:
// transformations, and even then using a single factor seems like a reasonable
// trade-off between quality and speed.
builder->fsCodeAppend("\tfloat afwidth;\n");
- if (dfTexEffect.isUniformScale()) {
+ if (isUniformScale) {
// this gives us a smooth step across approximately one fragment
builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n");
} else {
@@ -393,7 +401,7 @@ public:
texture->height() != fTextureSize.height()) {
fTextureSize = SkISize::Make(texture->width(), texture->height());
float delta = 1.0f/(3.0f*texture->width());
- if (dfTexEffect.useBGR()) {
+ if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
delta = -delta;
}
pdman.set3f(fTextureSizeUni,
@@ -418,7 +426,7 @@ public:
const GrDistanceFieldLCDTextureEffect& dfTexEffect =
drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
- b->add32(dfTexEffect.isUniformScale());
+ b->add32(dfTexEffect.getFlags());
}
private:
@@ -436,12 +444,13 @@ GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
GrTexture* texture, const GrTextureParams& params,
GrTexture* gamma, const GrTextureParams& gParams,
SkColor textColor,
- bool uniformScale, bool useBGR)
+ uint32_t flags)
: fTextureAccess(texture, params)
, fGammaTextureAccess(gamma, gParams)
, fTextColor(textColor)
- , fUniformScale(uniformScale)
- , fUseBGR(useBGR) {
+ , fFlags(flags & kLCD_DistanceFieldEffectMask) {
+ SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
+
this->addTextureAccess(&fTextureAccess);
this->addTextureAccess(&fGammaTextureAccess);
this->addVertexAttrib(kVec2f_GrSLType);
@@ -450,7 +459,10 @@ GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrEffect& other) const {
const GrDistanceFieldLCDTextureEffect& cte =
CastEffect<GrDistanceFieldLCDTextureEffect>(other);
- return (fTextureAccess == cte.fTextureAccess && fGammaTextureAccess == cte.fGammaTextureAccess);
+ return (fTextureAccess == cte.fTextureAccess &&
+ fGammaTextureAccess == cte.fGammaTextureAccess &&
+ fTextColor == cte.fTextColor &&
+ fFlags == cte.fFlags);
}
void GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color,
@@ -496,8 +508,11 @@ GrEffect* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random,
random->nextULessThan(256),
random->nextULessThan(256),
random->nextULessThan(256));
+ uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
+ flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
+ flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params,
textures[texIdx2], params2,
textColor,
- random->nextBool(), random->nextBool());
+ flags);
}
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h
index 38e41e5590..ab84753fff 100644
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.h
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h
@@ -14,6 +14,24 @@
class GrGLDistanceFieldTextureEffect;
class GrGLDistanceFieldLCDTextureEffect;
+enum GrDistanceFieldEffectFlags {
+ kSimilarity_DistanceFieldEffectFlag = 0x01, // ctm is similarity matrix
+ kRectToRect_DistanceFieldEffectFlag = 0x02, // ctm maps rects to rects
+ 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)
+
+ kUniformScale_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
+ kRectToRect_DistanceFieldEffectFlag,
+ // The subset of the flags relevant to GrDistanceFieldTextureEffect
+ kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag,
+ // The subset of the flags relevant to GrDistanceFieldLCDTextureEffect
+ kLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
+ kRectToRect_DistanceFieldEffectFlag |
+ kUseLCD_DistanceFieldEffectFlag |
+ kBGR_DistanceFieldEffectFlag,
+};
+
/**
* The output color of this effect is a modulation of the input color and a sample from a
* distance field texture (using a smoothed step function near 0.5).
@@ -25,14 +43,14 @@ public:
#ifdef SK_GAMMA_APPLY_TO_A8
static GrEffect* Create(GrTexture* tex, const GrTextureParams& params,
GrTexture* gamma, const GrTextureParams& gammaParams, float lum,
- bool similarity) {
+ uint32_t flags) {
return SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params, gamma, gammaParams, lum,
- similarity));
+ flags));
}
#else
static GrEffect* Create(GrTexture* tex, const GrTextureParams& params,
- bool similarity) {
- return SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params, similarity));
+ uint32_t flags) {
+ return SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params, flags));
}
#endif
@@ -44,7 +62,7 @@ public:
#ifdef SK_GAMMA_APPLY_TO_A8
float getLuminance() const { return fLuminance; }
#endif
- bool isSimilarity() const { return fIsSimilarity; }
+ uint32_t getFlags() const { return fFlags; }
typedef GrGLDistanceFieldTextureEffect GLEffect;
@@ -55,7 +73,7 @@ private:
#ifdef SK_GAMMA_APPLY_TO_A8
GrTexture* gamma, const GrTextureParams& gammaParams, float lum,
#endif
- bool uniformScale);
+ uint32_t flags);
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
@@ -64,7 +82,7 @@ private:
GrTextureAccess fGammaTextureAccess;
float fLuminance;
#endif
- bool fIsSimilarity;
+ uint32_t fFlags;
GR_DECLARE_EFFECT_TEST;
@@ -81,9 +99,9 @@ class GrDistanceFieldLCDTextureEffect : public GrVertexEffect {
public:
static GrEffect* Create(GrTexture* tex, const GrTextureParams& params,
GrTexture* gamma, const GrTextureParams& gammaParams,
- SkColor textColor, bool uniformScale, bool useBGR) {
+ SkColor textColor, uint32_t flags) {
return SkNEW_ARGS(GrDistanceFieldLCDTextureEffect,
- (tex, params, gamma, gammaParams, textColor, uniformScale, useBGR));
+ (tex, params, gamma, gammaParams, textColor, flags));
}
virtual ~GrDistanceFieldLCDTextureEffect() {}
@@ -92,8 +110,7 @@ public:
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
GrColor getTextColor() const { return fTextColor; }
- bool isUniformScale() const { return fUniformScale; }
- bool useBGR() const { return fUseBGR; }
+ uint32_t getFlags() const { return fFlags; }
typedef GrGLDistanceFieldLCDTextureEffect GLEffect;
@@ -103,15 +120,14 @@ private:
GrDistanceFieldLCDTextureEffect(GrTexture* texture, const GrTextureParams& params,
GrTexture* gamma, const GrTextureParams& gammaParams,
SkColor textColor,
- bool uniformScale, bool useBGR);
+ uint32_t flags);
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
GrTextureAccess fTextureAccess;
GrTextureAccess fGammaTextureAccess;
GrColor fTextColor;
- bool fUniformScale;
- bool fUseBGR;
+ uint32_t fFlags;
GR_DECLARE_EFFECT_TEST;