mirror of https://gitee.com/openkylin/qemu.git
ui: add shared surface format negotiation.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJUvPzoAAoJEEy22O7T6HE4bLIP/ArldZI4+I81+g5K70jWJ6KC MYDGlmU3bqd240KddsSMC6DNpJk+/hY/1iM6FSRZSFQxd4JRgK0BdLVluXji2T1w iSnd7vDmmCZt/hCccJCWt6A21hxlRWtwuQZvSOkfrx21FlSznWdzut0Bs0D80Kos vMYPnMOyqY3aBekD5Cgext6j+EBu7GscvzLSZ1gAn0+ul0DB1IhXD5U/HTJqFXi+ 5nZlFlmUGNUHndK38aGk2UK9+L/kE3OjcU1G0RbKm7gLvtGuPz3G9do2zqZZ3Ol1 CKmpbSPGKGYOPt4Pi/XiAj5O94MrNBQt9dvd3hQco3wVUN624HpT2eituotDTDuI N06PEsKy22UGDxD3bqYQxM2mu2b+TD/HWXHd8RGpTizLmo7If/xGRInqYRSA8+Fe xRvbSMNk1O4WmImULQ5sl4yOHBpFw4q8b35LMzK5i4oLqLrr7a6J37saAAd/wCrK rI7Jyv9OQydas1cHohQ0DyWaNtmN/f/bR6g13j8C7+ysUS8DrRZP4yAnYkYouo8D Rcg1fLq2chcYL7wqch+AaRV9O3jCFcjDifwzxQYdNqpl7kZ4ZyrCtuA1ZpKuHhK0 OIxFMiQG9UQzlcwx/07LAOjRx5W1KnKHg3nKG3eOG/+H/GJ5cOaGjDIlML6OZFlH /mNB1MzjpELArzhza/oQ =Rrau -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
74acb99737
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
25
ui/console.c
25
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;
|
||||
|
|
13
ui/gtk.c
13
ui/gtk.c
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
26
ui/sdl.c
26
ui/sdl.c
|
@ -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)
|
||||
|
|
13
ui/sdl2-2d.c
13
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);
|
||||
}
|
||||
|
|
13
ui/sdl2.c
13
ui/sdl2.c
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
15
ui/vnc.c
15
ui/vnc.c
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue