|
|
1.1 ! root 1: /* ! 2: * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE) ! 3: * ! 4: * From libvncserver/libvncserver/zrle.c ! 5: * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. ! 6: * Copyright (C) 2003 Sun Microsystems, Inc. ! 7: * ! 8: * Copyright (C) 2010 Corentin Chary <[email protected]> ! 9: * ! 10: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 11: * of this software and associated documentation files (the "Software"), to deal ! 12: * in the Software without restriction, including without limitation the rights ! 13: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 14: * copies of the Software, and to permit persons to whom the Software is ! 15: * furnished to do so, subject to the following conditions: ! 16: * ! 17: * The above copyright notice and this permission notice shall be included in ! 18: * all copies or substantial portions of the Software. ! 19: * ! 20: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 21: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 22: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 23: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 24: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 25: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 26: * THE SOFTWARE. ! 27: */ ! 28: ! 29: #include "vnc.h" ! 30: #include "vnc-enc-zrle.h" ! 31: ! 32: static const int bits_per_packed_pixel[] = { ! 33: 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ! 34: }; ! 35: ! 36: ! 37: static void vnc_zrle_start(VncState *vs) ! 38: { ! 39: buffer_reset(&vs->zrle.zrle); ! 40: ! 41: /* make the output buffer be the zlib buffer, so we can compress it later */ ! 42: vs->zrle.tmp = vs->output; ! 43: vs->output = vs->zrle.zrle; ! 44: } ! 45: ! 46: static void vnc_zrle_stop(VncState *vs) ! 47: { ! 48: /* switch back to normal output/zlib buffers */ ! 49: vs->zrle.zrle = vs->output; ! 50: vs->output = vs->zrle.tmp; ! 51: } ! 52: ! 53: static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, ! 54: int bpp) ! 55: { ! 56: Buffer tmp; ! 57: ! 58: buffer_reset(&vs->zrle.fb); ! 59: buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp); ! 60: ! 61: tmp = vs->output; ! 62: vs->output = vs->zrle.fb; ! 63: ! 64: vnc_raw_send_framebuffer_update(vs, x, y, w, h); ! 65: ! 66: vs->zrle.fb = vs->output; ! 67: vs->output = tmp; ! 68: return vs->zrle.fb.buffer; ! 69: } ! 70: ! 71: static int zrle_compress_data(VncState *vs, int level) ! 72: { ! 73: z_streamp zstream = &vs->zrle.stream; ! 74: ! 75: buffer_reset(&vs->zrle.zlib); ! 76: ! 77: if (zstream->opaque != vs) { ! 78: int err; ! 79: ! 80: zstream->zalloc = vnc_zlib_zalloc; ! 81: zstream->zfree = vnc_zlib_zfree; ! 82: ! 83: err = deflateInit2(zstream, level, Z_DEFLATED, MAX_WBITS, ! 84: MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); ! 85: ! 86: if (err != Z_OK) { ! 87: fprintf(stderr, "VNC: error initializing zlib\n"); ! 88: return -1; ! 89: } ! 90: ! 91: zstream->opaque = vs; ! 92: } ! 93: ! 94: /* reserve memory in output buffer */ ! 95: buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64); ! 96: ! 97: /* set pointers */ ! 98: zstream->next_in = vs->zrle.zrle.buffer; ! 99: zstream->avail_in = vs->zrle.zrle.offset; ! 100: zstream->next_out = vs->zrle.zlib.buffer + vs->zrle.zlib.offset; ! 101: zstream->avail_out = vs->zrle.zlib.capacity - vs->zrle.zlib.offset; ! 102: zstream->data_type = Z_BINARY; ! 103: ! 104: /* start encoding */ ! 105: if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { ! 106: fprintf(stderr, "VNC: error during zrle compression\n"); ! 107: return -1; ! 108: } ! 109: ! 110: vs->zrle.zlib.offset = vs->zrle.zlib.capacity - zstream->avail_out; ! 111: return vs->zrle.zlib.offset; ! 112: } ! 113: ! 114: /* Try to work out whether to use RLE and/or a palette. We do this by ! 115: * estimating the number of bytes which will be generated and picking the ! 116: * method which results in the fewest bytes. Of course this may not result ! 117: * in the fewest bytes after compression... */ ! 118: static void zrle_choose_palette_rle(VncState *vs, int w, int h, ! 119: VncPalette *palette, int bpp_out, ! 120: int runs, int single_pixels, ! 121: int zywrle_level, ! 122: bool *use_rle, bool *use_palette) ! 123: { ! 124: size_t estimated_bytes; ! 125: size_t plain_rle_bytes; ! 126: ! 127: *use_palette = *use_rle = false; ! 128: ! 129: estimated_bytes = w * h * (bpp_out / 8); /* start assuming raw */ ! 130: ! 131: if (bpp_out != 8) { ! 132: if (zywrle_level > 0 && !(zywrle_level & 0x80)) ! 133: estimated_bytes >>= zywrle_level; ! 134: } ! 135: ! 136: plain_rle_bytes = ((bpp_out / 8) + 1) * (runs + single_pixels); ! 137: ! 138: if (plain_rle_bytes < estimated_bytes) { ! 139: *use_rle = true; ! 140: estimated_bytes = plain_rle_bytes; ! 141: } ! 142: ! 143: if (palette_size(palette) < 128) { ! 144: int palette_rle_bytes; ! 145: ! 146: palette_rle_bytes = (bpp_out / 8) * palette_size(palette); ! 147: palette_rle_bytes += 2 * runs + single_pixels; ! 148: ! 149: if (palette_rle_bytes < estimated_bytes) { ! 150: *use_rle = true; ! 151: *use_palette = true; ! 152: estimated_bytes = palette_rle_bytes; ! 153: } ! 154: ! 155: if (palette_size(palette) < 17) { ! 156: int packed_bytes; ! 157: ! 158: packed_bytes = (bpp_out / 8) * palette_size(palette); ! 159: packed_bytes += w * h * ! 160: bits_per_packed_pixel[palette_size(palette)-1] / 8; ! 161: ! 162: if (packed_bytes < estimated_bytes) { ! 163: *use_rle = false; ! 164: *use_palette = true; ! 165: estimated_bytes = packed_bytes; ! 166: } ! 167: } ! 168: } ! 169: } ! 170: ! 171: static void zrle_write_u32(VncState *vs, uint32_t value) ! 172: { ! 173: vnc_write(vs, (uint8_t *)&value, 4); ! 174: } ! 175: ! 176: static void zrle_write_u24a(VncState *vs, uint32_t value) ! 177: { ! 178: vnc_write(vs, (uint8_t *)&value, 3); ! 179: } ! 180: ! 181: static void zrle_write_u24b(VncState *vs, uint32_t value) ! 182: { ! 183: vnc_write(vs, ((uint8_t *)&value) + 1, 3); ! 184: } ! 185: ! 186: static void zrle_write_u16(VncState *vs, uint16_t value) ! 187: { ! 188: vnc_write(vs, (uint8_t *)&value, 2); ! 189: } ! 190: ! 191: static void zrle_write_u8(VncState *vs, uint8_t value) ! 192: { ! 193: vnc_write_u8(vs, value); ! 194: } ! 195: ! 196: #define ENDIAN_LITTLE 0 ! 197: #define ENDIAN_BIG 1 ! 198: #define ENDIAN_NO 2 ! 199: ! 200: #define ZRLE_BPP 8 ! 201: #define ZYWRLE_ENDIAN ENDIAN_NO ! 202: #include "vnc-enc-zrle-template.c" ! 203: #undef ZRLE_BPP ! 204: ! 205: #define ZRLE_BPP 15 ! 206: #undef ZYWRLE_ENDIAN ! 207: #define ZYWRLE_ENDIAN ENDIAN_LITTLE ! 208: #include "vnc-enc-zrle-template.c" ! 209: ! 210: #undef ZYWRLE_ENDIAN ! 211: #define ZYWRLE_ENDIAN ENDIAN_BIG ! 212: #include "vnc-enc-zrle-template.c" ! 213: ! 214: #undef ZRLE_BPP ! 215: #define ZRLE_BPP 16 ! 216: #undef ZYWRLE_ENDIAN ! 217: #define ZYWRLE_ENDIAN ENDIAN_LITTLE ! 218: #include "vnc-enc-zrle-template.c" ! 219: ! 220: #undef ZYWRLE_ENDIAN ! 221: #define ZYWRLE_ENDIAN ENDIAN_BIG ! 222: #include "vnc-enc-zrle-template.c" ! 223: ! 224: #undef ZRLE_BPP ! 225: #define ZRLE_BPP 32 ! 226: #undef ZYWRLE_ENDIAN ! 227: #define ZYWRLE_ENDIAN ENDIAN_LITTLE ! 228: #include "vnc-enc-zrle-template.c" ! 229: ! 230: #undef ZYWRLE_ENDIAN ! 231: #define ZYWRLE_ENDIAN ENDIAN_BIG ! 232: #include "vnc-enc-zrle-template.c" ! 233: ! 234: #define ZRLE_COMPACT_PIXEL 24a ! 235: #undef ZYWRLE_ENDIAN ! 236: #define ZYWRLE_ENDIAN ENDIAN_LITTLE ! 237: #include "vnc-enc-zrle-template.c" ! 238: ! 239: #undef ZYWRLE_ENDIAN ! 240: #define ZYWRLE_ENDIAN ENDIAN_BIG ! 241: #include "vnc-enc-zrle-template.c" ! 242: ! 243: #undef ZRLE_COMPACT_PIXEL ! 244: #define ZRLE_COMPACT_PIXEL 24b ! 245: #undef ZYWRLE_ENDIAN ! 246: #define ZYWRLE_ENDIAN ENDIAN_LITTLE ! 247: #include "vnc-enc-zrle-template.c" ! 248: ! 249: #undef ZYWRLE_ENDIAN ! 250: #define ZYWRLE_ENDIAN ENDIAN_BIG ! 251: #include "vnc-enc-zrle-template.c" ! 252: #undef ZRLE_COMPACT_PIXEL ! 253: #undef ZRLE_BPP ! 254: ! 255: static int zrle_send_framebuffer_update(VncState *vs, int x, int y, ! 256: int w, int h) ! 257: { ! 258: bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG); ! 259: size_t bytes; ! 260: int zywrle_level; ! 261: ! 262: if (vs->zrle.type == VNC_ENCODING_ZYWRLE) { ! 263: if (!vs->vd->lossy || vs->tight.quality == (uint8_t)-1 ! 264: || vs->tight.quality == 9) { ! 265: zywrle_level = 0; ! 266: vs->zrle.type = VNC_ENCODING_ZRLE; ! 267: } else if (vs->tight.quality < 3) { ! 268: zywrle_level = 3; ! 269: } else if (vs->tight.quality < 6) { ! 270: zywrle_level = 2; ! 271: } else { ! 272: zywrle_level = 1; ! 273: } ! 274: } else { ! 275: zywrle_level = 0; ! 276: } ! 277: ! 278: vnc_zrle_start(vs); ! 279: ! 280: switch(vs->clientds.pf.bytes_per_pixel) { ! 281: case 1: ! 282: zrle_encode_8ne(vs, x, y, w, h, zywrle_level); ! 283: break; ! 284: ! 285: case 2: ! 286: if (vs->clientds.pf.gmax > 0x1F) { ! 287: if (be) { ! 288: zrle_encode_16be(vs, x, y, w, h, zywrle_level); ! 289: } else { ! 290: zrle_encode_16le(vs, x, y, w, h, zywrle_level); ! 291: } ! 292: } else { ! 293: if (be) { ! 294: zrle_encode_15be(vs, x, y, w, h, zywrle_level); ! 295: } else { ! 296: zrle_encode_15le(vs, x, y, w, h, zywrle_level); ! 297: } ! 298: } ! 299: break; ! 300: ! 301: case 4: ! 302: { ! 303: bool fits_in_ls3bytes; ! 304: bool fits_in_ms3bytes; ! 305: ! 306: fits_in_ls3bytes = ! 307: ((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) && ! 308: (vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) && ! 309: (vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24)); ! 310: ! 311: fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 && ! 312: vs->clientds.pf.gshift > 7 && ! 313: vs->clientds.pf.bshift > 7); ! 314: ! 315: if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) { ! 316: if (be) { ! 317: zrle_encode_24abe(vs, x, y, w, h, zywrle_level); ! 318: } else { ! 319: zrle_encode_24ale(vs, x, y, w, h, zywrle_level); ! 320: } ! 321: } else if ((fits_in_ls3bytes && be) || (fits_in_ms3bytes && !be)) { ! 322: if (be) { ! 323: zrle_encode_24bbe(vs, x, y, w, h, zywrle_level); ! 324: } else { ! 325: zrle_encode_24ble(vs, x, y, w, h, zywrle_level); ! 326: } ! 327: } else { ! 328: if (be) { ! 329: zrle_encode_32be(vs, x, y, w, h, zywrle_level); ! 330: } else { ! 331: zrle_encode_32le(vs, x, y, w, h, zywrle_level); ! 332: } ! 333: } ! 334: } ! 335: break; ! 336: } ! 337: ! 338: vnc_zrle_stop(vs); ! 339: bytes = zrle_compress_data(vs, Z_DEFAULT_COMPRESSION); ! 340: vnc_framebuffer_update(vs, x, y, w, h, vs->zrle.type); ! 341: vnc_write_u32(vs, bytes); ! 342: vnc_write(vs, vs->zrle.zlib.buffer, vs->zrle.zlib.offset); ! 343: return 1; ! 344: } ! 345: ! 346: int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) ! 347: { ! 348: vs->zrle.type = VNC_ENCODING_ZRLE; ! 349: return zrle_send_framebuffer_update(vs, x, y, w, h); ! 350: } ! 351: ! 352: int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) ! 353: { ! 354: vs->zrle.type = VNC_ENCODING_ZYWRLE; ! 355: return zrle_send_framebuffer_update(vs, x, y, w, h); ! 356: } ! 357: ! 358: void vnc_zrle_clear(VncState *vs) ! 359: { ! 360: if (vs->zrle.stream.opaque) { ! 361: deflateEnd(&vs->zrle.stream); ! 362: } ! 363: buffer_free(&vs->zrle.zrle); ! 364: buffer_free(&vs->zrle.fb); ! 365: buffer_free(&vs->zrle.zlib); ! 366: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.