2
0

vnc-enc-zrle.c.inc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE)
  3. *
  4. * From libvncserver/libvncserver/zrleencodetemplate.c
  5. * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
  6. * Copyright (C) 2003 Sun Microsystems, Inc.
  7. *
  8. * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
  9. *
  10. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  11. * See the COPYING file in the top-level directory.
  12. */
  13. /*
  14. * Before including this file, you must define a number of CPP macros.
  15. *
  16. * ZRLE_BPP should be 8, 16 or 32 depending on the bits per pixel.
  17. *
  18. * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
  19. * bigger than the largest tile of pixel data, since the ZRLE encoding
  20. * algorithm writes to the position one past the end of the pixel data.
  21. */
  22. #include "qemu/osdep.h"
  23. #undef ZRLE_ENDIAN_SUFFIX
  24. #if ZYWRLE_ENDIAN == ENDIAN_LITTLE
  25. #define ZRLE_ENDIAN_SUFFIX le
  26. #elif ZYWRLE_ENDIAN == ENDIAN_BIG
  27. #define ZRLE_ENDIAN_SUFFIX be
  28. #else
  29. #define ZRLE_ENDIAN_SUFFIX ne
  30. #endif
  31. #ifndef ZRLE_CONCAT
  32. #define ZRLE_CONCAT_I(a, b) a##b
  33. #define ZRLE_CONCAT2(a, b) ZRLE_CONCAT_I(a, b)
  34. #define ZRLE_CONCAT3(a, b, c) ZRLE_CONCAT2(a, ZRLE_CONCAT2(b, c))
  35. #endif
  36. #ifdef ZRLE_COMPACT_PIXEL
  37. #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_COMPACT_PIXEL,ZRLE_ENDIAN_SUFFIX)
  38. #define ZRLE_WRITE_SUFFIX ZRLE_COMPACT_PIXEL
  39. #define ZRLE_PIXEL ZRLE_CONCAT3(uint,ZRLE_BPP,_t)
  40. #define ZRLE_BPP_OUT 24
  41. #elif ZRLE_BPP == 15
  42. #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
  43. #define ZRLE_WRITE_SUFFIX 16
  44. #define ZRLE_PIXEL uint16_t
  45. #define ZRLE_BPP_OUT 16
  46. #else
  47. #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
  48. #define ZRLE_WRITE_SUFFIX ZRLE_BPP
  49. #define ZRLE_BPP_OUT ZRLE_BPP
  50. #define ZRLE_PIXEL ZRLE_CONCAT3(uint,ZRLE_BPP,_t)
  51. #endif
  52. #define ZRLE_WRITE_PIXEL ZRLE_CONCAT2(zrle_write_u, ZRLE_WRITE_SUFFIX)
  53. #define ZRLE_ENCODE ZRLE_CONCAT2(zrle_encode_, ZRLE_ENCODE_SUFFIX)
  54. #define ZRLE_ENCODE_TILE ZRLE_CONCAT2(zrle_encode_tile, ZRLE_ENCODE_SUFFIX)
  55. #define ZRLE_WRITE_PALETTE ZRLE_CONCAT2(zrle_write_palette,ZRLE_ENCODE_SUFFIX)
  56. static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h,
  57. int zywrle_level);
  58. #if ZRLE_BPP != 8
  59. #include "vnc-enc-zywrle-template.c"
  60. #endif
  61. static void ZRLE_ENCODE(VncState *vs, int x, int y, int w, int h,
  62. int zywrle_level)
  63. {
  64. int ty;
  65. for (ty = y; ty < y + h; ty += VNC_ZRLE_TILE_HEIGHT) {
  66. int tx, th;
  67. th = MIN(VNC_ZRLE_TILE_HEIGHT, y + h - ty);
  68. for (tx = x; tx < x + w; tx += VNC_ZRLE_TILE_WIDTH) {
  69. int tw;
  70. ZRLE_PIXEL *buf;
  71. tw = MIN(VNC_ZRLE_TILE_WIDTH, x + w - tx);
  72. buf = zrle_convert_fb(vs, tx, ty, tw, th, ZRLE_BPP);
  73. ZRLE_ENCODE_TILE(vs, buf, tw, th, zywrle_level);
  74. }
  75. }
  76. }
  77. static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h,
  78. int zywrle_level)
  79. {
  80. VncPalette *palette = &vs->zrle->palette;
  81. int runs = 0;
  82. int single_pixels = 0;
  83. bool use_rle;
  84. bool use_palette;
  85. int i;
  86. ZRLE_PIXEL *ptr = data;
  87. ZRLE_PIXEL *end = ptr + h * w;
  88. *end = ~*(end-1); /* one past the end is different so the while loop ends */
  89. /* Real limit is 127 but we want a way to know if there is more than 127 */
  90. palette_init(palette, 256, ZRLE_BPP);
  91. while (ptr < end) {
  92. ZRLE_PIXEL pix = *ptr;
  93. if (*++ptr != pix) { /* FIXME */
  94. single_pixels++;
  95. } else {
  96. while (*++ptr == pix) ;
  97. runs++;
  98. }
  99. palette_put(palette, pix);
  100. }
  101. /* Solid tile is a special case */
  102. if (palette_size(palette) == 1) {
  103. bool found;
  104. vnc_write_u8(vs, 1);
  105. ZRLE_WRITE_PIXEL(vs, palette_color(palette, 0, &found));
  106. return;
  107. }
  108. zrle_choose_palette_rle(vs, w, h, palette, ZRLE_BPP_OUT,
  109. runs, single_pixels, zywrle_level,
  110. &use_rle, &use_palette);
  111. if (!use_palette) {
  112. vnc_write_u8(vs, (use_rle ? 128 : 0));
  113. } else {
  114. uint32_t colors[VNC_PALETTE_MAX_SIZE];
  115. size_t size = palette_size(palette);
  116. vnc_write_u8(vs, (use_rle ? 128 : 0) | size);
  117. palette_fill(palette, colors);
  118. for (i = 0; i < size; i++) {
  119. ZRLE_WRITE_PIXEL(vs, colors[i]);
  120. }
  121. }
  122. if (use_rle) {
  123. ZRLE_PIXEL *run_start;
  124. ZRLE_PIXEL pix;
  125. ptr = data;
  126. end = ptr + w * h;
  127. while (ptr < end) {
  128. int len;
  129. int index = 0;
  130. run_start = ptr;
  131. pix = *ptr++;
  132. while (*ptr == pix && ptr < end) {
  133. ptr++;
  134. }
  135. len = ptr - run_start;
  136. if (use_palette)
  137. index = palette_idx(palette, pix);
  138. if (len <= 2 && use_palette) {
  139. if (len == 2) {
  140. vnc_write_u8(vs, index);
  141. }
  142. vnc_write_u8(vs, index);
  143. continue;
  144. }
  145. if (use_palette) {
  146. vnc_write_u8(vs, index | 128);
  147. } else {
  148. ZRLE_WRITE_PIXEL(vs, pix);
  149. }
  150. len -= 1;
  151. while (len >= 255) {
  152. vnc_write_u8(vs, 255);
  153. len -= 255;
  154. }
  155. vnc_write_u8(vs, len);
  156. }
  157. } else if (use_palette) { /* no RLE */
  158. int bppp;
  159. ptr = data;
  160. /* packed pixels */
  161. assert (palette_size(palette) < 17);
  162. bppp = bits_per_packed_pixel[palette_size(palette)-1];
  163. for (i = 0; i < h; i++) {
  164. uint8_t nbits = 0;
  165. uint8_t byte = 0;
  166. ZRLE_PIXEL *eol = ptr + w;
  167. while (ptr < eol) {
  168. ZRLE_PIXEL pix = *ptr++;
  169. uint8_t index = palette_idx(palette, pix);
  170. byte = (byte << bppp) | index;
  171. nbits += bppp;
  172. if (nbits >= 8) {
  173. vnc_write_u8(vs, byte);
  174. nbits = 0;
  175. }
  176. }
  177. if (nbits > 0) {
  178. byte <<= 8 - nbits;
  179. vnc_write_u8(vs, byte);
  180. }
  181. }
  182. } else {
  183. /* raw */
  184. #if ZRLE_BPP != 8
  185. if (zywrle_level > 0 && !(zywrle_level & 0x80)) {
  186. ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, vs->zywrle.buf);
  187. ZRLE_ENCODE_TILE(vs, data, w, h, zywrle_level | 0x80);
  188. }
  189. else
  190. #endif
  191. {
  192. #ifdef ZRLE_COMPACT_PIXEL
  193. for (ptr = data; ptr < data + w * h; ptr++) {
  194. ZRLE_WRITE_PIXEL(vs, *ptr);
  195. }
  196. #else
  197. vnc_write(vs, data, w * h * (ZRLE_BPP / 8));
  198. #endif
  199. }
  200. }
  201. }
  202. #undef ZRLE_PIXEL
  203. #undef ZRLE_WRITE_PIXEL
  204. #undef ZRLE_ENCODE
  205. #undef ZRLE_ENCODE_TILE
  206. #undef ZYWRLE_ENCODE_TILE
  207. #undef ZRLE_BPP_OUT
  208. #undef ZRLE_WRITE_SUFFIX
  209. #undef ZRLE_ENCODE_SUFFIX