diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-01-19 13:37:05 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-01-19 13:37:05 +0000 |
commit | 74acb99737dbedd86654d660c0c20815139a873c (patch) | |
tree | fc448d083e2ae57d7d3b7d8e361a2b052fabd2f3 | |
parent | 1e42c353469cb58ca4f3b450eea4211af7d0b147 (diff) | |
parent | 877417d9ae6846bea4744b198131a5fe5117d7a5 (diff) | |
download | qemu-74acb99737dbedd86654d660c0c20815139a873c.zip qemu-74acb99737dbedd86654d660c0c20815139a873c.tar.gz qemu-74acb99737dbedd86654d660c0c20815139a873c.tar.bz2 |
Merge remote-tracking branch 'remotes/kraxel/tags/pull-console-20150119-1' into staging
ui: add shared surface format negotiation.
# gpg: Signature made Mon 19 Jan 2015 12:47:36 GMT using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
* remotes/kraxel/tags/pull-console-20150119-1:
ui/sdl2: Support shared surface for more pixman formats
ui/sdl: Support shared surface for more pixman formats
ui/gtk: Support shared surface for most pixman formats
ui/spice: Support shared surface for most pixman formats
ui/vnc: Support shared surface for most pixman formats
ui/pixman: add qemu_pixman_check_format
ui: Add dpy_gfx_check_format() to check backend shared surface support
ui: Make qemu_default_pixman_format() return 0 on unsupported formats
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/display/vga.c | 18 | ||||
-rw-r--r-- | include/ui/console.h | 4 | ||||
-rw-r--r-- | include/ui/qemu-pixman.h | 2 | ||||
-rw-r--r-- | include/ui/sdl2.h | 2 | ||||
-rw-r--r-- | ui/console.c | 25 | ||||
-rw-r--r-- | ui/gtk.c | 13 | ||||
-rw-r--r-- | ui/qemu-pixman.c | 29 | ||||
-rw-r--r-- | ui/sdl.c | 26 | ||||
-rw-r--r-- | ui/sdl2-2d.c | 13 | ||||
-rw-r--r-- | ui/sdl2.c | 13 | ||||
-rw-r--r-- | ui/spice-display.c | 13 | ||||
-rw-r--r-- | ui/vnc.c | 15 |
12 files changed, 137 insertions, 36 deletions
diff --git a/hw/display/vga.c b/hw/display/vga.c index a620c07..ffcfce3 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1437,6 +1437,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line = NULL; bool share_surface; + pixman_format_code_t format; #ifdef HOST_WORDS_BIGENDIAN bool byteswap = !s->big_endian_fb; #else @@ -1481,8 +1482,19 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) depth = s->get_bpp(s); - share_surface = (!s->force_shadow) && - ( depth == 32 || (depth == 16 && !byteswap) ); + /* + * Check whether we can share the surface with the backend + * or whether we need a shadow surface. We share native + * endian surfaces for 15bpp and above and byteswapped + * surfaces for 24bpp and above. + */ + format = qemu_default_pixman_format(depth, !byteswap); + if (format) { + share_surface = dpy_gfx_check_format(s->con, format) + && !s->force_shadow; + } else { + share_surface = false; + } if (s->line_offset != s->last_line_offset || disp_width != s->last_width || height != s->last_height || @@ -1490,8 +1502,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s->last_byteswap != byteswap || share_surface != is_buffer_shared(surface)) { if (share_surface) { - pixman_format_code_t format = - qemu_default_pixman_format(depth, !byteswap); surface = qemu_create_displaysurface_from(disp_width, height, format, s->line_offset, s->vram_ptr + (s->start_addr * 4)); diff --git a/include/ui/console.h b/include/ui/console.h index 22ef8ca..047b6da 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -161,6 +161,8 @@ typedef struct DisplayChangeListenerOps { void (*dpy_gfx_copy)(DisplayChangeListener *dcl, int src_x, int src_y, int dst_x, int dst_y, int w, int h); + bool (*dpy_gfx_check_format)(DisplayChangeListener *dcl, + pixman_format_code_t format); void (*dpy_text_cursor)(DisplayChangeListener *dcl, int x, int y); @@ -235,6 +237,8 @@ void dpy_gfx_update_dirty(QemuConsole *con, MemoryRegion *address_space, uint64_t base, bool invalidate); +bool dpy_gfx_check_format(QemuConsole *con, + pixman_format_code_t format); static inline int surface_stride(DisplaySurface *s) { diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h index 381969d..3dee576 100644 --- a/include/ui/qemu-pixman.h +++ b/include/ui/qemu-pixman.h @@ -37,6 +37,8 @@ PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format); pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian); int qemu_pixman_get_type(int rshift, int gshift, int bshift); pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf); +bool qemu_pixman_check_format(DisplayChangeListener *dcl, + pixman_format_code_t format); pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, int width); diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index f56c596..51fff2e 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -28,5 +28,7 @@ void sdl2_2d_switch(DisplayChangeListener *dcl, DisplaySurface *new_surface); void sdl2_2d_refresh(DisplayChangeListener *dcl); void sdl2_2d_redraw(struct sdl2_console *scon); +bool sdl2_2d_check_format(DisplayChangeListener *dcl, + pixman_format_code_t format); #endif /* SDL2_H */ diff --git a/ui/console.c b/ui/console.c index 258af5d..87574a7 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1439,6 +1439,31 @@ void dpy_gfx_replace_surface(QemuConsole *con, qemu_free_displaysurface(old_surface); } +bool dpy_gfx_check_format(QemuConsole *con, + pixman_format_code_t format) +{ + DisplayChangeListener *dcl; + DisplayState *s = con->ds; + + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->con && dcl->con != con) { + /* dcl bound to another console -> skip */ + continue; + } + if (dcl->ops->dpy_gfx_check_format) { + if (!dcl->ops->dpy_gfx_check_format(dcl, format)) { + return false; + } + } else { + /* default is to whitelist native 32 bpp only */ + if (format != qemu_default_pixman_format(32, true)) { + return false; + } + } + } + return true; +} + static void dpy_refresh(DisplayState *s) { DisplayChangeListener *dcl; @@ -1654,12 +1654,13 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s) } static const DisplayChangeListenerOps dcl_ops = { - .dpy_name = "gtk", - .dpy_gfx_update = gd_update, - .dpy_gfx_switch = gd_switch, - .dpy_refresh = gd_refresh, - .dpy_mouse_set = gd_mouse_set, - .dpy_cursor_define = gd_cursor_define, + .dpy_name = "gtk", + .dpy_gfx_update = gd_update, + .dpy_gfx_switch = gd_switch, + .dpy_gfx_check_format = qemu_pixman_check_format, + .dpy_refresh = gd_refresh, + .dpy_mouse_set = gd_mouse_set, + .dpy_cursor_define = gd_cursor_define, }; static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c index 1f6fea5..4116e15 100644 --- a/ui/qemu-pixman.c +++ b/ui/qemu-pixman.c @@ -84,7 +84,7 @@ pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian) break; } } - g_assert_not_reached(); + return 0; } int qemu_pixman_get_type(int rshift, int gshift, int bshift) @@ -125,6 +125,33 @@ pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf) return format; } +/* + * Return true for known-good pixman conversions. + * + * UIs using pixman for format conversion can hook this into + * DisplayChangeListenerOps->dpy_gfx_check_format + */ +bool qemu_pixman_check_format(DisplayChangeListener *dcl, + pixman_format_code_t format) +{ + switch (format) { + /* 32 bpp */ + case PIXMAN_x8r8g8b8: + case PIXMAN_a8r8g8b8: + case PIXMAN_b8g8r8x8: + case PIXMAN_b8g8r8a8: + /* 24 bpp */ + case PIXMAN_r8g8b8: + case PIXMAN_b8g8r8: + /* 16 bpp */ + case PIXMAN_x1r5g5b5: + case PIXMAN_r5g6b5: + return true; + default: + return false; + } +} + pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, int width) { @@ -151,6 +151,19 @@ static void sdl_switch(DisplayChangeListener *dcl, pf.bmask, pf.amask); } +static bool sdl_check_format(DisplayChangeListener *dcl, + pixman_format_code_t format) +{ + /* + * We let SDL convert for us a few more formats than, + * the native ones. Thes are the ones I have tested. + */ + return (format == PIXMAN_x8r8g8b8 || + format == PIXMAN_b8g8r8x8 || + format == PIXMAN_x1r5g5b5 || + format == PIXMAN_r5g6b5); +} + /* generic keyboard conversion */ #include "sdl_keysym.h" @@ -865,12 +878,13 @@ static void sdl_cleanup(void) } static const DisplayChangeListenerOps dcl_ops = { - .dpy_name = "sdl", - .dpy_gfx_update = sdl_update, - .dpy_gfx_switch = sdl_switch, - .dpy_refresh = sdl_refresh, - .dpy_mouse_set = sdl_mouse_warp, - .dpy_cursor_define = sdl_mouse_define, + .dpy_name = "sdl", + .dpy_gfx_update = sdl_update, + .dpy_gfx_switch = sdl_switch, + .dpy_gfx_check_format = sdl_check_format, + .dpy_refresh = sdl_refresh, + .dpy_mouse_set = sdl_mouse_warp, + .dpy_cursor_define = sdl_mouse_define, }; void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c index 9264817..f907c21 100644 --- a/ui/sdl2-2d.c +++ b/ui/sdl2-2d.c @@ -120,3 +120,16 @@ void sdl2_2d_redraw(struct sdl2_console *scon) surface_width(scon->surface), surface_height(scon->surface)); } + +bool sdl2_2d_check_format(DisplayChangeListener *dcl, + pixman_format_code_t format) +{ + /* + * We let SDL convert for us a few more formats than, + * the native ones. Thes are the ones I have tested. + */ + return (format == PIXMAN_x8r8g8b8 || + format == PIXMAN_b8g8r8x8 || + format == PIXMAN_x1r5g5b5 || + format == PIXMAN_r5g6b5); +} @@ -668,12 +668,13 @@ static void sdl_cleanup(void) } static const DisplayChangeListenerOps dcl_2d_ops = { - .dpy_name = "sdl2-2d", - .dpy_gfx_update = sdl2_2d_update, - .dpy_gfx_switch = sdl2_2d_switch, - .dpy_refresh = sdl2_2d_refresh, - .dpy_mouse_set = sdl_mouse_warp, - .dpy_cursor_define = sdl_mouse_define, + .dpy_name = "sdl2-2d", + .dpy_gfx_update = sdl2_2d_update, + .dpy_gfx_switch = sdl2_2d_switch, + .dpy_gfx_check_format = sdl2_2d_check_format, + .dpy_refresh = sdl2_2d_refresh, + .dpy_mouse_set = sdl_mouse_warp, + .dpy_cursor_define = sdl_mouse_define, }; void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) diff --git a/ui/spice-display.c b/ui/spice-display.c index d2e3793..8c87212 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -760,12 +760,13 @@ static void display_mouse_define(DisplayChangeListener *dcl, } static const DisplayChangeListenerOps display_listener_ops = { - .dpy_name = "spice", - .dpy_gfx_update = display_update, - .dpy_gfx_switch = display_switch, - .dpy_refresh = display_refresh, - .dpy_mouse_set = display_mouse_set, - .dpy_cursor_define = display_mouse_define, + .dpy_name = "spice", + .dpy_gfx_update = display_update, + .dpy_gfx_switch = display_switch, + .dpy_gfx_check_format = qemu_pixman_check_format, + .dpy_refresh = display_refresh, + .dpy_mouse_set = display_mouse_set, + .dpy_cursor_define = display_mouse_define, }; static void qemu_spice_display_init_one(QemuConsole *con) @@ -2942,13 +2942,14 @@ static void vnc_listen_websocket_read(void *opaque) #endif /* CONFIG_VNC_WS */ static const DisplayChangeListenerOps dcl_ops = { - .dpy_name = "vnc", - .dpy_refresh = vnc_refresh, - .dpy_gfx_copy = vnc_dpy_copy, - .dpy_gfx_update = vnc_dpy_update, - .dpy_gfx_switch = vnc_dpy_switch, - .dpy_mouse_set = vnc_mouse_set, - .dpy_cursor_define = vnc_dpy_cursor_define, + .dpy_name = "vnc", + .dpy_refresh = vnc_refresh, + .dpy_gfx_copy = vnc_dpy_copy, + .dpy_gfx_update = vnc_dpy_update, + .dpy_gfx_switch = vnc_dpy_switch, + .dpy_gfx_check_format = qemu_pixman_check_format, + .dpy_mouse_set = vnc_mouse_set, + .dpy_cursor_define = vnc_dpy_cursor_define, }; void vnc_display_init(DisplayState *ds) |