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 void *vnc_zlib_zalloc(void *x
, unsigned items
, unsigned size
)
36 size
= (size
+ ZALLOC_ALIGNMENT
- 1) & ~(ZALLOC_ALIGNMENT
- 1);
43 void vnc_zlib_zfree(void *x
, void *addr
)
48 static void vnc_zlib_start(VncState
*vs
)
50 buffer_reset(&vs
->zlib
.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
.zlib
;
57 static int vnc_zlib_stop(VncState
*vs
)
59 z_streamp zstream
= &vs
->zlib
.stream
;
62 // switch back to normal output/zlib buffers
63 vs
->zlib
.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\n");
74 VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream
->opaque
, vs
);
75 zstream
->zalloc
= vnc_zlib_zalloc
;
76 zstream
->zfree
= vnc_zlib_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");
86 vs
->zlib
.level
= vs
->tight
.compression
;
90 if (vs
->tight
.compression
!= vs
->zlib
.level
) {
91 if (deflateParams(zstream
, vs
->tight
.compression
,
92 Z_DEFAULT_STRATEGY
) != Z_OK
) {
95 vs
->zlib
.level
= vs
->tight
.compression
;
98 // reserve memory in output buffer
99 buffer_reserve(&vs
->output
, vs
->zlib
.zlib
.offset
+ 64);
102 zstream
->next_in
= vs
->zlib
.zlib
.buffer
;
103 zstream
->avail_in
= vs
->zlib
.zlib
.offset
;
104 zstream
->next_out
= vs
->output
.buffer
+ vs
->output
.offset
;
105 zstream
->avail_out
= vs
->output
.capacity
- vs
->output
.offset
;
106 previous_out
= zstream
->avail_out
;
107 zstream
->data_type
= Z_BINARY
;
110 if (deflate(zstream
, Z_SYNC_FLUSH
) != Z_OK
) {
111 fprintf(stderr
, "VNC: error during zlib compression\n");
115 vs
->output
.offset
= vs
->output
.capacity
- zstream
->avail_out
;
116 return previous_out
- zstream
->avail_out
;
119 int vnc_zlib_send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
121 int old_offset
, new_offset
, bytes_written
;
123 vnc_framebuffer_update(vs
, x
, y
, w
, h
, VNC_ENCODING_ZLIB
);
125 // remember where we put in the follow-up size
126 old_offset
= vs
->output
.offset
;
127 vnc_write_s32(vs
, 0);
129 // compress the stream
131 vnc_raw_send_framebuffer_update(vs
, x
, y
, w
, h
);
132 bytes_written
= vnc_zlib_stop(vs
);
134 if (bytes_written
== -1)
138 new_offset
= vs
->output
.offset
;
139 vs
->output
.offset
= old_offset
;
140 vnc_write_u32(vs
, bytes_written
);
141 vs
->output
.offset
= new_offset
;
146 void vnc_zlib_clear(VncState
*vs
)
148 if (vs
->zlib
.stream
.opaque
) {
149 deflateEnd(&vs
->zlib
.stream
);
151 buffer_free(&vs
->zlib
.zlib
);