From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LhPf0-00007i-MN for qemu-devel@nongnu.org; Wed, 11 Mar 2009 10:43:54 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LhPex-0008UU-RN for qemu-devel@nongnu.org; Wed, 11 Mar 2009 10:43:54 -0400 Received: from [199.232.76.173] (port=56676 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LhPex-0008U4-A8 for qemu-devel@nongnu.org; Wed, 11 Mar 2009 10:43:51 -0400 Received: from mx2.redhat.com ([66.187.237.31]:45417) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LhPew-00050n-Mt for qemu-devel@nongnu.org; Wed, 11 Mar 2009 10:43:51 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n2BEhnsq010445 for ; Wed, 11 Mar 2009 10:43:49 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n2BEhnHv007544 for ; Wed, 11 Mar 2009 10:43:50 -0400 Received: from zweiblum.home.kraxel.org (vpn-10-70.str.redhat.com [10.32.10.70]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n2BEhlxg018569 for ; Wed, 11 Mar 2009 10:43:48 -0400 Message-ID: <49B7CE21.4030104@redhat.com> Date: Wed, 11 Mar 2009 15:43:45 +0100 From: Gerd Hoffmann MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------040204060306070607020106" Subject: [Qemu-devel] [PATCH] vnc: shared buffer: skip some optimizations. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------040204060306070607020106 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hi, When using a shared display surface buffer some of the optimizations done by the vnc server code don't work. In shared buffer mode the guest may update the screen while the vnc server looks at the framebuffer. That in turn makes some code racy, the dirty bitmap walk through for example, leading to screen corruption. Right now this is visible with xenfb only. I expect simliar issues will show up for vga too once we run the vcpus in threads. please apply Gerd --------------040204060306070607020106 Content-Type: text/plain; name="0001-vnc-shared-buffer-skip-some-optimizations.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename*0="0001-vnc-shared-buffer-skip-some-optimizations.patch" >>From eaff07da03b93fa59d6330a7e5e0e720d4573f3c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 11 Mar 2009 15:30:23 +0100 Subject: [PATCH] vnc: shared buffer: skip some optimizations. When using a shared display surface buffer some of the optimizations done by the vnc server code don't work. In shared buffer mode the guest may update the screen while the vnc server looks at the framebuffer. That in turn makes some code racy, the dirty bitmap walk through for example, leading to screen corruption. Right now this is visible with xenfb only. I expect simliar issues will show up for vga too once we run the vcpus in threads. Signed-off-by: Gerd Hoffmann --- vnc.c | 78 +++++++++++++++++++++++++++++++++++++++------------------------- 1 files changed, 47 insertions(+), 31 deletions(-) diff --git a/vnc.c b/vnc.c index 81c842a..66f8946 100644 --- a/vnc.c +++ b/vnc.c @@ -649,7 +649,8 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int VncDisplay *vd = ds->opaque; VncState *vs = vd->clients; while (vs != NULL) { - if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) + if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT) && + !is_buffer_shared(ds->surface)) vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h); else /* TODO */ vnc_update(vs, dst_x, dst_y, w, h); @@ -688,36 +689,51 @@ static void vnc_update_client(void *opaque) vnc_set_bits(width_mask, (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS); - /* Walk through the dirty map and eliminate tiles that - really aren't dirty */ - row = ds_get_data(vs->ds); - old_row = vs->old_data; - - for (y = 0; y < ds_get_height(vs->ds); y++) { - if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) { - int x; - uint8_t *ptr; - char *old_ptr; - - ptr = row; - old_ptr = (char*)old_row; - - for (x = 0; x < ds_get_width(vs->ds); x += 16) { - if (memcmp(old_ptr, ptr, 16 * ds_get_bytes_per_pixel(vs->ds)) == 0) { - vnc_clear_bit(vs->dirty_row[y], (x / 16)); - } else { - has_dirty = 1; - memcpy(old_ptr, ptr, 16 * ds_get_bytes_per_pixel(vs->ds)); - } - - ptr += 16 * ds_get_bytes_per_pixel(vs->ds); - old_ptr += 16 * ds_get_bytes_per_pixel(vs->ds); - } - } + if (!is_buffer_shared(vs->ds->surface)) { + /* Walk through the dirty map and eliminate tiles that + really aren't dirty */ + row = ds_get_data(vs->ds); + old_row = vs->old_data; + + for (y = 0; y < ds_get_height(vs->ds); y++) { + if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) { + int x; + uint8_t *ptr; + char *old_ptr; + + ptr = row; + old_ptr = (char*)old_row; + + for (x = 0; x < ds_get_width(vs->ds); x += 16) { + if (memcmp(old_ptr, ptr, 16 * ds_get_bytes_per_pixel(vs->ds)) == 0) { + vnc_clear_bit(vs->dirty_row[y], (x / 16)); + } else { + has_dirty = 1; + memcpy(old_ptr, ptr, 16 * ds_get_bytes_per_pixel(vs->ds)); + } + + ptr += 16 * ds_get_bytes_per_pixel(vs->ds); + old_ptr += 16 * ds_get_bytes_per_pixel(vs->ds); + } + } - row += ds_get_linesize(vs->ds); - old_row += ds_get_linesize(vs->ds); - } + row += ds_get_linesize(vs->ds); + old_row += ds_get_linesize(vs->ds); + } + } else { + /* + * shared buffer: + * -> verifying the dirty map is racy as the guest may + * update the screen while we are looking at it + * -> skip the check + */ + for (y = 0; y < ds_get_height(vs->ds); y++) { + if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) { + has_dirty = 1; + break; + } + } + } if (!has_dirty && !vs->audio_cap) { qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL); -- 1.6.1.3 --------------040204060306070607020106--