Add dithering to 32b radial gradients. Behind the same #ifdef as dithered

32b linear gradients so that we don't impact clients unexpectedly.
This commit *will* break GM.

http://codereview.appspot.com/5599050/



git-svn-id: http://skia.googlecode.com/svn/trunk@3126 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
tomhudson@google.com 2012-02-02 14:11:18 +00:00
parent dc3c78076e
commit 480e21f239

View File

@ -1557,20 +1557,22 @@ inline bool no_need_for_radial_pin(int fx, int dx,
#define UNPINNED_RADIAL_STEP \ #define UNPINNED_RADIAL_STEP \
fi = (fx * fx + fy * fy) >> (14 + 16 - kSQRT_TABLE_BITS); \ fi = (fx * fx + fy * fy) >> (14 + 16 - kSQRT_TABLE_BITS); \
*dstC++ = cache[sqrt_table[fi] >> Gradient_Shader::kSqrt32Shift]; \ *dstC++ = cache[toggle + \
(sqrt_table[fi] >> Gradient_Shader::kSqrt32Shift)]; \
toggle ^= Gradient_Shader::kDitherStride32; \
fx += dx; \ fx += dx; \
fy += dy; fy += dy;
typedef void (* RadialShadeProc)(SkScalar sfx, SkScalar sdx, typedef void (* RadialShadeProc)(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy, SkScalar sfy, SkScalar sdy,
SkPMColor* dstC, const SkPMColor* cache, SkPMColor* dstC, const SkPMColor* cache,
int count); int count, int toggle);
// On Linux, this is faster with SkPMColor[] params than SkPMColor* SK_RESTRICT // On Linux, this is faster with SkPMColor[] params than SkPMColor* SK_RESTRICT
void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx, void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy, SkScalar sfy, SkScalar sdy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) { int count, int toggle) {
// Floating point seems to be slower than fixed point, // Floating point seems to be slower than fixed point,
// even when we have float hardware. // even when we have float hardware.
const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table; const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
@ -1579,7 +1581,11 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
SkFixed fy = SkScalarToFixed(sfy) >> 1; SkFixed fy = SkScalarToFixed(sfy) >> 1;
SkFixed dy = SkScalarToFixed(sdy) >> 1; SkFixed dy = SkScalarToFixed(sdy) >> 1;
if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) { if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) {
sk_memset32(dstC, cache[Gradient_Shader::kGradient32Length], count); unsigned fi = Gradient_Shader::kGradient32Length;
sk_memset32_dither(dstC,
cache[toggle + fi],
cache[(toggle ^ Gradient_Shader::kDitherStride32) + fi],
count);
} else if ((count > 4) && } else if ((count > 4) &&
no_need_for_radial_pin(fx, dx, fy, dy, count)) { no_need_for_radial_pin(fx, dx, fy, dy, count)) {
unsigned fi; unsigned fi;
@ -1602,8 +1608,9 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
unsigned fi = (xx * xx + yy) >> (14 + 16 - kSQRT_TABLE_BITS); unsigned fi = (xx * xx + yy) >> (14 + 16 - kSQRT_TABLE_BITS);
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
*dstC++ = cache[sqrt_table[fi] >> *dstC++ = cache[toggle + (sqrt_table[fi] >>
Gradient_Shader::kSqrt32Shift]; Gradient_Shader::kSqrt32Shift)];
toggle ^= Gradient_Shader::kDitherStride32;
fx += dx; fx += dx;
} while (--count != 0); } while (--count != 0);
} else { } else {
@ -1612,8 +1619,9 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS); fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
*dstC++ = cache[sqrt_table[fi] >> *dstC++ = cache[toggle + (sqrt_table[fi] >>
Gradient_Shader::kSqrt32Shift]; Gradient_Shader::kSqrt32Shift)];
toggle ^= Gradient_Shader::kDitherStride32;
fx += dx; fx += dx;
fy += dy; fy += dy;
} while (--count != 0); } while (--count != 0);
@ -1627,7 +1635,7 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
void shadeSpan_radial_mirror(SkScalar sfx, SkScalar sdx, void shadeSpan_radial_mirror(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy, SkScalar sfy, SkScalar sdy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) { int count, int toggle) {
do { do {
#ifdef SK_SCALAR_IS_FLOAT #ifdef SK_SCALAR_IS_FLOAT
float fdist = sk_float_sqrt(sfx*sfx + sfy*sfy); float fdist = sk_float_sqrt(sfx*sfx + sfy*sfy);
@ -1641,7 +1649,8 @@ void shadeSpan_radial_mirror(SkScalar sfx, SkScalar sdx,
#endif #endif
unsigned fi = mirror_tileproc(dist); unsigned fi = mirror_tileproc(dist);
SkASSERT(fi <= 0xFFFF); SkASSERT(fi <= 0xFFFF);
*dstC++ = cache[fi >> Gradient_Shader::kCache32Shift]; *dstC++ = cache[toggle + (fi >> Gradient_Shader::kCache32Shift)];
toggle ^= Gradient_Shader::kDitherStride32;
sfx += sdx; sfx += sdx;
sfy += sdy; sfy += sdy;
} while (--count != 0); } while (--count != 0);
@ -1650,7 +1659,7 @@ void shadeSpan_radial_mirror(SkScalar sfx, SkScalar sdx,
void shadeSpan_radial_repeat(SkScalar sfx, SkScalar sdx, void shadeSpan_radial_repeat(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy, SkScalar sfy, SkScalar sdy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) { int count, int toggle) {
SkFixed fx = SkScalarToFixed(sfx); SkFixed fx = SkScalarToFixed(sfx);
SkFixed dx = SkScalarToFixed(sdx); SkFixed dx = SkScalarToFixed(sdx);
SkFixed fy = SkScalarToFixed(sfy); SkFixed fy = SkScalarToFixed(sfy);
@ -1663,7 +1672,8 @@ void shadeSpan_radial_repeat(SkScalar sfx, SkScalar sdx,
SkFixed dist = SkFixedSqrt(magnitudeSquared); SkFixed dist = SkFixedSqrt(magnitudeSquared);
unsigned fi = repeat_tileproc(dist); unsigned fi = repeat_tileproc(dist);
SkASSERT(fi <= 0xFFFF); SkASSERT(fi <= 0xFFFF);
*dstC++ = cache[fi >> Gradient_Shader::kCache32Shift]; *dstC++ = cache[toggle + (fi >> Gradient_Shader::kCache32Shift)];
toggle ^= Gradient_Shader::kDitherStride32;
fx += dx; fx += dx;
fy += dy; fy += dy;
} while (--count != 0); } while (--count != 0);
@ -1678,6 +1688,11 @@ void Radial_Gradient::shadeSpan(int x, int y,
SkMatrix::MapXYProc dstProc = fDstToIndexProc; SkMatrix::MapXYProc dstProc = fDstToIndexProc;
TileProc proc = fTileProc; TileProc proc = fTileProc;
const SkPMColor* SK_RESTRICT cache = this->getCache32(); const SkPMColor* SK_RESTRICT cache = this->getCache32();
#ifdef USE_DITHER_32BIT_GRADIENT
int toggle = ((x ^ y) & 1) * Gradient_Shader::kDitherStride32;
#else
int toggle = 0;
#endif
if (fDstToIndexClass != kPerspective_MatrixClass) { if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
@ -1703,7 +1718,7 @@ void Radial_Gradient::shadeSpan(int x, int y,
} else { } else {
SkASSERT(proc == repeat_tileproc); SkASSERT(proc == repeat_tileproc);
} }
(*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count); (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle);
} else { // perspective case } else { // perspective case
SkScalar dstX = SkIntToScalar(x); SkScalar dstX = SkIntToScalar(x);
SkScalar dstY = SkIntToScalar(y); SkScalar dstY = SkIntToScalar(y);