From: reed@google.com Date: Fri, 1 Feb 2013 12:59:40 +0000 (+0000) Subject: restore cache-count for gradients to p.o.2. so we can perform fancier dithering X-Git-Tag: submit/tizen/20180928.044319~13585 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3c2102c2d2cdad328a0d87329e1a973f12775836;p=platform%2Fupstream%2FlibSkiaSharp.git restore cache-count for gradients to p.o.2. so we can perform fancier dithering in the future. Review URL: https://codereview.appspot.com/7254043 git-svn-id: http://skia.googlecode.com/svn/trunk@7506 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 81a6659fbc..de9ae9e48b 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -364,14 +364,6 @@ static inline U16CPU bitsTo16(unsigned x, const unsigned bits) { return 0; } -/** We duplicate the last value in each half of the cache so that - interpolation doesn't have to special-case being at the last point. -*/ -static void complete_16bit_cache(uint16_t* cache, int stride) { - cache[stride - 1] = cache[stride - 2]; - cache[2 * stride - 1] = cache[2 * stride - 2]; -} - const uint16_t* SkGradientShaderBase::getCache16() const { if (fCache16 == NULL) { // double the count for dither entries @@ -384,7 +376,7 @@ const uint16_t* SkGradientShaderBase::getCache16() const { fCache16 = fCache16Storage; if (fColorCount == 2) { Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], - kGradient16Length); + kCache16Count); } else { Rec* rec = fRecs; int prevIndex = 0; @@ -396,8 +388,6 @@ const uint16_t* SkGradientShaderBase::getCache16() const { Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1); prevIndex = nextIndex; } - // one extra space left over at the end for complete_16bit_cache() - SkASSERT(prevIndex == kGradient16Length - 1); } if (fMapper) { @@ -405,7 +395,7 @@ const uint16_t* SkGradientShaderBase::getCache16() const { uint16_t* linear = fCache16; // just computed linear data uint16_t* mapped = fCache16Storage; // storage for mapped data SkUnitMapper* map = fMapper; - for (int i = 0; i < kGradient16Length; i++) { + for (int i = 0; i < kCache16Count; i++) { int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift; mapped[i] = linear[index]; mapped[i + kCache16Count] = linear[index + kCache16Count]; @@ -413,19 +403,10 @@ const uint16_t* SkGradientShaderBase::getCache16() const { sk_free(fCache16); fCache16 = fCache16Storage; } - complete_16bit_cache(fCache16, kCache16Count); } return fCache16; } -/** We duplicate the last value in each half of the cache so that - interpolation doesn't have to special-case being at the last point. -*/ -static void complete_32bit_cache(SkPMColor* cache, int stride) { - cache[stride - 1] = cache[stride - 2]; - cache[2 * stride - 1] = cache[2 * stride - 2]; -} - const SkPMColor* SkGradientShaderBase::getCache32() const { if (fCache32 == NULL) { // double the count for dither entries @@ -439,13 +420,13 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); if (fColorCount == 2) { Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], - kGradient32Length, fCacheAlpha); + kCache32Count, fCacheAlpha); } else { Rec* rec = fRecs; int prevIndex = 0; for (int i = 1; i < fColorCount; i++) { int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; - SkASSERT(nextIndex < kGradient32Length); + SkASSERT(nextIndex < kCache32Count); if (nextIndex > prevIndex) Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], @@ -453,7 +434,6 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { nextIndex - prevIndex + 1, fCacheAlpha); prevIndex = nextIndex; } - SkASSERT(prevIndex == kGradient32Length - 1); } if (fMapper) { @@ -462,7 +442,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { SkPMColor* linear = fCache32; // just computed linear data SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data SkUnitMapper* map = fMapper; - for (int i = 0; i < kGradient32Length; i++) { + 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]; @@ -471,7 +451,6 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { fCache32PixelRef = newPR; fCache32 = (SkPMColor*)newPR->getAddr(); } - complete_32bit_cache(fCache32, kCache32Count); } return fCache32; } @@ -493,7 +472,7 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { if (fMapper) { // force our cahce32pixelref to be built (void)this->getCache32(); - bitmap->setConfig(SkBitmap::kARGB_8888_Config, kGradient32Length, 1); + bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1); bitmap->setPixelRef(fCache32PixelRef); return; } @@ -533,9 +512,7 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { if (!gCache->find(storage.get(), size, bitmap)) { // force our cahce32pixelref to be built (void)this->getCache32(); - // Only expose the linear section of the cache; don't let the caller - // know about the padding at the end to make interpolation faster. - bitmap->setConfig(SkBitmap::kARGB_8888_Config, kGradient32Length, 1); + bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1); bitmap->setPixelRef(fCache32PixelRef); gCache->add(storage.get(), size, *bitmap); diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index 954acb2e45..d35fb1c596 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -101,26 +101,14 @@ public: /// Seems like enough for visual accuracy. TODO: if pos[] deserves /// it, use a larger cache. kCache16Bits = 8, - kGradient16Length = (1 << kCache16Bits), - /// Each cache gets 1 extra entry at the end so we don't have to - /// test for end-of-cache in lerps. This is also the value used - /// to stride *writes* into the dither cache; it must not be zero. - /// Total space for a cache is 2x kCache16Count entries: one - /// regular cache, one for dithering. - kCache16Count = kGradient16Length + 1, + kCache16Count = (1 << kCache16Bits), kCache16Shift = 16 - kCache16Bits, kSqrt16Shift = 8 - kCache16Bits, /// Seems like enough for visual accuracy. TODO: if pos[] deserves /// it, use a larger cache. kCache32Bits = 8, - kGradient32Length = (1 << kCache32Bits), - /// Each cache gets 1 extra entry at the end so we don't have to - /// test for end-of-cache in lerps. This is also the value used - /// to stride *writes* into the dither cache; it must not be zero. - /// Total space for a cache is 2x kCache32Count entries: one - /// regular cache, one for dithering. - kCache32Count = kGradient32Length + 1, + kCache32Count = (1 << kCache32Bits), kCache32Shift = 16 - kCache32Bits, kSqrt32Shift = 8 - kCache32Bits, @@ -132,7 +120,6 @@ public: kDitherStride32 = 0, #endif kDitherStride16 = kCache16Count, - kLerpRemainderMask32 = (1 << (16 - kCache32Bits)) - 1 }; diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index 1848571386..b194d50a84 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -131,16 +131,18 @@ void shadeSpan_linear_vertical_lerp(TileProc proc, SkFixed dx, SkFixed fx, // If colors change sharply across the gradient, dithering is // insufficient (it subsamples the color space) and we need to lerp. unsigned fullIndex = proc(fx); - unsigned fi = fullIndex >> (16 - SkGradientShaderBase::kCache32Bits); - unsigned remainder = fullIndex & SkGradientShaderBase::kLerpRemainderMask32; - SkPMColor lerp = - SkFastFourByteInterp( - cache[toggle + fi + 1], - cache[toggle + fi], remainder); - SkPMColor dlerp = - SkFastFourByteInterp( - cache[(toggle ^ SkGradientShaderBase::kDitherStride32) + fi + 1], - cache[(toggle ^ SkGradientShaderBase::kDitherStride32) + fi], remainder); + unsigned fi = fullIndex >> SkGradientShaderBase::kCache32Shift; + unsigned remainder = fullIndex & ((1 << SkGradientShaderBase::kCache32Shift) - 1); + + int index0 = fi + toggle; + int index1 = index0; + if (fi < SkGradientShaderBase::kCache32Count - 1) { + index1 += 1; + } + SkPMColor lerp = SkFastFourByteInterp(cache[index1], cache[index0], remainder); + index0 ^= SkGradientShaderBase::kDitherStride32; + index1 ^= SkGradientShaderBase::kDitherStride32; + SkPMColor dlerp = SkFastFourByteInterp(cache[index1], cache[index0], remainder); sk_memset32_dither(dstC, lerp, dlerp, count); } @@ -149,7 +151,7 @@ void shadeSpan_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx, const SkPMColor* SK_RESTRICT cache, int toggle, int count) { SkClampRange range; - range.init(fx, dx, count, 0, SkGradientShaderBase::kGradient32Length); + range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1); if ((count = range.fCount0) > 0) { sk_memset32_dither(dstC, @@ -334,7 +336,7 @@ void shadeSpan16_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx, const uint16_t* SK_RESTRICT cache, int toggle, int count) { SkClampRange range; - range.init(fx, dx, count, 0, SkGradientShaderBase::kGradient16Length); + range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1); if ((count = range.fCount0) > 0) { dither_memset16(dstC, diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index 3062105ee3..6945d5a8cc 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -227,8 +227,8 @@ SkShader::BitmapType SkRadialGradient::asABitmap(SkBitmap* bitmap, this->getGradientTableBitmap(bitmap); } if (matrix) { - matrix->setScale(SkIntToScalar(kGradient32Length), - SkIntToScalar(kGradient32Length)); + matrix->setScale(SkIntToScalar(kCache32Count), + SkIntToScalar(kCache32Count)); matrix->preConcat(fPtsToUnit); } if (xy) { @@ -318,7 +318,7 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx, SkFixed fy = SkScalarToFixed(sfy) >> 1; SkFixed dy = SkScalarToFixed(sdy) >> 1; if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) { - unsigned fi = SkGradientShaderBase::kGradient32Length; + unsigned fi = SkGradientShaderBase::kCache32Count - 1; sk_memset32_dither(dstC, cache[toggle + fi], cache[(toggle ^ SkGradientShaderBase::kDitherStride32) + fi],