PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/skia/sgl/SkPackBits.cpp

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