From 919ed4c73633e92bfc6694161360c5c3f45728e8 Mon Sep 17 00:00:00 2001 From: scroggo Date: Mon, 9 Jun 2014 13:06:34 -0700 Subject: [PATCH] Revert of Gamma correction for distance field text. (https://codereview.chromium.org/258883002/) Reason for revert: Memory leaks. I suspect this is due to the lack of destructors in SkAutoGlyphCache Original issue's description: > Gamma correction for distance field text. > > Handles both non-LCD and LCD text. Uses a texture to look up the gamma correction values for a given text color or luminance. > > BUG=skia: > > Committed: https://skia.googlesource.com/skia/+/4d517fdbb145cb95e5e935470df331e1b6667cfc NOTRY=true NOTREECHECKS=true R=reed@google.com, bungeman@google.com, robertphillips@google.com, bsalomon@google.com, jvanverth@google.com, mtklein@google.com Author: scroggo@google.com Review URL: https://codereview.chromium.org/323513005 --- include/core/SkPaint.h | 4 +- src/core/SkGlyphCache.h | 69 ++----- src/core/SkMaskGamma.h | 16 -- src/core/SkPaint.cpp | 42 +---- src/core/SkScalerContext.h | 11 -- src/gpu/GrDistanceFieldTextContext.cpp | 91 +--------- src/gpu/GrDistanceFieldTextContext.h | 1 - .../effects/GrDistanceFieldTextureEffect.cpp | 171 +++--------------- .../effects/GrDistanceFieldTextureEffect.h | 40 +--- 9 files changed, 71 insertions(+), 374 deletions(-) diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index f766ca1c7f..95fc0b87ad 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -1081,8 +1081,7 @@ private: SkScalar measure_text(SkGlyphCache*, const char* text, size_t length, int* count, SkRect* bounds) const; - SkGlyphCache* detachCache(const SkDeviceProperties* deviceProperties, const SkMatrix*, - bool ignoreGamma) const; + SkGlyphCache* detachCache(const SkDeviceProperties* deviceProperties, const SkMatrix*) const; void descriptorProc(const SkDeviceProperties* deviceProperties, const SkMatrix* deviceMatrix, void (*proc)(SkTypeface*, const SkDescriptor*, void*), @@ -1132,7 +1131,6 @@ private: } friend class SkAutoGlyphCache; - friend class SkAutoGlyphCacheNoGamma; friend class SkCanvas; friend class SkDraw; friend class SkGraphics; // So Term() can be called. diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index d18b61a0a9..8b404dcc09 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -244,8 +244,23 @@ private: friend class SkGlyphCache_Globals; }; -class SkAutoGlyphCacheBase { +class SkAutoGlyphCache { public: + SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {} + SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) { + fCache = SkGlyphCache::DetachCache(typeface, desc); + } + SkAutoGlyphCache(const SkPaint& paint, + const SkDeviceProperties* deviceProperties, + const SkMatrix* matrix) { + fCache = paint.detachCache(deviceProperties, matrix); + } + ~SkAutoGlyphCache() { + if (fCache) { + SkGlyphCache::AttachCache(fCache); + } + } + SkGlyphCache* getCache() const { return fCache; } void release() { @@ -255,61 +270,11 @@ public: } } -protected: - // Hide the constructors so we can't create one of these directly. - // Create SkAutoGlyphCache or SkAutoGlyphCacheNoCache instead. - SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {} - SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) { - fCache = SkGlyphCache::DetachCache(typeface, desc); - } - SkAutoGlyphCacheBase(const SkPaint& paint, - const SkDeviceProperties* deviceProperties, - const SkMatrix* matrix) { - fCache = NULL; - } - SkAutoGlyphCacheBase() {} - +private: SkGlyphCache* fCache; -private: static bool DetachProc(const SkGlyphCache*, void*); }; - -class SkAutoGlyphCache : public SkAutoGlyphCacheBase { -public: - SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {} - SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) : - SkAutoGlyphCacheBase(typeface, desc) {} - SkAutoGlyphCache(const SkPaint& paint, - const SkDeviceProperties* deviceProperties, - const SkMatrix* matrix) { - fCache = paint.detachCache(deviceProperties, matrix, false); - } - SkAutoGlyphCache() : SkAutoGlyphCacheBase() { - if (fCache) { - SkGlyphCache::AttachCache(fCache); - } - } -}; #define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache) -class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase { -public: - SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {} - SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) : - SkAutoGlyphCacheBase(typeface, desc) {} - SkAutoGlyphCacheNoGamma(const SkPaint& paint, - const SkDeviceProperties* deviceProperties, - const SkMatrix* matrix) { - fCache = paint.detachCache(deviceProperties, matrix, true); - } - SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() { - if (fCache) { - SkGlyphCache::AttachCache(fCache); - } - } -}; -#define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma) - - #endif diff --git a/src/core/SkMaskGamma.h b/src/core/SkMaskGamma.h index 08ed97f913..1f2b73caac 100644 --- a/src/core/SkMaskGamma.h +++ b/src/core/SkMaskGamma.h @@ -136,22 +136,6 @@ public: */ PreBlend preBlend(SkColor color) const; - /** - * Get dimensions for the full table set, so it can be allocated as a block. - */ - void getGammaTableDimensions(int* tableWidth, int* numTables) const { - *tableWidth = 256; - *numTables = (1 << MAX_LUM_BITS); - } - - /** - * Provides direct access to the full table set, so it can be uploaded - * into a texture. - */ - const uint8_t* getGammaTables() const { - return (const uint8_t*) fGammaTables; - } - private: static const int MAX_LUM_BITS = B_LUM_BITS > (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS) diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index b08b2c6da7..78d947020b 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -1814,8 +1814,10 @@ void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) { /* * ignoreGamma tells us that the caller just wants metrics that are unaffected - * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1, - * contrast = 0, luminanceColor = transparent black. + * by gamma correction, so we jam the luminance field to 0 (most common value + * for black text) in hopes that we get a cache hit easier. A better solution + * would be for the fontcache lookup to know to ignore the luminance field + * entirely, but not sure how to do that and keep it fast. */ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, const SkMatrix* deviceMatrix, @@ -1825,7 +1827,7 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec); if (ignoreGamma) { - rec.ignorePreBlend(); + rec.setLuminanceColor(0); } size_t descSize = sizeof(rec); @@ -1949,10 +1951,9 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, } SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties, - const SkMatrix* deviceMatrix, - bool ignoreGamma) const { + const SkMatrix* deviceMatrix) const { SkGlyphCache* cache; - this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma); + this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, false); return cache; } @@ -1968,33 +1969,6 @@ SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Re return maskGamma.preBlend(rec.getLuminanceColor()); } -size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, - SkScalar deviceGamma, int* width, int* height) { - SkAutoMutexAcquire ama(gMaskGammaCacheMutex); - const SkMaskGamma& maskGamma = cachedMaskGamma(contrast, - paintGamma, - deviceGamma); - - maskGamma.getGammaTableDimensions(width, height); - size_t size = (*width)*(*height)*sizeof(uint8_t); - - return size; -} - -void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma, - void* data) { - SkAutoMutexAcquire ama(gMaskGammaCacheMutex); - const SkMaskGamma& maskGamma = cachedMaskGamma(contrast, - paintGamma, - deviceGamma); - int width, height; - maskGamma.getGammaTableDimensions(&width, &height); - size_t size = width*height*sizeof(uint8_t); - const uint8_t* gammaTables = maskGamma.getGammaTables(); - memcpy(data, gammaTables, size); -} - - /////////////////////////////////////////////////////////////////////////////// #include "SkStream.h" @@ -2583,7 +2557,7 @@ SkTextToPathIter::SkTextToPathIter( const char text[], size_t length, fPaint.setPathEffect(NULL); } - fCache = fPaint.detachCache(NULL, NULL, false); + fCache = fPaint.detachCache(NULL, NULL); SkPaint::Style style = SkPaint::kFill_Style; SkPathEffect* pe = NULL; diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h index af83685eb6..f18d217f62 100644 --- a/src/core/SkScalerContext.h +++ b/src/core/SkScalerContext.h @@ -184,17 +184,6 @@ public: void getPath(const SkGlyph&, SkPath*); void getFontMetrics(SkPaint::FontMetrics*); - /** Return the size in bytes of the associated gamma lookup table - */ - static size_t GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma, - int* width, int* height); - - /** Get the associated gamma lookup table. The 'data' pointer must point to pre-allocated - memory, with size in bytes greater than or equal to the return value of getGammaLUTSize(). - */ - static void GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma, - void* data); - #ifdef SK_BUILD_FOR_ANDROID unsigned getBaseGlyphCount(SkUnichar charCode); diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index a7299393bd..2d2f9a1443 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -7,12 +7,10 @@ #include "GrDistanceFieldTextContext.h" #include "GrAtlas.h" -#include "SkColorFilter.h" #include "GrDrawTarget.h" #include "GrDrawTargetCaps.h" #include "GrFontScaler.h" #include "SkGlyphCache.h" -#include "GrGpu.h" #include "GrIndexBuffer.h" #include "GrTextStrike.h" #include "GrTextStrike_impl.h" @@ -45,7 +43,6 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, fEnableDFRendering = enable; #endif fStrike = NULL; - fGammaTexture = NULL; fCurrTexture = NULL; fCurrVertex = 0; @@ -56,7 +53,6 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { this->flushGlyphs(); - SkSafeSetNull(fGammaTexture); } bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) { @@ -111,26 +107,14 @@ void GrDistanceFieldTextContext::flushGlyphs() { SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); 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?) - SkColor filteredColor; - SkColorFilter* colorFilter = fSkPaint.getColorFilter(); - if (NULL != colorFilter) { - filteredColor = colorFilter->filterColor(fSkPaint.getColor()); - } else { - filteredColor = fSkPaint.getColor(); - } if (fUseLCDText) { - GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout == fDeviceProperties.fGeometry.getLayout(); drawState->addCoverageEffect(GrDistanceFieldLCDTextureEffect::Create( fCurrTexture, params, - fGammaTexture, - gammaParams, - colorNoPreMul, fContext->getMatrix().rectStaysRect() && fContext->getMatrix().isSimilarity(), useBGR), @@ -149,24 +133,13 @@ void GrDistanceFieldTextContext::flushGlyphs() { // paintAlpha drawState->setColor(SkColorSetARGB(a, a, a, a)); // paintColor - drawState->setBlendConstant(colorNoPreMul); + drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); } else { -#ifdef SK_GAMMA_APPLY_TO_A8 - U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.fGamma, - filteredColor); - drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create( - fCurrTexture, params, - fGammaTexture, gammaParams, - lum/255.f, + drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(fCurrTexture, params, fContext->getMatrix().isSimilarity()), kGlyphCoordsAttributeIndex)->unref(); -#else - drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create( - fCurrTexture, params, - fContext->getMatrix().isSimilarity()), - kGlyphCoordsAttributeIndex)->unref(); -#endif + // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(fPaint.getColor()); @@ -383,9 +356,7 @@ inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint fSkPaint.setLCDRenderText(false); fSkPaint.setAutohinted(false); - fSkPaint.setHinting(SkPaint::kNormal_Hinting); fSkPaint.setSubpixelText(true); - } inline void GrDistanceFieldTextContext::finish() { @@ -394,46 +365,6 @@ inline void GrDistanceFieldTextContext::finish() { GrTextContext::finish(); } -static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache, - const SkDeviceProperties& deviceProperties, - GrTexture** gammaTexture) { - if (NULL == *gammaTexture) { - int width, height; - size_t size; - -#ifdef SK_GAMMA_CONTRAST - SkScalar contrast = SK_GAMMA_CONTRAST; -#else - SkScalar contrast = 0.5f; -#endif - SkScalar paintGamma = deviceProperties.fGamma; - SkScalar deviceGamma = deviceProperties.fGamma; - - size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma, - &width, &height); - - SkAutoTArray data((int)size); - SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get()); - - // TODO: Update this to use the cache rather than directly creating a texture. - GrTextureDesc desc; - desc.fFlags = kDynamicUpdate_GrTextureFlagBit; - desc.fWidth = width; - desc.fHeight = height; - desc.fConfig = kAlpha_8_GrPixelConfig; - - *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0); - if (NULL == *gammaTexture) { - return; - } - - context->writeTexturePixels(*gammaTexture, - 0, 0, width, height, - (*gammaTexture)->config(), data.get(), 0, - GrContext::kDontFlush_PixelOpsFlag); - } -} - void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, const char text[], size_t byteLength, SkScalar x, SkScalar y) { @@ -451,11 +382,9 @@ void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& s SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); - SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); - SkGlyphCache* cache = autoCache.getCache(); - GrFontScaler* fontScaler = GetGrFontScaler(cache); - - setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); + SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL); + SkGlyphCache* cache = autoCache.getCache(); + GrFontScaler* fontScaler = GetGrFontScaler(cache); // need to measure first // TODO - generate positions and pre-load cache as well? @@ -526,11 +455,9 @@ void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); - SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); - SkGlyphCache* cache = autoCache.getCache(); - GrFontScaler* fontScaler = GetGrFontScaler(cache); - - setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); + SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL); + SkGlyphCache* cache = autoCache.getCache(); + GrFontScaler* fontScaler = GetGrFontScaler(cache); const char* stop = text + byteLength; diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h index 3a602f050b..3dfffd1c13 100644 --- a/src/gpu/GrDistanceFieldTextContext.h +++ b/src/gpu/GrDistanceFieldTextContext.h @@ -34,7 +34,6 @@ private: SkScalar fTextRatio; bool fUseLCDText; bool fEnableDFRendering; - GrTexture* fGammaTexture; void init(const GrPaint&, const SkPaint&); void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index 29f0985107..6196cce329 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -15,19 +15,6 @@ #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, @@ -69,8 +56,7 @@ public: kVec2f_GrSLType); builder->fsCodeAppend(";\n"); builder->fsCodeAppend("\tfloat distance = " - SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ")" - "+ " SK_DistanceFieldNonLCDFactor ";\n"); + SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\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 @@ -80,7 +66,8 @@ public: builder->fsCodeAppend("\tfloat afwidth;\n"); if (dfTexEffect.isSimilarity()) { // this gives us a smooth step across approximately one fragment - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n"); + // (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"); @@ -101,25 +88,12 @@ 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 - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); + // (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"); -#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()); } @@ -136,15 +110,6 @@ public: SkIntToScalar(fTextureSize.width()), SkIntToScalar(fTextureSize.height())); } -#ifdef SK_GAMMA_APPLY_TO_A8 - const GrDistanceFieldTextureEffect& dfTexEffect = - drawEffect.castEffect(); - float luminance = dfTexEffect.getLuminance(); - if (luminance != fLuminance) { - uman.set1f(fLuminanceUni, luminance); - fLuminance = luminance; - } -#endif } static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { @@ -157,8 +122,6 @@ public: private: GrGLUniformManager::UniformHandle fTextureSizeUni; SkISize fTextureSize; - GrGLUniformManager::UniformHandle fLuminanceUni; - float fLuminance; typedef GrGLVertexEffect INHERITED; }; @@ -167,22 +130,10 @@ 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); } @@ -215,10 +166,6 @@ 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, @@ -230,16 +177,8 @@ 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()); } @@ -272,7 +211,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; @@ -298,24 +237,22 @@ public: builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType); builder->fsCodeAppend(";\n"); builder->fsCodeAppend("\tvec3 distance;\n"); - builder->fsCodeAppend("\tdistance.y = texColor.r;\n"); + builder->fsCodeAppend("\tdistance.y = " + SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\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 = texColor.r;\n"); + builder->fsCodeAppend("\tdistance.x = " + SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\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 = texColor.r;\n"); - - builder->fsCodeAppend("\tdistance = " - "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"))" - "+ vec3(" SK_DistanceFieldLCDFactor ");\n"); - + builder->fsCodeAppend("\tdistance.z = " + SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\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. @@ -327,7 +264,8 @@ public: builder->fsCodeAppend("\tfloat afwidth;\n"); if (dfTexEffect.isUniformScale()) { // this gives us a smooth step across approximately one fragment - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n"); + // (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2) + builder->fsCodeAppend("\tafwidth = 0.7071*dx;\n"); } else { builder->fsCodeAppend("\tvec2 uv_grad;\n"); if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { @@ -345,36 +283,12 @@ 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 - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); + // (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("\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()); } @@ -382,13 +296,12 @@ public: virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE { SkASSERT(fTextureSizeUni.isValid()); - SkASSERT(fTextColorUni.isValid()); - const GrDistanceFieldLCDTextureEffect& dfTexEffect = - drawEffect.castEffect(); GrTexture* texture = drawEffect.effect()->get()->texture(0); if (texture->width() != fTextureSize.width() || texture->height() != fTextureSize.height()) { + const GrDistanceFieldLCDTextureEffect& dfTexEffect = + drawEffect.castEffect(); fTextureSize = SkISize::Make(texture->width(), texture->height()); float delta = 1.0f/(3.0f*texture->width()); if (dfTexEffect.useBGR()) { @@ -399,55 +312,40 @@ 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(); - return dfTexEffect.isUniformScale() ? 0x01 : 0x00;; + int uniformScale = dfTexEffect.isUniformScale() ? 0x01 : 0x00; + int useBGR = dfTexEffect.useBGR() ? 0x10 : 0x00; + return uniformScale | useBGR; } private: GrGLUniformManager::UniformHandle fTextureSizeUni; SkISize fTextureSize; - GrGLUniformManager::UniformHandle fTextColorUni; - SkColor fTextColor; typedef GrGLVertexEffect INHERITED; }; /////////////////////////////////////////////////////////////////////////////// -GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect( - GrTexture* texture, const GrTextureParams& params, - GrTexture* gamma, const GrTextureParams& gParams, - SkColor textColor, - bool uniformScale, bool useBGR) +GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(GrTexture* texture, + const GrTextureParams& params, + 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(other); - return (fTextureAccess == cte.fTextureAccess && fGammaTextureAccess == cte.fGammaTextureAccess); + const GrDistanceFieldLCDTextureEffect& cte = CastEffect(other); + return fTextureAccess == cte.fTextureAccess; } void GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color, @@ -473,9 +371,7 @@ GrEffectRef* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random, const GrDrawTargetCaps&, GrTexture* textures[]) { int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : - GrEffectUnitTest::kAlphaTextureIdx; - int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : - GrEffectUnitTest::kAlphaTextureIdx; + GrEffectUnitTest::kAlphaTextureIdx; static const SkShader::TileMode kTileModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, @@ -487,14 +383,7 @@ 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()); } diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h index 692290ccdb..937908f9bc 100644 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.h +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h @@ -18,23 +18,12 @@ class GrGLDistanceFieldLCDTextureEffect; * 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). * It allows explicit specification of the filtering and wrap modes (GrTextureParams). The input - * coords are a custom attribute. Gamma correction is handled via a texture LUT. + * coords are a custom attribute. */ class GrDistanceFieldTextureEffect : public GrVertexEffect { public: -#ifdef SK_GAMMA_APPLY_TO_A8 - static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params, - GrTexture* gamma, const GrTextureParams& gammaParams, float lum, - bool similarity) { - AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params, - gamma, gammaParams, lum, - similarity))); -#else - static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params, - bool similarity) { - AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params, - similarity))); -#endif + static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params, bool similarity) { + AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params, similarity))); return CreateEffectRef(effect); } @@ -43,9 +32,6 @@ public: static const char* Name() { return "DistanceFieldTexture"; } virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; -#ifdef SK_GAMMA_APPLY_TO_A8 - float getLuminance() const { return fLuminance; } -#endif bool isSimilarity() const { return fIsSimilarity; } typedef GrGLDistanceFieldTextureEffect GLEffect; @@ -54,18 +40,11 @@ public: private: GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params, -#ifdef SK_GAMMA_APPLY_TO_A8 - GrTexture* gamma, const GrTextureParams& gammaParams, float lum, -#endif bool uniformScale); virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; GrTextureAccess fTextureAccess; -#ifdef SK_GAMMA_APPLY_TO_A8 - GrTextureAccess fGammaTextureAccess; - float fLuminance; -#endif bool fIsSimilarity; GR_DECLARE_EFFECT_TEST; @@ -77,17 +56,14 @@ private: * The output color of this effect is a modulation of the input color and samples from a * distance field texture (using a smoothed step function near 0.5), adjusted for LCD displays. * It allows explicit specification of the filtering and wrap modes (GrTextureParams). The input - * coords are a custom attribute. Gamma correction is handled via a texture LUT. + * coords are a custom attribute. */ class GrDistanceFieldLCDTextureEffect : public GrVertexEffect { public: static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params, - GrTexture* gamma, const GrTextureParams& gammaParams, - SkColor textColor, bool uniformScale, bool useBGR) { AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldLCDTextureEffect, - (tex, params, gamma, gammaParams, textColor, uniformScale, - useBGR))); + (tex, params, uniformScale, useBGR))); return CreateEffectRef(effect); } @@ -96,7 +72,6 @@ public: static const char* Name() { return "DistanceFieldLCDTexture"; } 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; } @@ -106,15 +81,11 @@ public: private: GrDistanceFieldLCDTextureEffect(GrTexture* texture, const GrTextureParams& params, - GrTexture* gamma, const GrTextureParams& gammaParams, - SkColor textColor, bool uniformScale, bool useBGR); virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; GrTextureAccess fTextureAccess; - GrTextureAccess fGammaTextureAccess; - GrColor fTextColor; bool fUniformScale; bool fUseBGR; @@ -123,4 +94,5 @@ private: typedef GrVertexEffect INHERITED; }; + #endif