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:
Peter Maydell 2015-01-19 13:37:05 +00:00
commit 74acb99737
12 changed files with 137 additions and 36 deletions

View File

@ -1437,6 +1437,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
uint32_t v, addr1, addr; uint32_t v, addr1, addr;
vga_draw_line_func *vga_draw_line = NULL; vga_draw_line_func *vga_draw_line = NULL;
bool share_surface; bool share_surface;
pixman_format_code_t format;
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
bool byteswap = !s->big_endian_fb; bool byteswap = !s->big_endian_fb;
#else #else
@ -1481,8 +1482,19 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
depth = s->get_bpp(s); 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 || if (s->line_offset != s->last_line_offset ||
disp_width != s->last_width || disp_width != s->last_width ||
height != s->last_height || height != s->last_height ||
@ -1490,8 +1502,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->last_byteswap != byteswap || s->last_byteswap != byteswap ||
share_surface != is_buffer_shared(surface)) { share_surface != is_buffer_shared(surface)) {
if (share_surface) { if (share_surface) {
pixman_format_code_t format =
qemu_default_pixman_format(depth, !byteswap);
surface = qemu_create_displaysurface_from(disp_width, surface = qemu_create_displaysurface_from(disp_width,
height, format, s->line_offset, height, format, s->line_offset,
s->vram_ptr + (s->start_addr * 4)); s->vram_ptr + (s->start_addr * 4));

View File

@ -161,6 +161,8 @@ typedef struct DisplayChangeListenerOps {
void (*dpy_gfx_copy)(DisplayChangeListener *dcl, void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
int src_x, int src_y, int src_x, int src_y,
int dst_x, int dst_y, int w, int h); 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, void (*dpy_text_cursor)(DisplayChangeListener *dcl,
int x, int y); int x, int y);
@ -235,6 +237,8 @@ void dpy_gfx_update_dirty(QemuConsole *con,
MemoryRegion *address_space, MemoryRegion *address_space,
uint64_t base, uint64_t base,
bool invalidate); bool invalidate);
bool dpy_gfx_check_format(QemuConsole *con,
pixman_format_code_t format);
static inline int surface_stride(DisplaySurface *s) static inline int surface_stride(DisplaySurface *s)
{ {

View File

@ -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); pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian);
int qemu_pixman_get_type(int rshift, int gshift, int bshift); int qemu_pixman_get_type(int rshift, int gshift, int bshift);
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf); 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, pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
int width); int width);

View File

@ -28,5 +28,7 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
DisplaySurface *new_surface); DisplaySurface *new_surface);
void sdl2_2d_refresh(DisplayChangeListener *dcl); void sdl2_2d_refresh(DisplayChangeListener *dcl);
void sdl2_2d_redraw(struct sdl2_console *scon); void sdl2_2d_redraw(struct sdl2_console *scon);
bool sdl2_2d_check_format(DisplayChangeListener *dcl,
pixman_format_code_t format);
#endif /* SDL2_H */ #endif /* SDL2_H */

View File

@ -1439,6 +1439,31 @@ void dpy_gfx_replace_surface(QemuConsole *con,
qemu_free_displaysurface(old_surface); 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) static void dpy_refresh(DisplayState *s)
{ {
DisplayChangeListener *dcl; DisplayChangeListener *dcl;

View File

@ -1657,6 +1657,7 @@ static const DisplayChangeListenerOps dcl_ops = {
.dpy_name = "gtk", .dpy_name = "gtk",
.dpy_gfx_update = gd_update, .dpy_gfx_update = gd_update,
.dpy_gfx_switch = gd_switch, .dpy_gfx_switch = gd_switch,
.dpy_gfx_check_format = qemu_pixman_check_format,
.dpy_refresh = gd_refresh, .dpy_refresh = gd_refresh,
.dpy_mouse_set = gd_mouse_set, .dpy_mouse_set = gd_mouse_set,
.dpy_cursor_define = gd_cursor_define, .dpy_cursor_define = gd_cursor_define,

View File

@ -84,7 +84,7 @@ pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian)
break; break;
} }
} }
g_assert_not_reached(); return 0;
} }
int qemu_pixman_get_type(int rshift, int gshift, int bshift) 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 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, pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
int width) int width)
{ {

View File

@ -151,6 +151,19 @@ static void sdl_switch(DisplayChangeListener *dcl,
pf.bmask, pf.amask); 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 */ /* generic keyboard conversion */
#include "sdl_keysym.h" #include "sdl_keysym.h"
@ -868,6 +881,7 @@ static const DisplayChangeListenerOps dcl_ops = {
.dpy_name = "sdl", .dpy_name = "sdl",
.dpy_gfx_update = sdl_update, .dpy_gfx_update = sdl_update,
.dpy_gfx_switch = sdl_switch, .dpy_gfx_switch = sdl_switch,
.dpy_gfx_check_format = sdl_check_format,
.dpy_refresh = sdl_refresh, .dpy_refresh = sdl_refresh,
.dpy_mouse_set = sdl_mouse_warp, .dpy_mouse_set = sdl_mouse_warp,
.dpy_cursor_define = sdl_mouse_define, .dpy_cursor_define = sdl_mouse_define,

View File

@ -120,3 +120,16 @@ void sdl2_2d_redraw(struct sdl2_console *scon)
surface_width(scon->surface), surface_width(scon->surface),
surface_height(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);
}

View File

@ -671,6 +671,7 @@ static const DisplayChangeListenerOps dcl_2d_ops = {
.dpy_name = "sdl2-2d", .dpy_name = "sdl2-2d",
.dpy_gfx_update = sdl2_2d_update, .dpy_gfx_update = sdl2_2d_update,
.dpy_gfx_switch = sdl2_2d_switch, .dpy_gfx_switch = sdl2_2d_switch,
.dpy_gfx_check_format = sdl2_2d_check_format,
.dpy_refresh = sdl2_2d_refresh, .dpy_refresh = sdl2_2d_refresh,
.dpy_mouse_set = sdl_mouse_warp, .dpy_mouse_set = sdl_mouse_warp,
.dpy_cursor_define = sdl_mouse_define, .dpy_cursor_define = sdl_mouse_define,

View File

@ -763,6 +763,7 @@ static const DisplayChangeListenerOps display_listener_ops = {
.dpy_name = "spice", .dpy_name = "spice",
.dpy_gfx_update = display_update, .dpy_gfx_update = display_update,
.dpy_gfx_switch = display_switch, .dpy_gfx_switch = display_switch,
.dpy_gfx_check_format = qemu_pixman_check_format,
.dpy_refresh = display_refresh, .dpy_refresh = display_refresh,
.dpy_mouse_set = display_mouse_set, .dpy_mouse_set = display_mouse_set,
.dpy_cursor_define = display_mouse_define, .dpy_cursor_define = display_mouse_define,

View File

@ -2947,6 +2947,7 @@ static const DisplayChangeListenerOps dcl_ops = {
.dpy_gfx_copy = vnc_dpy_copy, .dpy_gfx_copy = vnc_dpy_copy,
.dpy_gfx_update = vnc_dpy_update, .dpy_gfx_update = vnc_dpy_update,
.dpy_gfx_switch = vnc_dpy_switch, .dpy_gfx_switch = vnc_dpy_switch,
.dpy_gfx_check_format = qemu_pixman_check_format,
.dpy_mouse_set = vnc_mouse_set, .dpy_mouse_set = vnc_mouse_set,
.dpy_cursor_define = vnc_dpy_cursor_define, .dpy_cursor_define = vnc_dpy_cursor_define,
}; };