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

[Xen-devel] sync DisplayAllocator interface



Hi all,
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@xxxxxxxxxxxxx>

---

diff --git a/console.c b/console.c
index 66b154b..5e6e3d0 100644
--- 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
diff --git a/console.h b/console.h
index aa735a8..4c29be4 100644
--- 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));
diff --git a/hw/vga.c b/hw/vga.c
index 422a2f5..de58735 100644
--- 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;
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 31bc8f3..4b71bf2 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -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 4c676c0..5d63607 100644
--- 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 9dc3caf..20a6d17 100644
--- 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);
 }
 
diff --git a/xenfbfront.c b/xenfbfront.c
index 254458d..32761a5 100644
--- a/xenfbfront.c
+++ b/xenfbfront.c
@@ -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;
 }

_______________________________________________
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®.