diff options
author | jvanverth <jvanverth@google.com> | 2014-07-30 06:17:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-07-30 06:17:59 -0700 |
commit | 78f0718f4dac8bdcc0df43a3280cf8a89d8cf87a (patch) | |
tree | b4607853b6cf4699f8d13e8ee9d6fdf0805ea1d2 /src/gpu | |
parent | 7510b224e52b9518a8ddf7418db0e9c258f79539 (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-x | src/gpu/GrDistanceFieldTextContext.cpp | 101 | ||||
-rw-r--r-- | src/gpu/GrDistanceFieldTextContext.h | 6 | ||||
-rwxr-xr-x | src/gpu/effects/GrDistanceFieldTextureEffect.cpp | 45 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldTextureEffect.h | 44 |
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; |