LCOV - app.info - gfx/skia/src/core/SkPackBits.cpp

LCOV - code coverage report
| Current view: | directory - gfx/skia/src/core - SkPackBits.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 222 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 13 | 0 | 0.0 %

           1                 :
           2                 : /*
           3                 :  * Copyright 2011 Google Inc.
           4                 :  *
           5                 :  * Use of this source code is governed by a BSD-style license that can be
           6                 :  * found in the LICENSE file.
           7                 :  */
           8                 : #include "SkPackBits.h"
           9                 :
          10                 : #define GATHER_STATSx
          11                 :
          12               0 : static inline void small_memcpy(void* SK_RESTRICT dst,
          13                 :                                 const void* SK_RESTRICT src, int n) {
          14               0 :     SkASSERT(n > 0 && n <= 15);
          15               0 :     uint8_t* d = (uint8_t*)dst;
          16               0 :     const uint8_t* s = (const uint8_t*)src;
          17               0 :     switch (n) {
          18               0 :         case 15: *d++ = *s++;
          19               0 :         case 14: *d++ = *s++;
          20               0 :         case 13: *d++ = *s++;
          21               0 :         case 12: *d++ = *s++;
          22               0 :         case 11: *d++ = *s++;
          23               0 :         case 10: *d++ = *s++;
          24               0 :         case  9: *d++ = *s++;
          25               0 :         case  8: *d++ = *s++;
          26               0 :         case  7: *d++ = *s++;
          27               0 :         case  6: *d++ = *s++;
          28               0 :         case  5: *d++ = *s++;
          29               0 :         case  4: *d++ = *s++;
          30               0 :         case  3: *d++ = *s++;
          31               0 :         case  2: *d++ = *s++;
          32               0 :         case  1: *d++ = *s++;
          33               0 :         case  0: break;
          34                 :     }
          35               0 : }
          36                 :
          37               0 : static inline void small_memset(void* dst, uint8_t value, int n) {
          38               0 :     SkASSERT(n > 0 && n <= 15);
          39               0 :     uint8_t* d = (uint8_t*)dst;
          40               0 :     switch (n) {
          41               0 :         case 15: *d++ = value;
          42               0 :         case 14: *d++ = value;
          43               0 :         case 13: *d++ = value;
          44               0 :         case 12: *d++ = value;
          45               0 :         case 11: *d++ = value;
          46               0 :         case 10: *d++ = value;
          47               0 :         case  9: *d++ = value;
          48               0 :         case  8: *d++ = value;
          49               0 :         case  7: *d++ = value;
          50               0 :         case  6: *d++ = value;
          51               0 :         case  5: *d++ = value;
          52               0 :         case  4: *d++ = value;
          53               0 :         case  3: *d++ = value;
          54               0 :         case  2: *d++ = value;
          55               0 :         case  1: *d++ = value;
          56               0 :         case  0: break;
          57                 :     }
          58               0 : }
          59                 :
          60                 : // can we do better for small counts with our own inlined memcpy/memset?
          61                 :
          62                 : #define PB_MEMSET(addr, value, count)       \
          63                 : do {                                        \
          64                 : if ((count) > 15) {                     \
          65                 : memset(addr, value, count);         \
          66                 : } else {                                \
          67                 : small_memset(addr, value, count);   \
          68                 : }                                       \
          69                 : } while (0)
          70                 :
          71                 : #define PB_MEMCPY(dst, src, count)      \
          72                 : do {                                    \
          73                 :     if ((count) > 15) {                 \
          74                 :         memcpy(dst, src, count);        \
          75                 :     } else {                            \
          76                 :         small_memcpy(dst, src, count);  \
          77                 :     }                                   \
          78                 : } while (0)
          79                 :
          80                 : ///////////////////////////////////////////////////////////////////////////////
          81                 :
          82                 : #ifdef GATHER_STATS
          83                 :     static int gMemSetBuckets[129];
          84                 :     static int gMemCpyBuckets[129];
          85                 :     static int gCounter;
          86                 :
          87                 : static void register_memset_count(int n) {
          88                 :     SkASSERT((unsigned)n <= 128);
          89                 :     gMemSetBuckets[n] += 1;
          90                 :     gCounter += 1;
          91                 :
          92                 :     if ((gCounter & 0xFF) == 0) {
          93                 :         SkDebugf("----- packbits memset stats: ");
          94                 :         for (size_t i = 0; i < SK_ARRAY_COUNT(gMemSetBuckets); i++) {
          95                 :             if (gMemSetBuckets[i]) {
          96                 :                 SkDebugf(" %d:%d", i, gMemSetBuckets[i]);
          97                 :             }
          98                 :         }
          99                 :     }
         100                 : }
         101                 : static void register_memcpy_count(int n) {
         102                 :     SkASSERT((unsigned)n <= 128);
         103                 :     gMemCpyBuckets[n] += 1;
         104                 :     gCounter += 1;
         105                 :
         106                 :     if ((gCounter & 0x1FF) == 0) {
         107                 :         SkDebugf("----- packbits memcpy stats: ");
         108                 :         for (size_t i = 0; i < SK_ARRAY_COUNT(gMemCpyBuckets); i++) {
         109                 :             if (gMemCpyBuckets[i]) {
         110                 :                 SkDebugf(" %d:%d", i, gMemCpyBuckets[i]);
         111                 :             }
         112                 :         }
         113                 :     }
         114                 : }
         115                 : #else
         116                 : #define register_memset_count(n)
         117                 : #define register_memcpy_count(n)
         118                 : #endif
         119                 :
         120                 :
         121                 : ///////////////////////////////////////////////////////////////////////////////
         122                 :
         123               0 : size_t SkPackBits::ComputeMaxSize16(int count) {
         124                 :     // worst case is the number of 16bit values (times 2) +
         125                 :     // 1 byte per (up to) 128 entries.
         126               0 :     return ((count + 127) >> 7) + (count << 1);
         127                 : }
         128                 :
         129               0 : size_t SkPackBits::ComputeMaxSize8(int count) {
         130                 :     // worst case is the number of 8bit values + 1 byte per (up to) 128 entries.
         131               0 :     return ((count + 127) >> 7) + count;
         132                 : }
         133                 :
         134               0 : static uint8_t* flush_same16(uint8_t dst[], uint16_t value, int count) {
         135               0 :     while (count > 0) {
         136               0 :         int n = count;
         137               0 :         if (n > 128) {
         138               0 :             n = 128;
         139                 :         }
         140               0 :         *dst++ = (uint8_t)(n - 1);
         141               0 :         *dst++ = (uint8_t)(value >> 8);
         142               0 :         *dst++ = (uint8_t)value;
         143               0 :         count -= n;
         144                 :     }
         145               0 :     return dst;
         146                 : }
         147                 :
         148               0 : static uint8_t* flush_same8(uint8_t dst[], uint8_t value, int count) {
         149               0 :     while (count > 0) {
         150               0 :         int n = count;
         151               0 :         if (n > 128) {
         152               0 :             n = 128;
         153                 :         }
         154               0 :         *dst++ = (uint8_t)(n - 1);
         155               0 :         *dst++ = (uint8_t)value;
         156               0 :         count -= n;
         157                 :     }
         158               0 :     return dst;
         159                 : }
         160                 :
         161               0 : static uint8_t* flush_diff16(uint8_t* SK_RESTRICT dst,
         162                 :                              const uint16_t* SK_RESTRICT src, int count) {
         163               0 :     while (count > 0) {
         164               0 :         int n = count;
         165               0 :         if (n > 128) {
         166               0 :             n = 128;
         167                 :         }
         168               0 :         *dst++ = (uint8_t)(n + 127);
         169               0 :         PB_MEMCPY(dst, src, n * sizeof(uint16_t));
         170               0 :         src += n;
         171               0 :         dst += n * sizeof(uint16_t);
         172               0 :         count -= n;
         173                 :     }
         174               0 :     return dst;
         175                 : }
         176                 :
         177               0 : static uint8_t* flush_diff8(uint8_t* SK_RESTRICT dst,
         178                 :                             const uint8_t* SK_RESTRICT src, int count) {
         179               0 :     while (count > 0) {
         180               0 :         int n = count;
         181               0 :         if (n > 128) {
         182               0 :             n = 128;
         183                 :         }
         184               0 :         *dst++ = (uint8_t)(n + 127);
         185               0 :         PB_MEMCPY(dst, src, n);
         186               0 :         src += n;
         187               0 :         dst += n;
         188               0 :         count -= n;
         189                 :     }
         190               0 :     return dst;
         191                 : }
         192                 :
         193               0 : size_t SkPackBits::Pack16(const uint16_t* SK_RESTRICT src, int count,
         194                 :                           uint8_t* SK_RESTRICT dst) {
         195               0 :     uint8_t* origDst = dst;
         196               0 :     const uint16_t* stop = src + count;
         197                 :
         198               0 :     for (;;) {
         199               0 :         count = stop - src;
         200               0 :         SkASSERT(count >= 0);
         201               0 :         if (count == 0) {
         202               0 :             return dst - origDst;
         203                 :         }
         204               0 :         if (1 == count) {
         205               0 :             *dst++ = 0;
         206               0 :             *dst++ = (uint8_t)(*src >> 8);
         207               0 :             *dst++ = (uint8_t)*src;
         208               0 :             return dst - origDst;
         209                 :         }
         210                 :
         211               0 :         unsigned value = *src;
         212               0 :         const uint16_t* s = src + 1;
         213                 :
         214               0 :         if (*s == value) { // accumulate same values...
         215               0 :             do {
         216               0 :                 s++;
         217               0 :                 if (s == stop) {
         218               0 :                     break;
         219                 :                 }
         220                 :             } while (*s == value);
         221               0 :             dst = flush_same16(dst, value, s - src);
         222                 :         } else {    // accumulate diff values...
         223               0 :             do {
         224               0 :                 if (++s == stop) {
         225               0 :                     goto FLUSH_DIFF;
         226                 :                 }
         227               0 :             } while (*s != s[-1]);
         228               0 :             s -= 1; // back up so we don't grab one of the "same" values that follow
         229                 :         FLUSH_DIFF:
         230               0 :             dst = flush_diff16(dst, src, s - src);
         231                 :         }
         232               0 :         src = s;
         233                 :     }
         234                 : }
         235                 :
         236               0 : size_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, int count,
         237                 :                          uint8_t* SK_RESTRICT dst) {
         238               0 :     uint8_t* origDst = dst;
         239               0 :     const uint8_t* stop = src + count;
         240                 :
         241               0 :     for (;;) {
         242               0 :         count = stop - src;
         243               0 :         SkASSERT(count >= 0);
         244               0 :         if (count == 0) {
         245               0 :             return dst - origDst;
         246                 :         }
         247               0 :         if (1 == count) {
         248               0 :             *dst++ = 0;
         249               0 :             *dst++ = *src;
         250               0 :             return dst - origDst;
         251                 :         }
         252                 :
         253               0 :         unsigned value = *src;
         254               0 :         const uint8_t* s = src + 1;
         255                 :
         256               0 :         if (*s == value) { // accumulate same values...
         257               0 :             do {
         258               0 :                 s++;
         259               0 :                 if (s == stop) {
         260               0 :                     break;
         261                 :                 }
         262                 :             } while (*s == value);
         263               0 :             dst = flush_same8(dst, value, s - src);
         264                 :         } else {    // accumulate diff values...
         265               0 :             do {
         266               0 :                 if (++s == stop) {
         267               0 :                     goto FLUSH_DIFF;
         268                 :                 }
         269                 :                 // only stop if we hit 3 in a row,
         270                 :                 // otherwise we get bigger than compuatemax
         271               0 :             } while (*s != s[-1] || s[-1] != s[-2]);
         272               0 :             s -= 2; // back up so we don't grab the "same" values that follow
         273                 :         FLUSH_DIFF:
         274               0 :             dst = flush_diff8(dst, src, s - src);
         275                 :         }
         276               0 :         src = s;
         277                 :     }
         278                 : }
         279                 :
         280                 : #include "SkUtils.h"
         281                 :
         282               0 : int SkPackBits::Unpack16(const uint8_t* SK_RESTRICT src, size_t srcSize,
         283                 :                          uint16_t* SK_RESTRICT dst) {
         284               0 :     uint16_t* origDst = dst;
         285               0 :     const uint8_t* stop = src + srcSize;
         286                 :
         287               0 :     while (src < stop) {
         288               0 :         unsigned n = *src++;
         289               0 :         if (n <= 127) {   // repeat count (n + 1)
         290               0 :             n += 1;
         291               0 :             sk_memset16(dst, (src[0] << 8) | src[1], n);
         292               0 :             src += 2;
         293                 :         } else {    // same count (n - 127)
         294               0 :             n -= 127;
         295               0 :             PB_MEMCPY(dst, src, n * sizeof(uint16_t));
         296               0 :             src += n * sizeof(uint16_t);
         297                 :         }
         298               0 :         dst += n;
         299                 :     }
         300               0 :     SkASSERT(src == stop);
         301               0 :     return dst - origDst;
         302                 : }
         303                 :
         304               0 : int SkPackBits::Unpack8(const uint8_t* SK_RESTRICT src, size_t srcSize,
         305                 :                         uint8_t* SK_RESTRICT dst) {
         306               0 :     uint8_t* origDst = dst;
         307               0 :     const uint8_t* stop = src + srcSize;
         308                 :
         309               0 :     while (src < stop) {
         310               0 :         unsigned n = *src++;
         311               0 :         if (n <= 127) {   // repeat count (n + 1)
         312               0 :             n += 1;
         313               0 :             PB_MEMSET(dst, *src++, n);
         314                 :         } else {    // same count (n - 127)
         315               0 :             n -= 127;
         316               0 :             PB_MEMCPY(dst, src, n);
         317               0 :             src += n;
         318                 :         }
         319               0 :         dst += n;
         320                 :     }
         321               0 :     SkASSERT(src == stop);
         322               0 :     return dst - origDst;
         323                 : }
         324                 :
         325                 : enum UnpackState {
         326                 :     CLEAN_STATE,
         327                 :     REPEAT_BYTE_STATE,
         328                 :     COPY_SRC_STATE
         329                 : };
         330                 :
         331               0 : void SkPackBits::Unpack8(uint8_t* SK_RESTRICT dst, size_t dstSkip,
         332                 :                          size_t dstWrite, const uint8_t* SK_RESTRICT src) {
         333               0 :     if (dstWrite == 0) {
         334               0 :         return;
         335                 :     }
         336                 :
         337               0 :     UnpackState state = CLEAN_STATE;
         338               0 :     size_t      stateCount = 0;
         339                 :
         340                 :     // state 1: do the skip-loop
         341               0 :     while (dstSkip > 0) {
         342               0 :         unsigned n = *src++;
         343               0 :         if (n <= 127) {   // repeat count (n + 1)
         344               0 :             n += 1;
         345               0 :             if (n > dstSkip) {
         346               0 :                 state = REPEAT_BYTE_STATE;
         347               0 :                 stateCount = n - dstSkip;
         348               0 :                 n = dstSkip;
         349                 :                 // we don't increment src here, since its needed in stage 2
         350                 :             } else {
         351               0 :                 src++;  // skip the src byte
         352                 :             }
         353                 :         } else {    // same count (n - 127)
         354               0 :             n -= 127;
         355               0 :             if (n > dstSkip) {
         356               0 :                 state = COPY_SRC_STATE;
         357               0 :                 stateCount = n - dstSkip;
         358               0 :                 n = dstSkip;
         359                 :             }
         360               0 :             src += n;
         361                 :         }
         362               0 :         dstSkip -= n;
         363                 :     }
         364                 :
         365                 :     // stage 2: perform any catchup from the skip-stage
         366               0 :     if (stateCount > dstWrite) {
         367               0 :         stateCount = dstWrite;
         368                 :     }
         369               0 :     switch (state) {
         370                 :         case REPEAT_BYTE_STATE:
         371               0 :             SkASSERT(stateCount > 0);
         372                 :             register_memset_count(stateCount);
         373               0 :             PB_MEMSET(dst, *src++, stateCount);
         374               0 :             break;
         375                 :         case COPY_SRC_STATE:
         376               0 :             SkASSERT(stateCount > 0);
         377                 :             register_memcpy_count(stateCount);
         378               0 :             PB_MEMCPY(dst, src, stateCount);
         379               0 :             src += stateCount;
         380               0 :             break;
         381                 :         default:
         382               0 :             SkASSERT(stateCount == 0);
         383               0 :             break;
         384                 :     }
         385               0 :     dst += stateCount;
         386               0 :     dstWrite -= stateCount;
         387                 :
         388                 :     // copy at most dstWrite bytes into dst[]
         389               0 :     while (dstWrite > 0) {
         390               0 :         unsigned n = *src++;
         391               0 :         if (n <= 127) {   // repeat count (n + 1)
         392               0 :             n += 1;
         393               0 :             if (n > dstWrite) {
         394               0 :                 n = dstWrite;
         395                 :             }
         396                 :             register_memset_count(n);
         397               0 :             PB_MEMSET(dst, *src++, n);
         398                 :         } else {    // same count (n - 127)
         399               0 :             n -= 127;
         400               0 :             if (n > dstWrite) {
         401               0 :                 n = dstWrite;
         402                 :             }
         403                 :             register_memcpy_count(n);
         404               0 :             PB_MEMCPY(dst, src, n);
         405               0 :             src += n;
         406                 :         }
         407               0 :         dst += n;
         408               0 :         dstWrite -= n;
         409                 :     }
         410               0 :     SkASSERT(0 == dstWrite);
         411                 : }

Generated by: LCOV version 1.7