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-06-02 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