summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hw/display/vga.c18
-rw-r--r--include/ui/console.h4
-rw-r--r--ui/console.c25
3 files changed, 43 insertions, 4 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/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;
OpenPOWER on IntegriCloud