diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-02-04 18:21:23 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-02-04 18:21:23 +0000 |
commit | 60040292be58ac553298209fb2e0684a4cb17dcc (patch) | |
tree | 6cfc2e2a1ccde64fd438978f49b036ae11ac1aa7 /src/effects | |
parent | 73349aa33277889d79e3e8bd8cef89cdf0310288 (diff) |
Go from a 1x2 to a 2x2 dither cell, and change/simplify the logic for how we
compute the "dithered" version of a color to just a graduated fixed-point-round.
Also, add this new dither to conical and sweep, which before had no dithering.
Disabled for now using SK_IGNORE_GRADIENT_DITHER_FIX. Will enable this and
and rebaseline skia.
http://code.google.com/p/skia/issues/detail?id=1098
Review URL: https://codereview.appspot.com/7248046
git-svn-id: http://skia.googlecode.com/svn/trunk@7549 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 43 | ||||
-rw-r--r-- | src/effects/gradients/SkGradientShaderPriv.h | 11 | ||||
-rw-r--r-- | src/effects/gradients/SkLinearGradient.cpp | 5 | ||||
-rw-r--r-- | src/effects/gradients/SkRadialGradient.cpp | 3 | ||||
-rw-r--r-- | src/effects/gradients/SkSweepGradient.cpp | 15 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointConicalGradient.cpp | 46 |
6 files changed, 103 insertions, 20 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index de9ae9e48b..aa03ecb208 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -327,18 +326,54 @@ void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo 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 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; @@ -410,7 +445,7 @@ const uint16_t* SkGradientShaderBase::getCache16() const { const SkPMColor* SkGradientShaderBase::getCache32() const { if (fCache32 == NULL) { // double the count for dither entries - const int entryCount = kCache32Count * 2; + const int entryCount = kCache32Count * 4; const size_t allocSize = sizeof(SkPMColor) * entryCount; if (NULL == fCache32PixelRef) { @@ -446,6 +481,10 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { 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*2] = linear[index + kCache32Count*2]; + mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; +#endif } fCache32PixelRef->unref(); fCache32PixelRef = newPR; diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index 4d14dc6a07..82535de5d3 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * @@ -20,6 +19,8 @@ #include "SkBitmapCache.h" #include "SkShader.h" +#define SK_IGNORE_GRADIENT_DITHER_FIX + #ifndef SK_DISABLE_DITHER_32BIT_GRADIENT #define USE_DITHER_32BIT_GRADIENT #endif @@ -108,7 +109,7 @@ public: /// Seems like enough for visual accuracy. TODO: if pos[] deserves /// it, use a larger cache. kCache32Bits = 8, - kCache32Count = (1 << kCache32Bits), + kCache32Count = (1 << kCache32Bits), kCache32Shift = 16 - kCache32Bits, kSqrt32Shift = 8 - kCache32Bits, @@ -176,7 +177,13 @@ 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) { diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index 03393f726a..059cc93493 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -94,7 +94,11 @@ bool SkLinearGradient::setContext(const SkBitmap& device, const SkPaint& paint, unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; if ((fDstToIndex.getType() & ~mask) == 0) { +#ifdef SK_IGNORE_GRADIENT_DITHER_FIX fFlags |= SkShader::kConstInY32_Flag; +#else + // when we dither, we are (usually) not const-in-Y +#endif if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) { // only claim this if we do have a 16bit mode (i.e. none of our // colors have alpha), and if we are not dithering (which obviously @@ -328,7 +332,6 @@ void shadeSpan16_linear_vertical(TileProc proc, SkFixed dx, SkFixed fx, SkASSERT(fi < SkGradientShaderBase::kCache16Count); dither_memset16(dstC, cache[toggle + fi], cache[next_dither_toggle16(toggle) + fi], count); - } void shadeSpan16_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx, diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index 328fe76e51..fdca340f3a 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -335,8 +335,7 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx, if (count) { UNPINNED_RADIAL_STEP; } - } - else { + } else { // Specializing for dy == 0 gains us 25% on Skia benchmarks if (dy == 0) { unsigned yy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index db18521066..458ddbc590 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -298,6 +298,11 @@ void SkSweepGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, SkMatrix::MapXYProc proc = fDstToIndexProc; const SkMatrix& matrix = fDstToIndex; const SkPMColor* SK_RESTRICT cache = this->getCache32(); +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + int toggle = init_dither_toggle(x, y); +#else + int toggle = 0; +#endif SkPoint srcPt; if (fDstToIndexClass != kPerspective_MatrixClass) { @@ -319,15 +324,21 @@ void SkSweepGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, } for (; count > 0; --count) { - *dstC++ = cache[SkATan2_255(fy, fx)]; + *dstC++ = cache[toggle + SkATan2_255(fy, fx)]; fx += dx; fy += dy; +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + toggle = next_dither_toggle(toggle); +#endif } } else { // perspective case for (int stop = x + count; x < stop; x++) { proc(matrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &srcPt); - *dstC++ = cache[SkATan2_255(srcPt.fY, srcPt.fX)]; + *dstC++ = cache[toggle + SkATan2_255(srcPt.fY, srcPt.fX)]; +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + toggle = next_dither_toggle(toggle); +#endif } } } diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp index e23953005b..f1acd551cc 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp @@ -113,11 +113,12 @@ SkFixed TwoPtRadial::nextT() { return SkFloatToFixed(t); } -typedef void (*TwoPointRadialProc)(TwoPtRadial* rec, SkPMColor* dstC, - const SkPMColor* cache, int count); +typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC, + const SkPMColor* cache, int toggle, int count); static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, - const SkPMColor* SK_RESTRICT cache, int count) { + const SkPMColor* SK_RESTRICT cache, int toggle, + int count) { for (; count > 0; --count) { SkFixed t = rec->nextT(); if (TwoPtRadial::DontDrawT(t)) { @@ -125,13 +126,18 @@ static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, } else { SkFixed index = SkClampMax(t, 0xFFFF); SkASSERT(index <= 0xFFFF); - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; + *dstC++ = cache[toggle + + (index >> SkGradientShaderBase::kCache32Shift)]; } +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + toggle = next_dither_toggle(toggle); +#endif } } static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, - const SkPMColor* SK_RESTRICT cache, int count) { + const SkPMColor* SK_RESTRICT cache, int toggle, + int count) { for (; count > 0; --count) { SkFixed t = rec->nextT(); if (TwoPtRadial::DontDrawT(t)) { @@ -139,13 +145,18 @@ static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, } else { SkFixed index = repeat_tileproc(t); SkASSERT(index <= 0xFFFF); - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; + *dstC++ = cache[toggle + + (index >> SkGradientShaderBase::kCache32Shift)]; } +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + toggle = next_dither_toggle(toggle); +#endif } } static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, - const SkPMColor* SK_RESTRICT cache, int count) { + const SkPMColor* SK_RESTRICT cache, int toggle, + int count) { for (; count > 0; --count) { SkFixed t = rec->nextT(); if (TwoPtRadial::DontDrawT(t)) { @@ -153,8 +164,12 @@ static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, } else { SkFixed index = mirror_tileproc(t); SkASSERT(index <= 0xFFFF); - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; + *dstC++ = cache[toggle + + (index >> SkGradientShaderBase::kCache32Shift)]; } +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + toggle = next_dither_toggle(toggle); +#endif } } @@ -183,6 +198,12 @@ SkTwoPointConicalGradient::SkTwoPointConicalGradient( void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, int count) { +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + int toggle = init_dither_toggle(x, y); +#else + int toggle = 0; +#endif + SkASSERT(count > 0); SkPMColor* SK_RESTRICT dstC = dstCParam; @@ -191,7 +212,7 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, const SkPMColor* SK_RESTRICT cache = this->getCache32(); - TwoPointRadialProc shadeProc = twopoint_repeat; + TwoPointConicalProc shadeProc = twopoint_repeat; if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = twopoint_clamp; } else if (SkShader::kMirror_TileMode == fTileMode) { @@ -219,7 +240,7 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, } fRec.setup(fx, fy, dx, dy); - (*shadeProc)(&fRec, dstC, cache, count); + (*shadeProc)(&fRec, dstC, cache, toggle, count); } else { // perspective case SkScalar dstX = SkIntToScalar(x); SkScalar dstY = SkIntToScalar(y); @@ -229,7 +250,10 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, dstX += SK_Scalar1; fRec.setup(srcPt.fX, srcPt.fY, 0, 0); - (*shadeProc)(&fRec, dstC, cache, 1); + (*shadeProc)(&fRec, dstC, cache, toggle, 1); +#ifndef SK_IGNORE_GRADIENT_DITHER_FIX + toggle = next_dither_toggle(toggle); +#endif } } } |