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
This commit is contained in:
parent
880914c35c
commit
919ed4c736
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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<uint8_t> 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;
|
||||
|
||||
|
@ -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*);
|
||||
|
@ -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<GrDistanceFieldTextureEffect>();
|
||||
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<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()) {
|
||||
@ -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<GrDistanceFieldLCDTextureEffect>();
|
||||
|
||||
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<GrDistanceFieldLCDTextureEffect>(other);
|
||||
return (fTextureAccess == cte.fTextureAccess && fGammaTextureAccess == cte.fGammaTextureAccess);
|
||||
const GrDistanceFieldLCDTextureEffect& cte = CastEffect<GrDistanceFieldLCDTextureEffect>(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());
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user