2 * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE)
4 * From libvncserver/libvncserver/zrleencodetemplate.c
5 * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
6 * Copyright (C) 2003 Sun Microsystems, Inc.
8 * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
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.
15 * Before including this file, you must define a number of CPP macros.
17 * ZRLE_BPP should be 8, 16 or 32 depending on the bits per pixel.
19 * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
20 * bigger than the largest tile of pixel data, since the ZRLE encoding
21 * algorithm writes to the position one past the end of the pixel data.
25 #include "qemu/osdep.h"
27 #undef ZRLE_ENDIAN_SUFFIX
29 #if ZYWRLE_ENDIAN == ENDIAN_LITTLE
30 #define ZRLE_ENDIAN_SUFFIX le
31 #elif ZYWRLE_ENDIAN == ENDIAN_BIG
32 #define ZRLE_ENDIAN_SUFFIX be
34 #define ZRLE_ENDIAN_SUFFIX ne
38 #define ZRLE_CONCAT_I(a, b) a##b
39 #define ZRLE_CONCAT2(a, b) ZRLE_CONCAT_I(a, b)
40 #define ZRLE_CONCAT3(a, b, c) ZRLE_CONCAT2(a, ZRLE_CONCAT2(b, c))
43 #ifdef ZRLE_COMPACT_PIXEL
44 #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_COMPACT_PIXEL,ZRLE_ENDIAN_SUFFIX)
45 #define ZRLE_WRITE_SUFFIX ZRLE_COMPACT_PIXEL
46 #define ZRLE_PIXEL ZRLE_CONCAT3(uint,ZRLE_BPP,_t)
47 #define ZRLE_BPP_OUT 24
49 #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
50 #define ZRLE_WRITE_SUFFIX 16
51 #define ZRLE_PIXEL uint16_t
52 #define ZRLE_BPP_OUT 16
54 #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
55 #define ZRLE_WRITE_SUFFIX ZRLE_BPP
56 #define ZRLE_BPP_OUT ZRLE_BPP
57 #define ZRLE_PIXEL ZRLE_CONCAT3(uint,ZRLE_BPP,_t)
60 #define ZRLE_WRITE_PIXEL ZRLE_CONCAT2(zrle_write_u, ZRLE_WRITE_SUFFIX)
61 #define ZRLE_ENCODE ZRLE_CONCAT2(zrle_encode_, ZRLE_ENCODE_SUFFIX)
62 #define ZRLE_ENCODE_TILE ZRLE_CONCAT2(zrle_encode_tile, ZRLE_ENCODE_SUFFIX)
63 #define ZRLE_WRITE_PALETTE ZRLE_CONCAT2(zrle_write_palette,ZRLE_ENCODE_SUFFIX)
65 static void ZRLE_ENCODE_TILE(VncState
*vs
, ZRLE_PIXEL
*data
, int w
, int h
,
69 #include "vnc-enc-zywrle-template.c"
73 static void ZRLE_ENCODE(VncState
*vs
, int x
, int y
, int w
, int h
,
78 for (ty
= y
; ty
< y
+ h
; ty
+= VNC_ZRLE_TILE_HEIGHT
) {
82 th
= MIN(VNC_ZRLE_TILE_HEIGHT
, y
+ h
- ty
);
84 for (tx
= x
; tx
< x
+ w
; tx
+= VNC_ZRLE_TILE_WIDTH
) {
88 tw
= MIN(VNC_ZRLE_TILE_WIDTH
, x
+ w
- tx
);
90 buf
= zrle_convert_fb(vs
, tx
, ty
, tw
, th
, ZRLE_BPP
);
91 ZRLE_ENCODE_TILE(vs
, buf
, tw
, th
, zywrle_level
);
96 static void ZRLE_ENCODE_TILE(VncState
*vs
, ZRLE_PIXEL
*data
, int w
, int h
,
99 VncPalette
*palette
= &vs
->zrle
->palette
;
102 int single_pixels
= 0;
109 ZRLE_PIXEL
*ptr
= data
;
110 ZRLE_PIXEL
*end
= ptr
+ h
* w
;
111 *end
= ~*(end
-1); /* one past the end is different so the while loop ends */
113 /* Real limit is 127 but we wan't a way to know if there is more than 127 */
114 palette_init(palette
, 256, ZRLE_BPP
);
117 ZRLE_PIXEL pix
= *ptr
;
118 if (*++ptr
!= pix
) { /* FIXME */
121 while (*++ptr
== pix
) ;
124 palette_put(palette
, pix
);
127 /* Solid tile is a special case */
129 if (palette_size(palette
) == 1) {
133 ZRLE_WRITE_PIXEL(vs
, palette_color(palette
, 0, &found
));
137 zrle_choose_palette_rle(vs
, w
, h
, palette
, ZRLE_BPP_OUT
,
138 runs
, single_pixels
, zywrle_level
,
139 &use_rle
, &use_palette
);
142 vnc_write_u8(vs
, (use_rle
? 128 : 0));
144 uint32_t colors
[VNC_PALETTE_MAX_SIZE
];
145 size_t size
= palette_size(palette
);
147 vnc_write_u8(vs
, (use_rle
? 128 : 0) | size
);
148 palette_fill(palette
, colors
);
150 for (i
= 0; i
< size
; i
++) {
151 ZRLE_WRITE_PIXEL(vs
, colors
[i
]);
156 ZRLE_PIXEL
*ptr
= data
;
157 ZRLE_PIXEL
*end
= ptr
+ w
* h
;
158 ZRLE_PIXEL
*run_start
;
168 while (*ptr
== pix
&& ptr
< end
) {
172 len
= ptr
- run_start
;
175 index
= palette_idx(palette
, pix
);
177 if (len
<= 2 && use_palette
) {
179 vnc_write_u8(vs
, index
);
181 vnc_write_u8(vs
, index
);
185 vnc_write_u8(vs
, index
| 128);
187 ZRLE_WRITE_PIXEL(vs
, pix
);
193 vnc_write_u8(vs
, 255);
197 vnc_write_u8(vs
, len
);
199 } else if (use_palette
) { /* no RLE */
201 ZRLE_PIXEL
*ptr
= data
;
205 assert (palette_size(palette
) < 17);
207 bppp
= bits_per_packed_pixel
[palette_size(palette
)-1];
209 for (i
= 0; i
< h
; i
++) {
213 ZRLE_PIXEL
*eol
= ptr
+ w
;
216 ZRLE_PIXEL pix
= *ptr
++;
217 uint8_t index
= palette_idx(palette
, pix
);
219 byte
= (byte
<< bppp
) | index
;
222 vnc_write_u8(vs
, byte
);
228 vnc_write_u8(vs
, byte
);
236 if (zywrle_level
> 0 && !(zywrle_level
& 0x80)) {
237 ZYWRLE_ANALYZE(data
, data
, w
, h
, w
, zywrle_level
, vs
->zywrle
.buf
);
238 ZRLE_ENCODE_TILE(vs
, data
, w
, h
, zywrle_level
| 0x80);
243 #ifdef ZRLE_COMPACT_PIXEL
246 for (ptr
= data
; ptr
< data
+ w
* h
; ptr
++) {
247 ZRLE_WRITE_PIXEL(vs
, *ptr
);
250 vnc_write(vs
, data
, w
* h
* (ZRLE_BPP
/ 8));
257 #undef ZRLE_WRITE_PIXEL
259 #undef ZRLE_ENCODE_TILE
260 #undef ZYWRLE_ENCODE_TILE
262 #undef ZRLE_WRITE_SUFFIX
263 #undef ZRLE_ENCODE_SUFFIX