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
27 #include "qemu/osdep.h"
30 #define ZALLOC_ALIGNMENT 16
32 void *vnc_zlib_zalloc(void *x
, unsigned items
, unsigned size
)
37 size
= (size
+ ZALLOC_ALIGNMENT
- 1) & ~(ZALLOC_ALIGNMENT
- 1);
44 void vnc_zlib_zfree(void *x
, void *addr
)
49 static void vnc_zlib_start(VncState
*vs
)
51 buffer_reset(&vs
->zlib
.zlib
);
53 // make the output buffer be the zlib buffer, so we can compress it later
54 vs
->zlib
.tmp
= vs
->output
;
55 vs
->output
= vs
->zlib
.zlib
;
58 static int vnc_zlib_stop(VncState
*vs
)
60 z_streamp zstream
= &vs
->zlib
.stream
;
63 // switch back to normal output/zlib buffers
64 vs
->zlib
.zlib
= vs
->output
;
65 vs
->output
= vs
->zlib
.tmp
;
67 // compress the zlib buffer
69 // initialize the stream
70 // XXX need one stream per session
71 if (zstream
->opaque
!= vs
) {
74 VNC_DEBUG("VNC: initializing zlib stream\n");
75 VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream
->opaque
, vs
);
76 zstream
->zalloc
= vnc_zlib_zalloc
;
77 zstream
->zfree
= vnc_zlib_zfree
;
79 err
= deflateInit2(zstream
, vs
->tight
.compression
, Z_DEFLATED
, MAX_WBITS
,
80 MAX_MEM_LEVEL
, Z_DEFAULT_STRATEGY
);
83 fprintf(stderr
, "VNC: error initializing zlib\n");
87 vs
->zlib
.level
= vs
->tight
.compression
;
91 if (vs
->tight
.compression
!= vs
->zlib
.level
) {
92 if (deflateParams(zstream
, vs
->tight
.compression
,
93 Z_DEFAULT_STRATEGY
) != Z_OK
) {
96 vs
->zlib
.level
= vs
->tight
.compression
;
99 // reserve memory in output buffer
100 buffer_reserve(&vs
->output
, vs
->zlib
.zlib
.offset
+ 64);
103 zstream
->next_in
= vs
->zlib
.zlib
.buffer
;
104 zstream
->avail_in
= vs
->zlib
.zlib
.offset
;
105 zstream
->next_out
= vs
->output
.buffer
+ vs
->output
.offset
;
106 zstream
->avail_out
= vs
->output
.capacity
- vs
->output
.offset
;
107 previous_out
= zstream
->avail_out
;
108 zstream
->data_type
= Z_BINARY
;
111 if (deflate(zstream
, Z_SYNC_FLUSH
) != Z_OK
) {
112 fprintf(stderr
, "VNC: error during zlib compression\n");
116 vs
->output
.offset
= vs
->output
.capacity
- zstream
->avail_out
;
117 return previous_out
- zstream
->avail_out
;
120 int vnc_zlib_send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
122 int old_offset
, new_offset
, bytes_written
;
124 vnc_framebuffer_update(vs
, x
, y
, w
, h
, VNC_ENCODING_ZLIB
);
126 // remember where we put in the follow-up size
127 old_offset
= vs
->output
.offset
;
128 vnc_write_s32(vs
, 0);
130 // compress the stream
132 vnc_raw_send_framebuffer_update(vs
, x
, y
, w
, h
);
133 bytes_written
= vnc_zlib_stop(vs
);
135 if (bytes_written
== -1)
139 new_offset
= vs
->output
.offset
;
140 vs
->output
.offset
= old_offset
;
141 vnc_write_u32(vs
, bytes_written
);
142 vs
->output
.offset
= new_offset
;
147 void vnc_zlib_clear(VncState
*vs
)
149 if (vs
->zlib
.stream
.opaque
) {
150 deflateEnd(&vs
->zlib
.stream
);
152 buffer_free(&vs
->zlib
.zlib
);