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
,
81 MAX_MEM_LEVEL
, Z_DEFAULT_STRATEGY
);
84 fprintf(stderr
, "VNC: error initializing zlib\n");
88 vs
->zlib
.level
= vs
->tight
->compression
;
92 if (vs
->tight
->compression
!= vs
->zlib
.level
) {
93 if (deflateParams(zstream
, vs
->tight
->compression
,
94 Z_DEFAULT_STRATEGY
) != Z_OK
) {
97 vs
->zlib
.level
= vs
->tight
->compression
;
100 // reserve memory in output buffer
101 buffer_reserve(&vs
->output
, vs
->zlib
.zlib
.offset
+ 64);
104 zstream
->next_in
= vs
->zlib
.zlib
.buffer
;
105 zstream
->avail_in
= vs
->zlib
.zlib
.offset
;
106 zstream
->next_out
= vs
->output
.buffer
+ vs
->output
.offset
;
107 zstream
->avail_out
= vs
->output
.capacity
- vs
->output
.offset
;
108 previous_out
= zstream
->avail_out
;
109 zstream
->data_type
= Z_BINARY
;
112 if (deflate(zstream
, Z_SYNC_FLUSH
) != Z_OK
) {
113 fprintf(stderr
, "VNC: error during zlib compression\n");
117 vs
->output
.offset
= vs
->output
.capacity
- zstream
->avail_out
;
118 return previous_out
- zstream
->avail_out
;
121 int vnc_zlib_send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
123 int old_offset
, new_offset
, bytes_written
;
125 vnc_framebuffer_update(vs
, x
, y
, w
, h
, VNC_ENCODING_ZLIB
);
127 // remember where we put in the follow-up size
128 old_offset
= vs
->output
.offset
;
129 vnc_write_s32(vs
, 0);
131 // compress the stream
133 vnc_raw_send_framebuffer_update(vs
, x
, y
, w
, h
);
134 bytes_written
= vnc_zlib_stop(vs
);
136 if (bytes_written
== -1)
140 new_offset
= vs
->output
.offset
;
141 vs
->output
.offset
= old_offset
;
142 vnc_write_u32(vs
, bytes_written
);
143 vs
->output
.offset
= new_offset
;
148 void vnc_zlib_clear(VncState
*vs
)
150 if (vs
->zlib
.stream
.opaque
) {
151 deflateEnd(&vs
->zlib
.stream
);
153 buffer_free(&vs
->zlib
.zlib
);