mirror of https://github.com/xemu-project/xemu.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;
|
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));
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
25
ui/console.c
25
ui/console.c
|
@ -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;
|
||||||
|
|
1
ui/gtk.c
1
ui/gtk.c
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
14
ui/sdl.c
14
ui/sdl.c
|
@ -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,
|
||||||
|
|
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_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);
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
1
ui/vnc.c
1
ui/vnc.c
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue