Patchwork [07/12] BACKPORT: vnc: fix copyrect screen corruption

login
register
mail settings
Submitter Glauber Costa
Date Aug. 26, 2009, 1:05 p.m.
Message ID <1251291946-25821-8-git-send-email-glommer@redhat.com>
Download mbox | patch
Permalink /patch/32165/
State Superseded
Headers show

Comments

Glauber Costa - Aug. 26, 2009, 1:05 p.m.
From: Gerd Hoffmann <kraxel@redhat.com>

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.

[ backport: uses ds_get_data() instead of direct dereference ]
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 vnc.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)
Mark McLoughlin - Oct. 1, 2009, 9:21 a.m.
Hey,

On Wed, 2009-08-26 at 09:05 -0400, Glauber Costa wrote:
> From: Gerd Hoffmann <kraxel@redhat.com>
> 
> 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.
> 
> [ backport: uses ds_get_data() instead of direct dereference ]

We have reports from two Fedora 11 users that this fix makes things
worse:

  https://bugzilla.redhat.com/503156

Cheers,
Mark.

Patch

diff --git a/vnc.c b/vnc.c
index 1d8ebe7..c0700c0 100644
--- a/vnc.c
+++ b/vnc.c
@@ -633,8 +633,14 @@  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;
+
     vnc_update_client(vs);
 
+    /* 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 */
@@ -642,6 +648,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 = ds_get_data(vs->ds) + pitch * src_y + depth * src_x;
+    dst_row = ds_get_data(vs->ds) + 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)