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