Emulate distance field gamma fix by making glyphs thicker or thinner
The idea here is that we determine the 0.5 crossover for each row in the gamma table, then invert the mapping to determine which point that maps to in the original range [-.65, .65]. That gives us a change in the apparent width of the glyph that closely corresponds to the change produced by the gamma fix. BUG=skia:2933 Review URL: https://codereview.chromium.org/1042373002
This commit is contained in:
parent
1d89e8d1a4
commit
21deace8ef
@ -43,6 +43,11 @@ static const int kLargeDFFontSize = 162;
|
||||
static const int kVerticesPerGlyph = 4;
|
||||
static const int kIndicesPerGlyph = 6;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
static const int kExpectedDistanceAdjustTableSize = 8;
|
||||
#endif
|
||||
static const int kDistanceAdjustLumShift = 5;
|
||||
|
||||
GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
|
||||
SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties& properties,
|
||||
@ -54,7 +59,7 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
|
||||
fEnableDFRendering = enable;
|
||||
#endif
|
||||
fStrike = NULL;
|
||||
fGammaTexture = NULL;
|
||||
fDistanceAdjustTable = NULL;
|
||||
|
||||
fEffectTextureUniqueID = SK_InvalidUniqueID;
|
||||
fEffectColor = GrColor_ILLEGAL;
|
||||
@ -75,6 +80,7 @@ GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* contex
|
||||
bool enable) {
|
||||
GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextContext,
|
||||
(context, gpuDevice, props, enable));
|
||||
textContext->buildDistanceAdjustTable();
|
||||
#ifdef USE_BITMAP_TEXTBLOBS
|
||||
textContext->fFallbackTextContext = GrBitmapTextContextB::Create(context, gpuDevice, props);
|
||||
#else
|
||||
@ -84,8 +90,92 @@ GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* contex
|
||||
return textContext;
|
||||
}
|
||||
|
||||
void GrDistanceFieldTextContext::buildDistanceAdjustTable() {
|
||||
|
||||
// This is used for an approximation of the mask gamma hack, used by raster and bitmap
|
||||
// text. The mask gamma hack is based off of guessing what the blend color is going to
|
||||
// be, and adjusting the mask so that when run through the linear blend will
|
||||
// produce the value closest to the desired result. However, in practice this means
|
||||
// that the 'adjusted' mask is just increasing or decreasing the coverage of
|
||||
// the mask depending on what it is thought it will blit against. For black (on
|
||||
// assumed white) this means that coverages are decreased (on a curve). For white (on
|
||||
// assumed black) this means that coverages are increased (on a a curve). At
|
||||
// middle (perceptual) gray (which could be blit against anything) the coverages
|
||||
// remain the same.
|
||||
//
|
||||
// The idea here is that instead of determining the initial (real) coverage and
|
||||
// then adjusting that coverage, we determine an adjusted coverage directly by
|
||||
// essentially manipulating the geometry (in this case, the distance to the glyph
|
||||
// edge). So for black (on assumed white) this thins a bit; for white (on
|
||||
// assumed black) this fake bolds the geometry a bit.
|
||||
//
|
||||
// The distance adjustment is calculated by determining the actual coverage value which
|
||||
// when fed into in the mask gamma table gives us an 'adjusted coverage' value of 0.5. This
|
||||
// actual coverage value (assuming it's between 0 and 1) corresponds to a distance from the
|
||||
// actual edge. So by subtracting this distance adjustment and computing without the
|
||||
// the coverage adjustment we should get 0.5 coverage at the same point.
|
||||
//
|
||||
// This has several implications:
|
||||
// For non-gray lcd smoothed text, each subpixel essentially is using a
|
||||
// slightly different geometry.
|
||||
//
|
||||
// For black (on assumed white) this may not cover some pixels which were
|
||||
// previously covered; however those pixels would have been only slightly
|
||||
// covered and that slight coverage would have been decreased anyway. Also, some pixels
|
||||
// which were previously fully covered may no longer be fully covered.
|
||||
//
|
||||
// For white (on assumed black) this may cover some pixels which weren't
|
||||
// previously covered at all.
|
||||
|
||||
int width, height;
|
||||
size_t size;
|
||||
|
||||
#ifdef SK_GAMMA_CONTRAST
|
||||
SkScalar contrast = SK_GAMMA_CONTRAST;
|
||||
#else
|
||||
SkScalar contrast = 0.5f;
|
||||
#endif
|
||||
SkScalar paintGamma = fDeviceProperties.gamma();
|
||||
SkScalar deviceGamma = fDeviceProperties.gamma();
|
||||
|
||||
size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
|
||||
&width, &height);
|
||||
|
||||
SkASSERT(kExpectedDistanceAdjustTableSize == height);
|
||||
fDistanceAdjustTable = SkNEW_ARRAY(SkScalar, height);
|
||||
|
||||
SkAutoTArray<uint8_t> data((int)size);
|
||||
SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get());
|
||||
|
||||
// find the inverse points where we cross 0.5
|
||||
// binsearch might be better, but we only need to do this once on creation
|
||||
for (int row = 0; row < height; ++row) {
|
||||
uint8_t* rowPtr = data.get() + row*width;
|
||||
for (int col = 0; col < width - 1; ++col) {
|
||||
if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) {
|
||||
// compute point where a mask value will give us a result of 0.5
|
||||
float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPtr[col]);
|
||||
float borderAlpha = (col + interp) / 255.f;
|
||||
|
||||
// compute t value for that alpha
|
||||
// this is an approximate inverse for smoothstep()
|
||||
float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5.0f) / 3.0f;
|
||||
|
||||
// compute distance which gives us that t value
|
||||
const float kDistanceFieldAAFactor = 0.65f; // should match SK_DistanceFieldAAFactor
|
||||
float d = 2.0f*kDistanceFieldAAFactor*t - kDistanceFieldAAFactor;
|
||||
|
||||
fDistanceAdjustTable[row] = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
|
||||
SkSafeSetNull(fGammaTexture);
|
||||
SkDELETE_ARRAY(fDistanceAdjustTable);
|
||||
fDistanceAdjustTable = NULL;
|
||||
}
|
||||
|
||||
bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt,
|
||||
@ -183,45 +273,6 @@ inline void GrDistanceFieldTextContext::init(GrRenderTarget* rt, const GrClip& c
|
||||
fSkPaint.setSubpixelText(true);
|
||||
}
|
||||
|
||||
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.gamma();
|
||||
SkScalar deviceGamma = deviceProperties.gamma();
|
||||
|
||||
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.
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = kNone_GrSurfaceFlags;
|
||||
desc.fWidth = width;
|
||||
desc.fHeight = height;
|
||||
desc.fConfig = kAlpha_8_GrPixelConfig;
|
||||
|
||||
*gammaTexture = context->getGpu()->createTexture(desc, true, NULL, 0);
|
||||
if (NULL == *gammaTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*gammaTexture)->writePixels(0, 0, width, height,
|
||||
(*gammaTexture)->config(), data.get(), 0,
|
||||
GrContext::kDontFlush_PixelOpsFlag);
|
||||
}
|
||||
}
|
||||
|
||||
void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkPaint& skPaint, const SkMatrix& viewMatrix,
|
||||
@ -314,8 +365,6 @@ void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip&
|
||||
SkGlyphCache* cache = autoCache.getCache();
|
||||
GrFontScaler* fontScaler = GetGrFontScaler(cache);
|
||||
|
||||
setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
|
||||
|
||||
int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
|
||||
fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
|
||||
|
||||
@ -443,13 +492,22 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo
|
||||
GrColor color = fPaint.getColor();
|
||||
if (fUseLCDText) {
|
||||
GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
|
||||
|
||||
float redCorrection =
|
||||
fDistanceAdjustTable[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift];
|
||||
float greenCorrection =
|
||||
fDistanceAdjustTable[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift];
|
||||
float blueCorrection =
|
||||
fDistanceAdjustTable[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift];
|
||||
GrDistanceFieldLCDTextureEffect::DistanceAdjust widthAdjust =
|
||||
GrDistanceFieldLCDTextureEffect::DistanceAdjust::Make(redCorrection,
|
||||
greenCorrection,
|
||||
blueCorrection);
|
||||
fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Create(color,
|
||||
fViewMatrix,
|
||||
fCurrTexture,
|
||||
params,
|
||||
fGammaTexture,
|
||||
gammaParams,
|
||||
colorNoPreMul,
|
||||
widthAdjust,
|
||||
flags));
|
||||
} else {
|
||||
flags |= kColorAttr_DistanceFieldEffectFlag;
|
||||
@ -457,13 +515,12 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.gamma(),
|
||||
filteredColor);
|
||||
float correction = fDistanceAdjustTable[lum >> kDistanceAdjustLumShift];
|
||||
fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(color,
|
||||
fViewMatrix,
|
||||
fCurrTexture,
|
||||
params,
|
||||
fGammaTexture,
|
||||
gammaParams,
|
||||
lum/255.f,
|
||||
correction,
|
||||
flags,
|
||||
opaque));
|
||||
#else
|
||||
|
@ -36,11 +36,11 @@ private:
|
||||
bool fUseLCDText;
|
||||
bool fEnableDFRendering;
|
||||
SkAutoTUnref<GrGeometryProcessor> fCachedGeometryProcessor;
|
||||
SkScalar* fDistanceAdjustTable;
|
||||
// Used to check whether fCachedEffect is still valid.
|
||||
uint32_t fEffectTextureUniqueID;
|
||||
SkColor fEffectColor;
|
||||
uint32_t fEffectFlags;
|
||||
GrTexture* fGammaTexture;
|
||||
void* fVertices;
|
||||
int fCurrVertex;
|
||||
int fAllocVertexCount;
|
||||
@ -50,6 +50,7 @@ private:
|
||||
SkMatrix fViewMatrix;
|
||||
|
||||
GrDistanceFieldTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&, bool enable);
|
||||
void buildDistanceAdjustTable();
|
||||
|
||||
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
|
||||
const SkPaint&, const SkMatrix& viewMatrix) override;
|
||||
|
@ -9,14 +9,16 @@
|
||||
#include "GrFontAtlasSizes.h"
|
||||
#include "GrInvariantOutput.h"
|
||||
#include "GrTexture.h"
|
||||
|
||||
#include "SkDistanceFieldGen.h"
|
||||
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLTexture.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
|
||||
// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
|
||||
// Assuming a radius of a little less than the diagonal of the fragment
|
||||
#define SK_DistanceFieldAAFactor "0.65"
|
||||
|
||||
struct DistanceFieldBatchTracker {
|
||||
@ -31,7 +33,7 @@ public:
|
||||
const GrBatchTracker&)
|
||||
: fColor(GrColor_ILLEGAL)
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
, fLuminance(-1.0f)
|
||||
, fDistanceAdjust(-1.0f)
|
||||
#endif
|
||||
{}
|
||||
|
||||
@ -59,6 +61,14 @@ public:
|
||||
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
|
||||
GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
|
||||
dfTexEffect.inTextureCoords()->fName);
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
// adjust based on gamma
|
||||
const char* distanceAdjustUniName = NULL;
|
||||
// width, height, 1/(3*width)
|
||||
fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"DistanceAdjust", &distanceAdjustUniName);
|
||||
#endif
|
||||
|
||||
// Setup pass through color
|
||||
this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
|
||||
@ -83,6 +93,10 @@ public:
|
||||
fsBuilder->codeAppend(".r;\n");
|
||||
fsBuilder->codeAppend("\tfloat distance = "
|
||||
SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
// adjust width based on gamma
|
||||
fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
|
||||
#endif
|
||||
|
||||
fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
|
||||
pb->ctxInfo().standard()));
|
||||
@ -119,21 +133,6 @@ public:
|
||||
}
|
||||
fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
|
||||
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
// adjust based on gamma
|
||||
const char* luminanceUniName = NULL;
|
||||
// width, height, 1/(3*width)
|
||||
fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"Luminance", &luminanceUniName);
|
||||
|
||||
fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
|
||||
fsBuilder->codeAppend("\tvec4 gammaColor = ");
|
||||
fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
|
||||
fsBuilder->codeAppend(";\n");
|
||||
fsBuilder->codeAppend("\tval = gammaColor.r;\n");
|
||||
#endif
|
||||
|
||||
fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
|
||||
}
|
||||
|
||||
@ -143,10 +142,10 @@ public:
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
const GrDistanceFieldTextureEffect& dfTexEffect =
|
||||
proc.cast<GrDistanceFieldTextureEffect>();
|
||||
float luminance = dfTexEffect.getLuminance();
|
||||
if (luminance != fLuminance) {
|
||||
pdman.set1f(fLuminanceUni, luminance);
|
||||
fLuminance = luminance;
|
||||
float distanceAdjust = dfTexEffect.getDistanceAdjust();
|
||||
if (distanceAdjust != fDistanceAdjust) {
|
||||
pdman.set1f(fDistanceAdjustUni, distanceAdjust);
|
||||
fDistanceAdjust = distanceAdjust;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -178,8 +177,8 @@ private:
|
||||
GrColor fColor;
|
||||
UniformHandle fColorUniform;
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
UniformHandle fLuminanceUni;
|
||||
float fLuminance;
|
||||
float fDistanceAdjust;
|
||||
UniformHandle fDistanceAdjustUni;
|
||||
#endif
|
||||
|
||||
typedef GrGLGeometryProcessor INHERITED;
|
||||
@ -192,16 +191,13 @@ GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrColor color,
|
||||
GrTexture* texture,
|
||||
const GrTextureParams& params,
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
GrTexture* gamma,
|
||||
const GrTextureParams& gammaParams,
|
||||
float luminance,
|
||||
float distanceAdjust,
|
||||
#endif
|
||||
uint32_t flags, bool opaqueVertexColors)
|
||||
: INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors)
|
||||
, fTextureAccess(texture, params)
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
, fGammaTextureAccess(gamma, gammaParams)
|
||||
, fLuminance(luminance)
|
||||
, fDistanceAdjust(distanceAdjust)
|
||||
#endif
|
||||
, fFlags(flags & kNonLCD_DistanceFieldEffectMask)
|
||||
, fInColor(NULL) {
|
||||
@ -215,16 +211,13 @@ GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrColor color,
|
||||
fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
|
||||
kVec2s_GrVertexAttribType));
|
||||
this->addTextureAccess(&fTextureAccess);
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
this->addTextureAccess(&fGammaTextureAccess);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GrDistanceFieldTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
|
||||
const GrDistanceFieldTextureEffect& cte = other.cast<GrDistanceFieldTextureEffect>();
|
||||
return
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
fLuminance == cte.fLuminance &&
|
||||
fDistanceAdjust == cte.fDistanceAdjust &&
|
||||
#endif
|
||||
fFlags == cte.fFlags;
|
||||
}
|
||||
@ -245,7 +238,8 @@ GrDistanceFieldTextureEffect::createGLInstance(const GrBatchTracker& bt,
|
||||
return SkNEW_ARGS(GrGLDistanceFieldTextureEffect, (*this, bt));
|
||||
}
|
||||
|
||||
void GrDistanceFieldTextureEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const {
|
||||
void GrDistanceFieldTextureEffect::initBatchTracker(GrBatchTracker* bt,
|
||||
const GrPipelineInfo& init) const {
|
||||
DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
|
||||
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
|
||||
SkToBool(fInColor));
|
||||
@ -273,10 +267,6 @@ GrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
|
||||
GrTexture* textures[]) {
|
||||
int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
|
||||
GrProcessorUnitTest::kAlphaTextureIdx;
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
|
||||
GrProcessorUnitTest::kAlphaTextureIdx;
|
||||
#endif
|
||||
static const SkShader::TileMode kTileModes[] = {
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kRepeat_TileMode,
|
||||
@ -288,16 +278,11 @@ GrGeometryProcessor* 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(GrRandomColor(random),
|
||||
GrProcessorUnitTest::TestMatrix(random),
|
||||
textures[texIdx], params,
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
textures[texIdx2], params2,
|
||||
random->nextF(),
|
||||
#endif
|
||||
random->nextBool() ?
|
||||
@ -487,7 +472,8 @@ bool GrDistanceFieldNoGammaTextureEffect::onIsEqual(const GrGeometryProcessor& o
|
||||
return fFlags == cte.fFlags;
|
||||
}
|
||||
|
||||
void GrDistanceFieldNoGammaTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const{
|
||||
void GrDistanceFieldNoGammaTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out)
|
||||
const {
|
||||
out->setUnknownSingleComponent();
|
||||
}
|
||||
|
||||
@ -563,8 +549,9 @@ class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor {
|
||||
public:
|
||||
GrGLDistanceFieldLCDTextureEffect(const GrGeometryProcessor&,
|
||||
const GrBatchTracker&)
|
||||
: fColor(GrColor_ILLEGAL)
|
||||
, fTextColor(GrColor_ILLEGAL) {}
|
||||
: fColor(GrColor_ILLEGAL) {
|
||||
fDistanceAdjust = GrDistanceFieldLCDTextureEffect::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
|
||||
const GrDistanceFieldLCDTextureEffect& dfTexEffect =
|
||||
@ -650,6 +637,13 @@ public:
|
||||
fsBuilder->codeAppend("\tdistance = "
|
||||
"vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
|
||||
|
||||
// adjust width based on gamma
|
||||
const char* distanceAdjustUniName = NULL;
|
||||
fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
"DistanceAdjust", &distanceAdjustUniName);
|
||||
fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
|
||||
|
||||
// To be strictly correct, we should compute the anti-aliasing factor separately
|
||||
// for each color component. However, this is only important when using perspective
|
||||
// transformations, and even then using a single factor seems like a reasonable
|
||||
@ -682,31 +676,8 @@ public:
|
||||
fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
|
||||
}
|
||||
|
||||
fsBuilder->codeAppend("vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
|
||||
|
||||
// adjust based on gamma
|
||||
const char* textColorUniName = NULL;
|
||||
fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
"TextColor", &textColorUniName);
|
||||
|
||||
fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
|
||||
fsBuilder->codeAppend("float gammaColor = ");
|
||||
fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
|
||||
fsBuilder->codeAppend(".r;\n");
|
||||
fsBuilder->codeAppend("\tval.x = gammaColor;\n");
|
||||
|
||||
fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
|
||||
fsBuilder->codeAppend("\tgammaColor = ");
|
||||
fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
|
||||
fsBuilder->codeAppend(".r;\n");
|
||||
fsBuilder->codeAppend("\tval.y = gammaColor;\n");
|
||||
|
||||
fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
|
||||
fsBuilder->codeAppend("\tgammaColor = ");
|
||||
fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
|
||||
fsBuilder->codeAppend(".r;\n");
|
||||
fsBuilder->codeAppend("\tval.z = gammaColor;\n");
|
||||
fsBuilder->codeAppend(
|
||||
"vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
|
||||
|
||||
fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
|
||||
}
|
||||
@ -714,18 +685,17 @@ public:
|
||||
virtual void setData(const GrGLProgramDataManager& pdman,
|
||||
const GrPrimitiveProcessor& processor,
|
||||
const GrBatchTracker& bt) override {
|
||||
SkASSERT(fTextColorUni.isValid());
|
||||
SkASSERT(fDistanceAdjustUni.isValid());
|
||||
|
||||
const GrDistanceFieldLCDTextureEffect& dfTexEffect =
|
||||
processor.cast<GrDistanceFieldLCDTextureEffect>();
|
||||
GrColor textColor = dfTexEffect.getTextColor();
|
||||
if (textColor != fTextColor) {
|
||||
static const float ONE_OVER_255 = 1.f / 255.f;
|
||||
pdman.set3f(fTextColorUni,
|
||||
GrColorUnpackR(textColor) * ONE_OVER_255,
|
||||
GrColorUnpackG(textColor) * ONE_OVER_255,
|
||||
GrColorUnpackB(textColor) * ONE_OVER_255);
|
||||
fTextColor = textColor;
|
||||
GrDistanceFieldLCDTextureEffect::DistanceAdjust wa = dfTexEffect.getDistanceAdjust();
|
||||
if (wa != fDistanceAdjust) {
|
||||
pdman.set3f(fDistanceAdjustUni,
|
||||
wa.fR,
|
||||
wa.fG,
|
||||
wa.fB);
|
||||
fDistanceAdjust = wa;
|
||||
}
|
||||
|
||||
this->setUniformViewMatrix(pdman, processor.viewMatrix());
|
||||
@ -755,10 +725,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
GrColor fColor;
|
||||
UniformHandle fColorUniform;
|
||||
UniformHandle fTextColorUni;
|
||||
SkColor fTextColor;
|
||||
GrColor fColor;
|
||||
UniformHandle fColorUniform;
|
||||
GrDistanceFieldLCDTextureEffect::DistanceAdjust fDistanceAdjust;
|
||||
UniformHandle fDistanceAdjustUni;
|
||||
|
||||
typedef GrGLGeometryProcessor INHERITED;
|
||||
};
|
||||
@ -768,13 +738,11 @@ private:
|
||||
GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
|
||||
GrColor color, const SkMatrix& viewMatrix,
|
||||
GrTexture* texture, const GrTextureParams& params,
|
||||
GrTexture* gamma, const GrTextureParams& gParams,
|
||||
SkColor textColor,
|
||||
DistanceAdjust distanceAdjust,
|
||||
uint32_t flags)
|
||||
: INHERITED(color, viewMatrix, SkMatrix::I())
|
||||
, fTextureAccess(texture, params)
|
||||
, fGammaTextureAccess(gamma, gParams)
|
||||
, fTextColor(textColor)
|
||||
, fDistanceAdjust(distanceAdjust)
|
||||
, fFlags(flags & kLCD_DistanceFieldEffectMask){
|
||||
SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
|
||||
this->initClassID<GrDistanceFieldLCDTextureEffect>();
|
||||
@ -782,16 +750,16 @@ GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
|
||||
fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
|
||||
kVec2s_GrVertexAttribType));
|
||||
this->addTextureAccess(&fTextureAccess);
|
||||
this->addTextureAccess(&fGammaTextureAccess);
|
||||
}
|
||||
|
||||
bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
|
||||
const GrDistanceFieldLCDTextureEffect& cte = other.cast<GrDistanceFieldLCDTextureEffect>();
|
||||
return (fTextColor == cte.fTextColor &&
|
||||
return (fDistanceAdjust == cte.fDistanceAdjust &&
|
||||
fFlags == cte.fFlags);
|
||||
}
|
||||
|
||||
void GrDistanceFieldLCDTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
|
||||
void GrDistanceFieldLCDTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out)
|
||||
const {
|
||||
out->setUnknownFourComponents();
|
||||
out->setUsingLCDCoverage();
|
||||
}
|
||||
@ -836,8 +804,6 @@ GrGeometryProcessor* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* rando
|
||||
GrTexture* textures[]) {
|
||||
int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
|
||||
GrProcessorUnitTest::kAlphaTextureIdx;
|
||||
int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
|
||||
GrProcessorUnitTest::kAlphaTextureIdx;
|
||||
static const SkShader::TileMode kTileModes[] = {
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kRepeat_TileMode,
|
||||
@ -849,19 +815,13 @@ GrGeometryProcessor* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* rando
|
||||
};
|
||||
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));
|
||||
DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
|
||||
uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
|
||||
flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
|
||||
flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
|
||||
return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random),
|
||||
GrProcessorUnitTest::TestMatrix(random),
|
||||
textures[texIdx], params,
|
||||
textures[texIdx2], params2,
|
||||
textColor,
|
||||
wa,
|
||||
flags);
|
||||
}
|
||||
|
@ -49,10 +49,8 @@ public:
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex,
|
||||
const GrTextureParams& params,
|
||||
GrTexture* gamma, const GrTextureParams& gammaParams,
|
||||
float lum, uint32_t flags, bool opaqueVertexColors) {
|
||||
return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, tex, params, gamma,
|
||||
gammaParams, lum,
|
||||
return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, tex, params, lum,
|
||||
flags, opaqueVertexColors));
|
||||
}
|
||||
#else
|
||||
@ -72,7 +70,7 @@ public:
|
||||
const Attribute* inColor() const { return fInColor; }
|
||||
const Attribute* inTextureCoords() const { return fInTextureCoords; }
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
float getLuminance() const { return fLuminance; }
|
||||
float getDistanceAdjust() const { return fDistanceAdjust; }
|
||||
#endif
|
||||
uint32_t getFlags() const { return fFlags; }
|
||||
|
||||
@ -93,7 +91,7 @@ private:
|
||||
GrDistanceFieldTextureEffect(GrColor, const SkMatrix& viewMatrix, GrTexture* texture,
|
||||
const GrTextureParams& params,
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
GrTexture* gamma, const GrTextureParams& gammaParams, float lum,
|
||||
float distanceAdjust,
|
||||
#endif
|
||||
uint32_t flags, bool opaqueVertexColors);
|
||||
|
||||
@ -101,12 +99,11 @@ private:
|
||||
|
||||
void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const override;
|
||||
|
||||
GrTextureAccess fTextureAccess;
|
||||
GrTextureAccess fTextureAccess;
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
GrTextureAccess fGammaTextureAccess;
|
||||
float fLuminance;
|
||||
float fDistanceAdjust;
|
||||
#endif
|
||||
uint32_t fFlags;
|
||||
uint32_t fFlags;
|
||||
const Attribute* fInPosition;
|
||||
const Attribute* fInColor;
|
||||
const Attribute* fInTextureCoords;
|
||||
@ -182,12 +179,26 @@ private:
|
||||
*/
|
||||
class GrDistanceFieldLCDTextureEffect : public GrGeometryProcessor {
|
||||
public:
|
||||
struct DistanceAdjust {
|
||||
SkScalar fR, fG, fB;
|
||||
static DistanceAdjust Make(SkScalar r, SkScalar g, SkScalar b) {
|
||||
DistanceAdjust result;
|
||||
result.fR = r; result.fG = g; result.fB = b;
|
||||
return result;
|
||||
}
|
||||
bool operator==(const DistanceAdjust& wa) const {
|
||||
return (fR == wa.fR && fG == wa.fG && fB == wa.fB);
|
||||
}
|
||||
bool operator!=(const DistanceAdjust& wa) const {
|
||||
return !(*this == wa);
|
||||
}
|
||||
};
|
||||
|
||||
static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex,
|
||||
const GrTextureParams& params, GrTexture* gamma,
|
||||
const GrTextureParams& gammaParams,
|
||||
SkColor textColor, uint32_t flags) {
|
||||
const GrTextureParams& params,
|
||||
DistanceAdjust distanceAdjust, uint32_t flags) {
|
||||
return SkNEW_ARGS(GrDistanceFieldLCDTextureEffect,
|
||||
(color, viewMatrix, tex, params, gamma, gammaParams, textColor, flags));
|
||||
(color, viewMatrix, tex, params, distanceAdjust, flags));
|
||||
}
|
||||
|
||||
virtual ~GrDistanceFieldLCDTextureEffect() {}
|
||||
@ -196,7 +207,7 @@ public:
|
||||
|
||||
const Attribute* inPosition() const { return fInPosition; }
|
||||
const Attribute* inTextureCoords() const { return fInTextureCoords; }
|
||||
GrColor getTextColor() const { return fTextColor; }
|
||||
DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; }
|
||||
uint32_t getFlags() const { return fFlags; }
|
||||
|
||||
virtual void getGLProcessorKey(const GrBatchTracker& bt,
|
||||
@ -215,17 +226,15 @@ public:
|
||||
private:
|
||||
GrDistanceFieldLCDTextureEffect(GrColor, const SkMatrix& viewMatrix, GrTexture* texture,
|
||||
const GrTextureParams& params,
|
||||
GrTexture* gamma, const GrTextureParams& gammaParams,
|
||||
SkColor textColor, uint32_t flags);
|
||||
DistanceAdjust wa, uint32_t flags);
|
||||
|
||||
bool onIsEqual(const GrGeometryProcessor& other) const override;
|
||||
|
||||
void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const override;
|
||||
|
||||
GrTextureAccess fTextureAccess;
|
||||
GrTextureAccess fGammaTextureAccess;
|
||||
GrColor fTextColor;
|
||||
uint32_t fFlags;
|
||||
GrTextureAccess fTextureAccess;
|
||||
DistanceAdjust fDistanceAdjust;
|
||||
uint32_t fFlags;
|
||||
const Attribute* fInPosition;
|
||||
const Attribute* fInTextureCoords;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user