Reduce SkMaskGamma cache thrashing.
https://codereview.appspot.com/6497114/ git-svn-id: http://skia.googlecode.com/svn/trunk@5492 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
fb3dd3a6f5
commit
ae30f56019
@ -36,14 +36,22 @@ SkGammaLuminance::SkGammaLuminance(SkScalar gamma)
|
||||
, fGammaInverse(SkScalarInvert(gamma)) {
|
||||
}
|
||||
|
||||
float SkGammaLuminance::toLuma(SkScalar luminance) const {
|
||||
SkScalar SkGammaLuminance::toLuma(SkScalar luminance) const {
|
||||
return SkScalarPow(luminance, fGamma);
|
||||
}
|
||||
|
||||
float SkGammaLuminance::fromLuma(SkScalar luma) const {
|
||||
SkScalar SkGammaLuminance::fromLuma(SkScalar luma) const {
|
||||
return SkScalarPow(luma, fGammaInverse);
|
||||
}
|
||||
|
||||
SkScalar SkLinearLuminance::toLuma(SkScalar luminance) const {
|
||||
return luminance;
|
||||
}
|
||||
|
||||
SkScalar SkLinearLuminance::fromLuma(SkScalar luma) const {
|
||||
return luma;
|
||||
}
|
||||
|
||||
static float apply_contrast(float srca, float contrast) {
|
||||
return srca + ((1.0f - srca) * contrast * srca);
|
||||
}
|
||||
|
@ -58,6 +58,12 @@ private:
|
||||
SkScalar fGammaInverse;
|
||||
};
|
||||
|
||||
class SkLinearLuminance : public SkColorSpaceLuminance {
|
||||
public:
|
||||
SkScalar toLuma(SkScalar luminance) const SK_OVERRIDE;
|
||||
SkScalar fromLuma(SkScalar luma) const SK_OVERRIDE;
|
||||
};
|
||||
|
||||
///@{
|
||||
/**
|
||||
* Scales base <= 2^N-1 to 2^8-1
|
||||
@ -107,6 +113,9 @@ template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskGamma : p
|
||||
public:
|
||||
SK_DECLARE_INST_COUNT_TEMPLATE(SkTMaskGamma)
|
||||
|
||||
SkTMaskGamma() : fIsLinear(true) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates tables to convert linear alpha values to gamma correcting alpha
|
||||
* values.
|
||||
@ -118,7 +127,7 @@ public:
|
||||
*/
|
||||
SkTMaskGamma(SkScalar contrast,
|
||||
const SkColorSpaceLuminance& paint,
|
||||
const SkColorSpaceLuminance& device) {
|
||||
const SkColorSpaceLuminance& device) : fIsLinear(false) {
|
||||
for (U8CPU i = 0; i < (1 << kLuminanceBits_Max); ++i) {
|
||||
U8CPU lum = sk_t_scale255<kLuminanceBits_Max>(i);
|
||||
SkTMaskGamma_build_correcting_lut(fGammaTables[i], lum, contrast, paint, device);
|
||||
@ -126,7 +135,7 @@ public:
|
||||
}
|
||||
|
||||
/** Given a color, returns the closest cannonical color. */
|
||||
SkColor cannonicalColor(SkColor color) {
|
||||
static SkColor cannonicalColor(SkColor color) {
|
||||
return SkColorSetRGB(
|
||||
sk_t_scale255<kLuminanceBits_R>(SkColorGetR(color) >> (8 - kLuminanceBits_R)),
|
||||
sk_t_scale255<kLuminanceBits_G>(SkColorGetG(color) >> (8 - kLuminanceBits_G)),
|
||||
@ -153,6 +162,7 @@ private:
|
||||
: (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS)
|
||||
};
|
||||
uint8_t fGammaTables[1 << kLuminanceBits_Max][256];
|
||||
bool fIsLinear;
|
||||
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
@ -167,6 +177,9 @@ SK_DEFINE_INST_COUNT_TEMPLATE(
|
||||
* SkTMaskPreBlend is a tear-off of SkTMaskGamma. It provides the tables to
|
||||
* convert a linear alpha value for a given channel to a gamma correcting alpha
|
||||
* value for that channel. This class is immutable.
|
||||
*
|
||||
* If fR, fG, or fB is NULL, all of them will be. This indicates that no mask
|
||||
* pre blend should be applied.
|
||||
*/
|
||||
template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskPreBlend {
|
||||
private:
|
||||
@ -175,7 +188,7 @@ private:
|
||||
const uint8_t* g,
|
||||
const uint8_t* b)
|
||||
: fParent(parent), fR(r), fG(g), fB(b) {
|
||||
parent->ref();
|
||||
SkSafeRef(parent);
|
||||
}
|
||||
SkAutoTUnref<SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS> > fParent;
|
||||
friend class SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>;
|
||||
@ -186,7 +199,7 @@ public:
|
||||
*/
|
||||
SkTMaskPreBlend(const SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>& that)
|
||||
: fParent(that.fParent.get()), fR(that.fR), fG(that.fG), fB(that.fB) {
|
||||
fParent.get()->ref();
|
||||
SkSafeRef(fParent.get());
|
||||
}
|
||||
~SkTMaskPreBlend() { }
|
||||
const uint8_t* fR;
|
||||
@ -197,7 +210,9 @@ public:
|
||||
template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS>
|
||||
SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>
|
||||
SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>::preBlend(SkColor color) {
|
||||
return SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>(
|
||||
return fIsLinear ? SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>(
|
||||
NULL, NULL, NULL, NULL)
|
||||
: SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>(
|
||||
this,
|
||||
fGammaTables[SkColorGetR(color) >> (8 - kLuminanceBits_Max)],
|
||||
fGammaTables[SkColorGetG(color) >> (8 - kLuminanceBits_Max)],
|
||||
|
@ -1621,6 +1621,8 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
|
||||
*/
|
||||
SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
|
||||
|
||||
static SkColorSpaceLuminance* gLinearLuminance = NULL;
|
||||
|
||||
static SkColorSpaceLuminance* gDeviceLuminance = NULL;
|
||||
static SkScalar gDeviceGammaExponent = SK_ScalarMin;
|
||||
/**
|
||||
@ -1628,6 +1630,12 @@ static SkScalar gDeviceGammaExponent = SK_ScalarMin;
|
||||
* the returned SkColorSpaceLuminance pointer is forgotten.
|
||||
*/
|
||||
static SkColorSpaceLuminance* cachedDeviceLuminance(SkScalar gammaExponent) {
|
||||
if (SK_Scalar1 == gammaExponent) {
|
||||
if (NULL == gLinearLuminance) {
|
||||
gLinearLuminance = SkNEW(SkLinearLuminance);
|
||||
}
|
||||
return gLinearLuminance;
|
||||
}
|
||||
if (gDeviceGammaExponent != gammaExponent) {
|
||||
SkDELETE(gDeviceLuminance);
|
||||
if (0 == gammaExponent) {
|
||||
@ -1647,6 +1655,12 @@ static SkScalar gPaintGammaExponent = SK_ScalarMin;
|
||||
* the returned SkColorSpaceLuminance pointer is forgotten.
|
||||
*/
|
||||
static SkColorSpaceLuminance* cachedPaintLuminance(SkScalar gammaExponent) {
|
||||
if (SK_Scalar1 == gammaExponent) {
|
||||
if (NULL == gLinearLuminance) {
|
||||
gLinearLuminance = SkNEW(SkLinearLuminance);
|
||||
}
|
||||
return gLinearLuminance;
|
||||
}
|
||||
if (gPaintGammaExponent != gammaExponent) {
|
||||
SkDELETE(gPaintLuminance);
|
||||
if (0 == gammaExponent) {
|
||||
@ -1659,6 +1673,7 @@ static SkColorSpaceLuminance* cachedPaintLuminance(SkScalar gammaExponent) {
|
||||
return gPaintLuminance;
|
||||
}
|
||||
|
||||
static SkMaskGamma* gLinearMaskGamma = NULL;
|
||||
static SkMaskGamma* gMaskGamma = NULL;
|
||||
static SkScalar gContrast = SK_ScalarMin;
|
||||
static SkScalar gPaintGamma = SK_ScalarMin;
|
||||
@ -1668,6 +1683,12 @@ static SkScalar gDeviceGamma = SK_ScalarMin;
|
||||
* the returned SkMaskGamma pointer is refed or forgotten.
|
||||
*/
|
||||
static SkMaskGamma* cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
|
||||
if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
|
||||
if (NULL == gLinearMaskGamma) {
|
||||
gLinearMaskGamma = SkNEW(SkMaskGamma);
|
||||
}
|
||||
return gLinearMaskGamma;
|
||||
}
|
||||
if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
|
||||
SkSafeUnref(gMaskGamma);
|
||||
SkColorSpaceLuminance* paintLuminance = cachedPaintLuminance(paintGamma);
|
||||
@ -1683,11 +1704,15 @@ static SkMaskGamma* cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkSc
|
||||
/*static*/ void SkPaint::Term() {
|
||||
SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
|
||||
|
||||
SkSafeUnref(gLinearMaskGamma);
|
||||
|
||||
SkSafeUnref(gMaskGamma);
|
||||
SkDEBUGCODE(gContrast = SK_ScalarMin;)
|
||||
SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
|
||||
SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
|
||||
|
||||
SkDELETE(gLinearLuminance);
|
||||
|
||||
SkDELETE(gPaintLuminance);
|
||||
SkDEBUGCODE(gPaintLuminance = NULL;)
|
||||
SkDEBUGCODE(gPaintGammaExponent = SK_ScalarMin;)
|
||||
@ -1711,11 +1736,7 @@ void SkScalerContext::PostMakeRec(const SkPaint& paint, SkScalerContext::Rec* re
|
||||
case SkMask::kLCD32_Format: {
|
||||
// filter down the luminance color to a finite number of bits
|
||||
SkColor color = rec->getLuminanceColor();
|
||||
SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
|
||||
SkMaskGamma* maskGamma = cachedMaskGamma(rec->getContrast(),
|
||||
rec->getPaintGamma(),
|
||||
rec->getDeviceGamma());
|
||||
rec->setLuminanceColor(maskGamma->cannonicalColor(color));
|
||||
rec->setLuminanceColor(SkMaskGamma::cannonicalColor(color));
|
||||
break;
|
||||
}
|
||||
case SkMask::kA8_Format: {
|
||||
@ -1732,11 +1753,8 @@ void SkScalerContext::PostMakeRec(const SkPaint& paint, SkScalerContext::Rec* re
|
||||
}
|
||||
|
||||
// reduce to our finite number of bits
|
||||
SkMaskGamma* maskGamma = cachedMaskGamma(rec->getContrast(),
|
||||
rec->getPaintGamma(),
|
||||
rec->getDeviceGamma());
|
||||
color = SkColorSetRGB(lum, lum, lum);
|
||||
rec->setLuminanceColor(maskGamma->cannonicalColor(color));
|
||||
rec->setLuminanceColor(SkMaskGamma::cannonicalColor(color));
|
||||
break;
|
||||
}
|
||||
case SkMask::kBW_Format:
|
||||
|
@ -491,7 +491,7 @@ static void applyLUTToA8Glyph(const SkGlyph& glyph, const uint8_t* lut) {
|
||||
void SkScalerContext::getImage(const SkGlyph& origGlyph) {
|
||||
const SkGlyph* glyph = &origGlyph;
|
||||
SkGlyph tmpGlyph;
|
||||
SkMaskGamma::PreBlend* maskPreBlend = &fMaskPreBlend;
|
||||
SkMaskGamma::PreBlend* maskPreBlend = fMaskPreBlend.fParent ? &fMaskPreBlend : NULL;
|
||||
|
||||
if (fMaskFilter) { // restore the prefilter bounds
|
||||
tmpGlyph.init(origGlyph.fID);
|
||||
|
Loading…
Reference in New Issue
Block a user