vnc: fix copyrect screen corruption
authorGerd Hoffmann <kraxel@redhat.com>
Mon, 27 Jul 2009 15:10:48 +0000 (17:10 +0200)
committerAnthony Liguori <aliguori@us.ibm.com>
Thu, 30 Jul 2009 14:50:37 +0000 (09:50 -0500)
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>
vnc.c

diff --git a/vnc.c b/vnc.c
index dfcf34c01e67778e5260ac60cdb74f306bc5b04c..903dd953d9a434cdc2ab7c4cab485f989d471f3d 100644 (file)
--- 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)