ia64/xen-unstable

changeset 17036:7b0c0ab0566b

ioemu: Dynamic VNC colour depth.

The qemu vnc server changes its internal colour depth based on the
client request. This way just one colour conversion is done: the one
in vga_template.h, from the guest colour depth and the vnc server
internal colour depth.

This patch is meant to remove this colour conversion to improve
performances. It accomplishes the goal making the qemu internal colour
depth always the same as the guest colour depth.
The basic idea is that the vnc client is the one that should do the
colour conversion, if necessary. In general it should accept the pixel
format suggested by the server during the initial negotiation. This
behaviour can be set in most vnc clients (vncviewer included).

If the guest changes colour depth, the qemu vnc server changes colour
depth too and notifies the client. The problem is that the vnc
protocol doesn't provide a message from the server to the client to
ask for a colour depth change. So what I am doing is either:

1) quietly starting to do the conversion on vnc server (not gaining
any performance here);

2) closing the vnc connection with the client, so the client can
reconnect and choose the new pixel format.

By default I am doing 1), however the second choice can be enabled
passing the -vnc-switch-bpp command line option.
In order to do the colour conversion on the vnc server I had to
improve the colour conversion code already in place because it only
supported conversions from 32 bpp. The patch adds colour conversion
code that support conversions from any resolution to any resolution.

A last note: to get most out of this patch it is best to set Windows
to 16 bit colour depth, because the 24 bit mode is 24 bit depth and 24
bpp, meaning no alpha channel. The vnc protocol doesn't support 24
bpp, only 32 bpp, so this conversion is unavoidable.

From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 11 14:55:33 2008 +0000 (2008-02-11)
parents 7fd49c55c0b0
children 2a3111016f88
files tools/ioemu/console.c tools/ioemu/hw/vga.c tools/ioemu/sdl.c tools/ioemu/vl.c tools/ioemu/vl.h tools/ioemu/vnc.c tools/ioemu/vnchextile.h
line diff
     1.1 --- a/tools/ioemu/console.c	Mon Feb 11 14:51:22 2008 +0000
     1.2 +++ b/tools/ioemu/console.c	Mon Feb 11 14:55:33 2008 +0000
     1.3 @@ -169,16 +169,12 @@ static unsigned int vga_get_color(Displa
     1.4      unsigned int r, g, b, color;
     1.5  
     1.6      switch(ds->depth) {
     1.7 -#if 0
     1.8      case 8:
     1.9          r = (rgba >> 16) & 0xff;
    1.10          g = (rgba >> 8) & 0xff;
    1.11          b = (rgba) & 0xff;
    1.12 -        color = (rgb_to_index[r] * 6 * 6) + 
    1.13 -            (rgb_to_index[g] * 6) + 
    1.14 -            (rgb_to_index[b]);
    1.15 +        color = ((r >> 5) << 5 | (g >> 5) << 2 | (b >> 6));
    1.16          break;
    1.17 -#endif
    1.18      case 15:
    1.19          r = (rgba >> 16) & 0xff;
    1.20          g = (rgba >> 8) & 0xff;
     2.1 --- a/tools/ioemu/hw/vga.c	Mon Feb 11 14:51:22 2008 +0000
     2.2 +++ b/tools/ioemu/hw/vga.c	Mon Feb 11 14:55:33 2008 +0000
     2.3 @@ -1071,7 +1071,7 @@ static const uint8_t cursor_glyph[32 * 4
     2.4   */
     2.5  static void vga_draw_text(VGAState *s, int full_update)
     2.6  {
     2.7 -    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
     2.8 +    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr, depth;
     2.9      int cx_min, cx_max, linesize, x_incr;
    2.10      uint32_t offset, fgcol, bgcol, v, cursor_offset;
    2.11      uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
    2.12 @@ -1134,6 +1134,11 @@ static void vga_draw_text(VGAState *s, i
    2.13          return;
    2.14      }
    2.15  
    2.16 +    depth = s->get_bpp(s);
    2.17 +    if (depth == 24)
    2.18 +        depth = 32;
    2.19 +    if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth)
    2.20 +        s->ds->dpy_colourdepth(s->ds, depth);
    2.21      if (width != s->last_width || height != s->last_height ||
    2.22          cw != s->last_cw || cheight != s->last_ch) {
    2.23          s->last_scr_width = width * cw;
    2.24 @@ -1477,7 +1482,7 @@ void check_sse2(void)
    2.25   */
    2.26  static void vga_draw_graphic(VGAState *s, int full_update)
    2.27  {
    2.28 -    int y1, y, update, linesize, y_start, double_scan, mask;
    2.29 +    int y1, y, update, linesize, y_start, double_scan, mask, depth;
    2.30      int width, height, shift_control, line_offset, bwidth;
    2.31      ram_addr_t page0, page1;
    2.32      int disp_width, multi_scan, multi_run;
    2.33 @@ -1551,6 +1556,11 @@ static void vga_draw_graphic(VGAState *s
    2.34      }
    2.35      vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
    2.36  
    2.37 +    depth = s->get_bpp(s);
    2.38 +    if (depth == 24)
    2.39 +        depth = 32;
    2.40 +    if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth)
    2.41 +        s->ds->dpy_colourdepth(s->ds, depth);
    2.42      if (disp_width != s->last_width ||
    2.43          height != s->last_height) {
    2.44          dpy_resize(s->ds, disp_width, height);
     3.1 --- a/tools/ioemu/sdl.c	Mon Feb 11 14:51:22 2008 +0000
     3.2 +++ b/tools/ioemu/sdl.c	Mon Feb 11 14:55:33 2008 +0000
     3.3 @@ -508,6 +508,7 @@ void sdl_display_init(DisplayState *ds, 
     3.4      ds->dpy_update = sdl_update;
     3.5      ds->dpy_resize = sdl_resize;
     3.6      ds->dpy_refresh = sdl_refresh;
     3.7 +    ds->dpy_colourdepth = NULL;
     3.8  
     3.9      sdl_resize(ds, 640, 400);
    3.10      sdl_update_caption();
     4.1 --- a/tools/ioemu/vl.c	Mon Feb 11 14:51:22 2008 +0000
     4.2 +++ b/tools/ioemu/vl.c	Mon Feb 11 14:55:33 2008 +0000
     4.3 @@ -147,6 +147,7 @@ static DisplayState display_state;
     4.4  int nographic;
     4.5  int vncviewer;
     4.6  int vncunused;
     4.7 +int vncswitchbpp;
     4.8  const char* keyboard_layout = NULL;
     4.9  int64_t ticks_per_sec;
    4.10  char *boot_device = NULL;
    4.11 @@ -4420,6 +4421,7 @@ void dumb_display_init(DisplayState *ds)
    4.12      ds->depth = 0;
    4.13      ds->dpy_update = dumb_update;
    4.14      ds->dpy_resize = dumb_resize;
    4.15 +    ds->dpy_colourdepth = NULL;
    4.16      ds->dpy_refresh = dumb_refresh;
    4.17  }
    4.18  
    4.19 @@ -6533,6 +6535,7 @@ void help(void)
    4.20  	   "-vnc display    start a VNC server on display\n"
    4.21             "-vncviewer      start a vncviewer process for this domain\n"
    4.22             "-vncunused      bind the VNC server to an unused port\n"
    4.23 +           "-vnc-switch-bpp VNC server closes connections when the guest OS changes colour depth\n"
    4.24  #ifndef NO_DAEMONIZE
    4.25  	   "-daemonize      daemonize QEMU after initializing\n"
    4.26  #endif
    4.27 @@ -6634,6 +6637,7 @@ enum {
    4.28      QEMU_OPTION_acpi,
    4.29      QEMU_OPTION_vncviewer,
    4.30      QEMU_OPTION_vncunused,
    4.31 +    QEMU_OPTION_vncswitchbpp,
    4.32      QEMU_OPTION_pci,
    4.33  };
    4.34  
    4.35 @@ -6717,6 +6721,7 @@ const QEMUOption qemu_options[] = {
    4.36      { "vnc", HAS_ARG, QEMU_OPTION_vnc },
    4.37      { "vncviewer", 0, QEMU_OPTION_vncviewer },
    4.38      { "vncunused", 0, QEMU_OPTION_vncunused },
    4.39 +    { "vnc-switch-bpp", 0, QEMU_OPTION_vncswitchbpp },
    4.40  
    4.41      /* temporary options */
    4.42      { "usb", 0, QEMU_OPTION_usb },
    4.43 @@ -7130,6 +7135,7 @@ int main(int argc, char **argv)
    4.44      nographic = 0;
    4.45      vncviewer = 0;
    4.46      vncunused = 0;
    4.47 +    vncswitchbpp = 0;
    4.48      kernel_filename = NULL;
    4.49      kernel_cmdline = "";
    4.50  #ifndef CONFIG_DM
    4.51 @@ -7560,6 +7566,9 @@ int main(int argc, char **argv)
    4.52              case QEMU_OPTION_vncunused:
    4.53                  vncunused++;
    4.54                  break;
    4.55 +            case QEMU_OPTION_vncswitchbpp:
    4.56 +                vncswitchbpp++;
    4.57 +                break;
    4.58              case QEMU_OPTION_pci:
    4.59                  direct_pci = optarg;
    4.60                  break;
    4.61 @@ -7784,6 +7793,7 @@ int main(int argc, char **argv)
    4.62      } else if (vnc_display != NULL || vncunused != 0) {
    4.63  	int vnc_display_port;
    4.64  	char password[20];
    4.65 +        ds->switchbpp = vncswitchbpp;
    4.66  	vnc_display_init(ds);
    4.67  	xenstore_read_vncpasswd(domid, password, sizeof(password));
    4.68  	vnc_display_password(ds, password);
     5.1 --- a/tools/ioemu/vl.h	Mon Feb 11 14:51:22 2008 +0000
     5.2 +++ b/tools/ioemu/vl.h	Mon Feb 11 14:55:33 2008 +0000
     5.3 @@ -912,8 +912,11 @@ struct DisplayState {
     5.4      int height;
     5.5      void *opaque;
     5.6  
     5.7 +    int switchbpp;
     5.8 +    
     5.9      void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
    5.10      void (*dpy_resize)(struct DisplayState *s, int w, int h);
    5.11 +    void (*dpy_colourdepth)(struct DisplayState *s, int depth);
    5.12      void (*dpy_refresh)(struct DisplayState *s);
    5.13      void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h);
    5.14  };
     6.1 --- a/tools/ioemu/vnc.c	Mon Feb 11 14:51:22 2008 +0000
     6.2 +++ b/tools/ioemu/vnc.c	Mon Feb 11 14:55:33 2008 +0000
     6.3 @@ -27,6 +27,7 @@
     6.4  #include <sys/stat.h>
     6.5  #include <sys/socket.h>
     6.6  #include <netinet/in.h>
     6.7 +#include <arpa/inet.h>
     6.8  #include "vl.h"
     6.9  #include "qemu_socket.h"
    6.10  #include <assert.h>
    6.11 @@ -85,8 +86,8 @@ typedef void VncWritePixels(VncState *vs
    6.12  
    6.13  typedef void VncSendHextileTile(VncState *vs,
    6.14                                  int x, int y, int w, int h,
    6.15 -                                uint32_t *last_bg, 
    6.16 -                                uint32_t *last_fg,
    6.17 +                                void *last_bg, 
    6.18 +                                void *last_fg,
    6.19                                  int *has_bg, int *has_fg);
    6.20  
    6.21  #if 0
    6.22 @@ -187,9 +188,9 @@ struct VncState
    6.23      VncWritePixels *write_pixels;
    6.24      VncSendHextileTile *send_hextile_tile;
    6.25      int pix_bpp, pix_big_endian;
    6.26 -    int red_shift, red_max, red_shift1;
    6.27 -    int green_shift, green_max, green_shift1;
    6.28 -    int blue_shift, blue_max, blue_shift1;
    6.29 +    int red_shift, red_max, red_shift1, red_max1;
    6.30 +    int green_shift, green_max, green_shift1, green_max1;
    6.31 +    int blue_shift, blue_max, blue_shift1, blue_max1;
    6.32  
    6.33      VncReadEvent *read_handler;
    6.34      size_t read_handler_expect;
    6.35 @@ -379,54 +380,67 @@ static void vnc_write_pixels_copy(VncSta
    6.36  /* slowest but generic code. */
    6.37  static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
    6.38  {
    6.39 -    unsigned int r, g, b;
    6.40 +    uint8_t r, g, b;
    6.41  
    6.42 -    r = (v >> vs->red_shift1) & vs->red_max;
    6.43 -    g = (v >> vs->green_shift1) & vs->green_max;
    6.44 -    b = (v >> vs->blue_shift1) & vs->blue_max;
    6.45 -    v = (r << vs->red_shift) | 
    6.46 -        (g << vs->green_shift) | 
    6.47 -        (b << vs->blue_shift);
    6.48 +    r = ((v >> vs->red_shift1) & vs->red_max1) * (vs->red_max + 1) / (vs->red_max1 + 1);
    6.49 +    g = ((v >> vs->green_shift1) & vs->green_max1) * (vs->green_max + 1) / (vs->green_max1 + 1);
    6.50 +    b = ((v >> vs->blue_shift1) & vs->blue_max1) * (vs->blue_max + 1) / (vs->blue_max1 + 1);
    6.51      switch(vs->pix_bpp) {
    6.52      case 1:
    6.53 -        buf[0] = v;
    6.54 +        buf[0] = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
    6.55          break;
    6.56      case 2:
    6.57 +    {
    6.58 +        uint16_t *p = (uint16_t *) buf;
    6.59 +        *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
    6.60          if (vs->pix_big_endian) {
    6.61 -            buf[0] = v >> 8;
    6.62 -            buf[1] = v;
    6.63 -        } else {
    6.64 -            buf[1] = v >> 8;
    6.65 -            buf[0] = v;
    6.66 +            *p = htons(*p);
    6.67          }
    6.68 +    }
    6.69          break;
    6.70      default:
    6.71      case 4:
    6.72 +    {
    6.73 +        uint32_t *p = (uint32_t *) buf;
    6.74 +        *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
    6.75          if (vs->pix_big_endian) {
    6.76 -            buf[0] = v >> 24;
    6.77 -            buf[1] = v >> 16;
    6.78 -            buf[2] = v >> 8;
    6.79 -            buf[3] = v;
    6.80 -        } else {
    6.81 -            buf[3] = v >> 24;
    6.82 -            buf[2] = v >> 16;
    6.83 -            buf[1] = v >> 8;
    6.84 -            buf[0] = v;
    6.85 +            *p = htonl(*p);
    6.86          }
    6.87          break;
    6.88      }
    6.89 +    }
    6.90  }
    6.91  
    6.92  static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
    6.93  {
    6.94 -    uint32_t *pixels = pixels1;
    6.95      uint8_t buf[4];
    6.96 -    int n, i;
    6.97  
    6.98 -    n = size >> 2;
    6.99 -    for(i = 0; i < n; i++) {
   6.100 -        vnc_convert_pixel(vs, buf, pixels[i]);
   6.101 -        vnc_write(vs, buf, vs->pix_bpp);
   6.102 +    if (vs->depth == 4) {
   6.103 +        uint32_t *pixels = pixels1;
   6.104 +        int n, i;
   6.105 +        n = size >> 2;
   6.106 +        for(i = 0; i < n; i++) {
   6.107 +            vnc_convert_pixel(vs, buf, pixels[i]);
   6.108 +            vnc_write(vs, buf, vs->pix_bpp);
   6.109 +        }
   6.110 +    } else if (vs->depth == 2) {
   6.111 +        uint16_t *pixels = pixels1;
   6.112 +        int n, i;
   6.113 +        n = size >> 1;
   6.114 +        for(i = 0; i < n; i++) {
   6.115 +            vnc_convert_pixel(vs, buf, pixels[i]);
   6.116 +            vnc_write(vs, buf, vs->pix_bpp);
   6.117 +        }
   6.118 +    } else if (vs->depth == 1) {
   6.119 +        uint8_t *pixels = pixels1;
   6.120 +        int n, i;
   6.121 +        n = size;
   6.122 +        for(i = 0; i < n; i++) {
   6.123 +            vnc_convert_pixel(vs, buf, pixels[i]);
   6.124 +            vnc_write(vs, buf, vs->pix_bpp);
   6.125 +        }
   6.126 +    } else {
   6.127 +        fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
   6.128      }
   6.129  }
   6.130  
   6.131 @@ -463,6 +477,18 @@ static void hextile_enc_cord(uint8_t *pt
   6.132  #undef BPP
   6.133  
   6.134  #define GENERIC
   6.135 +#define BPP 8
   6.136 +#include "vnchextile.h"
   6.137 +#undef BPP
   6.138 +#undef GENERIC
   6.139 +
   6.140 +#define GENERIC
   6.141 +#define BPP 16
   6.142 +#include "vnchextile.h"
   6.143 +#undef BPP
   6.144 +#undef GENERIC
   6.145 +
   6.146 +#define GENERIC
   6.147  #define BPP 32
   6.148  #include "vnchextile.h"
   6.149  #undef BPP
   6.150 @@ -472,18 +498,22 @@ static void send_framebuffer_update_hext
   6.151  {
   6.152      int i, j;
   6.153      int has_fg, has_bg;
   6.154 -    uint32_t last_fg32, last_bg32;
   6.155 +    void *last_fg, *last_bg;
   6.156  
   6.157      vnc_framebuffer_update(vs, x, y, w, h, 5);
   6.158  
   6.159 +    last_fg = (void *) malloc(vs->depth);
   6.160 +    last_bg = (void *) malloc(vs->depth);
   6.161      has_fg = has_bg = 0;
   6.162      for (j = y; j < (y + h); j += 16) {
   6.163  	for (i = x; i < (x + w); i += 16) {
   6.164              vs->send_hextile_tile(vs, i, j, 
   6.165                                    MIN(16, x + w - i), MIN(16, y + h - j),
   6.166 -                                  &last_bg32, &last_fg32, &has_bg, &has_fg);
   6.167 +                                  last_bg, last_fg, &has_bg, &has_fg);
   6.168  	}
   6.169      }
   6.170 +    free(last_fg);
   6.171 +    free(last_bg);    
   6.172  }
   6.173  
   6.174  static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
   6.175 @@ -1306,17 +1336,6 @@ static void set_encodings(VncState *vs, 
   6.176      check_pointer_type_change(vs, kbd_mouse_is_absolute());
   6.177  }
   6.178  
   6.179 -static int compute_nbits(unsigned int val)
   6.180 -{
   6.181 -    int n;
   6.182 -    n = 0;
   6.183 -    while (val != 0) {
   6.184 -        n++;
   6.185 -        val >>= 1;
   6.186 -    }
   6.187 -    return n;
   6.188 -}
   6.189 -
   6.190  static void set_pixel_format(VncState *vs,
   6.191  			     int bits_per_pixel, int depth,
   6.192  			     int big_endian_flag, int true_color_flag,
   6.193 @@ -1335,23 +1354,24 @@ static void set_pixel_format(VncState *v
   6.194  	vnc_client_error(vs);
   6.195          return;
   6.196      }
   6.197 -    if (bits_per_pixel == 32 && 
   6.198 +    if (bits_per_pixel == 32 &&
   6.199 +        bits_per_pixel == vs->depth * 8 && 
   6.200          host_big_endian_flag == big_endian_flag &&
   6.201          red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
   6.202          red_shift == 16 && green_shift == 8 && blue_shift == 0) {
   6.203 -        vs->depth = 4;
   6.204          vs->write_pixels = vnc_write_pixels_copy;
   6.205          vs->send_hextile_tile = send_hextile_tile_32;
   6.206      } else 
   6.207 -    if (bits_per_pixel == 16 && 
   6.208 +    if (bits_per_pixel == 16 &&
   6.209 +        bits_per_pixel == vs->depth * 8 && 
   6.210          host_big_endian_flag == big_endian_flag &&
   6.211          red_max == 31 && green_max == 63 && blue_max == 31 &&
   6.212          red_shift == 11 && green_shift == 5 && blue_shift == 0) {
   6.213 -        vs->depth = 2;
   6.214          vs->write_pixels = vnc_write_pixels_copy;
   6.215          vs->send_hextile_tile = send_hextile_tile_16;
   6.216      } else 
   6.217      if (bits_per_pixel == 8 && 
   6.218 +        bits_per_pixel == vs->depth * 8 &&
   6.219          red_max == 7 && green_max == 7 && blue_max == 3 &&
   6.220          red_shift == 5 && green_shift == 2 && blue_shift == 0) {
   6.221          vs->depth = 1;
   6.222 @@ -1364,28 +1384,111 @@ static void set_pixel_format(VncState *v
   6.223              bits_per_pixel != 16 &&
   6.224              bits_per_pixel != 32)
   6.225              goto fail;
   6.226 -        vs->depth = 4;
   6.227 -        vs->red_shift = red_shift;
   6.228 -        vs->red_max = red_max;
   6.229 -        vs->red_shift1 = 24 - compute_nbits(red_max);
   6.230 -        vs->green_shift = green_shift;
   6.231 -        vs->green_max = green_max;
   6.232 -        vs->green_shift1 = 16 - compute_nbits(green_max);
   6.233 -        vs->blue_shift = blue_shift;
   6.234 -        vs->blue_max = blue_max;
   6.235 -        vs->blue_shift1 = 8 - compute_nbits(blue_max);
   6.236 -        vs->pix_bpp = bits_per_pixel / 8;
   6.237 +        if (vs->depth == 4) {
   6.238 +            vs->send_hextile_tile = send_hextile_tile_generic_32;
   6.239 +        } else if (vs->depth == 2) {
   6.240 +            vs->send_hextile_tile = send_hextile_tile_generic_16;
   6.241 +        } else {
   6.242 +            vs->send_hextile_tile = send_hextile_tile_generic_8;
   6.243 +        }
   6.244 +            
   6.245          vs->pix_big_endian = big_endian_flag;
   6.246          vs->write_pixels = vnc_write_pixels_generic;
   6.247 -        vs->send_hextile_tile = send_hextile_tile_generic;
   6.248      }
   6.249 -
   6.250 -    vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
   6.251 + 
   6.252 +    vs->red_shift = red_shift;
   6.253 +    vs->red_max = red_max;
   6.254 +    vs->green_shift = green_shift;
   6.255 +    vs->green_max = green_max;
   6.256 +    vs->blue_shift = blue_shift;
   6.257 +    vs->blue_max = blue_max;
   6.258 +    vs->pix_bpp = bits_per_pixel / 8;
   6.259  
   6.260      vga_hw_invalidate();
   6.261      vga_hw_update();
   6.262  }
   6.263  
   6.264 +static void vnc_dpy_colourdepth(DisplayState *ds, int depth)
   6.265 +{
   6.266 +    int host_big_endian_flag;
   6.267 +    struct VncState *vs;
   6.268 +    
   6.269 +    if (!depth) return;
   6.270 +    
   6.271 +#ifdef WORDS_BIGENDIAN
   6.272 +    host_big_endian_flag = 1;
   6.273 +#else
   6.274 +    host_big_endian_flag = 0;
   6.275 +#endif
   6.276 +    vs = ds->opaque;   
   6.277 +    
   6.278 +    switch (depth) {
   6.279 +        case 8:
   6.280 +            vs->depth = depth / 8;
   6.281 +            vs->red_max1 = 7;
   6.282 +            vs->green_max1 = 7;
   6.283 +            vs->blue_max1 = 3;
   6.284 +            vs->red_shift1 = 5;
   6.285 +            vs->green_shift1 = 2;
   6.286 +            vs->blue_shift1 = 0;
   6.287 +            break;
   6.288 +        case 16:
   6.289 +            vs->depth = depth / 8;
   6.290 +            vs->red_max1 = 31;
   6.291 +            vs->green_max1 = 63;
   6.292 +            vs->blue_max1 = 31;
   6.293 +            vs->red_shift1 = 11;
   6.294 +            vs->green_shift1 = 5;
   6.295 +            vs->blue_shift1 = 0;
   6.296 +            break;
   6.297 +        case 32:
   6.298 +            vs->depth = 4;
   6.299 +            vs->red_max1 = 255;
   6.300 +            vs->green_max1 = 255;
   6.301 +            vs->blue_max1 = 255;
   6.302 +            vs->red_shift1 = 16;
   6.303 +            vs->green_shift1 = 8;
   6.304 +            vs->blue_shift1 = 0;
   6.305 +            break;
   6.306 +        default:
   6.307 +            return;
   6.308 +    }
   6.309 +    if (ds->switchbpp) {
   6.310 +        vnc_client_error(vs);
   6.311 +    } else {
   6.312 +        if (vs->pix_bpp == 4 && vs->depth == 4 &&
   6.313 +            host_big_endian_flag == vs->pix_big_endian &&
   6.314 +            vs->red_max == 0xff && vs->green_max == 0xff && vs->blue_max == 0xff &&
   6.315 +            vs->red_shift == 16 && vs->green_shift == 8 && vs->blue_shift == 0) {
   6.316 +            vs->write_pixels = vnc_write_pixels_copy;
   6.317 +            vs->send_hextile_tile = send_hextile_tile_32;
   6.318 +        } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
   6.319 +            host_big_endian_flag == vs->pix_big_endian &&
   6.320 +            vs->red_max == 31 && vs->green_max == 63 && vs->blue_max == 31 &&
   6.321 +            vs->red_shift == 11 && vs->green_shift == 5 && vs->blue_shift == 0) {
   6.322 +            vs->write_pixels = vnc_write_pixels_copy;
   6.323 +            vs->send_hextile_tile = send_hextile_tile_16;
   6.324 +        } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
   6.325 +            host_big_endian_flag == vs->pix_big_endian &&
   6.326 +            vs->red_max == 7 && vs->green_max == 7 && vs->blue_max == 3 &&
   6.327 +            vs->red_shift == 5 && vs->green_shift == 2 && vs->blue_shift == 0) {
   6.328 +            vs->write_pixels = vnc_write_pixels_copy;
   6.329 +            vs->send_hextile_tile = send_hextile_tile_8;
   6.330 +        } else {
   6.331 +            if (vs->depth == 4) {
   6.332 +                vs->send_hextile_tile = send_hextile_tile_generic_32;
   6.333 +            } else if (vs->depth == 2) {
   6.334 +                vs->send_hextile_tile = send_hextile_tile_generic_16;
   6.335 +            } else {
   6.336 +                vs->send_hextile_tile = send_hextile_tile_generic_8;
   6.337 +            }
   6.338 +            vs->write_pixels = vnc_write_pixels_generic;
   6.339 +        }
   6.340 +    }
   6.341 +
   6.342 +    vnc_dpy_resize(ds, ds->width, ds->height);
   6.343 +}
   6.344 +
   6.345  static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
   6.346  {
   6.347      int i;
   6.348 @@ -1483,7 +1586,9 @@ static int protocol_client_init(VncState
   6.349      vnc_write_u16(vs, vs->ds->height);
   6.350  
   6.351      vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
   6.352 -    vnc_write_u8(vs, vs->depth * 8); /* depth */
   6.353 +    if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
   6.354 +    else vnc_write_u8(vs, vs->depth * 8); /* depth */
   6.355 +
   6.356  #ifdef WORDS_BIGENDIAN
   6.357      vnc_write_u8(vs, 1);             /* big-endian-flag */
   6.358  #else
   6.359 @@ -2160,7 +2265,6 @@ void vnc_display_init(DisplayState *ds)
   6.360  
   6.361      vs->lsock = -1;
   6.362      vs->csock = -1;
   6.363 -    vs->depth = 4;
   6.364      vs->last_x = -1;
   6.365      vs->last_y = -1;
   6.366  
   6.367 @@ -2177,9 +2281,12 @@ void vnc_display_init(DisplayState *ds)
   6.368      vs->ds->data = NULL;
   6.369      vs->ds->dpy_update = vnc_dpy_update;
   6.370      vs->ds->dpy_resize = vnc_dpy_resize;
   6.371 +    vs->ds->dpy_colourdepth = vnc_dpy_colourdepth;
   6.372      vs->ds->dpy_refresh = vnc_dpy_refresh;
   6.373  
   6.374 -    vnc_dpy_resize(vs->ds, 640, 400);
   6.375 +    vs->ds->width = 640;
   6.376 +    vs->ds->height = 400;
   6.377 +    vnc_dpy_colourdepth(vs->ds, 32);
   6.378  }
   6.379  
   6.380  #if CONFIG_VNC_TLS
     7.1 --- a/tools/ioemu/vnchextile.h	Mon Feb 11 14:51:22 2008 +0000
     7.2 +++ b/tools/ioemu/vnchextile.h	Mon Feb 11 14:55:33 2008 +0000
     7.3 @@ -2,29 +2,29 @@
     7.4  #define CONCAT(a, b) CONCAT_I(a, b)
     7.5  #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
     7.6  #ifdef GENERIC
     7.7 -#define NAME generic
     7.8 +#define NAME CONCAT(generic_, BPP)
     7.9  #else
    7.10  #define NAME BPP
    7.11  #endif
    7.12  
    7.13  static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
    7.14                                               int x, int y, int w, int h,
    7.15 -                                             uint32_t *last_bg32, 
    7.16 -                                             uint32_t *last_fg32,
    7.17 +                                             void *last_bg_, 
    7.18 +                                             void *last_fg_,
    7.19                                               int *has_bg, int *has_fg)
    7.20  {
    7.21      uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth);
    7.22      pixel_t *irow = (pixel_t *)row;
    7.23      int j, i;
    7.24 -    pixel_t *last_bg = (pixel_t *)last_bg32;
    7.25 -    pixel_t *last_fg = (pixel_t *)last_fg32;
    7.26 +    pixel_t *last_bg = (pixel_t *)last_bg_;
    7.27 +    pixel_t *last_fg = (pixel_t *)last_fg_;
    7.28      pixel_t bg = 0;
    7.29      pixel_t fg = 0;
    7.30      int n_colors = 0;
    7.31      int bg_count = 0;
    7.32      int fg_count = 0;
    7.33      int flags = 0;
    7.34 -    uint8_t data[(sizeof(pixel_t) + 2) * 16 * 16];
    7.35 +    uint8_t data[(vs->pix_bpp + 2) * 16 * 16];
    7.36      int n_data = 0;
    7.37      int n_subtiles = 0;
    7.38