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 : }
|