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@eu.citrix.com> --- 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@lists.xensource.com http://lists.xensource.com/xen-devel