]> xenbits.xen.org Git - xenclient/ioemu.git/commitdiff
sync DisplayAllocator interface
authorIan Jackson <ian.jackson@eu.citrix.com>
Wed, 8 Apr 2009 16:32:57 +0000 (17:32 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Wed, 8 Apr 2009 16:32:57 +0000 (17:32 +0100)
this simple patch sync's the DisplayAllocator interface with upstream
qemu. The only non trivial change, is the new ability for sdl to support
the DisplayAllocator interface, hence improving performances (avoid a
memcpy) when the guest is in text mode or uses a color depth of 8bpp or
24bpp (no DisplayState surface sharing allowed).

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
console.c
console.h
hw/vga.c
hw/xenfb.c
sdl.c
vl.c
xenfbfront.c

index 66b154b24031be3c5af08c0182d328ea1d2e89a2..5e6e3d09f875331416e3ff476cb8ab19f63f6f2e 100644 (file)
--- a/console.c
+++ b/console.c
@@ -1033,8 +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, s->g_width,
-                    s->g_height, 32, 4 * s->g_width);
+            ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
         } else {
             s->ds->surface->width = s->width;
             s->ds->surface->height = s->height;
@@ -1243,7 +1242,7 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
 
     ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
     ds->allocator = &default_allocator; 
-    ds->surface = qemu_create_displaysurface(ds, 640, 480, 32, 640 * 4);
+    ds->surface = qemu_create_displaysurface(ds, 640, 480);
 
     s = new_console(ds, GRAPHIC_CONSOLE);
     if (s == NULL) {
@@ -1395,7 +1394,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, width, height, 32, 4 * width);
+        ds->surface = qemu_resize_displaysurface(ds, width, height);
         dpy_resize(ds);
     }
 }
@@ -1518,14 +1517,14 @@ PixelFormat qemu_default_pixelformat(int bpp)
     return pf;
 }
 
-DisplaySurface* defaultallocator_create_displaysurface(int width, int height, int bpp, int linesize)
+DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
 {
     DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
 
     surface->width = width;
     surface->height = height;
-    surface->linesize = linesize;
-    surface->pf = qemu_default_pixelformat(bpp);
+    surface->linesize = width * 4;
+    surface->pf = qemu_default_pixelformat(32);
 #ifdef WORDS_BIGENDIAN
     surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
 #else
@@ -1537,12 +1536,12 @@ DisplaySurface* defaultallocator_create_displaysurface(int width, int height, in
 }
 
 DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
-                                          int width, int height, int bpp, int linesize)
+                                          int width, int height)
 {
     surface->width = width;
     surface->height = height;
-    surface->linesize = linesize;
-    surface->pf = qemu_default_pixelformat(bpp);
+    surface->linesize = width * 4;
+    surface->pf = qemu_default_pixelformat(32);
     if (surface->flags & QEMU_ALLOCATED_FLAG)
         surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
     else
index aa735a82e6b511a54eccb0479689739d4f1f7291..4c29be478f29304f6dff55be15d4eae2fdce5580 100644 (file)
--- a/console.h
+++ b/console.h
@@ -108,9 +108,8 @@ struct DisplayChangeListener {
 };
 
 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);
+    DisplaySurface* (*create_displaysurface)(int width, int height);
+    DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
     void (*free_displaysurface)(DisplaySurface *surface);
 };
 
@@ -138,19 +137,18 @@ 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);
+DisplaySurface* defaultallocator_create_displaysurface(int width, int height);
+DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, int width, int height);
 void defaultallocator_free_displaysurface(DisplaySurface *surface);
 
-static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height, int bpp, int linesize)
+static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height)
 {
-    return ds->allocator->create_displaysurface(width, height, bpp, linesize);    
+    return ds->allocator->create_displaysurface(width, height);    
 }
 
-static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height, int bpp, int linesize)
+static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
 {
-    return ds->allocator->resize_displaysurface(ds->surface, width, height, bpp, linesize);
+    return ds->allocator->resize_displaysurface(ds->surface, width, height);
 }
 
 static inline void qemu_free_displaysurface(DisplayState *ds)
@@ -158,6 +156,14 @@ static inline void qemu_free_displaysurface(DisplayState *ds)
     ds->allocator->free_displaysurface(ds->surface);
 }
 
+static inline int is_surface_bgr(DisplaySurface *surface)
+{
+    if (surface->pf.bits_per_pixel == 32 && surface->pf.rshift == 0)
+        return 1;
+    else
+        return 0;
+}
+
 static inline int is_buffer_shared(DisplaySurface *surface)
 {
     return (!(surface->flags & QEMU_ALLOCATED_FLAG));
index 422a2f58fbe238374b66eab0c8e4550edc6d011d..de5873558966525d6324e9bada652e8241ed8231 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1173,7 +1173,10 @@ static inline int get_depth_index(DisplayState *s)
     case 16:
         return 2;
     case 32:
-        return 3;
+        if (is_surface_bgr(s->surface))
+            return 4;
+        else
+            return 3;
     }
 }
 
@@ -2794,7 +2797,8 @@ 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(ds, w, h, 32, 4 * w);
+    ds->allocator = &default_allocator;
+    ds->surface = qemu_create_displaysurface(ds, w, h);
  
     s->ds = ds;
     s->graphic_mode = -1;
index 31bc8f3d9c48463a559448c8040afdb280d702d1..4b71bf2825b3b499df0669ef3bafec163b8e5ea0 100644 (file)
@@ -744,9 +744,7 @@ static void xenfb_update(void *opaque)
             break;
         default:
             /* we must convert stuff */
-            qemu_resize_displaysurface(xenfb->c.ds,
-                                       xenfb->width, xenfb->height,
-                                       xenfb->depth, xenfb->row_stride);
+            qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, xenfb->height);
             break;
         }
         dpy_resize(xenfb->c.ds);
diff --git a/sdl.c b/sdl.c
index 4c676c043d7a8d1379a5099e906b2344f71fef11..5d636074db1c50b6060cd605bf2d7b0ab66f41c6 100644 (file)
--- a/sdl.c
+++ b/sdl.c
@@ -55,6 +55,8 @@ static SDL_Cursor *sdl_cursor_normal;
 static SDL_Cursor *sdl_cursor_hidden;
 static int absolute_enabled = 0;
 static int opengl_enabled;
+static uint8_t allocator;
+static uint8_t hostbpp;
 
 #ifdef CONFIG_OPENGL
 static GLint tex_format;
@@ -142,14 +144,15 @@ static void opengl_update(DisplayState *ds, int x, int y, int w, int h)
 
 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 {
-    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);
+    if (guest_screen) {
+        SDL_Rect rec;
+        rec.x = x;
+        rec.y = y;
+        rec.w = w;
+        rec.h = h;
+        SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
+    }
     SDL_UpdateRect(real_screen, x, y, w, h);
 }
 
@@ -169,7 +172,7 @@ static void sdl_setdata(DisplayState *ds)
                                             ds->surface->pf.bmask, ds->surface->pf.amask);
 }
 
-static void sdl_resize(DisplayState *ds)
+static void do_sdl_resize(int new_width, int new_height, int bpp)
 {
     int flags;
 
@@ -186,16 +189,16 @@ static void sdl_resize(DisplayState *ds)
     if (gui_noframe)
         flags |= SDL_NOFRAME;
 
-    width = ds_get_width(ds);
-    height = ds_get_height(ds);
-    real_screen = SDL_SetVideoMode(width, height, 0, flags);
+    width = new_width;
+    height = new_height;
+    real_screen = SDL_SetVideoMode(width, height, bpp, flags);
     if (!real_screen) {
         if (opengl_enabled) {
             /* Fallback to SDL */
             opengl_enabled = 0;
             dcl->dpy_update = sdl_update;
             dcl->dpy_setdata = sdl_setdata;
-            sdl_resize(ds);
+            do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
             return;
         }
         fprintf(stderr, "Could not open SDL display\n");
@@ -226,8 +229,96 @@ static void sdl_resize(DisplayState *ds)
             break;
     };
 #endif
+}
+
+static void sdl_resize(DisplayState *ds)
+{
+    if  (!allocator) {
+        do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
+        dcl->dpy_setdata(ds);
+    } else {
+        if (guest_screen != NULL) {
+            SDL_FreeSurface(guest_screen);
+            guest_screen = NULL;
+        }
+    }
+}
+
+static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
+{
+    PixelFormat qemu_pf;
+
+    memset(&qemu_pf, 0x00, sizeof(PixelFormat));
+
+    qemu_pf.bits_per_pixel = sdl_pf->BitsPerPixel;
+    qemu_pf.bytes_per_pixel = sdl_pf->BytesPerPixel;
+    qemu_pf.depth = (qemu_pf.bits_per_pixel) == 32 ? 24 : (qemu_pf.bits_per_pixel);
+
+    qemu_pf.rmask = sdl_pf->Rmask;
+    qemu_pf.gmask = sdl_pf->Gmask;
+    qemu_pf.bmask = sdl_pf->Bmask;
+    qemu_pf.amask = sdl_pf->Amask;
 
-    dcl->dpy_setdata(ds);
+    qemu_pf.rshift = sdl_pf->Rshift;
+    qemu_pf.gshift = sdl_pf->Gshift;
+    qemu_pf.bshift = sdl_pf->Bshift;
+    qemu_pf.ashift = sdl_pf->Ashift;
+
+    qemu_pf.rbits = 8 - sdl_pf->Rloss;
+    qemu_pf.gbits = 8 - sdl_pf->Gloss;
+    qemu_pf.bbits = 8 - sdl_pf->Bloss;
+    qemu_pf.abits = 8 - sdl_pf->Aloss;
+
+    qemu_pf.rmax = ((1 << qemu_pf.rbits) - 1);
+    qemu_pf.gmax = ((1 << qemu_pf.gbits) - 1);
+    qemu_pf.bmax = ((1 << qemu_pf.bbits) - 1);
+    qemu_pf.amax = ((1 << qemu_pf.abits) - 1);
+
+    return qemu_pf;
+}
+
+static DisplaySurface* sdl_create_displaysurface(int width, int height)
+{
+    DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
+    if (surface == NULL) {
+        fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
+        exit(1);
+    }
+
+    surface->width = width;
+    surface->height = height;
+
+    if (hostbpp == 16)
+        do_sdl_resize(width, height, 16);
+    else
+        do_sdl_resize(width, height, 32);
+
+    surface->pf = sdl_to_qemu_pixelformat(real_screen->format);
+    surface->linesize = real_screen->pitch;
+    surface->data = real_screen->pixels;
+
+#ifdef WORDS_BIGENDIAN
+    surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+#else
+    surface->flags = QEMU_ALLOCATED_FLAG;
+#endif
+    allocator = 1;
+
+    return surface;
+}
+
+static void sdl_free_displaysurface(DisplaySurface *surface)
+{
+    allocator = 0;
+    if (surface == NULL)
+        return;
+    qemu_free(surface);
+}
+
+static DisplaySurface* sdl_resize_displaysurface(DisplaySurface *surface, int width, int height)
+{
+    sdl_free_displaysurface(surface);
+    return sdl_create_displaysurface(width, height);
 }
 
 /* generic keyboard conversion */
@@ -758,6 +849,26 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame, int openg
 #endif
     register_displaychangelistener(ds, dcl);
 
+    if (!opengl_enabled) {
+        DisplayAllocator *da;
+        const SDL_VideoInfo *vi;
+
+        vi = SDL_GetVideoInfo();
+        hostbpp = vi->vfmt->BitsPerPixel;
+
+        da = qemu_mallocz(sizeof(DisplayAllocator));
+        da->create_displaysurface = sdl_create_displaysurface;
+        da->resize_displaysurface = sdl_resize_displaysurface;
+        da->free_displaysurface = sdl_free_displaysurface;
+        if (register_displayallocator(ds, da) == da) {
+            DisplaySurface *surf;
+            surf = sdl_create_displaysurface(ds_get_width(ds), ds_get_height(ds));
+            defaultallocator_free_displaysurface(ds->surface);
+            ds->surface = surf;
+            dpy_resize(ds);
+        }
+    }
+
     sdl_update_caption();
     SDL_EnableKeyRepeat(250, 50);
     gui_grab = 0;
diff --git a/vl.c b/vl.c
index 9dc3caf0bf656d796a3dd17783481e8079e5c738..20a6d177f0d803c5f6aa2cf0289f95103872696e 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -2922,7 +2922,7 @@ static void dumb_display_init(void)
         exit(1);
     }
     ds->allocator = &default_allocator;
-    ds->surface = qemu_create_displaysurface(ds, 640, 480, 32, 640 * 4);
+    ds->surface = qemu_create_displaysurface(ds, 640, 480);
     register_displaystate(ds);
 }
 
index 254458d4f9d296983a770ba12f4e14fdd5d3cebc..32761a599241b93863eeec9eaa3fa27b4f632acb 100644 (file)
@@ -216,7 +216,7 @@ static void kbdfront_thread(void *p)
 }
 
 
-static DisplaySurface* xenfb_create_displaysurface(int width, int height, int bpp, int linesize)
+static DisplaySurface* xenfb_create_displaysurface(int width, int height)
 {
     DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
     if (surface == NULL) {
@@ -226,8 +226,8 @@ static DisplaySurface* xenfb_create_displaysurface(int width, int height, int bp
 
     surface->width = width;
     surface->height = height;
-    surface->linesize = linesize;
-    surface->pf = qemu_default_pixelformat(bpp);
+    surface->linesize = width * 4;
+    surface->pf = qemu_default_pixelformat(32);
 #ifdef WORDS_BIGENDIAN
     surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
 #else
@@ -239,12 +239,12 @@ static DisplaySurface* xenfb_create_displaysurface(int width, int height, int bp
 }
 
 static DisplaySurface* xenfb_resize_displaysurface(DisplaySurface *surface,
-                                          int width, int height, int bpp, int linesize)
+                                          int width, int height)
 {
     surface->width = width;
     surface->height = height;
-    surface->linesize = linesize;
-    surface->pf = qemu_default_pixelformat(bpp);
+    surface->linesize = width * 4;
+    surface->pf = qemu_default_pixelformat(32);
 #ifdef WORDS_BIGENDIAN
     surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
 #else
@@ -282,7 +282,7 @@ static void xenfb_pv_display_allocator(void)
     /* Touch the pages before sharing them */
     memset(xs->nonshared_vram, 0xff, vga_ram_size);
 
-    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));
+    ds = xenfb_create_displaysurface(ds_get_width(xs->ds), ds_get_height(xs->ds));
     defaultallocator_free_displaysurface(xs->ds->surface);
     xs->ds->surface = ds;
 }