|
|
1.1 ! root 1: /* ! 2: * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE) ! 3: * ! 4: * From libvncserver/libvncserver/zrleencodetemplate.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: * This work is licensed under the terms of the GNU GPL, version 2 or later. ! 11: * See the COPYING file in the top-level directory. ! 12: */ ! 13: ! 14: /* ! 15: * Before including this file, you must define a number of CPP macros. ! 16: * ! 17: * ZRLE_BPP should be 8, 16 or 32 depending on the bits per pixel. ! 18: * ! 19: * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel ! 20: * bigger than the largest tile of pixel data, since the ZRLE encoding ! 21: * algorithm writes to the position one past the end of the pixel data. ! 22: */ ! 23: ! 24: ! 25: #include <assert.h> ! 26: ! 27: #undef ZRLE_ENDIAN_SUFFIX ! 28: ! 29: #if ZYWRLE_ENDIAN == ENDIAN_LITTLE ! 30: #define ZRLE_ENDIAN_SUFFIX le ! 31: #elif ZYWRLE_ENDIAN == ENDIAN_BIG ! 32: #define ZRLE_ENDIAN_SUFFIX be ! 33: #else ! 34: #define ZRLE_ENDIAN_SUFFIX ne ! 35: #endif ! 36: ! 37: #ifndef ZRLE_CONCAT ! 38: #define ZRLE_CONCAT_I(a, b) a##b ! 39: #define ZRLE_CONCAT2(a, b) ZRLE_CONCAT_I(a, b) ! 40: #define ZRLE_CONCAT3(a, b, c) ZRLE_CONCAT2(a, ZRLE_CONCAT2(b, c)) ! 41: #endif ! 42: ! 43: #ifdef ZRLE_COMPACT_PIXEL ! 44: #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_COMPACT_PIXEL,ZRLE_ENDIAN_SUFFIX) ! 45: #define ZRLE_WRITE_SUFFIX ZRLE_COMPACT_PIXEL ! 46: #define ZRLE_PIXEL ZRLE_CONCAT3(uint,ZRLE_BPP,_t) ! 47: #define ZRLE_BPP_OUT 24 ! 48: #elif ZRLE_BPP == 15 ! 49: #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX) ! 50: #define ZRLE_WRITE_SUFFIX 16 ! 51: #define ZRLE_PIXEL uint16_t ! 52: #define ZRLE_BPP_OUT 16 ! 53: #else ! 54: #define ZRLE_ENCODE_SUFFIX ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX) ! 55: #define ZRLE_WRITE_SUFFIX ZRLE_BPP ! 56: #define ZRLE_BPP_OUT ZRLE_BPP ! 57: #define ZRLE_PIXEL ZRLE_CONCAT3(uint,ZRLE_BPP,_t) ! 58: #endif ! 59: ! 60: #define ZRLE_WRITE_PIXEL ZRLE_CONCAT2(zrle_write_u, ZRLE_WRITE_SUFFIX) ! 61: #define ZRLE_ENCODE ZRLE_CONCAT2(zrle_encode_, ZRLE_ENCODE_SUFFIX) ! 62: #define ZRLE_ENCODE_TILE ZRLE_CONCAT2(zrle_encode_tile, ZRLE_ENCODE_SUFFIX) ! 63: #define ZRLE_WRITE_PALETTE ZRLE_CONCAT2(zrle_write_palette,ZRLE_ENCODE_SUFFIX) ! 64: ! 65: static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, ! 66: int zywrle_level); ! 67: ! 68: #if ZRLE_BPP != 8 ! 69: #include "vnc-enc-zywrle-template.c" ! 70: #endif ! 71: ! 72: ! 73: static void ZRLE_ENCODE(VncState *vs, int x, int y, int w, int h, ! 74: int zywrle_level) ! 75: { ! 76: int ty; ! 77: ! 78: for (ty = y; ty < y + h; ty += VNC_ZRLE_TILE_HEIGHT) { ! 79: ! 80: int tx, th; ! 81: ! 82: th = MIN(VNC_ZRLE_TILE_HEIGHT, y + h - ty); ! 83: ! 84: for (tx = x; tx < x + w; tx += VNC_ZRLE_TILE_WIDTH) { ! 85: int tw; ! 86: ZRLE_PIXEL *buf; ! 87: ! 88: tw = MIN(VNC_ZRLE_TILE_WIDTH, x + w - tx); ! 89: ! 90: buf = zrle_convert_fb(vs, tx, ty, tw, th, ZRLE_BPP); ! 91: ZRLE_ENCODE_TILE(vs, buf, tw, th, zywrle_level); ! 92: } ! 93: } ! 94: } ! 95: ! 96: static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, ! 97: int zywrle_level) ! 98: { ! 99: VncPalette *palette = &vs->zrle.palette; ! 100: ! 101: int runs = 0; ! 102: int single_pixels = 0; ! 103: ! 104: bool use_rle; ! 105: bool use_palette; ! 106: ! 107: int i; ! 108: ! 109: ZRLE_PIXEL *ptr = data; ! 110: ZRLE_PIXEL *end = ptr + h * w; ! 111: *end = ~*(end-1); /* one past the end is different so the while loop ends */ ! 112: ! 113: /* Real limit is 127 but we wan't a way to know if there is more than 127 */ ! 114: palette_init(palette, 256, ZRLE_BPP); ! 115: ! 116: while (ptr < end) { ! 117: ZRLE_PIXEL pix = *ptr; ! 118: if (*++ptr != pix) { /* FIXME */ ! 119: single_pixels++; ! 120: } else { ! 121: while (*++ptr == pix) ; ! 122: runs++; ! 123: } ! 124: palette_put(palette, pix); ! 125: } ! 126: ! 127: /* Solid tile is a special case */ ! 128: ! 129: if (palette_size(palette) == 1) { ! 130: bool found; ! 131: ! 132: vnc_write_u8(vs, 1); ! 133: ZRLE_WRITE_PIXEL(vs, palette_color(palette, 0, &found)); ! 134: return; ! 135: } ! 136: ! 137: zrle_choose_palette_rle(vs, w, h, palette, ZRLE_BPP_OUT, ! 138: runs, single_pixels, zywrle_level, ! 139: &use_rle, &use_palette); ! 140: ! 141: if (!use_palette) { ! 142: vnc_write_u8(vs, (use_rle ? 128 : 0)); ! 143: } else { ! 144: uint32_t colors[VNC_PALETTE_MAX_SIZE]; ! 145: size_t size = palette_size(palette); ! 146: ! 147: vnc_write_u8(vs, (use_rle ? 128 : 0) | size); ! 148: palette_fill(palette, colors); ! 149: ! 150: for (i = 0; i < size; i++) { ! 151: ZRLE_WRITE_PIXEL(vs, colors[i]); ! 152: } ! 153: } ! 154: ! 155: if (use_rle) { ! 156: ZRLE_PIXEL *ptr = data; ! 157: ZRLE_PIXEL *end = ptr + w * h; ! 158: ZRLE_PIXEL *run_start; ! 159: ZRLE_PIXEL pix; ! 160: ! 161: while (ptr < end) { ! 162: int len; ! 163: int index = 0; ! 164: ! 165: run_start = ptr; ! 166: pix = *ptr++; ! 167: ! 168: while (*ptr == pix && ptr < end) { ! 169: ptr++; ! 170: } ! 171: ! 172: len = ptr - run_start; ! 173: ! 174: if (use_palette) ! 175: index = palette_idx(palette, pix); ! 176: ! 177: if (len <= 2 && use_palette) { ! 178: if (len == 2) { ! 179: vnc_write_u8(vs, index); ! 180: } ! 181: vnc_write_u8(vs, index); ! 182: continue; ! 183: } ! 184: if (use_palette) { ! 185: vnc_write_u8(vs, index | 128); ! 186: } else { ! 187: ZRLE_WRITE_PIXEL(vs, pix); ! 188: } ! 189: ! 190: len -= 1; ! 191: ! 192: while (len >= 255) { ! 193: vnc_write_u8(vs, 255); ! 194: len -= 255; ! 195: } ! 196: ! 197: vnc_write_u8(vs, len); ! 198: } ! 199: } else if (use_palette) { /* no RLE */ ! 200: int bppp; ! 201: ZRLE_PIXEL *ptr = data; ! 202: ! 203: /* packed pixels */ ! 204: ! 205: assert (palette_size(palette) < 17); ! 206: ! 207: bppp = bits_per_packed_pixel[palette_size(palette)-1]; ! 208: ! 209: for (i = 0; i < h; i++) { ! 210: uint8_t nbits = 0; ! 211: uint8_t byte = 0; ! 212: ! 213: ZRLE_PIXEL *eol = ptr + w; ! 214: ! 215: while (ptr < eol) { ! 216: ZRLE_PIXEL pix = *ptr++; ! 217: uint8_t index = palette_idx(palette, pix); ! 218: ! 219: byte = (byte << bppp) | index; ! 220: nbits += bppp; ! 221: if (nbits >= 8) { ! 222: vnc_write_u8(vs, byte); ! 223: nbits = 0; ! 224: } ! 225: } ! 226: if (nbits > 0) { ! 227: byte <<= 8 - nbits; ! 228: vnc_write_u8(vs, byte); ! 229: } ! 230: } ! 231: } else { ! 232: ! 233: /* raw */ ! 234: ! 235: #if ZRLE_BPP != 8 ! 236: if (zywrle_level > 0 && !(zywrle_level & 0x80)) { ! 237: ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, vs->zywrle.buf); ! 238: ZRLE_ENCODE_TILE(vs, data, w, h, zywrle_level | 0x80); ! 239: } ! 240: else ! 241: #endif ! 242: { ! 243: #ifdef ZRLE_COMPACT_PIXEL ! 244: ZRLE_PIXEL *ptr; ! 245: ! 246: for (ptr = data; ptr < data + w * h; ptr++) { ! 247: ZRLE_WRITE_PIXEL(vs, *ptr); ! 248: } ! 249: #else ! 250: vnc_write(vs, data, w * h * (ZRLE_BPP / 8)); ! 251: #endif ! 252: } ! 253: } ! 254: } ! 255: ! 256: #undef ZRLE_PIXEL ! 257: #undef ZRLE_WRITE_PIXEL ! 258: #undef ZRLE_ENCODE ! 259: #undef ZRLE_ENCODE_TILE ! 260: #undef ZYWRLE_ENCODE_TILE ! 261: #undef ZRLE_BPP_OUT ! 262: #undef ZRLE_WRITE_SUFFIX ! 263: #undef ZRLE_ENCODE_SUFFIX
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.