]> xenbits.xensource.com Git - qemu-xen-4.0-testing.git/commitdiff
introducing a DisplayAllocator interface
authorIan Jackson <ian.jackson@eu.citrix.com>
Tue, 10 Mar 2009 18:17:31 +0000 (18:17 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Tue, 10 Mar 2009 18:17:31 +0000 (18:17 +0000)
This patch introduces a new DisplayAllocator interface to allow
frontends to allocate the DisplaySurface for the graphic device to use.
At the moment it is used only by xenfbfront, to be able to page align
the displaysurface and also keep the same backing data across multiple
DisplaySurface resize.
Howeveri in the near future it is going to be a useful improvement for
SDL as well.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
console.c
console.h
curses.c
hw/nseries.c
hw/palm.c
hw/vga.c
qemu-common.h
vl.c
xenfbfront.c

index db2ea53c9da239516a97565c0301a8346d41d3e1..147daf16d2949fe775fe19744e5e528c15770fe8 100644 (file)
--- a/console.c
+++ b/console.c
@@ -1033,7 +1033,7 @@ void console_select(unsigned int index)
         DisplayState *ds = s->ds;
         active_console = s;
         if (ds_get_bits_per_pixel(s->ds)) {
-            ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
+            ds->surface = qemu_resize_displaysurface(ds, s->g_width,
                     s->g_height, 32, 4 * s->g_width);
         } else {
             s->ds->surface->width = s->width;
@@ -1247,11 +1247,12 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
     ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
     if (ds == NULL)
         return NULL;
-    ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
+    ds->allocator = &default_allocator; 
+    ds->surface = qemu_create_displaysurface(ds, 640, 480, 32, 640 * 4);
 
     s = new_console(ds, GRAPHIC_CONSOLE);
     if (s == NULL) {
-        qemu_free_displaysurface(ds->surface);
+        qemu_free_displaysurface(ds);
         qemu_free(ds);
         return NULL;
     }
@@ -1401,7 +1402,7 @@ void qemu_console_resize(DisplayState *ds, int width, int height)
     s->g_width = width;
     s->g_height = height;
     if (is_graphic_console()) {
-        ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width);
+        ds->surface = qemu_resize_displaysurface(ds, width, height, 32, 4 * width);
         dpy_resize(ds);
     }
 }
@@ -1524,11 +1525,11 @@ PixelFormat qemu_default_pixelformat(int bpp)
     return pf;
 }
 
-DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
+DisplaySurface* defaultallocator_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");
+        fprintf(stderr, "defaultallocator_create_displaysurface: malloc failed\n");
         exit(1);
     }
 
@@ -1543,14 +1544,14 @@ DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int l
 #endif
     surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
     if (surface->data == NULL) {
-        fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
+        fprintf(stderr, "defaultallocator_create_displaysurface: malloc failed\n");
         exit(1);
     }
 
     return surface;
 }
 
-DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
+DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
                                           int width, int height, int bpp, int linesize)
 {
     surface->width = width;
@@ -1562,7 +1563,7 @@ DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
     else
         surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
     if (surface->data == NULL) {
-        fprintf(stderr, "qemu_resize_displaysurface: malloc failed\n");
+        fprintf(stderr, "defaultallocator_resize_displaysurface: malloc failed\n");
         exit(1);
     }
 #ifdef WORDS_BIGENDIAN
@@ -1595,7 +1596,7 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
     return surface;
 }
 
-void qemu_free_displaysurface(DisplaySurface *surface)
+void defaultallocator_free_displaysurface(DisplaySurface *surface)
 {
     if (surface == NULL)
         return;
index 0006230d867bfe5fd87f8cf9984ee12457a41daa..3919e88955b53526dadcf64320520d2d6a68d6b1 100644 (file)
--- a/console.h
+++ b/console.h
@@ -107,11 +107,19 @@ struct DisplayChangeListener {
     struct DisplayChangeListener *next;
 };
 
+struct DisplayAllocator {
+    DisplaySurface* (*create_displaysurface)(int width, int height, int bpp, int linesize);
+    DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface,
+            int width, int height, int bpp, int linesize);
+    void (*free_displaysurface)(DisplaySurface *surface);
+};
+
 struct DisplayState {
     struct DisplaySurface *surface;
     void *opaque;
     struct QEMUTimer *gui_timer;
 
+    struct DisplayAllocator* allocator;
     struct DisplayChangeListener* listeners;
 
     void (*mouse_set)(int x, int y, int on);
@@ -123,15 +131,33 @@ struct DisplayState {
 
 void register_displaystate(DisplayState *ds);
 DisplayState *get_displaystate(void);
-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);
 
+extern struct DisplayAllocator default_allocator;
+DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da);
+DisplaySurface* defaultallocator_create_displaysurface(int width, int height, int bpp, int linesize);
+DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
+        int width, int height, int bpp, int linesize);
+void defaultallocator_free_displaysurface(DisplaySurface *surface);
+
+static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height, int bpp, int linesize)
+{
+    return ds->allocator->create_displaysurface(width, height, bpp, linesize);    
+}
+
+static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height, int bpp, int linesize)
+{
+    return ds->allocator->resize_displaysurface(ds->surface, width, height, bpp, linesize);
+}
+
+static inline void qemu_free_displaysurface(DisplayState *ds)
+{
+    ds->allocator->free_displaysurface(ds->surface);
+}
+
 static inline int is_buffer_shared(DisplaySurface *surface)
 {
     return (!(surface->flags & QEMU_ALLOCATED_FLAG));
index 97ab41263296df22be52f225c3aa8d259e4f0e3a..8a9083dceeeb3825a913bc2d5c380e0ab4d46137 100644 (file)
--- a/curses.c
+++ b/curses.c
@@ -368,7 +368,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
     dcl->dpy_refresh = curses_refresh;
     dcl->dpy_text_cursor = curses_cursor_position;
     register_displaychangelistener(ds, dcl);
-    qemu_free_displaysurface(ds->surface);
+    qemu_free_displaysurface(ds);
     ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
 
     invalidate = 1;
index 7003b02a53dacebcbd496f0445604f2be9ea7bc5..db6bf609df59a12324ba2d85a7f9807e0d7ad832 100644 (file)
@@ -1362,7 +1362,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
     /* 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.  */
-    ds->surface = qemu_resize_displaysurface(ds->surface, 800, 480, 32, 4 * 800);
+    ds->surface = qemu_resize_displaysurface(ds, 800, 480, 32, 4 * 800);
     dpy_resize(ds);
 }
 
index 95176213c4f8129e0069ea2f70851eb4eb4f0a92..1c09d383ec9ce7ffc0fea33f4316019c87cd19e4 100644 (file)
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -279,7 +279,7 @@ static void palmte_init(ram_addr_t ram_size, int vga_ram_size,
     /* 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.  */
-    ds->surface = qemu_resize_displaysurface(ds->surface, 320, 320, 32, 4 * 320);
+    ds->surface = qemu_resize_displaysurface(ds, 320, 320, 32, 4 * 320);
     dpy_resize(ds);
 }
 
index 0d5dff4b9e017476d22f4a3b06ceabd35d8c27f0..13519255794af03c9f9060183df37510deb39076 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1628,7 +1628,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         if (depth == 32) {
 #endif
             if (is_graphic_console()) {
-                qemu_free_displaysurface(s->ds->surface);
+                qemu_free_displaysurface(s->ds);
                 s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
                                                                s->line_offset,
                                                                s->vram_ptr + (s->start_addr * 4));
@@ -2769,7 +2769,7 @@ static void vga_screen_dump(void *opaque, const char *filename)
     dcl.dpy_resize = vga_save_dpy_resize;
     dcl.dpy_refresh = vga_save_dpy_refresh;
     register_displaychangelistener(ds, &dcl);
-    ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w);
+    ds->surface = qemu_create_displaysurface(ds, w, h, 32, 4 * w);
  
     s->ds = ds;
     s->graphic_mode = -1;
@@ -2777,6 +2777,6 @@ static void vga_screen_dump(void *opaque, const char *filename)
 
     ppm_save(filename, ds->surface);
 
-    qemu_free_displaysurface(ds->surface);
+    qemu_free_displaysurface(ds);
     s->ds = saved_ds;
 }
index 99e1bffc3f1cd7cd3f8d306f6e9a510f0f834d42..d17810945a3220ce3687a2f9018a3fc4d3b32b43 100644 (file)
@@ -133,6 +133,7 @@ typedef struct BlockDriverState BlockDriverState;
 typedef struct DisplayState DisplayState;
 typedef struct DisplayChangeListener DisplayChangeListener;
 typedef struct DisplaySurface DisplaySurface;
+typedef struct DisplayAllocator DisplayAllocator;
 typedef struct PixelFormat PixelFormat;
 typedef struct TextConsole TextConsole;
 typedef TextConsole QEMUConsole;
diff --git a/vl.c b/vl.c
index 52836d1cc62dfa1f90536104e4d02e31a3fe49aa..134a2e8394dc0771b4c25f948de4cb3339a58603 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -6243,6 +6243,12 @@ void pcmcia_info(void)
 /***********************************************************/
 /* register display */
 
+struct DisplayAllocator default_allocator = {
+    defaultallocator_create_displaysurface,
+    defaultallocator_resize_displaysurface,
+    defaultallocator_free_displaysurface
+};
+
 void register_displaystate(DisplayState *ds)
 {
     DisplayState **s;
@@ -6258,6 +6264,12 @@ DisplayState *get_displaystate(void)
     return display_state;
 }
 
+DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
+{
+    if(ds->allocator ==  &default_allocator) ds->allocator = da;
+    return ds->allocator;
+}
+
 /* dumb display */
 
 static void dumb_display_init(void)
@@ -6267,7 +6279,8 @@ static void dumb_display_init(void)
         fprintf(stderr, "dumb_display_init: DisplayState allocation failed\n");
         exit(1);
     }
-    ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
+    ds->allocator = &default_allocator;
+    ds->surface = qemu_create_displaysurface(ds, 640, 480, 32, 640 * 4);
     register_displaystate(ds);
 }
 
@@ -10107,6 +10120,9 @@ int main(int argc, char **argv)
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model,
                  direct_pci);
 
+    if (loadvm)
+        do_loadvm(loadvm);
+
     /* init USB devices */
     if (usb_enabled) {
         for(i = 0; i < usb_devices_index; i++) {
@@ -10219,9 +10235,6 @@ int main(int argc, char **argv)
     }
 #endif
 
-    if (loadvm)
-        do_loadvm(loadvm);
-
     if (incoming) {
         autostart = 0; /* fixme how to deal with -daemonize */
         qemu_start_incoming_migration(incoming);
index 491bc421bd068c7f66c8e78c88a1c1b319df3477..af8e0ae5393994050880279ad7c33371100e51c5 100644 (file)
@@ -215,6 +215,76 @@ static void kbdfront_thread(void *p)
     }
 }
 
+
+static DisplaySurface* xenfb_create_displaysurface(int width, int height, int bpp, int linesize)
+{
+    DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
+    if (surface == NULL) {
+        fprintf(stderr, "xenfb_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 = xs->nonshared_vram;
+
+    return surface;
+}
+
+static DisplaySurface* xenfb_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);
+#ifdef WORDS_BIGENDIAN
+    surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+#else
+    surface->flags = QEMU_ALLOCATED_FLAG;
+#endif
+    surface->data = xs->nonshared_vram;
+
+    return surface;
+}
+
+static void xenfb_free_displaysurface(DisplaySurface *surface)
+{
+    if (surface == NULL)
+        return;
+    qemu_free(surface);
+}
+
+static void xenfb_pv_display_allocator(void)
+{
+    DisplaySurface *ds;
+    DisplayAllocator *da = qemu_mallocz(sizeof(DisplayAllocator));
+    da->create_displaysurface = xenfb_create_displaysurface;
+    da->resize_displaysurface = xenfb_resize_displaysurface;
+    da->free_displaysurface = xenfb_free_displaysurface;
+    if (register_displayallocator(xs->ds, da) != da) {
+        fprintf(stderr, "xenfb_pv_display_allocator: could not register DisplayAllocator\n");
+        exit(1);
+    }
+
+    xs->nonshared_vram = qemu_memalign(PAGE_SIZE, vga_ram_size);
+    if (!xs->nonshared_vram) {
+        fprintf(stderr, "xenfb_pv_display_allocator: could not allocate nonshared_vram\n");
+        exit(1);
+    }
+
+    ds = xenfb_create_displaysurface(ds_get_width(xs->ds), ds_get_height(xs->ds), ds_get_bits_per_pixel(xs->ds), ds_get_linesize(xs->ds));
+    qemu_free_displaysurface(xs->ds);
+    xs->ds->surface = ds;
+}
+
 int xenfb_pv_display_init(DisplayState *ds)
 {
     struct fbfront_dev *fb_dev;
@@ -233,7 +303,8 @@ int xenfb_pv_display_init(DisplayState *ds)
 
     init_SEMAPHORE(&xs->kbd_sem, 0);
     xs->ds = ds;
-    xs->nonshared_vram = ds_get_data(ds);
+
+    xenfb_pv_display_allocator();
 
     create_thread("kbdfront", kbdfront_thread, (void*) xs);