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
|