summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-07-27 17:10:48 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-08-27 21:23:35 -0500
commit82944b87db46af80bfacb02bbd4864581e519308 (patch)
treefd35f48811553ca099ef4285417dc66673473311
parent19e4a89ee6a44a2237c170d3029cff922a5b8098 (diff)
downloadqemu-82944b87db46af80bfacb02bbd4864581e519308.tar.gz
vnc: fix copyrect screen corruption
When sending a copyrect command to the vnc client, we must also update the local server surface. Otherwise the server's and the client's idea of the screen content run out of sync and screen updates don't work correctly. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r--vnc.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/vnc.c b/vnc.c
index de0ff872d4..a50ee0c1ef 100644
--- a/vnc.c
+++ b/vnc.c
@@ -654,6 +654,11 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
{
+ uint8_t *src_row;
+ uint8_t *dst_row;
+ int y,pitch,depth;
+
+ /* send bitblit op to the vnc client */
vnc_write_u8(vs, 0); /* msg id */
vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1); /* number of rects */
@@ -661,6 +666,23 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i
vnc_write_u16(vs, src_x);
vnc_write_u16(vs, src_y);
vnc_flush(vs);
+
+ /* do bitblit op on the local surface too */
+ pitch = ds_get_linesize(vs->ds);
+ depth = ds_get_bytes_per_pixel(vs->ds);
+ src_row = vs->server.ds->data + pitch * src_y + depth * src_x;
+ dst_row = vs->server.ds->data + pitch * dst_y + depth * dst_x;
+ if (dst_y > src_y) {
+ /* copy backwards */
+ src_row += pitch * (h-1);
+ dst_row += pitch * (h-1);
+ pitch = -pitch;
+ }
+ for (y = 0; y < h; y++) {
+ memmove(dst_row, src_row, w * depth);
+ src_row += pitch;
+ dst_row += pitch;
+ }
}
static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)