PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/core/SkPackBits.cpp

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