From: Ian Jackson Date: Wed, 8 Apr 2009 16:32:57 +0000 (+0100) Subject: sync DisplayAllocator interface X-Git-Tag: xen-3.4.0-rc2~6 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=3793d85f111a0dfe055ca8ac17a9d1881af43240;p=qemu-xen-4.0-testing.git sync DisplayAllocator interface 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 --- diff --git a/console.c b/console.c index 66b154b2..5e6e3d09 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 aa735a82..4c29be47 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 422a2f58..de587355 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 31bc8f3d..4b71bf28 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 4c676c04..5d636074 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 9dc3caf0..20a6d177 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 254458d4..32761a59 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; }