180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPackBits.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GATHER_STATSx 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void small_memcpy(void* SK_RESTRICT dst, 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* SK_RESTRICT src, int n) { 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(n > 0 && n <= 15); 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* d = (uint8_t*)dst; 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* s = (const uint8_t*)src; 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (n) { 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 15: *d++ = *s++; 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 14: *d++ = *s++; 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 13: *d++ = *s++; 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 12: *d++ = *s++; 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 11: *d++ = *s++; 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 10: *d++ = *s++; 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 9: *d++ = *s++; 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 8: *d++ = *s++; 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 7: *d++ = *s++; 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 6: *d++ = *s++; 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 5: *d++ = *s++; 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 4: *d++ = *s++; 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 3: *d++ = *s++; 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 2: *d++ = *s++; 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 1: *d++ = *s++; 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 0: break; 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void small_memset(void* dst, uint8_t value, int n) { 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(n > 0 && n <= 15); 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* d = (uint8_t*)dst; 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (n) { 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 15: *d++ = value; 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 14: *d++ = value; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 13: *d++ = value; 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 12: *d++ = value; 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 11: *d++ = value; 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 10: *d++ = value; 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 9: *d++ = value; 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 8: *d++ = value; 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 7: *d++ = value; 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 6: *d++ = value; 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 5: *d++ = value; 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 4: *d++ = value; 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 3: *d++ = value; 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 2: *d++ = value; 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 1: *d++ = value; 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 0: break; 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// can we do better for small counts with our own inlined memcpy/memset? 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define PB_MEMSET(addr, value, count) \ 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudo { \ 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruif ((count) > 15) { \ 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querumemset(addr, value, count); \ 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} else { \ 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusmall_memset(addr, value, count); \ 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} \ 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} while (0) 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define PB_MEMCPY(dst, src, count) \ 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudo { \ 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if ((count) > 15) { \ 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memcpy(dst, src, count); \ 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { \ 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru small_memcpy(dst, src, count); \ 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } \ 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} while (0) 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef GATHER_STATS 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static int gMemSetBuckets[129]; 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static int gMemCpyBuckets[129]; 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static int gCounter; 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void register_memset_count(int n) { 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)n <= 128); 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gMemSetBuckets[n] += 1; 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gCounter += 1; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if ((gCounter & 0xFF) == 0) { 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("----- packbits memset stats: "); 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (size_t i = 0; i < SK_ARRAY_COUNT(gMemSetBuckets); i++) { 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (gMemSetBuckets[i]) { 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf(" %d:%d", i, gMemSetBuckets[i]); 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void register_memcpy_count(int n) { 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)n <= 128); 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gMemCpyBuckets[n] += 1; 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gCounter += 1; 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if ((gCounter & 0x1FF) == 0) { 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("----- packbits memcpy stats: "); 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (size_t i = 0; i < SK_ARRAY_COUNT(gMemCpyBuckets); i++) { 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (gMemCpyBuckets[i]) { 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf(" %d:%d", i, gMemCpyBuckets[i]); 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define register_memset_count(n) 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define register_memcpy_count(n) 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPackBits::ComputeMaxSize16(int count) { 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // worst case is the number of 16bit values (times 2) + 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // 1 byte per (up to) 128 entries. 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return ((count + 127) >> 7) + (count << 1); 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPackBits::ComputeMaxSize8(int count) { 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // worst case is the number of 8bit values + 1 byte per (up to) 128 entries. 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return ((count + 127) >> 7) + count; 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint8_t* flush_same16(uint8_t dst[], uint16_t value, int count) { 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (count > 0) { 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int n = count; 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > 128) { 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = 128; 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)(n - 1); 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)(value >> 8); 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)value; 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count -= n; 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst; 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint8_t* flush_same8(uint8_t dst[], uint8_t value, int count) { 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (count > 0) { 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int n = count; 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > 128) { 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = 128; 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)(n - 1); 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)value; 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count -= n; 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst; 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint8_t* flush_diff16(uint8_t* SK_RESTRICT dst, 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* SK_RESTRICT src, int count) { 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (count > 0) { 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int n = count; 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > 128) { 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = 128; 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)(n + 127); 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMCPY(dst, src, n * sizeof(uint16_t)); 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += n; 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += n * sizeof(uint16_t); 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count -= n; 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst; 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint8_t* flush_diff8(uint8_t* SK_RESTRICT dst, 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* SK_RESTRICT src, int count) { 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (count > 0) { 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int n = count; 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > 128) { 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = 128; 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)(n + 127); 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMCPY(dst, src, n); 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += n; 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += n; 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count -= n; 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst; 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPackBits::Pack16(const uint16_t* SK_RESTRICT src, int count, 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* SK_RESTRICT dst) { 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* origDst = dst; 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* stop = src + count; 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (;;) { 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count = stop - src; 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count >= 0); 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (count == 0) { 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst - origDst; 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (1 == count) { 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = 0; 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)(*src >> 8); 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (uint8_t)*src; 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst - origDst; 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned value = *src; 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* s = src + 1; 21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (*s == value) { // accumulate same values... 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru s++; 21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (s == stop) { 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (*s == value); 22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst = flush_same16(dst, value, s - src); 22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // accumulate diff values... 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (++s == stop) { 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru goto FLUSH_DIFF; 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (*s != s[-1]); 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru s -= 1; // back up so we don't grab one of the "same" values that follow 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru FLUSH_DIFF: 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst = flush_diff16(dst, src, s - src); 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src = s; 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, int count, 23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* SK_RESTRICT dst) { 23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* origDst = dst; 23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* stop = src + count; 24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (;;) { 24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count = stop - src; 24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count >= 0); 24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (count == 0) { 24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst - origDst; 24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (1 == count) { 24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = 0; 24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = *src; 25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst - origDst; 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned value = *src; 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* s = src + 1; 25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (*s == value) { // accumulate same values... 25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru s++; 25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (s == stop) { 26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (*s == value); 26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst = flush_same8(dst, value, s - src); 26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // accumulate diff values... 26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (++s == stop) { 26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru goto FLUSH_DIFF; 26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // only stop if we hit 3 in a row, 27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // otherwise we get bigger than compuatemax 27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (*s != s[-1] || s[-1] != s[-2]); 27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru s -= 2; // back up so we don't grab the "same" values that follow 27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru FLUSH_DIFF: 27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst = flush_diff8(dst, src, s - src); 27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src = s; 27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h" 28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkPackBits::Unpack16(const uint8_t* SK_RESTRICT src, size_t srcSize, 28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t* SK_RESTRICT dst) { 28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t* origDst = dst; 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* stop = src + srcSize; 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (src < stop) { 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned n = *src++; 28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n <= 127) { // repeat count (n + 1) 29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n += 1; 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sk_memset16(dst, (src[0] << 8) | src[1], n); 29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += 2; 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // same count (n - 127) 29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n -= 127; 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMCPY(dst, src, n * sizeof(uint16_t)); 29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += n * sizeof(uint16_t); 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += n; 29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(src == stop); 30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst - origDst; 30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkPackBits::Unpack8(const uint8_t* SK_RESTRICT src, size_t srcSize, 30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* SK_RESTRICT dst) { 30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* origDst = dst; 30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* stop = src + srcSize; 30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (src < stop) { 31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned n = *src++; 31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n <= 127) { // repeat count (n + 1) 31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n += 1; 31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMSET(dst, *src++, n); 31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // same count (n - 127) 31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n -= 127; 31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMCPY(dst, src, n); 31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += n; 31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += n; 32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(src == stop); 32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst - origDst; 32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruenum UnpackState { 32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CLEAN_STATE, 32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru REPEAT_BYTE_STATE, 32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru COPY_SRC_STATE 32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPackBits::Unpack8(uint8_t* SK_RESTRICT dst, size_t dstSkip, 33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t dstWrite, const uint8_t* SK_RESTRICT src) { 33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (dstWrite == 0) { 33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru UnpackState state = CLEAN_STATE; 33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t stateCount = 0; 33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // state 1: do the skip-loop 34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (dstSkip > 0) { 34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned n = *src++; 34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n <= 127) { // repeat count (n + 1) 34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n += 1; 34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > dstSkip) { 34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru state = REPEAT_BYTE_STATE; 34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru stateCount = n - dstSkip; 34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = dstSkip; 34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we don't increment src here, since its needed in stage 2 35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src++; // skip the src byte 35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // same count (n - 127) 35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n -= 127; 35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > dstSkip) { 35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru state = COPY_SRC_STATE; 35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru stateCount = n - dstSkip; 35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = dstSkip; 35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += n; 36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dstSkip -= n; 36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // stage 2: perform any catchup from the skip-stage 36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (stateCount > dstWrite) { 36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru stateCount = dstWrite; 36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (state) { 37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case REPEAT_BYTE_STATE: 37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(stateCount > 0); 37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru register_memset_count(stateCount); 37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMSET(dst, *src++, stateCount); 37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case COPY_SRC_STATE: 37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(stateCount > 0); 37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru register_memcpy_count(stateCount); 37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMCPY(dst, src, stateCount); 37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += stateCount; 38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru default: 38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(stateCount == 0); 38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += stateCount; 38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dstWrite -= stateCount; 38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // copy at most dstWrite bytes into dst[] 38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (dstWrite > 0) { 39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned n = *src++; 39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n <= 127) { // repeat count (n + 1) 39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n += 1; 39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > dstWrite) { 39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = dstWrite; 39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru register_memset_count(n); 39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMSET(dst, *src++, n); 39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // same count (n - 127) 39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n -= 127; 40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n > dstWrite) { 40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = dstWrite; 40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru register_memcpy_count(n); 40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PB_MEMCPY(dst, src, n); 40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += n; 40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += n; 40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dstWrite -= n; 40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == dstWrite); 41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 412