Changeset View
Changeset View
Standalone View
Standalone View
head/sysutils/xen-tools/files/xsa211-qemuu-4.7.patch
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
From 9de536fbc2be97ae887560f08f0fd824efa3d5db Mon Sep 17 00:00:00 2001 | |||||
From: Gerd Hoffmann <kraxel@redhat.com> | |||||
Date: Tue, 14 Feb 2017 19:09:59 +0100 | |||||
Subject: [PATCH] cirrus/vnc: zap bitblit support from console code. | |||||
There is a special code path (dpy_gfx_copy) to allow graphic emulation | |||||
notify user interface code about bitblit operations carryed out by | |||||
guests. It is supported by cirrus and vnc server. The intended purpose | |||||
is to optimize display scrolls and just send over the scroll op instead | |||||
of a full display update. | |||||
This is rarely used these days though because modern guests simply don't | |||||
use the cirrus blitter any more. Any linux guest using the cirrus drm | |||||
driver doesn't. Any windows guest newer than winxp doesn't ship with a | |||||
cirrus driver any more and thus uses the cirrus as simple framebuffer. | |||||
So this code tends to bitrot and bugs can go unnoticed for a long time. | |||||
See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV" | |||||
which fixes a bug lingering in the code for almost a year, added by | |||||
commit "c7628bf vnc: only alloc server surface with clients connected". | |||||
Also the vnc server will throttle the frame rate in case it figures the | |||||
network can't keep up (send buffers are full). This doesn't work with | |||||
dpy_gfx_copy, for any copy operation sent to the vnc client we have to | |||||
send all outstanding updates beforehand, otherwise the vnc client might | |||||
run the client side blit on outdated data and thereby corrupt the | |||||
display. So this dpy_gfx_copy "optimization" might even make things | |||||
worse on slow network links. | |||||
Lets kill it once for all. | |||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> | |||||
--- | |||||
hw/display/cirrus_vga.c | 12 ++----- | |||||
include/ui/console.h | 7 ---- | |||||
ui/console.c | 28 --------------- | |||||
ui/vnc.c | 91 ------------------------------------------------- | |||||
4 files changed, 3 insertions(+), 135 deletions(-) | |||||
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c | |||||
index 5901250..2841676 100644 | |||||
--- a/hw/display/cirrus_vga.c | |||||
+++ b/hw/display/cirrus_vga.c | |||||
@@ -758,11 +758,6 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) | |||||
} | |||||
} | |||||
- /* we have to flush all pending changes so that the copy | |||||
- is generated at the appropriate moment in time */ | |||||
- if (notify) | |||||
- graphic_hw_update(s->vga.con); | |||||
- | |||||
(*s->cirrus_rop) (s, s->vga.vram_ptr + | |||||
(s->cirrus_blt_dstaddr & s->cirrus_addr_mask), | |||||
s->vga.vram_ptr + | |||||
@@ -771,10 +766,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) | |||||
s->cirrus_blt_width, s->cirrus_blt_height); | |||||
if (notify) { | |||||
- qemu_console_copy(s->vga.con, | |||||
- sx, sy, dx, dy, | |||||
- s->cirrus_blt_width / depth, | |||||
- s->cirrus_blt_height); | |||||
+ dpy_gfx_update(s->vga.con, dx, dy, | |||||
+ s->cirrus_blt_width / depth, | |||||
+ s->cirrus_blt_height); | |||||
} | |||||
/* we don't have to notify the display that this portion has | |||||
diff --git a/include/ui/console.h b/include/ui/console.h | |||||
index 047a2b4..ed07065 100644 | |||||
--- a/include/ui/console.h | |||||
+++ b/include/ui/console.h | |||||
@@ -166,9 +166,6 @@ typedef struct DisplayChangeListenerOps { | |||||
int x, int y, int w, int h); | |||||
void (*dpy_gfx_switch)(DisplayChangeListener *dcl, | |||||
struct DisplaySurface *new_surface); | |||||
- 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); | |||||
@@ -233,8 +230,6 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info); | |||||
void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h); | |||||
void dpy_gfx_replace_surface(QemuConsole *con, | |||||
DisplaySurface *surface); | |||||
-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, | |||||
- int dst_x, int dst_y, int w, int h); | |||||
void dpy_text_cursor(QemuConsole *con, int x, int y); | |||||
void dpy_text_update(QemuConsole *con, int x, int y, int w, int h); | |||||
void dpy_text_resize(QemuConsole *con, int w, int h); | |||||
@@ -329,8 +324,6 @@ void text_consoles_set_display(DisplayState *ds); | |||||
void console_select(unsigned int index); | |||||
void console_color_init(DisplayState *ds); | |||||
void qemu_console_resize(QemuConsole *con, int width, int height); | |||||
-void qemu_console_copy(QemuConsole *con, int src_x, int src_y, | |||||
- int dst_x, int dst_y, int w, int h); | |||||
DisplaySurface *qemu_console_surface(QemuConsole *con); | |||||
/* console-gl.c */ | |||||
diff --git a/ui/console.c b/ui/console.c | |||||
index 75fc492..72d91cb 100644 | |||||
--- a/ui/console.c | |||||
+++ b/ui/console.c | |||||
@@ -1495,27 +1495,6 @@ static void dpy_refresh(DisplayState *s) | |||||
} | |||||
} | |||||
-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, | |||||
- int dst_x, int dst_y, int w, int h) | |||||
-{ | |||||
- DisplayState *s = con->ds; | |||||
- DisplayChangeListener *dcl; | |||||
- | |||||
- if (!qemu_console_is_visible(con)) { | |||||
- return; | |||||
- } | |||||
- QLIST_FOREACH(dcl, &s->listeners, next) { | |||||
- if (con != (dcl->con ? dcl->con : active_console)) { | |||||
- continue; | |||||
- } | |||||
- if (dcl->ops->dpy_gfx_copy) { | |||||
- dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h); | |||||
- } else { /* TODO */ | |||||
- dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h); | |||||
- } | |||||
- } | |||||
-} | |||||
- | |||||
void dpy_text_cursor(QemuConsole *con, int x, int y) | |||||
{ | |||||
DisplayState *s = con->ds; | |||||
@@ -1968,13 +1947,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height) | |||||
dpy_gfx_replace_surface(s, surface); | |||||
} | |||||
-void qemu_console_copy(QemuConsole *con, int src_x, int src_y, | |||||
- int dst_x, int dst_y, int w, int h) | |||||
-{ | |||||
- assert(con->console_type == GRAPHIC_CONSOLE); | |||||
- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h); | |||||
-} | |||||
- | |||||
DisplaySurface *qemu_console_surface(QemuConsole *console) | |||||
{ | |||||
return console->surface; | |||||
diff --git a/ui/vnc.c b/ui/vnc.c | |||||
index 52c6809..61ab611 100644 | |||||
--- a/ui/vnc.c | |||||
+++ b/ui/vnc.c | |||||
@@ -908,96 +908,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) | |||||
return n; | |||||
} | |||||
-static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h) | |||||
-{ | |||||
- /* send bitblit op to the vnc client */ | |||||
- vnc_lock_output(vs); | |||||
- vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); | |||||
- vnc_write_u8(vs, 0); | |||||
- vnc_write_u16(vs, 1); /* number of rects */ | |||||
- vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT); | |||||
- vnc_write_u16(vs, src_x); | |||||
- vnc_write_u16(vs, src_y); | |||||
- vnc_unlock_output(vs); | |||||
- vnc_flush(vs); | |||||
-} | |||||
- | |||||
-static void vnc_dpy_copy(DisplayChangeListener *dcl, | |||||
- int src_x, int src_y, | |||||
- int dst_x, int dst_y, int w, int h) | |||||
-{ | |||||
- VncDisplay *vd = container_of(dcl, VncDisplay, dcl); | |||||
- VncState *vs, *vn; | |||||
- uint8_t *src_row; | |||||
- uint8_t *dst_row; | |||||
- int i, x, y, pitch, inc, w_lim, s; | |||||
- int cmp_bytes; | |||||
- | |||||
- vnc_refresh_server_surface(vd); | |||||
- QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { | |||||
- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { | |||||
- vs->force_update = 1; | |||||
- vnc_update_client(vs, 1, true); | |||||
- /* vs might be free()ed here */ | |||||
- } | |||||
- } | |||||
- | |||||
- /* do bitblit op on the local surface too */ | |||||
- pitch = vnc_server_fb_stride(vd); | |||||
- src_row = vnc_server_fb_ptr(vd, src_x, src_y); | |||||
- dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y); | |||||
- y = dst_y; | |||||
- inc = 1; | |||||
- if (dst_y > src_y) { | |||||
- /* copy backwards */ | |||||
- src_row += pitch * (h-1); | |||||
- dst_row += pitch * (h-1); | |||||
- pitch = -pitch; | |||||
- y = dst_y + h - 1; | |||||
- inc = -1; | |||||
- } | |||||
- w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT)); | |||||
- if (w_lim < 0) { | |||||
- w_lim = w; | |||||
- } else { | |||||
- w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT); | |||||
- } | |||||
- for (i = 0; i < h; i++) { | |||||
- for (x = 0; x <= w_lim; | |||||
- x += s, src_row += cmp_bytes, dst_row += cmp_bytes) { | |||||
- if (x == w_lim) { | |||||
- if ((s = w - w_lim) == 0) | |||||
- break; | |||||
- } else if (!x) { | |||||
- s = (VNC_DIRTY_PIXELS_PER_BIT - | |||||
- (dst_x % VNC_DIRTY_PIXELS_PER_BIT)); | |||||
- s = MIN(s, w_lim); | |||||
- } else { | |||||
- s = VNC_DIRTY_PIXELS_PER_BIT; | |||||
- } | |||||
- cmp_bytes = s * VNC_SERVER_FB_BYTES; | |||||
- if (memcmp(src_row, dst_row, cmp_bytes) == 0) | |||||
- continue; | |||||
- memmove(dst_row, src_row, cmp_bytes); | |||||
- QTAILQ_FOREACH(vs, &vd->clients, next) { | |||||
- if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { | |||||
- set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT), | |||||
- vs->dirty[y]); | |||||
- } | |||||
- } | |||||
- } | |||||
- src_row += pitch - w * VNC_SERVER_FB_BYTES; | |||||
- dst_row += pitch - w * VNC_SERVER_FB_BYTES; | |||||
- y += inc; | |||||
- } | |||||
- | |||||
- QTAILQ_FOREACH(vs, &vd->clients, next) { | |||||
- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { | |||||
- vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h); | |||||
- } | |||||
- } | |||||
-} | |||||
- | |||||
static void vnc_mouse_set(DisplayChangeListener *dcl, | |||||
int x, int y, int visible) | |||||
{ | |||||
@@ -3131,7 +3041,6 @@ static void vnc_listen_websocket_read(void *opaque) | |||||
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_gfx_check_format = qemu_pixman_check_format, | |||||
-- | |||||
2.1.4 | |||||