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:
jvanverth 2015-04-01 12:43:48 -07:00 committed by Commit bot
parent 1d89e8d1a4
commit 21deace8ef
4 changed files with 197 additions and 170 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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;