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