2 * QEMU VNC display driver: zlib encoding
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
6 * Copyright (C) 2009 Red Hat, Inc
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 #define ZALLOC_ALIGNMENT 16
31 static void *zalloc(void *x
, unsigned items
, unsigned size
)
36 size
= (size
+ ZALLOC_ALIGNMENT
- 1) & ~(ZALLOC_ALIGNMENT
- 1);
38 p
= qemu_mallocz(size
);
43 static void zfree(void *x
, void *addr
)
48 static void vnc_zlib_start(VncState
*vs
)
50 buffer_reset(&vs
->zlib
);
52 // make the output buffer be the zlib buffer, so we can compress it later
53 vs
->zlib_tmp
= vs
->output
;
54 vs
->output
= vs
->zlib
;
57 static int vnc_zlib_stop(VncState
*vs
, int stream_id
)
59 z_streamp zstream
= &vs
->zlib_stream
[stream_id
];
62 // switch back to normal output/zlib buffers
63 vs
->zlib
= vs
->output
;
64 vs
->output
= vs
->zlib_tmp
;
66 // compress the zlib buffer
68 // initialize the stream
69 // XXX need one stream per session
70 if (zstream
->opaque
!= vs
) {
73 VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id
);
74 VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream
->opaque
, vs
);
75 zstream
->zalloc
= zalloc
;
76 zstream
->zfree
= zfree
;
78 err
= deflateInit2(zstream
, vs
->tight_compression
, Z_DEFLATED
, MAX_WBITS
,
79 MAX_MEM_LEVEL
, Z_DEFAULT_STRATEGY
);
82 fprintf(stderr
, "VNC: error initializing zlib\n");
89 // XXX what to do if tight_compression changed in between?
91 // reserve memory in output buffer
92 buffer_reserve(&vs
->output
, vs
->zlib
.offset
+ 64);
95 zstream
->next_in
= vs
->zlib
.buffer
;
96 zstream
->avail_in
= vs
->zlib
.offset
;
97 zstream
->next_out
= vs
->output
.buffer
+ vs
->output
.offset
;
98 zstream
->avail_out
= vs
->output
.capacity
- vs
->output
.offset
;
99 zstream
->data_type
= Z_BINARY
;
100 previous_out
= zstream
->total_out
;
103 if (deflate(zstream
, Z_SYNC_FLUSH
) != Z_OK
) {
104 fprintf(stderr
, "VNC: error during zlib compression\n");
108 vs
->output
.offset
= vs
->output
.capacity
- zstream
->avail_out
;
109 return zstream
->total_out
- previous_out
;
112 void vnc_zlib_send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
114 int old_offset
, new_offset
, bytes_written
;
116 vnc_framebuffer_update(vs
, x
, y
, w
, h
, VNC_ENCODING_ZLIB
);
118 // remember where we put in the follow-up size
119 old_offset
= vs
->output
.offset
;
120 vnc_write_s32(vs
, 0);
122 // compress the stream
124 vnc_raw_send_framebuffer_update(vs
, x
, y
, w
, h
);
125 bytes_written
= vnc_zlib_stop(vs
, 0);
127 if (bytes_written
== -1)
131 new_offset
= vs
->output
.offset
;
132 vs
->output
.offset
= old_offset
;
133 vnc_write_u32(vs
, bytes_written
);
134 vs
->output
.offset
= new_offset
;
137 void vnc_zlib_init(VncState
*vs
)
140 for (i
=0; i
<(sizeof(vs
->zlib_stream
) / sizeof(z_stream
)); i
++)
141 vs
->zlib_stream
[i
].opaque
= NULL
;