summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-01-19 13:37:05 +0000
committerPeter Maydell <peter.maydell@linaro.org>2015-01-19 13:37:05 +0000
commit74acb99737dbedd86654d660c0c20815139a873c (patch)
treefc448d083e2ae57d7d3b7d8e361a2b052fabd2f3
parent1e42c353469cb58ca4f3b450eea4211af7d0b147 (diff)
parent877417d9ae6846bea4744b198131a5fe5117d7a5 (diff)
downloadqemu-74acb99737dbedd86654d660c0c20815139a873c.tar.gz
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.c18
-rw-r--r--include/ui/console.h4
-rw-r--r--include/ui/qemu-pixman.h2
-rw-r--r--include/ui/sdl2.h2
-rw-r--r--ui/console.c25
-rw-r--r--ui/gtk.c13
-rw-r--r--ui/qemu-pixman.c29
-rw-r--r--ui/sdl.c26
-rw-r--r--ui/sdl2-2d.c13
-rw-r--r--ui/sdl2.c13
-rw-r--r--ui/spice-display.c13
-rw-r--r--ui/vnc.c15
12 files changed, 137 insertions, 36 deletions
diff --git a/hw/display/vga.c b/hw/display/vga.c
index a620c07864..ffcfce38a4 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 22ef8ca6b3..047b6dab8d 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 381969d97b..3dee5761cc 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 f56c596e31..51fff2e9b8 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 258af5dfff..87574a73a8 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;
diff --git a/ui/gtk.c b/ui/gtk.c
index 0385757bf5..6a81076ffc 100644
--- a/ui/gtk.c
+++ b/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,
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 1f6fea535b..4116e1507b 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)
{
diff --git a/ui/sdl.c b/ui/sdl.c
index 3e9d81076b..138ca73407 100644
--- a/ui/sdl.c
+++ b/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)
diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c
index 9264817e76..f907c21895 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);
+}
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 1ae2781624..60e3c3b6fa 100644
--- a/ui/sdl2.c
+++ b/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)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index d2e379379f..8c872129de 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)
diff --git a/ui/vnc.c b/ui/vnc.c
index 57070150d4..0385160a8b 100644
--- a/ui/vnc.c
+++ b/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)