restore cache-count for gradients to p.o.2. so we can perform fancier dithering
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 1 Feb 2013 12:59:40 +0000 (12:59 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 1 Feb 2013 12:59:40 +0000 (12:59 +0000)
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

src/effects/gradients/SkGradientShader.cpp
src/effects/gradients/SkGradientShaderPriv.h
src/effects/gradients/SkLinearGradient.cpp
src/effects/gradients/SkRadialGradient.cpp

index 81a6659fbc058ec72a44540644c0abe780dd8df4..de9ae9e48b835f814adce41e82c4043b5cec51da 100644 (file)
@@ -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);
index 954acb2e45ec9637a45d96b5566e7bee25d105b9..d35fb1c5961719d75bb49d4180fd38cb3b919789 100644 (file)
@@ -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
     };
 
 
index 18485713867f123286a0055dc1db65b03f6971a5..b194d50a8446b5ddc9a6e1ed05b997a3e0e350df 100644 (file)
@@ -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,
index 3062105ee3c8f72a4a979f0bec931f992d4ccaf2..6945d5a8ccde3a9c40a26ab9a18f7857c7da720d 100644 (file)
@@ -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],