[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 4 of 13] DisplayState interface change



Import "DisplayState interface change" from qemu mainstream: the patch
has been adapted to qemu-xen and merged with several following fixes.

The original qemu svn commit is the following:
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6336 
c046a42c-6fe2-441c-8c8c-71466251a162

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

---

diff --git a/console.c b/console.c
--- a/console.c
+++ b/console.c
@@ -1000,20 +1000,16 @@
 
     if (index >= MAX_CONSOLES)
         return;
+    active_console->g_width = ds_get_width(active_console->ds);
+    active_console->g_height = ds_get_height(active_console->ds);
     s = consoles[index];
     if (s) {
+        DisplayState *ds = s->ds;
         active_console = s;
-        if (s->console_type == TEXT_CONSOLE) {
-            if (s->g_width != s->ds->width ||
-                s->g_height != s->ds->height) {
-                s->g_width = s->ds->width;
-                s->g_height = s->ds->height;
-                text_console_resize(s);
-            }
-            console_refresh(s);
-        } else {
-            vga_hw_invalidate();
-        }
+        ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
+                                                s->g_height, 32, 4 * 
s->g_width);
+        dpy_resize(s->ds);
+        vga_hw_invalidate();
     }
 }
 
@@ -1121,15 +1117,6 @@
 {
     TextConsole *s = (TextConsole *) opaque;
 
-    if (s->g_width != ds_get_width(s->ds) || s->g_height != 
ds_get_height(s->ds)) {
-        if (s->console_type == TEXT_CONSOLE_FIXED_SIZE)
-            dpy_resize(s->ds, s->g_width, s->g_height);
-        else {
-            s->g_width = ds_get_width(s->ds);
-            s->g_height = ds_get_height(s->ds);
-            text_console_resize(s);
-        }
-    }
     console_refresh(s);
 }
 
@@ -1263,8 +1250,8 @@
     s->total_height = DEFAULT_BACKSCROLL;
     s->x = 0;
     s->y = 0;
-    s->g_width = s->ds->width;
-    s->g_height = s->ds->height;
+    s->g_width = ds_get_width(s->ds);
+    s->g_height = ds_get_height(s->ds);
 
     /* Set text attribute defaults */
     s->t_attrib_default.bold = 0;
@@ -1286,26 +1273,191 @@
 
 void qemu_console_resize(QEMUConsole *console, int width, int height)
 {
-    if (console->g_width != width || console->g_height != height
-        || !ds_get_data(console->ds)) {
-        console->g_width = width;
-        console->g_height = height;
-        if (active_console == console) {
-            dpy_resize(console->ds, width, height);
-        }
+    console->g_width = width;
+    console->g_height = height;
+    if (active_console == console) {
+        DisplayState *ds = console->ds;
+        ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 
32, 4 * width);
+        dpy_resize(console->ds);
     }
 }
 
 void qemu_console_copy(QEMUConsole *console, int src_x, int src_y,
                 int dst_x, int dst_y, int w, int h)
 {
-    if (active_console == console) {
-        if (console->ds->dpy_copy)
-            console->ds->dpy_copy(console->ds,
-                            src_x, src_y, dst_x, dst_y, w, h);
-        else {
-            /* TODO */
-            console->ds->dpy_update(console->ds, dst_x, dst_y, w, h);
-        }
+    if (active_console == console)
+        dpy_copy(console->ds, src_x, src_y, dst_x, dst_y, w, h);
+}
+
+PixelFormat qemu_different_endianness_pixelformat(int bpp)
+{
+    PixelFormat pf;
+
+    memset(&pf, 0x00, sizeof(PixelFormat));
+
+    pf.bits_per_pixel = bpp;
+    pf.bytes_per_pixel = bpp / 8;
+    pf.depth = bpp == 32 ? 24 : bpp;
+
+    switch (bpp) {
+        case 24:
+            pf.rmask = 0x000000FF;
+            pf.gmask = 0x0000FF00;
+            pf.bmask = 0x00FF0000;
+            pf.rmax = 255;
+            pf.gmax = 255;
+            pf.bmax = 255;
+            pf.rshift = 0;
+            pf.gshift = 8;
+            pf.bshift = 16;
+            break;
+        case 32:
+            pf.rmask = 0x0000FF00;
+            pf.gmask = 0x00FF0000;
+            pf.bmask = 0xFF000000;
+            pf.amask = 0x00000000;
+            pf.amax = 255;
+            pf.rmax = 255;
+            pf.gmax = 255;
+            pf.bmax = 255;
+            pf.ashift = 0;
+            pf.rshift = 8;
+            pf.gshift = 16;
+            pf.bshift = 24;
+            break;
+        default:
+            break;
     }
+    return pf;
 }
+
+PixelFormat qemu_default_pixelformat(int bpp)
+{
+    PixelFormat pf;
+
+    memset(&pf, 0x00, sizeof(PixelFormat));
+
+    pf.bits_per_pixel = bpp;
+    pf.bytes_per_pixel = bpp / 8;
+    pf.depth = bpp == 32 ? 24 : bpp;
+
+    switch (bpp) {
+        case 16:
+            pf.rmask = 0x0000F800;
+            pf.gmask = 0x000007E0;
+            pf.bmask = 0x0000001F;
+            pf.rmax = 31;
+            pf.gmax = 63;
+            pf.bmax = 31;
+            pf.rshift = 11;
+            pf.gshift = 5;
+            pf.bshift = 0;
+            break;
+        case 24:
+            pf.rmask = 0x00FF0000;
+            pf.gmask = 0x0000FF00;
+            pf.bmask = 0x000000FF;
+            pf.rmax = 255;
+            pf.gmax = 255;
+            pf.bmax = 255;
+            pf.rshift = 16;
+            pf.gshift = 8;
+            pf.bshift = 0;
+        case 32:
+            pf.rmask = 0x00FF0000;
+            pf.gmask = 0x0000FF00;
+            pf.bmask = 0x000000FF;
+            pf.amax = 255;
+            pf.rmax = 255;
+            pf.gmax = 255;
+            pf.bmax = 255;
+            pf.ashift = 24;
+            pf.rshift = 16;
+            pf.gshift = 8;
+            pf.bshift = 0;
+            break;
+        default:
+            break;
+    }
+    return pf;
+}
+
+DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int 
linesize)
+{
+    DisplaySurface *surface = (DisplaySurface*) 
qemu_mallocz(sizeof(DisplaySurface));
+    if (surface == NULL) {
+        fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
+        exit(1);
+    }
+
+    surface->width = width;
+    surface->height = height;
+    surface->linesize = linesize;
+    surface->pf = qemu_default_pixelformat(bpp);
+#ifdef WORDS_BIGENDIAN
+    surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+#else
+    surface->flags = QEMU_ALLOCATED_FLAG;
+#endif
+    surface->data = (uint8_t*) qemu_mallocz(surface->linesize * 
surface->height);
+    if (surface->data == NULL) {
+        fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
+        exit(1);
+    }
+
+    return surface;
+}
+
+DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
+                                          int width, int height, int bpp, int 
linesize)
+{
+    surface->width = width;
+    surface->height = height;
+    surface->linesize = linesize;
+    surface->pf = qemu_default_pixelformat(bpp);
+    if (surface->flags & QEMU_ALLOCATED_FLAG)
+        surface->data = (uint8_t*) qemu_realloc(surface->data, 
surface->linesize * surface->height);
+    else
+        surface->data = (uint8_t*) qemu_malloc(surface->linesize * 
surface->height);
+    if (surface->data == NULL) {
+        fprintf(stderr, "qemu_resize_displaysurface: malloc failed\n");
+        exit(1);
+    }
+#ifdef WORDS_BIGENDIAN
+    surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+#else
+    surface->flags = QEMU_ALLOCATED_FLAG;
+#endif
+
+    return surface;
+}
+
+DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
+                                              int linesize, uint8_t *data)
+{
+    DisplaySurface *surface = (DisplaySurface*) 
qemu_mallocz(sizeof(DisplaySurface));
+    if (surface == NULL) {
+        fprintf(stderr, "qemu_create_displaysurface_from: malloc failed\n");
+        exit(1);
+    }
+
+    surface->width = width;
+    surface->height = height;
+    surface->linesize = linesize;
+    surface->pf = qemu_default_pixelformat(bpp);
+#ifdef WORDS_BIGENDIAN
+    surface->flags = QEMU_BIG_ENDIAN_FLAG;
+#endif
+    surface->data = data;
+
+    return surface;
+}
+
+void qemu_free_displaysurface(DisplaySurface *surface)
+{
+    if (surface == NULL)
+        return;
+    if (surface->flags & QEMU_ALLOCATED_FLAG)
+        qemu_free(surface->data);
+    qemu_free(surface);
+}
diff --git a/console.h b/console.h
--- a/console.h
+++ b/console.h
@@ -67,80 +67,170 @@
 
 /* in ms */
 #define GUI_REFRESH_INTERVAL 30
+#define QEMU_BIG_ENDIAN_FLAG    0x01
+#define QEMU_ALLOCATED_FLAG     0x02
 
-struct DisplayState {
-    uint8_t *data;
-    int linesize;
-    int depth;
-    int bgr; /* BGR color order instead of RGB. Only valid for depth == 32 */
+struct PixelFormat {
+    uint8_t bits_per_pixel;
+    uint8_t bytes_per_pixel;
+    uint8_t depth; /* color depth in bits */
+    uint32_t rmask, gmask, bmask, amask;
+    uint8_t rshift, gshift, bshift, ashift;
+    uint8_t rmax, gmax, bmax, amax;
+};
+
+struct DisplaySurface {
+    uint8_t flags;
     int width;
     int height;
-    void *opaque;
-    uint32_t *palette;
-    struct QEMUTimer *gui_timer;
+    int linesize;        /* bytes per line */
+    uint8_t *data;
+
+    struct PixelFormat pf;
+};
+
+struct DisplayChangeListener {
+    int idle;
     uint64_t gui_timer_interval;
-    int idle; /* there is nothing to update (window invisible), set by vnc/sdl 
*/
-    int shared_buf;
 
     void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
-    void (*dpy_resize)(struct DisplayState *s, int w, int h);
-    void (*dpy_resize_shared)(struct DisplayState *s, int w, int h, int depth, 
int linesize, void *pixels);
-    void (*dpy_setdata)(DisplayState *s, void *pixels);
+    void (*dpy_resize)(struct DisplayState *s);
+    void (*dpy_setdata)(struct DisplayState *s);
     void (*dpy_refresh)(struct DisplayState *s);
     void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
                      int dst_x, int dst_y, int w, int h);
     void (*dpy_fill)(struct DisplayState *s, int x, int y,
                      int w, int h, uint32_t c);
     void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
+
+    struct DisplayChangeListener *next;
 };
+
+struct DisplayState {
+    struct DisplaySurface *surface;
+    void *opaque;
+    struct QEMUTimer *gui_timer;
+
+    struct DisplayChangeListener* listeners;
+
+    void (*mouse_set)(int x, int y, int on);
+    void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
+                          uint8_t *image, uint8_t *mask);
+};
+
+DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int 
linesize);
+DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
+                                           int width, int height, int bpp, int 
linesize);
+DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
+                                                int linesize, uint8_t *data);
+void qemu_free_displaysurface(DisplaySurface *surface);
+PixelFormat qemu_different_endianness_pixelformat(int bpp);
+PixelFormat qemu_default_pixelformat(int bpp);
+
+static inline int is_buffer_shared(DisplaySurface *surface)
+{
+    return (!(surface->flags & QEMU_ALLOCATED_FLAG));
+}
+
+static inline void register_displaychangelistener(DisplayState *ds, 
DisplayChangeListener *dcl)
+{
+    dcl->next = ds->listeners;
+    ds->listeners = dcl;
+}
 
 static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
 {
-    s->dpy_update(s, x, y, w, h);
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        dcl->dpy_update(s, x, y, w, h);
+        dcl = dcl->next;
+    }
 }
 
-static inline void dpy_resize(DisplayState *s, int w, int h)
+static inline void dpy_resize(DisplayState *s)
 {
-    s->dpy_resize(s, w, h);
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        dcl->dpy_resize(s);
+        dcl = dcl->next;
+    }
 }
-static inline void dpy_resize_shared(DisplayState *s, int w, int h, int depth, 
int linesize, void *pixels)
+
+static inline void dpy_setdata(DisplayState *s)
 {
-    s->dpy_resize_shared(s, w, h, depth, linesize, pixels);
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        if (dcl->dpy_setdata) dcl->dpy_setdata(s);
+        dcl = dcl->next;
+    }
 }
-static inline void dpy_cursor(DisplayState *s, int x, int y)
+
+static inline void dpy_refresh(DisplayState *s)
 {
-    if (s->dpy_text_cursor)
-        s->dpy_text_cursor(s, x, y);
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        if (dcl->dpy_refresh) dcl->dpy_refresh(s);
+        dcl = dcl->next;
+    }
+}
+
+static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
+                             int dst_x, int dst_y, int w, int h) {
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        if (dcl->dpy_copy)
+            dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
+        else /* TODO */
+            dcl->dpy_update(s, dst_x, dst_y, w, h);
+        dcl = dcl->next;
+    }
+}
+
+static inline void dpy_fill(struct DisplayState *s, int x, int y,
+                             int w, int h, uint32_t c) {
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c);
+        dcl = dcl->next;
+    }
+}
+
+static inline void dpy_cursor(struct DisplayState *s, int x, int y) {
+    struct DisplayChangeListener *dcl = s->listeners;
+    while (dcl != NULL) {
+        if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y);
+        dcl = dcl->next;
+    }
 }
 
 static inline int ds_get_linesize(DisplayState *ds)
 {
-    return ds->linesize;
+    return ds->surface->linesize;
 }
 
 static inline uint8_t* ds_get_data(DisplayState *ds)
 {
-    return ds->data;
+    return ds->surface->data;
 }
 
 static inline int ds_get_width(DisplayState *ds)
 {
-    return ds->width;
+    return ds->surface->width;
 }
 
 static inline int ds_get_height(DisplayState *ds)
 {
-    return ds->height;
+    return ds->surface->height;
 }
 
 static inline int ds_get_bits_per_pixel(DisplayState *ds)
 {
-    return ds->depth;
+    return ds->surface->pf.bits_per_pixel;
 }
 
 static inline int ds_get_bytes_per_pixel(DisplayState *ds)
 {
-    return (ds->depth / 8);
+    return ds->surface->pf.bytes_per_pixel;
 }
 
 typedef unsigned long console_ch_t;
diff --git a/curses.c b/curses.c
--- a/curses.c
+++ b/curses.c
@@ -97,13 +97,13 @@
     }
 }
 
-static void curses_resize(DisplayState *ds, int w, int h)
+static void curses_resize(DisplayState *ds)
 {
-    if (w == gwidth && h == gheight)
+    if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight)
         return;
 
-    gwidth = w;
-    gheight = h;
+    gwidth = ds_get_width(ds);
+    gheight = ds_get_height(ds);
 
     curses_calc_pad();
 }
@@ -169,8 +169,8 @@
         clear();
         refresh();
         curses_calc_pad();
-        ds->width = FONT_WIDTH * width;
-        ds->height = FONT_HEIGHT * height;
+        ds->surface->width = FONT_WIDTH * width;
+        ds->surface->height = FONT_HEIGHT * height;
         vga_hw_invalidate();
         invalidate = 0;
     }
@@ -197,8 +197,8 @@
             refresh();
             curses_calc_pad();
             curses_update(ds, 0, 0, width, height);
-            ds->width = FONT_WIDTH * width;
-            ds->height = FONT_HEIGHT * height;
+            ds->surface->width = FONT_WIDTH * width;
+            ds->surface->height = FONT_HEIGHT * height;
             continue;
         }
 #endif
@@ -338,6 +338,7 @@
 
 void curses_display_init(DisplayState *ds, int full_screen)
 {
+    DisplayChangeListener *dcl;
 #ifndef _WIN32
     if (!isatty(1)) {
         fprintf(stderr, "We need a terminal output\n");
@@ -357,18 +358,19 @@
 #endif
 #endif
 
-    ds->data = (void *) screen;
-    ds->linesize = 0;
-    ds->depth = 0;
-    ds->width = 640;
-    ds->height = 400;
-    ds->dpy_update = curses_update;
-    ds->dpy_resize = curses_resize;
-    ds->dpy_refresh = curses_refresh;
-    ds->dpy_text_cursor = curses_cursor_position;
+    dcl = (DisplayChangeListener *) 
qemu_mallocz(sizeof(DisplayChangeListener));
+    if (!dcl)
+        exit(1);
+    dcl->dpy_update = curses_update;
+    dcl->dpy_resize = curses_resize;
+    dcl->dpy_refresh = curses_refresh;
+    dcl->dpy_text_cursor = curses_cursor_position;
+    register_displaychangelistener(ds, dcl);
+    qemu_free_displaysurface(ds->surface);
+    ds->surface = qemu_create_displaysurface_from(80, 25, 0, 0, (uint8_t*) 
screen);
 
     invalidate = 1;
 
     /* Standard VGA initial text mode dimensions */
-    curses_resize(ds, 80, 25);
+    curses_resize(ds);
 }
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -794,26 +794,9 @@
 
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
 {
-    if (s->ds->dpy_copy) {
-       cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
-                      s->cirrus_blt_srcaddr - s->start_addr,
-                      s->cirrus_blt_width, s->cirrus_blt_height);
-    } else {
-
-    if (BLTUNSAFE(s))
-        return 0;
-
-       (*s->cirrus_rop) (s, s->vram_ptr +
-                (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
-                         s->vram_ptr +
-                (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
-                         s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
-                         s->cirrus_blt_width, s->cirrus_blt_height);
-
-       cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
-                                s->cirrus_blt_dstpitch, s->cirrus_blt_width,
-                                s->cirrus_blt_height);
-    }
+    cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
+            s->cirrus_blt_srcaddr - s->start_addr,
+            s->cirrus_blt_width, s->cirrus_blt_height);
 
     return 1;
 }
diff --git a/hw/nseries.c b/hw/nseries.c
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1361,7 +1361,8 @@
     /* FIXME: We shouldn't really be doing this here.  The LCD controller
        will set the size once configured, so this just sets an initial
        size until the guest activates the display.  */
-    dpy_resize(ds, 800, 480);
+    ds->surface = qemu_resize_displaysurface(ds->surface, 800, 480, 32, 4 * 
800);
+    dpy_resize(ds);
 }
 
 static struct arm_boot_info n800_binfo = {
diff --git a/hw/palm.c b/hw/palm.c
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -278,7 +278,8 @@
     /* FIXME: We shouldn't really be doing this here.  The LCD controller
        will set the size once configured, so this just sets an initial
        size until the guest activates the display.  */
-    dpy_resize(ds, 320, 320);
+    ds->surface = qemu_resize_displaysurface(ds->surface, 320, 320, 32, 4 * 
320);
+    dpy_resize(ds);
 }
 
 QEMUMachine palmte_machine = {
diff --git a/hw/vga.c b/hw/vga.c
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1270,18 +1270,19 @@
         return;
     }
 
-    s->last_scr_width = width * cw;
-    s->last_scr_height = height * cheight;
     if (width != s->last_width || height != s->last_height ||
         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
-        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
+        s->last_scr_width = width * cw;
+        s->last_scr_height = height * cheight;
+        qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
+        dpy_resize(s->ds);
         s->last_depth = 0;
+        s->last_width = width;
+        s->last_height = height;
+        s->last_ch = cheight;
+        s->last_cw = cw;
         full_update = 1;
     }
-    s->last_width = width;
-    s->last_height = height;
-    s->last_ch = cheight;
-    s->last_cw = cw;
 
     s->rgb_to_pixel = 
         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
@@ -1289,7 +1290,7 @@
     full_update |= update_palette16(s);
     palette = s->last_palette;
     
-    x_incr = cw * ((s->ds->depth + 7) >> 3);
+    x_incr = cw * ds_get_bytes_per_pixel(s->ds);
     /* compute font data address (in plane 2) */
     v = s->sr[3];
     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
@@ -1323,7 +1324,7 @@
         cw = 9;
     if (s->sr[1] & 0x08)
         cw = 16; /* NOTE: no 18 pixel wide */
-    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
+    x_incr = cw * ds_get_bytes_per_pixel(s->ds);
     width = (s->cr[0x01] + 1);
     if (s->cr[0x06] == 100) {
         /* ugly hack for CGA 160x100x16 - explain me the logic */
@@ -1616,31 +1617,43 @@
         disp_width <<= 1;
     }
 
-    ds_depth = s->ds->depth;
+    ds_depth = ds_get_bits_per_pixel(s->ds);
     depth = s->get_bpp(s);
-    if (s->ds->dpy_resize_shared) {
-        if (s->line_offset != s->last_line_offset || 
-            disp_width != s->last_width ||
-            height != s->last_height ||
-            s->last_depth != depth) {
-            dpy_resize_shared(s->ds, disp_width, height, depth, 
s->line_offset, s->vram_ptr + (s->start_addr * 4));
-            s->last_scr_width = disp_width;
-            s->last_scr_height = height;
-            s->last_width = disp_width;
-            s->last_height = height;
-            s->last_line_offset = s->line_offset;
-            s->last_depth = depth;
-            full_update = 1;
-        } else if (s->ds->shared_buf && (full_update || s->ds->data != 
s->vram_ptr + (s->start_addr * 4)))
-            s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4));
-    } else if (disp_width != s->last_width ||
-               height != s->last_height) {
-        dpy_resize(s->ds, disp_width, height);
+    if (s->line_offset != s->last_line_offset || 
+        disp_width != s->last_width ||
+        height != s->last_height ||
+        s->last_depth != depth) {
+#if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+        if (depth == 16 || depth == 32) {
+#else
+        if (depth == 32) {
+#endif
+            if (is_graphic_console()) {
+                qemu_free_displaysurface(s->ds->surface);
+                s->ds->surface = qemu_create_displaysurface_from(disp_width, 
height, depth,
+                                                               s->line_offset,
+                                                               s->vram_ptr + 
(s->start_addr * 4));
+#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+                s->ds->surface->pf = 
qemu_different_endianness_pixelformat(depth);
+#endif
+                dpy_resize(s->ds);
+            } else {
+                qemu_console_resize(s->console, disp_width, height);
+            }
+        } else {
+            qemu_console_resize(s->console, disp_width, height);
+        }
         s->last_scr_width = disp_width;
         s->last_scr_height = height;
         s->last_width = disp_width;
         s->last_height = height;
+        s->last_line_offset = s->line_offset;
+        s->last_depth = depth;
         full_update = 1;
+    } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
+               (full_update || s->ds->surface->data != s->vram_ptr + 
(s->start_addr * 4))) {
+        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
+        dpy_setdata(s->ds);
     }
 
     s->rgb_to_pixel = 
@@ -1695,7 +1708,7 @@
     }
 
     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + 
get_depth_index(s->ds)];
-    if (!s->ds->shared_buf && s->cursor_invalidate)
+    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
         s->cursor_invalidate(s);
 
     line_offset = s->line_offset;
@@ -1756,8 +1769,8 @@
     y_start = -1;
     page_min = 0;
     page_max = 0;
-    d = s->ds->data;
-    linesize = s->ds->linesize;
+    d = ds_get_data(s->ds);
+    linesize = ds_get_linesize(s->ds);
     y1 = 0;
     for(y = 0; y < height; y++) {
         addr = addr1;
@@ -1789,7 +1802,7 @@
                 page_min = page0;
             if (page_max == 0 || page1 > page_max)
                 page_max = page1;
-            if (!s->ds->shared_buf) {
+            if (!is_buffer_shared(s->ds->surface)) {
                 vga_draw_line(s, d, s->vram_ptr + addr, width);
                 if (s->cursor_draw_line)
                     s->cursor_draw_line(s, d, y);
@@ -1844,15 +1857,15 @@
 
     s->rgb_to_pixel =
         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
-    if (s->ds->depth == 8)
+    if (ds_get_bits_per_pixel(s->ds) == 8)
         val = s->rgb_to_pixel(0, 0, 0);
     else
         val = 0;
-    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
-    d = s->ds->data;
+    w = s->last_scr_width * ds_get_bytes_per_pixel(s->ds);
+    d = ds_get_data(s->ds);
     for(i = 0; i < s->last_scr_height; i++) {
         memset(d, val, w);
-        d += s->ds->linesize;
+        d += ds_get_linesize(s->ds);
     }
     dpy_update(s->ds, 0, 0,
                s->last_scr_width, s->last_scr_height);
@@ -1977,7 +1990,9 @@
             cw != s->last_cw || cheight != s->last_ch) {
             s->last_scr_width = width * cw;
             s->last_scr_height = height * cheight;
-            qemu_console_resize(s->console, width, height);
+            s->ds->surface->width = width;
+            s->ds->surface->height = height;
+            dpy_resize(s->ds);
             s->last_width = width;
             s->last_height = height;
             s->last_ch = cheight;
@@ -2058,7 +2073,9 @@
     s->last_width = 60;
     s->last_height = height = 3;
     dpy_cursor(s->ds, -1, -1);
-    qemu_console_resize(s->console, s->last_width, height);
+    s->ds->surface->width = s->last_width;
+    s->ds->surface->height = height;
+    dpy_resize(s->ds);
 
     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
         console_write_ch(dst ++, ' ');
@@ -2520,7 +2537,6 @@
     s->vram_offset = vga_ram_offset;
     s->vram_size = vga_ram_size;
     s->ds = ds;
-    ds->palette = s->last_palette;
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
     s->get_resolution = vga_get_resolution;
@@ -2690,12 +2706,8 @@
 {
 }
 
-static void vga_save_dpy_resize(DisplayState *s, int w, int h)
+static void vga_save_dpy_resize(DisplayState *s)
 {
-    s->linesize = w * 4;
-    s->data = qemu_mallocz(h * s->linesize);
-    vga_save_w = w;
-    vga_save_h = h;
 }
 
 static void vga_save_dpy_refresh(DisplayState *s)
@@ -2737,25 +2749,28 @@
 {
     VGAState *s = (VGAState *)opaque;
     DisplayState *saved_ds, ds1, *ds = &ds1;
+    DisplayChangeListener dcl;
 
     /* XXX: this is a little hackish */
     vga_invalidate_display(s);
     saved_ds = s->ds;
 
     memset(ds, 0, sizeof(DisplayState));
-    ds->dpy_update = vga_save_dpy_update;
-    ds->dpy_resize = vga_save_dpy_resize;
-    ds->dpy_refresh = vga_save_dpy_refresh;
-    ds->depth = 32;
-
+    memset(&dcl, 0, sizeof(DisplayChangeListener));
+    dcl.dpy_update = vga_save_dpy_update;
+    dcl.dpy_resize = vga_save_dpy_resize;
+    dcl.dpy_refresh = vga_save_dpy_refresh;
+    register_displaychangelistener(ds, &dcl);
+    ds->surface = qemu_create_displaysurface(ds_get_width(saved_ds),
+            ds_get_height(saved_ds), 32, 4 * ds_get_width(saved_ds));
+ 
     s->ds = ds;
     s->graphic_mode = -1;
     vga_update_display(s);
 
-    if (ds_get_data(ds)) {
-        ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
-                 ds_get_linesize(s->ds));
-        qemu_free(ds_get_data(ds));
-    }
+    ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
+            ds_get_linesize(ds));
+
+    qemu_free_displaysurface(ds->surface);
     s->ds = saved_ds;
 }
diff --git a/hw/xenfb.c b/hw/xenfb.c
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -700,21 +700,30 @@
 {
     struct XenFB *xenfb = opaque;
     int i;
+    struct DisplayChangeListener *l;
 
     if (xenfb->feature_update) {
 #ifdef XENFB_TYPE_REFRESH_PERIOD
-       int period;
+        int period = 99999999;
+        int idle = 1;
 
        if (xenfb_queue_full(xenfb))
            return;
 
-       if (xenfb->c.ds->idle)
-           period = XENFB_NO_REFRESH;
-       else {
-           period = xenfb->c.ds->gui_timer_interval;
-           if (!period)
-               period = GUI_REFRESH_INTERVAL;
-       }
+        for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) {
+            if (l->idle)
+                continue;
+            idle = 0;
+            if (!l->gui_timer_interval) {
+                if (period > GUI_REFRESH_INTERVAL)
+                    period = GUI_REFRESH_INTERVAL;
+            } else {
+                if (period > l->gui_timer_interval)
+                    period = l->gui_timer_interval;
+            }
+        }
+        if (idle)
+            period = XENFB_NO_REFRESH;
 
        if (xenfb->refresh_period != period) {
            xenfb_send_refresh_period(xenfb, period);
@@ -733,7 +742,9 @@
     if (xenfb->width != ds_get_width(xenfb->c.ds) || xenfb->height != 
ds_get_height(xenfb->c.ds)) {
         xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d\n",
                       xenfb->width, xenfb->height);
-        dpy_resize(xenfb->c.ds, xenfb->width, xenfb->height);
+        xenfb->c.ds->surface->width = xenfb->width;
+        xenfb->c.ds->surface->height = xenfb->height;
+        dpy_resize(xenfb->c.ds);
         xenfb->up_fullscreen = 1;
     }
 
diff --git a/qemu-common.h b/qemu-common.h
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -131,6 +131,9 @@
 typedef struct AudioState AudioState;
 typedef struct BlockDriverState BlockDriverState;
 typedef struct DisplayState DisplayState;
+typedef struct DisplayChangeListener DisplayChangeListener;
+typedef struct DisplaySurface DisplaySurface;
+typedef struct PixelFormat PixelFormat;
 typedef struct TextConsole TextConsole;
 typedef TextConsole QEMUConsole;
 typedef struct CharDriverState CharDriverState;
diff --git a/sdl.c b/sdl.c
--- a/sdl.c
+++ b/sdl.c
@@ -35,8 +35,9 @@
 #include <SDL_opengl.h>
 #endif
 
-static SDL_Surface *screen;
-static SDL_Surface *shared = NULL;
+static DisplayChangeListener *dcl;
+static SDL_Surface *real_screen;
+static SDL_Surface *guest_screen = NULL;
 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
 static int last_vm_running;
 static int gui_saved_grab;
@@ -52,17 +53,15 @@
 static SDL_Cursor *sdl_cursor_hidden;
 static int absolute_enabled = 0;
 static int opengl_enabled;
-static uint8_t bgr;
-
-static void sdl_colourdepth(DisplayState *ds, int depth);
 
 #ifdef CONFIG_OPENGL
 static GLint tex_format;
 static GLint tex_type;
 static GLuint texture_ref = 0;
 static GLint gl_format;
+static uint8_t bgr;
 
-static void opengl_setdata(DisplayState *ds, void *pixels)
+static void opengl_setdata(DisplayState *ds)
 {
     glEnable(GL_TEXTURE_RECTANGLE_ARB);
     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
@@ -72,14 +71,13 @@
     glDisable(GL_DEPTH_TEST);
     glDepthMask(GL_FALSE);
     glDisable(GL_CULL_FACE);
-    glViewport( 0, 0, screen->w, screen->h);
+    glViewport( 0, 0, real_screen->w, real_screen->h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrtho(0, screen->w, screen->h, 0, -1,1);
+    glOrtho(0, real_screen->w, real_screen->h, 0, -1,1);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glClear(GL_COLOR_BUFFER_BIT);
-    ds->data = pixels;
 
     if (texture_ref) {
         glDeleteTextures(1, &texture_ref);
@@ -90,27 +88,6 @@
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref);
     glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
     switch (ds_get_bits_per_pixel(ds)) {
-        case 8:
-            if (ds->palette == NULL) {
-                tex_format = GL_RGB;
-                tex_type = GL_UNSIGNED_BYTE_3_3_2;
-            } else {
-                int i;
-                GLushort paletter[256], paletteg[256], paletteb[256];
-                for (i = 0; i < 256; i++) {
-                    uint8_t rgb = ds->palette[i] >> 16;
-                    paletter[i] = ((rgb & 0xe0) >> 5) * 65535 / 7;
-                    paletteg[i] = ((rgb & 0x1c) >> 2) * 65535 / 7;
-                    paletteb[i] = (rgb & 0x3) * 65535 / 3;
-                }
-                glPixelMapusv(GL_PIXEL_MAP_I_TO_R, 256, paletter);
-                glPixelMapusv(GL_PIXEL_MAP_I_TO_G, 256, paletteg);
-                glPixelMapusv(GL_PIXEL_MAP_I_TO_B, 256, paletteb);
-
-                tex_format = GL_COLOR_INDEX;
-                tex_type = GL_UNSIGNED_BYTE;
-            }
-            break;
         case 16:
             tex_format = GL_RGB;
             tex_type = GL_UNSIGNED_SHORT_5_6_5;
@@ -120,7 +97,7 @@
             tex_type = GL_UNSIGNED_BYTE;
             break;
         case 32:
-            if (!bgr) {
+            if (bgr == (ds->surface->pf.rshift < ds->surface->pf.bshift)) {
                 tex_format = GL_BGRA;
                 tex_type = GL_UNSIGNED_BYTE;
             } else {
@@ -130,7 +107,7 @@
             break;
     }   
     glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds_get_linesize(ds) / 
ds_get_bytes_per_pixel(ds)));
-    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds_get_width(ds), 
ds_get_height(ds), 0, tex_format, tex_type, pixels);
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds_get_width(ds), 
ds_get_height(ds), 0, tex_format, tex_type, ds_get_data(ds));
     glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 1.0);
     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, 
GL_LINEAR);
     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, 
GL_LINEAR);
@@ -149,12 +126,12 @@
     glBegin(GL_QUADS);
         glTexCoord2d(0, 0);
         glVertex2d(0, 0);
-        glTexCoord2d(ds->width, 0);
-        glVertex2d(screen->w, 0);
-        glTexCoord2d(ds->width, ds->height);
-        glVertex2d(screen->w, screen->h);
-        glTexCoord2d(0, ds->height);
-        glVertex2d(0, screen->h);
+        glTexCoord2d(ds_get_width(ds), 0);
+        glVertex2d(real_screen->w, 0);
+        glTexCoord2d(ds_get_width(ds), ds_get_height(ds));
+        glVertex2d(real_screen->w, real_screen->h);
+        glTexCoord2d(0, ds_get_height(ds));
+        glVertex2d(0, real_screen->h);
     glEnd();
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
     SDL_GL_SwapBuffers();
@@ -163,130 +140,73 @@
 
 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 {
-    //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
-    if (shared) {
-        SDL_Rect rec;
-        rec.x = x;
-        rec.y = y;
-        rec.w = w;
-        rec.h = h;
-        SDL_BlitSurface(shared, &rec, screen, &rec);
-    }
-    SDL_Flip(screen);
+    SDL_Rect rec;
+    rec.x = x;
+    rec.y = y;
+    rec.w = w;
+    rec.h = h;
+    //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);i
+
+    SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
+    SDL_UpdateRect(real_screen, x, y, w, h);
 }
 
-static void sdl_setdata(DisplayState *ds, void *pixels)
+static void sdl_setdata(DisplayState *ds)
 {
-    uint32_t rmask, gmask, bmask, amask = 0;
-    switch (ds_get_bits_per_pixel(ds)) {
-        case 8:
-            rmask = 0x000000E0;
-            gmask = 0x0000001C;
-            bmask = 0x00000003;
-            break;
-        case 16:
-            rmask = 0x0000F800;
-            gmask = 0x000007E0;
-            bmask = 0x0000001F;
-            break;
-        case 24:
-            rmask = 0x00FF0000;
-            gmask = 0x0000FF00;
-            bmask = 0x000000FF;
-            break;
-        case 32:
-            rmask = 0x00FF0000;
-            gmask = 0x0000FF00;
-            bmask = 0x000000FF;
-            break;
-        default:
-            return;
-    }
-    shared = SDL_CreateRGBSurfaceFrom(pixels, width, height, 
ds_get_bits_per_pixel(ds), ds_get_linesize(ds), rmask , gmask, bmask, amask);
-    if (ds_get_bits_per_pixel(ds) == 8 && ds->palette != NULL) {
-        SDL_Color palette[256];
-        int i;
-        for (i = 0; i < 256; i++) {
-            uint8_t rgb = ds->palette[i] >> 16;
-            palette[i].r = ((rgb & 0xe0) >> 5) * 255 / 7;
-            palette[i].g = ((rgb & 0x1c) >> 2) * 255 / 7;
-            palette[i].b = (rgb & 0x3) * 255 / 3;
-        }
-        SDL_SetColors(shared, palette, 0, 256);
-    }
-    ds->data = pixels;
+    SDL_Rect rec;
+    rec.x = 0;
+    rec.y = 0;
+    rec.w = real_screen->w;
+    rec.h = real_screen->h;
+
+    if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
+
+    guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), 
ds_get_height(ds),
+                                            ds_get_bits_per_pixel(ds), 
ds_get_linesize(ds),
+                                            ds->surface->pf.rmask, 
ds->surface->pf.gmask,
+                                            ds->surface->pf.bmask, 
ds->surface->pf.amask);
 }
 
-static void sdl_resize_shared(DisplayState *ds, int w, int h, int depth, int 
linesize, void *pixels)
+static void sdl_resize(DisplayState *ds)
 {
     int flags;
 
     //    printf("resizing to %d %d\n", w, h);
-
-    sdl_colourdepth(ds, depth);
-
 #ifdef CONFIG_OPENGL
-    if (ds->shared_buf && opengl_enabled)
+    if (opengl_enabled)
         flags = SDL_OPENGL|SDL_RESIZABLE;
     else
 #endif
-        flags = 
SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
+        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
 
-    if (gui_fullscreen) {
+    if (gui_fullscreen)
         flags |= SDL_FULLSCREEN;
-        flags &= ~SDL_RESIZABLE;
-    }
     if (gui_noframe)
         flags |= SDL_NOFRAME;
 
-    width = w;
-    height = h;
-
- again:
-    screen = SDL_SetVideoMode(w, h, 0, flags);
-
-    if (!screen) {
-        fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError());
+    width = ds_get_width(ds);
+    height = ds_get_height(ds);
+    real_screen = SDL_SetVideoMode(width, height, 0, flags);
+    if (!real_screen) {
         if (opengl_enabled) {
             /* Fallback to SDL */
             opengl_enabled = 0;
-            ds->dpy_update = sdl_update;
-            ds->dpy_setdata = sdl_setdata;
-            ds->dpy_resize_shared = sdl_resize_shared;
-            sdl_resize_shared(ds, w, h, depth, linesize, pixels);
+            dcl->dpy_update = sdl_update;
+            dcl->dpy_setdata = sdl_setdata;
+            sdl_resize(ds);
             return;
         }
+        fprintf(stderr, "Could not open SDL display\n");
         exit(1);
     }
 
-    if (!opengl_enabled) {
-        if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & 
SDL_FULLSCREEN)) {
-            flags &= ~SDL_HWSURFACE;
-            goto again;
-        }
-
-        if (!screen->pixels) {
-            fprintf(stderr, "Could not open SDL display: %s\n", 
SDL_GetError());
-            exit(1);
-        }
+#ifdef CONFIG_OPENGL
+    if (real_screen->format->Bshift > real_screen->format->Rshift) {
+        bgr = 1;
+    } else {
+        bgr = 0;
     }
-
-    ds->width = w;
-    ds->height = h;
-    if (!ds->shared_buf) {
-        ds->depth = screen->format->BitsPerPixel;
-       if (screen->format->Bshift > screen->format->Rshift) {
-            bgr = 1;
-        } else {
-            bgr = 0;
-        }
-        shared = NULL;
-        ds->data = screen->pixels;
-        ds->linesize = screen->pitch;
-    } else {
-        ds->linesize = linesize;
-#ifdef CONFIG_OPENGL
-        switch(screen->format->BitsPerPixel) {
+    switch(real_screen->format->BitsPerPixel) {
         case 8:
             gl_format = GL_RGB;
             break;
@@ -297,36 +217,15 @@
             gl_format = GL_RGB;
             break;
         case 32:
-            if (!screen->format->Rshift)
+            if (!real_screen->format->Rshift)
                 gl_format = GL_BGRA;
             else
                 gl_format = GL_RGBA;
             break;
-        };
+    };
 #endif
-    }
-    if (ds->shared_buf) ds->dpy_setdata(ds, pixels);
-}
 
-static void sdl_resize(DisplayState *ds, int w, int h)
-{
-    sdl_resize_shared(ds, w, h, 0, w * ds_get_bytes_per_pixel(ds), NULL);
-}
-
-static void sdl_colourdepth(DisplayState *ds, int depth)
-{
-    if (!depth || !ds->depth) {
-       ds->shared_buf = 0;
-       ds->dpy_update = sdl_update;
-       return;
-    }
-    ds->shared_buf = 1;
-    ds->depth = depth;
-#ifdef CONFIG_OPENGL
-    if (opengl_enabled) {
-        ds->dpy_update = opengl_update;
-    }
-#endif
+    dcl->dpy_setdata(ds);
 }
 
 /* generic keyboard conversion */
@@ -525,8 +424,8 @@
        }
 
        SDL_GetMouseState(&dx, &dy);
-        dx = dx * 0x7FFF / (screen->w - 1);
-        dy = dy * 0x7FFF / (screen->h - 1);
+        dx = dx * 0x7FFF / (real_screen->w - 1);
+        dy = dy * 0x7FFF / (real_screen->h - 1);
     } else if (absolute_enabled) {
        sdl_show_cursor();
        absolute_enabled = 0;
@@ -538,7 +437,7 @@
 static void toggle_full_screen(DisplayState *ds)
 {
     gui_fullscreen = !gui_fullscreen;
-    sdl_resize_shared(ds, ds_get_width(ds), ds_get_height(ds), 
ds_get_bits_per_pixel(ds), ds_get_linesize(ds), ds_get_data(ds));
+    sdl_resize(ds);
     if (gui_fullscreen) {
         gui_saved_grab = gui_grab;
         sdl_grab_start();
@@ -566,7 +465,7 @@
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
         case SDL_VIDEOEXPOSE:
-            ds->dpy_update(ds, 0, 0, ds->width, ds->height);
+            dcl->dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
             break;
         case SDL_KEYDOWN:
         case SDL_KEYUP:
@@ -726,23 +625,23 @@
            if (ev->active.state & SDL_APPACTIVE) {
                if (ev->active.gain) {
                    /* Back to default interval */
-                   ds->gui_timer_interval = 0;
-                   ds->idle = 0;
+                   dcl->gui_timer_interval = 0;
+                   dcl->idle = 0;
                } else {
                    /* Sleeping interval */
-                   ds->gui_timer_interval = 500;
-                   ds->idle = 1;
+                   dcl->gui_timer_interval = 500;
+                   dcl->idle = 1;
                }
            }
             break;
 #ifdef CONFIG_OPENGL
         case SDL_VIDEORESIZE:
         {
-            if (ds->shared_buf && opengl_enabled) {
+            if (opengl_enabled) {
                 SDL_ResizeEvent *rev = &ev->resize;
-                screen = SDL_SetVideoMode(rev->w, rev->h, 0, 
SDL_OPENGL|SDL_RESIZABLE);
-                opengl_setdata(ds, ds->data);
-                opengl_update(ds, 0, 0, ds->width, ds->height);
+                real_screen = SDL_SetVideoMode(rev->w, rev->h, 0, 
SDL_OPENGL|SDL_RESIZABLE);
+                opengl_setdata(ds);
+                opengl_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
             }
             break;
         }
@@ -792,17 +691,21 @@
     signal(SIGQUIT, SIG_DFL);
 #endif
 
-    ds->dpy_update = sdl_update;
-    ds->dpy_resize = sdl_resize;
-    ds->dpy_resize_shared = sdl_resize_shared;
-    ds->dpy_refresh = sdl_refresh;
-    ds->dpy_setdata = sdl_setdata;
+    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
+    if (!dcl)
+        exit(1);
+    dcl->dpy_update = sdl_update;
+    dcl->dpy_resize = sdl_resize;
+    dcl->dpy_refresh = sdl_refresh;
+    dcl->dpy_setdata = sdl_setdata;
 #ifdef CONFIG_OPENGL
-    if (opengl_enabled)
-        ds->dpy_setdata = opengl_setdata;
+    if (opengl_enabled) {
+        dcl->dpy_update = opengl_update;
+        dcl->dpy_setdata = opengl_setdata;
+    }
 #endif
+    register_displaychangelistener(ds, dcl);
 
-    sdl_resize(ds, 640, 400);
     sdl_update_caption();
     SDL_EnableKeyRepeat(250, 50);
     gui_grab = 0;
diff --git a/vl.c b/vl.c
--- a/vl.c
+++ b/vl.c
@@ -195,6 +195,7 @@
 static DisplayState display_state;
 int nographic;
 static int curses;
+static int sdl;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
 ram_addr_t ram_size;
@@ -6245,7 +6246,7 @@
 {
 }
 
-static void dumb_resize(DisplayState *ds, int w, int h)
+static void dumb_resize(DisplayState *ds)
 {
 }
 
@@ -6258,14 +6259,15 @@
 
 static void dumb_display_init(DisplayState *ds)
 {
-    ds->data = NULL;
-    ds->linesize = 0;
-    ds->depth = 0;
-    ds->dpy_update = dumb_update;
-    ds->dpy_resize = dumb_resize;
-    ds->dpy_refresh = dumb_refresh;
-    ds->gui_timer_interval = 500;
-    ds->idle = 1;
+    DisplayChangeListener *dcl = qemu_mallocz(sizeof(DisplayChangeListener));
+    if (!dcl)
+        exit(1);
+    dcl->dpy_update = dumb_update;
+    dcl->dpy_resize = dumb_resize;
+    dcl->dpy_refresh = NULL;
+    dcl->idle = 1;
+    dcl->gui_timer_interval = 500;
+    register_displaychangelistener(ds, dcl);
 }
 
 /***********************************************************/
@@ -7901,13 +7903,19 @@
 
 static void gui_update(void *opaque)
 {
+    uint64_t interval = GUI_REFRESH_INTERVAL;
     DisplayState *ds = opaque;
-    ds->dpy_refresh(ds);
-    qemu_mod_timer(ds->gui_timer,
-        (ds->gui_timer_interval ?
-           ds->gui_timer_interval :
-           GUI_REFRESH_INTERVAL)
-       + qemu_get_clock(rt_clock));
+    DisplayChangeListener *dcl = ds->listeners;
+
+    dpy_refresh(ds);
+
+    while (dcl != NULL) {
+        if (dcl->gui_timer_interval &&
+            dcl->gui_timer_interval < interval)
+            interval = dcl->gui_timer_interval;
+        dcl = dcl->next;
+    }
+    qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
 }
 
 struct vm_change_state_entry {
@@ -8394,6 +8402,7 @@
            "-no-frame       open SDL window without a frame and window 
decorations\n"
            "-alt-grab       use Ctrl-Alt-Shift to grab mouse (instead of 
Ctrl-Alt)\n"
            "-no-quit        disable SDL window close capability\n"
+           "-sdl            enable SDL\n"
 #endif
 #ifdef CONFIG_OPENGL
            "-disable-opengl disable OpenGL rendering, using SDL"
@@ -8607,6 +8616,7 @@
     QEMU_OPTION_no_frame,
     QEMU_OPTION_alt_grab,
     QEMU_OPTION_no_quit,
+    QEMU_OPTION_sdl,
     QEMU_OPTION_domid,
     QEMU_OPTION_disable_opengl,
     QEMU_OPTION_direct_pci,
@@ -8727,6 +8737,7 @@
     { "no-frame", 0, QEMU_OPTION_no_frame },
     { "alt-grab", 0, QEMU_OPTION_alt_grab },
     { "no-quit", 0, QEMU_OPTION_no_quit },
+    { "sdl", 0, QEMU_OPTION_sdl },
 #endif
 #ifdef CONFIG_OPENGL
     { "disable-opengl", 0, QEMU_OPTION_disable_opengl },
@@ -9048,6 +9059,7 @@
     const char *kernel_filename, *kernel_cmdline;
     const char *boot_devices = "";
     DisplayState *ds = &display_state;
+    DisplayChangeListener *dcl;
     int cyls, heads, secs, translation;
     const char *net_clients[MAX_NET_CLIENTS];
     int nb_net_clients;
@@ -9593,6 +9605,9 @@
                 break;
             case QEMU_OPTION_no_quit:
                 no_quit = 1;
+                break;
+            case QEMU_OPTION_sdl:
+                sdl = 1;
                 break;
 #endif
             case QEMU_OPTION_disable_opengl:
@@ -10033,6 +10048,7 @@
 
     /* terminal init */
     memset(&display_state, 0, sizeof(display_state));
+    ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
 #ifdef CONFIG_STUBDOM
     if (xenfb_pv_display_init(ds) == 0) {
     } else
@@ -10042,33 +10058,35 @@
             fprintf(stderr, "fatal: -nographic can't be used with -curses\n");
             exit(1);
         }
-        /* nearly nothing to do */
-        dumb_display_init(ds);
-    } else if (vnc_display != NULL || vncunused != 0) {
-       int vnc_display_port;
-        char password[20];
-        vnc_display_init(ds);
-        xenstore_read_vncpasswd(domid, password, sizeof(password));
-        vnc_display_password(ds, password);
-        vnc_display_port = vnc_display_open(ds, vnc_display, vncunused);
-        if (vnc_display_port < 0)
-            exit(1);
-       xenstore_write_vncport(vnc_display_port);
-    } else
+    } else {
 #if defined(CONFIG_CURSES)
-    if (curses) {
-        curses_display_init(ds, full_screen);
-    } else
-#endif
-    {
+        if (curses) {
+            /* At the moment curses cannot be used with other displays */
+            curses_display_init(ds, full_screen);
+        } else
+#endif
+        {
+            if (vnc_display != NULL || vncunused != 0) {
+                int vnc_display_port;
+                char password[20];
+                vnc_display_init(ds);
+                xenstore_read_vncpasswd(domid, password, sizeof(password));
+                vnc_display_password(ds, password);
+                vnc_display_port = vnc_display_open(ds, vnc_display, 
vncunused);
+                if (vnc_display_port < 0)
+                    exit(1);
+                xenstore_write_vncport(vnc_display_port);
+            }
 #if defined(CONFIG_SDL)
-        sdl_display_init(ds, full_screen, no_frame, opengl_enabled);
+            if (sdl || !vnc_display)
+                sdl_display_init(ds, full_screen, no_frame, opengl_enabled);
 #elif defined(CONFIG_COCOA)
-        cocoa_display_init(ds, full_screen);
-#else
-        dumb_display_init(ds);
-#endif
-    }
+            if (sdl || !vnc_display)
+                cocoa_display_init(ds, full_screen);
+#endif
+        }
+    }
+    dpy_resize(ds);
 
 #ifndef _WIN32
     /* must be after terminal init, SDL library changes signal handlers */
@@ -10155,9 +10173,13 @@
         }
     }
 
-    if (display_state.dpy_refresh) {
-        display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, 
&display_state);
-        qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock));
+    dcl = ds->listeners;
+    while (dcl != NULL) {
+        if (dcl->dpy_refresh != NULL) {
+            display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, 
&display_state);
+            qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock));
+        }
+        dcl = dcl->next;
     }
 
 #ifdef CONFIG_GDBSTUB
diff --git a/vnc.c b/vnc.c
--- a/vnc.c
+++ b/vnc.c
@@ -232,6 +232,7 @@
 };
 
 static VncState *vnc_state; /* needed for info vnc */
+static DisplayChangeListener *dcl;
 
 #define DIRTY_PIXEL_BITS 64
 #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
@@ -277,7 +278,7 @@
 static void dequeue_framebuffer_update(VncState *vs);
 static int is_empty_queue(VncState *vs);
 static void free_queue(VncState *vs);
-static void vnc_colourdepth(DisplayState *ds, int depth);
+static void vnc_colordepth(DisplayState *ds);
 
 #if 0
 static inline void vnc_set_bit(uint32_t *d, int k)
@@ -340,8 +341,8 @@
        mask = ~(0ULL);
 
     h += y;
-    if (h > vs->ds->height)
-        h = vs->ds->height;
+    if (h > ds_get_height(vs->ds))
+        h = ds_get_height(vs->ds);
     for (; y < h; y++)
        row[y] |= mask;
 }
@@ -369,69 +370,43 @@
     vnc_write_s32(vs, encoding);
 }
 
-static void vnc_dpy_resize_shared(DisplayState *ds, int w, int h, int depth, 
int linesize, void *pixels)
+static void vnc_dpy_resize(DisplayState *ds)
 {
-    static int allocated;
     int size_changed;
     VncState *vs = ds->opaque;
     int o;
 
-    vnc_colourdepth(ds, depth);
-    if (!ds->shared_buf) {
-        ds->linesize = w * vs->depth;
-        if (allocated)
-            ds->data = qemu_realloc(ds->data,  h * ds->linesize);
-        else
-            ds->data = malloc(h * ds->linesize);
-        allocated = 1;
-    } else {
-        ds->linesize = linesize;
-        if (allocated) {
-            free(ds->data);
-            allocated = 0;
-        }
-    }
-    vs->old_data = qemu_realloc(vs->old_data, h * ds->linesize);
-    vs->dirty_row = qemu_realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
-    vs->update_row = qemu_realloc(vs->update_row, h * 
sizeof(vs->dirty_row[0]));
+    vs->old_data = qemu_realloc(vs->old_data, ds_get_height(ds) * 
ds_get_linesize(ds));
+    vs->dirty_row = qemu_realloc(vs->dirty_row, ds_get_height(ds) * 
sizeof(vs->dirty_row[0]));
+    vs->update_row = qemu_realloc(vs->update_row, ds_get_height(ds) * 
sizeof(vs->dirty_row[0]));
 
-    if (ds->data == NULL || vs->old_data == NULL ||
-       vs->dirty_row == NULL || vs->update_row == NULL) {
+    if (vs->old_data == NULL || vs->dirty_row == NULL || vs->update_row == 
NULL) {
        fprintf(stderr, "vnc: memory allocation failed\n");
        exit(1);
     }
 
-    if (ds->depth != vs->depth * 8) {
-        ds->depth = vs->depth * 8;
+    if (ds_get_bytes_per_pixel(ds) != vs->depth)
         console_color_init(ds);
-    }
-    size_changed = ds->width != w || ds->height != h;
-    ds->width = w;
-    ds->height = h;
+    vnc_colordepth(ds);
+    size_changed = ds_get_width(ds) != vs->width || ds_get_height(ds) != 
vs->height;
     if (vs->csock != -1 && vs->has_resize && size_changed) {
-        vs->width = ds->width;
-        vs->height = ds->height;
+        vs->width = ds_get_width(ds);
+        vs->height = ds_get_height(ds);
         if (vs->update_requested) {
            vnc_write_u8(vs, 0);  /* msg id */
            vnc_write_u8(vs, 0);
            vnc_write_u16(vs, 1); /* number of rects */
-           vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
+           vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), 
ds_get_height(ds), -223);
            vnc_flush(vs);
             vs->update_requested--;
         } else {
-            enqueue_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
+            enqueue_framebuffer_update(vs, 0, 0, ds_get_width(ds), 
ds_get_height(ds), -223);
         }
     }
     vs->dirty_pixel_shift = 0;
-    for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
+    for (o = DIRTY_PIXEL_BITS; o < ds_get_width(ds); o *= 2)
        vs->dirty_pixel_shift++;
-    framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
-    if (ds->shared_buf) ds->data = pixels;
-}
-
-static void vnc_dpy_resize(DisplayState *ds, int w, int h)
-{
-    vnc_dpy_resize_shared(ds, w, h, 0, w * (ds->depth / 8), NULL);
+    framebuffer_set_updated(vs, 0, 0, ds_get_width(ds), ds_get_height(ds));
 }
 
 /* fastest code */
@@ -589,19 +564,8 @@
 
 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int 
dst_y, int w, int h)
 {
-    int src, dst;
-    uint8_t *src_row;
-    uint8_t *dst_row;
-    uint8_t *old_row;
-    int y = 0;
-    int pitch = ds_get_linesize(ds);
     VncState *vs = ds->opaque;
     int updating_client = 1;
-
-    if (ds->shared_buf) {
-        framebuffer_set_updated(vs, dst_x, dst_y, w, h);
-        return;
-    }
 
     if (!vs->update_requested ||
         src_x < vs->visible_x || src_y < vs->visible_y ||
@@ -613,27 +577,7 @@
        updating_client = 0;
 
     if (updating_client)
-       _vnc_update_client(vs);
-
-    if (dst_y > src_y) {
-       y = h - 1;
-       pitch = -pitch;
-    }
-
-    src = (ds_get_linesize(ds) * (src_y + y) + vs->depth * src_x);
-    dst = (ds_get_linesize(ds) * (dst_y + y) + vs->depth * dst_x);
-
-    src_row = ds_get_data(ds) + src;
-    dst_row = ds_get_data(ds) + dst;
-    old_row = vs->old_data + dst;
-
-    for (y = 0; y < h; y++) {
-       memmove(old_row, src_row, w * vs->depth);
-       memmove(dst_row, src_row, w * vs->depth);
-       src_row += pitch;
-       dst_row += pitch;
-       old_row += pitch;
-    }
+        _vnc_update_client(vs);
 
     if (updating_client && vs->csock != -1 && !vs->has_update) {
        vnc_write_u8(vs, 0);  /* msg id */
@@ -695,16 +639,16 @@
     now = qemu_get_clock(rt_clock);
 
     if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
-       width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
+       width_mask = (1ULL << X2DP_UP(vs, ds_get_width(vs->ds))) - 1;
     else
        width_mask = ~(0ULL);
 
     /* Walk through the dirty map and eliminate tiles that really
        aren't dirty */
-    row = vs->ds->data;
+    row = ds_get_data(vs->ds);
     old_row = vs->old_data;
 
-    for (y = 0; y < vs->ds->height; y++) {
+    for (y = 0; y < ds_get_height(vs->ds); y++) {
        if (vs->dirty_row[y] & width_mask) {
            int x;
            uint8_t *ptr, *old_ptr;
@@ -712,7 +656,7 @@
            ptr = row;
            old_ptr = old_row;
 
-           for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
+           for (x = 0; x < X2DP_UP(vs, ds_get_width(vs->ds)); x++) {
                if (vs->dirty_row[y] & (1ULL << x)) {
                    if (memcmp(old_ptr, ptr, tile_bytes)) {
                        vs->has_update = 1;
@@ -727,12 +671,12 @@
            }
        }
   
-       row += vs->ds->linesize;
-       old_row += vs->ds->linesize;
+       row += ds_get_linesize(vs->ds);
+       old_row += ds_get_linesize(vs->ds);
     }
 
-    if (!vs->has_update || vs->visible_y >= vs->ds->height ||
-       vs->visible_x >= vs->ds->width)
+    if (!vs->has_update || vs->visible_y >= ds_get_height(vs->ds) ||
+       vs->visible_x >= ds_get_width(vs->ds))
        goto backoff;
 
     /* Count rectangles */
@@ -743,11 +687,11 @@
     vnc_write_u16(vs, 0);
     
     maxy = vs->visible_y + vs->visible_h;
-    if (maxy > vs->ds->height)
-       maxy = vs->ds->height;
+    if (maxy > ds_get_height(vs->ds))
+       maxy = ds_get_height(vs->ds);
     maxx = vs->visible_x + vs->visible_w;
-    if (maxx > vs->ds->width)
-       maxx = vs->ds->width;
+    if (maxx > ds_get_width(vs->ds))
+       maxx = ds_get_width(vs->ds);
 
     for (y = vs->visible_y; y < maxy; y++) {
        int x;
@@ -791,7 +735,7 @@
     vs->has_update = 0;
     vnc_flush(vs);
     vs->last_update_time = now;
-    vs->ds->idle = 0;
+    dcl->idle = 0;
 
     vs->timer_interval /= 2;
     if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)
@@ -806,7 +750,7 @@
        vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;
        if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {
             if (!vs->update_requested) {
-                vs->ds->idle = 1;
+                dcl->idle = 1;
             } else {
                 /* Send a null update.  If the client is no longer
                    interested (e.g. minimised) it'll ignore this, and we
@@ -992,7 +936,7 @@
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
        closesocket(vs->csock);
        vs->csock = -1;
-       vs->ds->idle = 1;
+       dcl->idle = 1;
        buffer_reset(&vs->input);
        buffer_reset(&vs->output);
         free_queue(vs);
@@ -1213,12 +1157,12 @@
            vnc_write_u8(vs, 0);
            vnc_write_u16(vs, 1);
            vnc_framebuffer_update(vs, absolute, 0,
-                              vs->ds->width, vs->ds->height, -257);
+                              ds_get_width(vs->ds), ds_get_height(vs->ds), 
-257);
            vnc_flush(vs);
             vs->update_requested--;
         } else {
             enqueue_framebuffer_update(vs, absolute, 0,
-                               vs->ds->width, vs->ds->height, -257);
+                               ds_get_width(vs->ds), ds_get_height(vs->ds), 
-257);
         }
     }
     vs->absolute = absolute;
@@ -1241,8 +1185,8 @@
        dz = 1;
 
     if (vs->absolute) {
-        kbd_mouse_event(x * 0x7FFF / (vs->ds->width - 1),
-                        y * 0x7FFF / (vs->ds->height - 1),
+        kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1),
+                        y * 0x7FFF / (ds_get_height(vs->ds) - 1),
                        dz, buttons);
     } else if (vs->has_pointer_type_change) {
        x -= 0x7FFF;
@@ -1568,7 +1512,7 @@
     vs->has_pointer_type_change = 0;
     vs->has_WMVi = 0;
     vs->absolute = -1;
-    vs->ds->dpy_copy = NULL;
+    dcl->dpy_copy = NULL;
 
     for (i = n_encodings - 1; i >= 0; i--) {
        switch (encodings[i]) {
@@ -1576,7 +1520,7 @@
            vs->has_hextile = 0;
            break;
        case 1: /* CopyRect */
-           vs->ds->dpy_copy = vnc_copy;
+           dcl->dpy_copy = vnc_copy;
            break;
        case 5: /* Hextile */
            vs->has_hextile = 1;
@@ -1717,30 +1661,15 @@
     vnc_write(vs, pad, 3);           /* padding */
 }
 
-static void vnc_dpy_setdata(DisplayState *ds, void *pixels)
+static void vnc_dpy_setdata(DisplayState *ds)
 {
-    ds->data = pixels;
+    /* We don't have to do anything */
 }
 
-static void vnc_colourdepth(DisplayState *ds, int depth)
+static void vnc_colordepth(DisplayState *ds)
 {
     int host_big_endian_flag;
     struct VncState *vs = ds->opaque;
-
-    switch (depth) {
-        case 24:
-            ds->shared_buf = 0;
-            if (ds->depth == 32) return;
-            depth = 32;
-            break;
-        case 8:
-        case 0:
-            ds->shared_buf = 0;
-            return;
-        default:
-            ds->shared_buf = 1;
-            break;
-    }
 
 #ifdef WORDS_BIGENDIAN
     host_big_endian_flag = 1;
@@ -1748,9 +1677,9 @@
     host_big_endian_flag = 0;
 #endif   
     
-    switch (depth) {
+    switch (ds_get_bits_per_pixel(ds)) {
         case 8:
-            vs->depth = depth / 8;
+            vs->depth = 1;
             vs->red_max1 = 7;
             vs->green_max1 = 7;
             vs->blue_max1 = 3;
@@ -1759,7 +1688,7 @@
             vs->blue_shift1 = 0;
             break;
         case 16:
-            vs->depth = depth / 8;
+            vs->depth = 2;
             vs->red_max1 = 31;
             vs->green_max1 = 63;
             vs->blue_max1 = 31;
@@ -1787,12 +1716,12 @@
             vnc_write_u8(vs, 0);  /* msg id */
             vnc_write_u8(vs, 0);
             vnc_write_u16(vs, 1); /* number of rects */
-            vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 
0x574D5669);
+            vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), 
ds_get_height(ds), 0x574D5669);
             pixel_format_message(vs);
             vnc_flush(vs);
             vs->update_requested--;
         } else {
-            enqueue_framebuffer_update(vs, 0, 0, ds->width, ds->height, 
0x574D5669);
+            enqueue_framebuffer_update(vs, 0, 0, ds_get_width(ds), 
ds_get_height(ds), 0x574D5669);
         }
     } else {
         if (vs->pix_bpp == 4 && vs->depth == 4 &&
@@ -2536,17 +2465,17 @@
     vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
     if (vs->csock != -1) {
        VNC_DEBUG("New client on socket %d\n", vs->csock);
-       vs->ds->idle = 0;
+       dcl->idle = 0;
         socket_set_nonblock(vs->csock);
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
        vnc_write(vs, "RFB 003.008\n", 12);
        vnc_flush(vs);
        vnc_read_when(vs, protocol_version, 12);
-       framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
+       framebuffer_set_updated(vs, 0, 0, ds_get_width(vs->ds), 
ds_get_height(vs->ds));
        vs->has_resize = 0;
        vs->has_hextile = 0;
         vs->update_requested = 0;
-       vs->ds->dpy_copy = NULL;
+       dcl->dpy_copy = NULL;
        vnc_timer_init(vs);
     }
 }
@@ -2558,11 +2487,12 @@
     VncState *vs;
 
     vs = qemu_mallocz(sizeof(VncState));
-    if (!vs)
+    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
+    if (!vs || !dcl)
        exit(1);
 
     ds->opaque = vs;
-    ds->idle = 1;
+    dcl->idle = 1;
     vnc_state = vs;
     vs->display = NULL;
     vs->password = NULL;
@@ -2582,17 +2512,11 @@
        exit(1);
     vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
 
-    vs->ds->data = NULL;
-    vs->ds->dpy_update = vnc_dpy_update;
-    vs->ds->dpy_resize = vnc_dpy_resize;
-    vs->ds->dpy_setdata = vnc_dpy_setdata;
-    vs->ds->dpy_resize_shared = vnc_dpy_resize_shared;
-    vs->ds->dpy_refresh = NULL;
-
-    vs->ds->width = 640;
-    vs->ds->height = 400;
-    vs->ds->linesize = 640 * 4;
-    vnc_dpy_resize_shared(ds, ds->width, ds->height, 24, ds->linesize, NULL);
+    dcl->dpy_update = vnc_dpy_update;
+    dcl->dpy_resize = vnc_dpy_resize;
+    dcl->dpy_setdata = vnc_dpy_setdata;
+    dcl->dpy_refresh = NULL;
+    register_displaychangelistener(ds, dcl);
 }
 
 #ifdef CONFIG_VNC_TLS
diff --git a/xenfbfront.c b/xenfbfront.c
--- a/xenfbfront.c
+++ b/xenfbfront.c
@@ -23,6 +23,7 @@
 static char *kbd_path, *fb_path;
 
 static unsigned char linux2scancode[KEY_MAX + 1];
+static DisplayChangeListener *dcl;
 
 extern uint32_t vga_ram_size;
 
@@ -47,50 +48,27 @@
     fbfront_update(fb_dev, x, y, w, h);
 }
 
-static void xenfb_pv_resize_shared(DisplayState *ds, int w, int h, int depth, 
int linesize, void *pixels)
+static void xenfb_pv_resize(DisplayState *ds)
 {
     XenFBState *xs = ds->opaque;
     struct fbfront_dev *fb_dev = xs->fb_dev;
     int offset;
 
-    fprintf(stderr,"resize to %dx%d@%d, %d required\n", w, h, depth, linesize);
-    ds->width = w;
-    ds->height = h;
-    if (!depth) {
-        ds->shared_buf = 0;
-        ds->depth = 32;
-    } else {
-        ds->shared_buf = 1;
-        ds->depth = depth;
-    }
-    if (!linesize)
-        ds->shared_buf = 0;
-    if (!ds->shared_buf)
-        linesize = w * 4;
-    ds->linesize = linesize;
+    fprintf(stderr,"resize to %dx%d@%d, %d required\n", ds_get_width(ds), 
ds_get_height(ds), ds_get_bits_per_pixel(ds), ds_get_linesize(ds));
     if (!fb_dev)
         return;
-    if (ds->shared_buf) {
-        offset = pixels - xs->vga_vram;
-        ds->data = pixels;
-        fbfront_resize(fb_dev, ds_get_width(ds), ds_get_height(ds), 
ds_get_linesize(ds), ds_get_bits_per_pixel(ds), offset);
-    } else {
-        ds->data = xs->nonshared_vram;
-        fbfront_resize(fb_dev, w, h, linesize, ds_get_bits_per_pixel(ds), 
vga_ram_size);
-    }
+    if (!(ds->surface->flags & QEMU_ALLOCATED_FLAG))
+        offset = ((void *) ds_get_data(ds)) - xs->vga_vram;
+    else
+        offset = vga_ram_size;
+    fbfront_resize(fb_dev, ds_get_width(ds), ds_get_height(ds), 
ds_get_linesize(ds), ds_get_bits_per_pixel(ds), offset);
 }
 
-static void xenfb_pv_resize(DisplayState *ds, int w, int h)
-{
-    xenfb_pv_resize_shared(ds, w, h, 0, 0, NULL);
-}
-
-static void xenfb_pv_setdata(DisplayState *ds, void *pixels)
+static void xenfb_pv_setdata(DisplayState *ds)
 {
     XenFBState *xs = ds->opaque;
     struct fbfront_dev *fb_dev = xs->fb_dev;
-    int offset = pixels - xs->vga_vram;
-    ds->data = pixels;
+    int offset = ((void *) ds_get_data(ds)) - xs->vga_vram;
     if (!fb_dev)
         return;
     fbfront_resize(fb_dev, ds_get_width(ds), ds_get_height(ds), 
ds_get_linesize(ds), ds_get_bits_per_pixel(ds), offset);
@@ -115,12 +93,12 @@
         case XENFB_TYPE_REFRESH_PERIOD:
             if (buf[i].refresh_period.period == XENFB_NO_REFRESH) {
                 /* Sleeping interval */
-                ds->idle = 1;
-                ds->gui_timer_interval = 500;
+                dcl->idle = 1;
+                dcl->gui_timer_interval = 500;
             } else {
                 /* Set interval */
-                ds->idle = 0;
-                ds->gui_timer_interval = buf[i].refresh_period.period;
+                dcl->idle = 0;
+                dcl->gui_timer_interval = buf[i].refresh_period.period;
             }
         default:
             /* ignore unknown events */
@@ -247,22 +225,19 @@
 
     init_SEMAPHORE(&xs->kbd_sem, 0);
     xs->ds = ds;
+    xs->nonshared_vram = ds_get_data(ds);
 
     create_thread("kbdfront", kbdfront_thread, (void*) xs);
 
-    ds->data = xs->nonshared_vram = qemu_memalign(PAGE_SIZE, vga_ram_size);
-    memset(ds->data, 0, vga_ram_size);
+    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
+    if (!dcl)
+        exit(1);
     ds->opaque = xs;
-    ds->depth = 32;
-    ds->bgr = 0;
-    ds->width = 640;
-    ds->height = 400;
-    ds->linesize = 640 * 4;
-    ds->dpy_update = xenfb_pv_update;
-    ds->dpy_resize = xenfb_pv_resize;
-    ds->dpy_resize_shared = xenfb_pv_resize_shared;
-    ds->dpy_setdata = xenfb_pv_setdata;
-    ds->dpy_refresh = xenfb_pv_refresh;
+    dcl->dpy_update = xenfb_pv_update;
+    dcl->dpy_resize = xenfb_pv_resize;
+    dcl->dpy_setdata = xenfb_pv_setdata;
+    dcl->dpy_refresh = xenfb_pv_refresh;
+    register_displaychangelistener(ds, dcl);
     return 0;
 }
 
@@ -295,11 +270,10 @@
     }
     free(fb_path);
 
-    if (ds->shared_buf) {
-        offset = (void*) ds->data - xs->vga_vram;
+    if (!(ds->surface->flags & QEMU_ALLOCATED_FLAG)) {
+        offset = (void*) ds_get_data(ds) - xs->vga_vram;
     } else {
         offset = vga_ram_size;
-        ds->data = xs->nonshared_vram;
     }
     if (offset)
         fbfront_resize(fb_dev, ds_get_width(ds), ds_get_height(ds), 
ds_get_linesize(ds), ds_get_bits_per_pixel(ds), offset);

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.