Optimize building gradient cache for when we know alpha is always 0xFF.

remove old build guard for dithering.
Review URL: https://codereview.appspot.com/7309064

git-svn-id: http://skia.googlecode.com/svn/trunk@7678 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2013-02-08 19:48:12 +00:00
parent 0556ea0ede
commit d8e0d6a87d
2 changed files with 85 additions and 82 deletions

View File

@ -289,24 +289,6 @@ void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor
} while (--count != 0);
}
/*
* 2x2 dither a fixed-point color component (8.16) down to 8, matching the
* semantics of how we 2x2 dither 32->16
*/
static inline U8CPU dither_fixed_to_8(SkFixed n) {
n >>= 8;
return ((n << 1) - ((n >> 8 << 8) | (n >> 8))) >> 8;
}
/*
* For dithering with premultiply, we want to ceiling the alpha component,
* to ensure that it is always >= any color component.
*/
static inline U8CPU dither_ceil_fixed_to_8(SkFixed n) {
n >>= 8;
return ((n << 1) - (n | (n >> 8))) >> 8;
}
void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
int count, U8CPU paintAlpha) {
SkASSERT(count > 1);
@ -319,67 +301,94 @@ void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo
da = SkIntToFixed(tmp - a) / (count - 1);
}
SkFixed r = SkColorGetR(c0);
SkFixed g = SkColorGetG(c0);
SkFixed b = SkColorGetB(c0);
/*
* r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
* release builds, we saw a compiler error where the 0xFF parameter in
* SkPackARGB32() was being totally ignored whenever it was called with
* a non-zero add (e.g. 0x8000).
*
* We found two work-arounds:
* 1. change r,g,b to unsigned (or just one of them)
* 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
* of using |
*
* We chose #1 just because it was more localized.
* See http://code.google.com/p/skia/issues/detail?id=1113
*/
uint32_t r = SkColorGetR(c0);
uint32_t g = SkColorGetG(c0);
uint32_t b = SkColorGetB(c0);
SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
#ifdef SK_IGNORE_GRADIENT_DITHER_FIX
a = SkIntToFixed(a) + 0x8000;
r = SkIntToFixed(r) + 0x8000;
g = SkIntToFixed(g) + 0x8000;
b = SkIntToFixed(b) + 0x8000;
#else
a = SkIntToFixed(a);
r = SkIntToFixed(r);
g = SkIntToFixed(g);
b = SkIntToFixed(b);
#endif
/* We pre-add 1/8 to avoid having to add this to our [0] value each time
in the loop. Without this, the bias for each would be
0x2000 0xA000 0xE000 0x6000
With this trick, we can add 0 for the first (no-op) and just adjust the
others.
*/
r = SkIntToFixed(r) + 0x2000;
g = SkIntToFixed(g) + 0x2000;
b = SkIntToFixed(b) + 0x2000;
do {
#ifdef SK_IGNORE_GRADIENT_DITHER_FIX
cache[0] = SkPremultiplyARGBInline(a >> 16, r >> 16, g >> 16, b >> 16);
cache[kCache32Count] =
SkPremultiplyARGBInline(dither_ceil_fixed_to_8(a),
dither_fixed_to_8(r),
dither_fixed_to_8(g),
dither_fixed_to_8(b));
#else
/*
* Our dither-cell (spatially) is
* 0 2
* 3 1
* Where
* [0] -> [-1/8 ... 1/8 ) values near 0
* [1] -> [ 1/8 ... 3/8 ) values near 1/4
* [2] -> [ 3/8 ... 5/8 ) values near 1/2
* [3] -> [ 5/8 ... 7/8 ) values near 3/4
*/
cache[kCache32Count*0] = SkPremultiplyARGBInline((a + 0x2000) >> 16,
(r + 0x2000) >> 16,
(g + 0x2000) >> 16,
(b + 0x2000) >> 16);
cache[kCache32Count*3] = SkPremultiplyARGBInline((a + 0x6000) >> 16,
(r + 0x6000) >> 16,
(g + 0x6000) >> 16,
(b + 0x6000) >> 16);
cache[kCache32Count*1] = SkPremultiplyARGBInline((a + 0xA000) >> 16,
(r + 0xA000) >> 16,
(g + 0xA000) >> 16,
(b + 0xA000) >> 16);
cache[kCache32Count*2] = SkPremultiplyARGBInline((a + 0xE000) >> 16,
(r + 0xE000) >> 16,
(g + 0xE000) >> 16,
(b + 0xE000) >> 16);
#endif
cache += 1;
a += da;
r += dr;
g += dg;
b += db;
} while (--count != 0);
/*
* Our dither-cell (spatially) is
* 0 2
* 3 1
* Where
* [0] -> [-1/8 ... 1/8 ) values near 0
* [1] -> [ 1/8 ... 3/8 ) values near 1/4
* [2] -> [ 3/8 ... 5/8 ) values near 1/2
* [3] -> [ 5/8 ... 7/8 ) values near 3/4
*/
if (0xFF == a && 0 == da) {
do {
cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0 ) >> 16,
(g + 0 ) >> 16,
(b + 0 ) >> 16);
cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + 0x8000) >> 16,
(g + 0x8000) >> 16,
(b + 0x8000) >> 16);
cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + 0xC000) >> 16,
(g + 0xC000) >> 16,
(b + 0xC000) >> 16);
cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + 0x4000) >> 16,
(g + 0x4000) >> 16,
(b + 0x4000) >> 16);
cache += 1;
r += dr;
g += dg;
b += db;
} while (--count != 0);
} else {
a = SkIntToFixed(a) + 0x2000;
do {
cache[kCache32Count*0] = SkPremultiplyARGBInline((a + 0 ) >> 16,
(r + 0 ) >> 16,
(g + 0 ) >> 16,
(b + 0 ) >> 16);
cache[kCache32Count*1] = SkPremultiplyARGBInline((a + 0x8000) >> 16,
(r + 0x8000) >> 16,
(g + 0x8000) >> 16,
(b + 0x8000) >> 16);
cache[kCache32Count*2] = SkPremultiplyARGBInline((a + 0xC000) >> 16,
(r + 0xC000) >> 16,
(g + 0xC000) >> 16,
(b + 0xC000) >> 16);
cache[kCache32Count*3] = SkPremultiplyARGBInline((a + 0x4000) >> 16,
(r + 0x4000) >> 16,
(g + 0x4000) >> 16,
(b + 0x4000) >> 16);
cache += 1;
a += da;
r += dr;
g += dg;
b += db;
} while (--count != 0);
}
}
static inline int SkFixedToFFFF(SkFixed x) {
@ -479,12 +488,10 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
SkUnitMapper* map = fMapper;
for (int i = 0; i < kCache32Count; i++) {
int index = map->mapUnit16((i << 8) | i) >> 8;
mapped[i] = linear[index];
mapped[i + kCache32Count] = linear[index + kCache32Count];
#ifndef SK_IGNORE_GRADIENT_DITHER_FIX
mapped[i + kCache32Count*0] = linear[index + kCache32Count*0];
mapped[i + kCache32Count*1] = linear[index + kCache32Count*1];
mapped[i + kCache32Count*2] = linear[index + kCache32Count*2];
mapped[i + kCache32Count*3] = linear[index + kCache32Count*3];
#endif
}
fCache32PixelRef->unref();
fCache32PixelRef = newPR;

View File

@ -167,13 +167,9 @@ private:
};
static inline int init_dither_toggle(int x, int y) {
#ifdef SK_IGNORE_GRADIENT_DITHER_FIX
return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride32;
#else
x &= 1;
y = (y & 1) << 1;
return (x | y) * SkGradientShaderBase::kDitherStride32;
#endif
}
static inline int next_dither_toggle(int toggle) {