All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] ui: improve precision of VNC desktop resizing
@ 2021-03-11 18:29 Daniel P. Berrangé
  2021-03-11 18:29 ` [PATCH 1/4] ui: add more trace points for VNC client/server messages Daniel P. Berrangé
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2021-03-11 18:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Gerd Hoffmann

Currently when resizing the VNC desktop we get a thin black bar down the
right hand side of the screen 93% of the time, because the VNC server
rounds up the display to a multiple of 16. This series solves this
problem by fixing the separation between the server surface dimensions
(which are important for dirty bitmap tracking) and the client desktop
size (which is what the client actually renders).

Daniel P. Berrangé (4):
  ui: add more trace points for VNC client/server messages
  ui: avoid sending framebuffer updates outside client desktop bounds
  ui: use client width/height in WMVi message
  ui: honour the actual guest display dimensions without rounding

 ui/trace-events | 16 ++++++++++++++++
 ui/vnc-jobs.c   | 44 ++++++++++++++++++++++++++++++++++++++++----
 ui/vnc.c        | 48 ++++++++++++++++++++++++++++++++++++++++--------
 ui/vnc.h        |  1 +
 4 files changed, 97 insertions(+), 12 deletions(-)

-- 
2.29.2




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] ui: add more trace points for VNC client/server messages
  2021-03-11 18:29 [PATCH 0/4] ui: improve precision of VNC desktop resizing Daniel P. Berrangé
@ 2021-03-11 18:29 ` Daniel P. Berrangé
  2021-03-11 21:12   ` Marc-André Lureau
  2021-03-11 18:29 ` [PATCH 2/4] ui: avoid sending framebuffer updates outside client desktop bounds Daniel P. Berrangé
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel P. Berrangé @ 2021-03-11 18:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Gerd Hoffmann

This adds trace points for desktop size and audio related messages.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 ui/trace-events |  9 +++++++++
 ui/vnc.c        | 21 +++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/ui/trace-events b/ui/trace-events
index 0ffcdb4408..bd8f8a9d18 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -37,6 +37,15 @@ vnc_key_event_ext(bool down, int sym, int keycode, const char *name) "down %d, s
 vnc_key_event_map(bool down, int sym, int keycode, const char *name) "down %d, sym 0x%x -> keycode 0x%x [%s]"
 vnc_key_sync_numlock(bool on) "%d"
 vnc_key_sync_capslock(bool on) "%d"
+vnc_msg_server_audio_begin(void *state, void *ioc) "VNC server msg audio begin state=%p ioc=%p"
+vnc_msg_server_audio_end(void *state, void *ioc) "VNC server msg audio end state=%p ioc=%p"
+vnc_msg_server_audio_data(void *state, void *ioc, const void *buf, size_t len) "VNC server msg audio data state=%p ioc=%p buf=%p len=%zd"
+vnc_msg_server_desktop_resize(void *state, void *ioc, int width, int height) "VNC server msg ext resize state=%p ioc=%p size=%dx%d"
+vnc_msg_server_ext_desktop_resize(void *state, void *ioc, int width, int height, int reason) "VNC server msg ext resize state=%p ioc=%p size=%dx%d reason=%d"
+vnc_msg_client_audio_enable(void *state, void *ioc) "VNC client msg audio enable state=%p ioc=%p"
+vnc_msg_client_audio_disable(void *state, void *ioc) "VNC client msg audio disable state=%p ioc=%p"
+vnc_msg_client_audio_format(void *state, void *ioc, int fmt, int channels, int freq) "VNC client msg audio format state=%p ioc=%p fmt=%d channels=%d freq=%d"
+vnc_msg_client_set_desktop_size(void *state, void *ioc, int width, int height, int screens) "VNC client msg set desktop size  state=%p ioc=%p size=%dx%d screens=%d"
 vnc_client_eof(void *state, void *ioc) "VNC client EOF state=%p ioc=%p"
 vnc_client_io_error(void *state, void *ioc, const char *msg) "VNC client I/O error state=%p ioc=%p errmsg=%s"
 vnc_client_connect(void *state, void *ioc) "VNC client connect state=%p ioc=%p"
diff --git a/ui/vnc.c b/ui/vnc.c
index e8e3426a65..7291429c04 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -659,6 +659,9 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
 
 static void vnc_desktop_resize_ext(VncState *vs, int reject_reason)
 {
+    trace_vnc_msg_server_ext_desktop_resize(
+        vs, vs->ioc, vs->client_width, vs->client_height, reject_reason);
+
     vnc_lock_output(vs);
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
@@ -705,6 +708,9 @@ static void vnc_desktop_resize(VncState *vs)
         return;
     }
 
+    trace_vnc_msg_server_desktop_resize(
+        vs, vs->ioc, vs->client_width, vs->client_height);
+
     vnc_lock_output(vs);
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
@@ -1182,6 +1188,7 @@ static void audio_capture_notify(void *opaque, audcnotification_e cmd)
     assert(vs->magic == VNC_MAGIC);
     switch (cmd) {
     case AUD_CNOTIFY_DISABLE:
+        trace_vnc_msg_server_audio_end(vs, vs->ioc);
         vnc_lock_output(vs);
         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
@@ -1191,6 +1198,7 @@ static void audio_capture_notify(void *opaque, audcnotification_e cmd)
         break;
 
     case AUD_CNOTIFY_ENABLE:
+        trace_vnc_msg_server_audio_begin(vs, vs->ioc);
         vnc_lock_output(vs);
         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
@@ -1210,6 +1218,7 @@ static void audio_capture(void *opaque, const void *buf, int size)
     VncState *vs = opaque;
 
     assert(vs->magic == VNC_MAGIC);
+    trace_vnc_msg_server_audio_data(vs, vs->ioc, buf, size);
     vnc_lock_output(vs);
     if (vs->output.offset < vs->throttle_output_offset) {
         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
@@ -2454,9 +2463,11 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
 
             switch (read_u16 (data, 2)) {
             case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
+                trace_vnc_msg_client_audio_enable(vs, vs->ioc);
                 audio_add(vs);
                 break;
             case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
+                trace_vnc_msg_client_audio_disable(vs, vs->ioc);
                 audio_del(vs);
                 break;
             case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
@@ -2492,6 +2503,8 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
                     break;
                 }
                 vs->as.freq = freq;
+                trace_vnc_msg_client_audio_format(
+                    vs, vs->ioc, vs->as.fmt, vs->as.nchannels, vs->as.freq);
                 break;
             default:
                 VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 4));
@@ -2510,6 +2523,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
     {
         size_t size;
         uint8_t screens;
+        int w, h;
 
         if (len < 8) {
             return 8;
@@ -2520,12 +2534,15 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
         if (len < size) {
             return size;
         }
+        w = read_u16(data, 2);
+        h = read_u16(data, 4);
 
+        trace_vnc_msg_client_set_desktop_size(vs, vs->ioc, w, h, screens);
         if (dpy_ui_info_supported(vs->vd->dcl.con)) {
             QemuUIInfo info;
             memset(&info, 0, sizeof(info));
-            info.width = read_u16(data, 2);
-            info.height = read_u16(data, 4);
+            info.width = w;
+            info.height = h;
             dpy_set_ui_info(vs->vd->dcl.con, &info);
             vnc_desktop_resize_ext(vs, 4 /* Request forwarded */);
         } else {
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] ui: avoid sending framebuffer updates outside client desktop bounds
  2021-03-11 18:29 [PATCH 0/4] ui: improve precision of VNC desktop resizing Daniel P. Berrangé
  2021-03-11 18:29 ` [PATCH 1/4] ui: add more trace points for VNC client/server messages Daniel P. Berrangé
@ 2021-03-11 18:29 ` Daniel P. Berrangé
  2021-03-11 21:15   ` Marc-André Lureau
  2021-03-11 18:29 ` [PATCH 3/4] ui: use client width/height in WMVi message Daniel P. Berrangé
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel P. Berrangé @ 2021-03-11 18:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Gerd Hoffmann

We plan framebuffer update rects based on the VNC server surface. If the
client doesn't support desktop resize, then the client bounds may differ
from the server surface bounds. VNC clients may become upset if we then
send an update message outside the bounds of the client desktop.

This takes the approach of clamping the rectangles from the worker
thread immediately before sending them. This may sometimes results in
sending a framebuffer update message with zero rectangles.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 ui/trace-events |  5 +++++
 ui/vnc-jobs.c   | 44 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/ui/trace-events b/ui/trace-events
index bd8f8a9d18..3838ae2d84 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -59,6 +59,11 @@ vnc_client_throttle_audio(void *state, void *ioc, size_t offset) "VNC client thr
 vnc_client_unthrottle_forced(void *state, void *ioc) "VNC client unthrottle forced offset state=%p ioc=%p"
 vnc_client_unthrottle_incremental(void *state, void *ioc, size_t offset) "VNC client unthrottle incremental state=%p ioc=%p offset=%zu"
 vnc_client_output_limit(void *state, void *ioc, size_t offset, size_t threshold) "VNC client output limit state=%p ioc=%p offset=%zu threshold=%zu"
+vnc_job_add_rect(void *state, void *job, int x, int y, int w, int h) "VNC add rect state=%p job=%p offset=%d,%d size=%dx%d"
+vnc_job_discard_rect(void *state, void *job, int x, int y, int w, int h) "VNC job discard rect state=%p job=%p offset=%d,%d size=%dx%d"
+vnc_job_clamp_rect(void *state, void *job, int x, int y, int w, int h) "VNC job clamp rect state=%p job=%p offset=%d,%d size=%dx%d"
+vnc_job_clamped_rect(void *state, void *job, int x, int y, int w, int h) "VNC job clamp rect state=%p job=%p offset=%d,%d size=%dx%d"
+vnc_job_nrects(void *state, void *job, int nrects) "VNC job state=%p job=%p nrects=%d"
 vnc_auth_init(void *display, int websock, int auth, int subauth) "VNC auth init state=%p websock=%d auth=%d subauth=%d"
 vnc_auth_start(void *state, int method) "VNC client auth start state=%p method=%d"
 vnc_auth_pass(void *state, int method) "VNC client auth passed state=%p method=%d"
diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
index dbbfbefe56..4562bf8928 100644
--- a/ui/vnc-jobs.c
+++ b/ui/vnc-jobs.c
@@ -32,6 +32,7 @@
 #include "qemu/sockets.h"
 #include "qemu/main-loop.h"
 #include "block/aio.h"
+#include "trace.h"
 
 /*
  * Locking:
@@ -94,6 +95,8 @@ int vnc_job_add_rect(VncJob *job, int x, int y, int w, int h)
 {
     VncRectEntry *entry = g_new0(VncRectEntry, 1);
 
+    trace_vnc_job_add_rect(job->vs, job, x, y, w, h);
+
     entry->rect.x = x;
     entry->rect.y = y;
     entry->rect.w = w;
@@ -190,6 +193,8 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
     local->zlib = orig->zlib;
     local->hextile = orig->hextile;
     local->zrle = orig->zrle;
+    local->client_width = orig->client_width;
+    local->client_height = orig->client_height;
 }
 
 static void vnc_async_encoding_end(VncState *orig, VncState *local)
@@ -202,6 +207,34 @@ static void vnc_async_encoding_end(VncState *orig, VncState *local)
     orig->lossy_rect = local->lossy_rect;
 }
 
+static bool vnc_worker_clamp_rect(VncState *vs, VncJob *job, VncRect *rect)
+{
+    trace_vnc_job_clamp_rect(vs, job, rect->x, rect->y, rect->w, rect->h);
+
+    if (rect->x >= vs->client_width) {
+        goto discard;
+    }
+    rect->w = MIN(vs->client_width - rect->x, rect->w);
+    if (rect->w == 0) {
+        goto discard;
+    }
+
+    if (rect->y >= vs->client_height) {
+        goto discard;
+    }
+    rect->h = MIN(vs->client_height - rect->y, rect->h);
+    if (rect->h == 0) {
+        goto discard;
+    }
+
+    trace_vnc_job_clamped_rect(vs, job, rect->x, rect->y, rect->w, rect->h);
+    return true;
+
+ discard:
+    trace_vnc_job_discard_rect(vs, job, rect->x, rect->y, rect->w, rect->h);
+    return false;
+}
+
 static int vnc_worker_thread_loop(VncJobQueue *queue)
 {
     VncJob *job;
@@ -260,14 +293,17 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
             goto disconnected;
         }
 
-        n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y,
-                                        entry->rect.w, entry->rect.h);
+        if (vnc_worker_clamp_rect(&vs, job, &entry->rect)) {
+            n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y,
+                                            entry->rect.w, entry->rect.h);
 
-        if (n >= 0) {
-            n_rectangles += n;
+            if (n >= 0) {
+                n_rectangles += n;
+            }
         }
         g_free(entry);
     }
+    trace_vnc_job_nrects(&vs, job, n_rectangles);
     vnc_unlock_display(job->vs->vd);
 
     /* Put n_rectangles at the beginning of the message */
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] ui: use client width/height in WMVi message
  2021-03-11 18:29 [PATCH 0/4] ui: improve precision of VNC desktop resizing Daniel P. Berrangé
  2021-03-11 18:29 ` [PATCH 1/4] ui: add more trace points for VNC client/server messages Daniel P. Berrangé
  2021-03-11 18:29 ` [PATCH 2/4] ui: avoid sending framebuffer updates outside client desktop bounds Daniel P. Berrangé
@ 2021-03-11 18:29 ` Daniel P. Berrangé
  2021-03-11 21:19   ` Marc-André Lureau
  2021-03-11 18:29 ` [PATCH 4/4] ui: honour the actual guest display dimensions without rounding Daniel P. Berrangé
  2021-03-12 10:36 ` [PATCH 0/4] ui: improve precision of VNC desktop resizing Gerd Hoffmann
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel P. Berrangé @ 2021-03-11 18:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Gerd Hoffmann

The WMVi message is supposed to provide the same width/height
information as the regular desktop resize and extended desktop
resize messages. There can be times where the client width and
height are different from the pixman surface dimensions.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 ui/vnc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 7291429c04..8c9890b3cd 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2319,8 +2319,8 @@ static void vnc_colordepth(VncState *vs)
         vnc_write_u8(vs, 0);
         vnc_write_u16(vs, 1); /* number of rects */
         vnc_framebuffer_update(vs, 0, 0,
-                               pixman_image_get_width(vs->vd->server),
-                               pixman_image_get_height(vs->vd->server),
+                               vs->client_width,
+                               vs->client_height,
                                VNC_ENCODING_WMVi);
         pixel_format_message(vs);
         vnc_unlock_output(vs);
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] ui: honour the actual guest display dimensions without rounding
  2021-03-11 18:29 [PATCH 0/4] ui: improve precision of VNC desktop resizing Daniel P. Berrangé
                   ` (2 preceding siblings ...)
  2021-03-11 18:29 ` [PATCH 3/4] ui: use client width/height in WMVi message Daniel P. Berrangé
@ 2021-03-11 18:29 ` Daniel P. Berrangé
  2021-03-12  6:48   ` Marc-André Lureau
  2021-03-12 10:36 ` [PATCH 0/4] ui: improve precision of VNC desktop resizing Gerd Hoffmann
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel P. Berrangé @ 2021-03-11 18:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Gerd Hoffmann

A long time ago the VNC server code had some memory corruption
fixes done in:

  commit bea60dd7679364493a0d7f5b54316c767cf894ef
  Author: Peter Lieven <pl@kamp.de>
  Date:   Mon Jun 30 10:57:51 2014 +0200

    ui/vnc: fix potential memory corruption issues

One of the implications of the fix was that the VNC server would have a
thin black bad down the right hand side if the guest desktop width was
not a multiple of 16. In practice this was a non-issue since the VNC
server was always honouring a guest specified resolution and guests
essentially always pick from a small set of sane resolutions likely in
real world hardware.

We recently introduced support for the extended desktop resize extension
and as a result the VNC client has ability to specify an arbitrary
desktop size and the guest OS may well honour it exactly. As a result we
no longer have any guarantee that the width will be a multiple of 16,
and so when resizing the desktop we have a 93% chance of getting the
black bar on the right hand size.

The VNC server maintains three different desktop dimensions

 1. The guest surface
 2. The server surface
 3. The client desktop

The requirement for the width to be a multiple of 16 only applies to
item 2, the server surface, for the purpose of doing dirty bitmap
tracking.

Normally we will set the client desktop size to always match the server
surface size, but that's not a strict requirement. In order to cope with
clients that don't support the desktop size encoding, we already allow
for the client desktop to be a different size that the server surface.

Thus we can trivially eliminate the black bar, but setting the client
desktop size to be the un-rounded server surface size - the so called
"true width".

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 ui/trace-events |  2 ++
 ui/vnc.c        | 23 +++++++++++++++++++----
 ui/vnc.h        |  1 +
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/ui/trace-events b/ui/trace-events
index 3838ae2d84..5d1da6f236 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -59,6 +59,8 @@ vnc_client_throttle_audio(void *state, void *ioc, size_t offset) "VNC client thr
 vnc_client_unthrottle_forced(void *state, void *ioc) "VNC client unthrottle forced offset state=%p ioc=%p"
 vnc_client_unthrottle_incremental(void *state, void *ioc, size_t offset) "VNC client unthrottle incremental state=%p ioc=%p offset=%zu"
 vnc_client_output_limit(void *state, void *ioc, size_t offset, size_t threshold) "VNC client output limit state=%p ioc=%p offset=%zu threshold=%zu"
+vnc_server_dpy_pageflip(void *dpy, int w, int h, int fmt) "VNC server dpy pageflip dpy=%p size=%dx%d fmt=%d"
+vnc_server_dpy_recreate(void *dpy, int w, int h, int fmt) "VNC server dpy recreate dpy=%p size=%dx%d fmt=%d"
 vnc_job_add_rect(void *state, void *job, int x, int y, int w, int h) "VNC add rect state=%p job=%p offset=%d,%d size=%dx%d"
 vnc_job_discard_rect(void *state, void *job, int x, int y, int w, int h) "VNC job discard rect state=%p job=%p offset=%d,%d size=%dx%d"
 vnc_job_clamp_rect(void *state, void *job, int x, int y, int w, int h) "VNC job clamp rect state=%p job=%p offset=%d,%d size=%dx%d"
diff --git a/ui/vnc.c b/ui/vnc.c
index 8c9890b3cd..9c004a11f4 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -608,6 +608,11 @@ static int vnc_width(VncDisplay *vd)
                                        VNC_DIRTY_PIXELS_PER_BIT));
 }
 
+static int vnc_true_width(VncDisplay *vd)
+{
+    return MIN(VNC_MAX_WIDTH, surface_width(vd->ds));
+}
+
 static int vnc_height(VncDisplay *vd)
 {
     return MIN(VNC_MAX_HEIGHT, surface_height(vd->ds));
@@ -691,16 +696,16 @@ static void vnc_desktop_resize(VncState *vs)
                             !vnc_has_feature(vs, VNC_FEATURE_RESIZE_EXT))) {
         return;
     }
-    if (vs->client_width == pixman_image_get_width(vs->vd->server) &&
+    if (vs->client_width == vs->vd->true_width &&
         vs->client_height == pixman_image_get_height(vs->vd->server)) {
         return;
     }
 
-    assert(pixman_image_get_width(vs->vd->server) < 65536 &&
-           pixman_image_get_width(vs->vd->server) >= 0);
+    assert(vs->vd->true_width < 65536 &&
+           vs->vd->true_width >= 0);
     assert(pixman_image_get_height(vs->vd->server) < 65536 &&
            pixman_image_get_height(vs->vd->server) >= 0);
-    vs->client_width = pixman_image_get_width(vs->vd->server);
+    vs->client_width = vs->vd->true_width;
     vs->client_height = pixman_image_get_height(vs->vd->server);
 
     if (vnc_has_feature(vs, VNC_FEATURE_RESIZE_EXT)) {
@@ -774,6 +779,7 @@ static void vnc_update_server_surface(VncDisplay *vd)
 
     width = vnc_width(vd);
     height = vnc_height(vd);
+    vd->true_width = vnc_true_width(vd);
     vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
                                           width, height,
                                           NULL, 0);
@@ -809,13 +815,22 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
     vd->guest.fb = pixman_image_ref(surface->image);
     vd->guest.format = surface->format;
 
+
     if (pageflip) {
+        trace_vnc_server_dpy_pageflip(vd,
+                                      surface_width(surface),
+                                      surface_height(surface),
+                                      surface_format(surface));
         vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0,
                            surface_width(surface),
                            surface_height(surface));
         return;
     }
 
+    trace_vnc_server_dpy_recreate(vd,
+                                  surface_width(surface),
+                                  surface_height(surface),
+                                  surface_format(surface));
     /* server surface */
     vnc_update_server_surface(vd);
 
diff --git a/ui/vnc.h b/ui/vnc.h
index 116463d5f0..d4f3e15558 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -164,6 +164,7 @@ struct VncDisplay
 
     struct VncSurface guest;   /* guest visible surface (aka ds->surface) */
     pixman_image_t *server;    /* vnc server surface */
+    int true_width; /* server surface width before rounding up */
 
     const char *id;
     QTAILQ_ENTRY(VncDisplay) next;
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/4] ui: add more trace points for VNC client/server messages
  2021-03-11 18:29 ` [PATCH 1/4] ui: add more trace points for VNC client/server messages Daniel P. Berrangé
@ 2021-03-11 21:12   ` Marc-André Lureau
  0 siblings, 0 replies; 10+ messages in thread
From: Marc-André Lureau @ 2021-03-11 21:12 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: QEMU, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 6475 bytes --]

On Thu, Mar 11, 2021 at 10:43 PM Daniel P. Berrangé <berrange@redhat.com>
wrote:

> This adds trace points for desktop size and audio related messages.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

---
>  ui/trace-events |  9 +++++++++
>  ui/vnc.c        | 21 +++++++++++++++++++--
>  2 files changed, 28 insertions(+), 2 deletions(-)
>
> diff --git a/ui/trace-events b/ui/trace-events
> index 0ffcdb4408..bd8f8a9d18 100644
> --- a/ui/trace-events
> +++ b/ui/trace-events
> @@ -37,6 +37,15 @@ vnc_key_event_ext(bool down, int sym, int keycode,
> const char *name) "down %d, s
>  vnc_key_event_map(bool down, int sym, int keycode, const char *name)
> "down %d, sym 0x%x -> keycode 0x%x [%s]"
>  vnc_key_sync_numlock(bool on) "%d"
>  vnc_key_sync_capslock(bool on) "%d"
> +vnc_msg_server_audio_begin(void *state, void *ioc) "VNC server msg audio
> begin state=%p ioc=%p"
> +vnc_msg_server_audio_end(void *state, void *ioc) "VNC server msg audio
> end state=%p ioc=%p"
> +vnc_msg_server_audio_data(void *state, void *ioc, const void *buf, size_t
> len) "VNC server msg audio data state=%p ioc=%p buf=%p len=%zd"
> +vnc_msg_server_desktop_resize(void *state, void *ioc, int width, int
> height) "VNC server msg ext resize state=%p ioc=%p size=%dx%d"
> +vnc_msg_server_ext_desktop_resize(void *state, void *ioc, int width, int
> height, int reason) "VNC server msg ext resize state=%p ioc=%p size=%dx%d
> reason=%d"
> +vnc_msg_client_audio_enable(void *state, void *ioc) "VNC client msg audio
> enable state=%p ioc=%p"
> +vnc_msg_client_audio_disable(void *state, void *ioc) "VNC client msg
> audio disable state=%p ioc=%p"
> +vnc_msg_client_audio_format(void *state, void *ioc, int fmt, int
> channels, int freq) "VNC client msg audio format state=%p ioc=%p fmt=%d
> channels=%d freq=%d"
> +vnc_msg_client_set_desktop_size(void *state, void *ioc, int width, int
> height, int screens) "VNC client msg set desktop size  state=%p ioc=%p
> size=%dx%d screens=%d"
>  vnc_client_eof(void *state, void *ioc) "VNC client EOF state=%p ioc=%p"
>  vnc_client_io_error(void *state, void *ioc, const char *msg) "VNC client
> I/O error state=%p ioc=%p errmsg=%s"
>  vnc_client_connect(void *state, void *ioc) "VNC client connect state=%p
> ioc=%p"
> diff --git a/ui/vnc.c b/ui/vnc.c
> index e8e3426a65..7291429c04 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -659,6 +659,9 @@ void vnc_framebuffer_update(VncState *vs, int x, int
> y, int w, int h,
>
>  static void vnc_desktop_resize_ext(VncState *vs, int reject_reason)
>  {
> +    trace_vnc_msg_server_ext_desktop_resize(
> +        vs, vs->ioc, vs->client_width, vs->client_height, reject_reason);
> +
>      vnc_lock_output(vs);
>      vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
>      vnc_write_u8(vs, 0);
> @@ -705,6 +708,9 @@ static void vnc_desktop_resize(VncState *vs)
>          return;
>      }
>
> +    trace_vnc_msg_server_desktop_resize(
> +        vs, vs->ioc, vs->client_width, vs->client_height);
> +
>      vnc_lock_output(vs);
>      vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
>      vnc_write_u8(vs, 0);
> @@ -1182,6 +1188,7 @@ static void audio_capture_notify(void *opaque,
> audcnotification_e cmd)
>      assert(vs->magic == VNC_MAGIC);
>      switch (cmd) {
>      case AUD_CNOTIFY_DISABLE:
> +        trace_vnc_msg_server_audio_end(vs, vs->ioc);
>          vnc_lock_output(vs);
>          vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
>          vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
> @@ -1191,6 +1198,7 @@ static void audio_capture_notify(void *opaque,
> audcnotification_e cmd)
>          break;
>
>      case AUD_CNOTIFY_ENABLE:
> +        trace_vnc_msg_server_audio_begin(vs, vs->ioc);
>          vnc_lock_output(vs);
>          vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
>          vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
> @@ -1210,6 +1218,7 @@ static void audio_capture(void *opaque, const void
> *buf, int size)
>      VncState *vs = opaque;
>
>      assert(vs->magic == VNC_MAGIC);
> +    trace_vnc_msg_server_audio_data(vs, vs->ioc, buf, size);
>      vnc_lock_output(vs);
>      if (vs->output.offset < vs->throttle_output_offset) {
>          vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
> @@ -2454,9 +2463,11 @@ static int protocol_client_msg(VncState *vs,
> uint8_t *data, size_t len)
>
>              switch (read_u16 (data, 2)) {
>              case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
> +                trace_vnc_msg_client_audio_enable(vs, vs->ioc);
>                  audio_add(vs);
>                  break;
>              case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
> +                trace_vnc_msg_client_audio_disable(vs, vs->ioc);
>                  audio_del(vs);
>                  break;
>              case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
> @@ -2492,6 +2503,8 @@ static int protocol_client_msg(VncState *vs, uint8_t
> *data, size_t len)
>                      break;
>                  }
>                  vs->as.freq = freq;
> +                trace_vnc_msg_client_audio_format(
> +                    vs, vs->ioc, vs->as.fmt, vs->as.nchannels,
> vs->as.freq);
>                  break;
>              default:
>                  VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 4));
> @@ -2510,6 +2523,7 @@ static int protocol_client_msg(VncState *vs, uint8_t
> *data, size_t len)
>      {
>          size_t size;
>          uint8_t screens;
> +        int w, h;
>
>          if (len < 8) {
>              return 8;
> @@ -2520,12 +2534,15 @@ static int protocol_client_msg(VncState *vs,
> uint8_t *data, size_t len)
>          if (len < size) {
>              return size;
>          }
> +        w = read_u16(data, 2);
> +        h = read_u16(data, 4);
>
> +        trace_vnc_msg_client_set_desktop_size(vs, vs->ioc, w, h, screens);
>          if (dpy_ui_info_supported(vs->vd->dcl.con)) {
>              QemuUIInfo info;
>              memset(&info, 0, sizeof(info));
> -            info.width = read_u16(data, 2);
> -            info.height = read_u16(data, 4);
> +            info.width = w;
> +            info.height = h;
>              dpy_set_ui_info(vs->vd->dcl.con, &info);
>              vnc_desktop_resize_ext(vs, 4 /* Request forwarded */);
>          } else {
> --
> 2.29.2
>
>
>

-- 
Marc-André Lureau

[-- Attachment #2: Type: text/html, Size: 7987 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] ui: avoid sending framebuffer updates outside client desktop bounds
  2021-03-11 18:29 ` [PATCH 2/4] ui: avoid sending framebuffer updates outside client desktop bounds Daniel P. Berrangé
@ 2021-03-11 21:15   ` Marc-André Lureau
  0 siblings, 0 replies; 10+ messages in thread
From: Marc-André Lureau @ 2021-03-11 21:15 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: QEMU, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 5468 bytes --]

On Thu, Mar 11, 2021 at 10:37 PM Daniel P. Berrangé <berrange@redhat.com>
wrote:

> We plan framebuffer update rects based on the VNC server surface. If the
> client doesn't support desktop resize, then the client bounds may differ
> from the server surface bounds. VNC clients may become upset if we then
> send an update message outside the bounds of the client desktop.
>
> This takes the approach of clamping the rectangles from the worker
> thread immediately before sending them. This may sometimes results in
> sending a framebuffer update message with zero rectangles.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

---
>  ui/trace-events |  5 +++++
>  ui/vnc-jobs.c   | 44 ++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 45 insertions(+), 4 deletions(-)
>
> diff --git a/ui/trace-events b/ui/trace-events
> index bd8f8a9d18..3838ae2d84 100644
> --- a/ui/trace-events
> +++ b/ui/trace-events
> @@ -59,6 +59,11 @@ vnc_client_throttle_audio(void *state, void *ioc,
> size_t offset) "VNC client thr
>  vnc_client_unthrottle_forced(void *state, void *ioc) "VNC client
> unthrottle forced offset state=%p ioc=%p"
>  vnc_client_unthrottle_incremental(void *state, void *ioc, size_t offset)
> "VNC client unthrottle incremental state=%p ioc=%p offset=%zu"
>  vnc_client_output_limit(void *state, void *ioc, size_t offset, size_t
> threshold) "VNC client output limit state=%p ioc=%p offset=%zu
> threshold=%zu"
> +vnc_job_add_rect(void *state, void *job, int x, int y, int w, int h) "VNC
> add rect state=%p job=%p offset=%d,%d size=%dx%d"
> +vnc_job_discard_rect(void *state, void *job, int x, int y, int w, int h)
> "VNC job discard rect state=%p job=%p offset=%d,%d size=%dx%d"
> +vnc_job_clamp_rect(void *state, void *job, int x, int y, int w, int h)
> "VNC job clamp rect state=%p job=%p offset=%d,%d size=%dx%d"
> +vnc_job_clamped_rect(void *state, void *job, int x, int y, int w, int h)
> "VNC job clamp rect state=%p job=%p offset=%d,%d size=%dx%d"
> +vnc_job_nrects(void *state, void *job, int nrects) "VNC job state=%p
> job=%p nrects=%d"
>  vnc_auth_init(void *display, int websock, int auth, int subauth) "VNC
> auth init state=%p websock=%d auth=%d subauth=%d"
>  vnc_auth_start(void *state, int method) "VNC client auth start state=%p
> method=%d"
>  vnc_auth_pass(void *state, int method) "VNC client auth passed state=%p
> method=%d"
> diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
> index dbbfbefe56..4562bf8928 100644
> --- a/ui/vnc-jobs.c
> +++ b/ui/vnc-jobs.c
> @@ -32,6 +32,7 @@
>  #include "qemu/sockets.h"
>  #include "qemu/main-loop.h"
>  #include "block/aio.h"
> +#include "trace.h"
>
>  /*
>   * Locking:
> @@ -94,6 +95,8 @@ int vnc_job_add_rect(VncJob *job, int x, int y, int w,
> int h)
>  {
>      VncRectEntry *entry = g_new0(VncRectEntry, 1);
>
> +    trace_vnc_job_add_rect(job->vs, job, x, y, w, h);
> +
>      entry->rect.x = x;
>      entry->rect.y = y;
>      entry->rect.w = w;
> @@ -190,6 +193,8 @@ static void vnc_async_encoding_start(VncState *orig,
> VncState *local)
>      local->zlib = orig->zlib;
>      local->hextile = orig->hextile;
>      local->zrle = orig->zrle;
> +    local->client_width = orig->client_width;
> +    local->client_height = orig->client_height;
>  }
>
>  static void vnc_async_encoding_end(VncState *orig, VncState *local)
> @@ -202,6 +207,34 @@ static void vnc_async_encoding_end(VncState *orig,
> VncState *local)
>      orig->lossy_rect = local->lossy_rect;
>  }
>
> +static bool vnc_worker_clamp_rect(VncState *vs, VncJob *job, VncRect
> *rect)
> +{
> +    trace_vnc_job_clamp_rect(vs, job, rect->x, rect->y, rect->w, rect->h);
> +
> +    if (rect->x >= vs->client_width) {
> +        goto discard;
> +    }
> +    rect->w = MIN(vs->client_width - rect->x, rect->w);
> +    if (rect->w == 0) {
> +        goto discard;
> +    }
> +
> +    if (rect->y >= vs->client_height) {
> +        goto discard;
> +    }
> +    rect->h = MIN(vs->client_height - rect->y, rect->h);
> +    if (rect->h == 0) {
> +        goto discard;
> +    }
> +
> +    trace_vnc_job_clamped_rect(vs, job, rect->x, rect->y, rect->w,
> rect->h);
> +    return true;
> +
> + discard:
> +    trace_vnc_job_discard_rect(vs, job, rect->x, rect->y, rect->w,
> rect->h);
> +    return false;
> +}
> +
>  static int vnc_worker_thread_loop(VncJobQueue *queue)
>  {
>      VncJob *job;
> @@ -260,14 +293,17 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
>              goto disconnected;
>          }
>
> -        n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y,
> -                                        entry->rect.w, entry->rect.h);
> +        if (vnc_worker_clamp_rect(&vs, job, &entry->rect)) {
> +            n = vnc_send_framebuffer_update(&vs, entry->rect.x,
> entry->rect.y,
> +                                            entry->rect.w, entry->rect.h);
>
> -        if (n >= 0) {
> -            n_rectangles += n;
> +            if (n >= 0) {
> +                n_rectangles += n;
> +            }
>          }
>          g_free(entry);
>      }
> +    trace_vnc_job_nrects(&vs, job, n_rectangles);
>      vnc_unlock_display(job->vs->vd);
>
>      /* Put n_rectangles at the beginning of the message */
> --
> 2.29.2
>
>
>

-- 
Marc-André Lureau

[-- Attachment #2: Type: text/html, Size: 6896 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] ui: use client width/height in WMVi message
  2021-03-11 18:29 ` [PATCH 3/4] ui: use client width/height in WMVi message Daniel P. Berrangé
@ 2021-03-11 21:19   ` Marc-André Lureau
  0 siblings, 0 replies; 10+ messages in thread
From: Marc-André Lureau @ 2021-03-11 21:19 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: QEMU, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 1307 bytes --]

On Thu, Mar 11, 2021 at 10:46 PM Daniel P. Berrangé <berrange@redhat.com>
wrote:

> The WMVi message is supposed to provide the same width/height
> information as the regular desktop resize and extended desktop
> resize messages. There can be times where the client width and
> height are different from the pixman surface dimensions.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

---
>  ui/vnc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 7291429c04..8c9890b3cd 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -2319,8 +2319,8 @@ static void vnc_colordepth(VncState *vs)
>          vnc_write_u8(vs, 0);
>          vnc_write_u16(vs, 1); /* number of rects */
>          vnc_framebuffer_update(vs, 0, 0,
> -                               pixman_image_get_width(vs->vd->server),
> -                               pixman_image_get_height(vs->vd->server),
> +                               vs->client_width,
> +                               vs->client_height,
>                                 VNC_ENCODING_WMVi);
>          pixel_format_message(vs);
>          vnc_unlock_output(vs);
> --
> 2.29.2
>
>
>

-- 
Marc-André Lureau

[-- Attachment #2: Type: text/html, Size: 2155 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] ui: honour the actual guest display dimensions without rounding
  2021-03-11 18:29 ` [PATCH 4/4] ui: honour the actual guest display dimensions without rounding Daniel P. Berrangé
@ 2021-03-12  6:48   ` Marc-André Lureau
  0 siblings, 0 replies; 10+ messages in thread
From: Marc-André Lureau @ 2021-03-12  6:48 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: QEMU, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 6853 bytes --]

On Thu, Mar 11, 2021 at 10:38 PM Daniel P. Berrangé <berrange@redhat.com>
wrote:

> A long time ago the VNC server code had some memory corruption
> fixes done in:
>
>   commit bea60dd7679364493a0d7f5b54316c767cf894ef
>   Author: Peter Lieven <pl@kamp.de>
>   Date:   Mon Jun 30 10:57:51 2014 +0200
>
>     ui/vnc: fix potential memory corruption issues
>
> One of the implications of the fix was that the VNC server would have a
> thin black bad down the right hand side if the guest desktop width was
> not a multiple of 16. In practice this was a non-issue since the VNC
> server was always honouring a guest specified resolution and guests
> essentially always pick from a small set of sane resolutions likely in
> real world hardware.
>
> We recently introduced support for the extended desktop resize extension
> and as a result the VNC client has ability to specify an arbitrary
> desktop size and the guest OS may well honour it exactly. As a result we
> no longer have any guarantee that the width will be a multiple of 16,
> and so when resizing the desktop we have a 93% chance of getting the
> black bar on the right hand size.
>
> The VNC server maintains three different desktop dimensions
>
>  1. The guest surface
>  2. The server surface
>  3. The client desktop
>
> The requirement for the width to be a multiple of 16 only applies to
> item 2, the server surface, for the purpose of doing dirty bitmap
> tracking.
>
> Normally we will set the client desktop size to always match the server
> surface size, but that's not a strict requirement. In order to cope with
> clients that don't support the desktop size encoding, we already allow
> for the client desktop to be a different size that the server surface.
>
> Thus we can trivially eliminate the black bar, but setting the client
> desktop size to be the un-rounded server surface size - the so called
> "true width".
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  ui/trace-events |  2 ++
>  ui/vnc.c        | 23 +++++++++++++++++++----
>  ui/vnc.h        |  1 +
>  3 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/ui/trace-events b/ui/trace-events
> index 3838ae2d84..5d1da6f236 100644
> --- a/ui/trace-events
> +++ b/ui/trace-events
> @@ -59,6 +59,8 @@ vnc_client_throttle_audio(void *state, void *ioc, size_t
> offset) "VNC client thr
>  vnc_client_unthrottle_forced(void *state, void *ioc) "VNC client
> unthrottle forced offset state=%p ioc=%p"
>  vnc_client_unthrottle_incremental(void *state, void *ioc, size_t offset)
> "VNC client unthrottle incremental state=%p ioc=%p offset=%zu"
>  vnc_client_output_limit(void *state, void *ioc, size_t offset, size_t
> threshold) "VNC client output limit state=%p ioc=%p offset=%zu
> threshold=%zu"
> +vnc_server_dpy_pageflip(void *dpy, int w, int h, int fmt) "VNC server dpy
> pageflip dpy=%p size=%dx%d fmt=%d"
> +vnc_server_dpy_recreate(void *dpy, int w, int h, int fmt) "VNC server dpy
> recreate dpy=%p size=%dx%d fmt=%d"
>  vnc_job_add_rect(void *state, void *job, int x, int y, int w, int h) "VNC
> add rect state=%p job=%p offset=%d,%d size=%dx%d"
>  vnc_job_discard_rect(void *state, void *job, int x, int y, int w, int h)
> "VNC job discard rect state=%p job=%p offset=%d,%d size=%dx%d"
>  vnc_job_clamp_rect(void *state, void *job, int x, int y, int w, int h)
> "VNC job clamp rect state=%p job=%p offset=%d,%d size=%dx%d"
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 8c9890b3cd..9c004a11f4 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -608,6 +608,11 @@ static int vnc_width(VncDisplay *vd)
>                                         VNC_DIRTY_PIXELS_PER_BIT));
>  }
>
> +static int vnc_true_width(VncDisplay *vd)
> +{
> +    return MIN(VNC_MAX_WIDTH, surface_width(vd->ds));
> +}
> +
>  static int vnc_height(VncDisplay *vd)
>  {
>      return MIN(VNC_MAX_HEIGHT, surface_height(vd->ds));
> @@ -691,16 +696,16 @@ static void vnc_desktop_resize(VncState *vs)
>                              !vnc_has_feature(vs,
> VNC_FEATURE_RESIZE_EXT))) {
>          return;
>      }
> -    if (vs->client_width == pixman_image_get_width(vs->vd->server) &&
> +    if (vs->client_width == vs->vd->true_width &&
>          vs->client_height == pixman_image_get_height(vs->vd->server)) {
>          return;
>      }
>
> -    assert(pixman_image_get_width(vs->vd->server) < 65536 &&
> -           pixman_image_get_width(vs->vd->server) >= 0);
> +    assert(vs->vd->true_width < 65536 &&
> +           vs->vd->true_width >= 0);
>      assert(pixman_image_get_height(vs->vd->server) < 65536 &&
>             pixman_image_get_height(vs->vd->server) >= 0);
> -    vs->client_width = pixman_image_get_width(vs->vd->server);
> +    vs->client_width = vs->vd->true_width;
>      vs->client_height = pixman_image_get_height(vs->vd->server);
>
>      if (vnc_has_feature(vs, VNC_FEATURE_RESIZE_EXT)) {
> @@ -774,6 +779,7 @@ static void vnc_update_server_surface(VncDisplay *vd)
>
>      width = vnc_width(vd);
>      height = vnc_height(vd);
> +    vd->true_width = vnc_true_width(vd);
>      vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
>                                            width, height,
>                                            NULL, 0);
> @@ -809,13 +815,22 @@ static void vnc_dpy_switch(DisplayChangeListener
> *dcl,
>      vd->guest.fb = pixman_image_ref(surface->image);
>      vd->guest.format = surface->format;
>
> +
>      if (pageflip) {
> +        trace_vnc_server_dpy_pageflip(vd,
> +                                      surface_width(surface),
> +                                      surface_height(surface),
> +                                      surface_format(surface));
>          vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0,
>                             surface_width(surface),
>                             surface_height(surface));
>          return;
>      }
>
> +    trace_vnc_server_dpy_recreate(vd,
> +                                  surface_width(surface),
> +                                  surface_height(surface),
> +                                  surface_format(surface));
>      /* server surface */
>      vnc_update_server_surface(vd);
>
> diff --git a/ui/vnc.h b/ui/vnc.h
> index 116463d5f0..d4f3e15558 100644
> --- a/ui/vnc.h
> +++ b/ui/vnc.h
> @@ -164,6 +164,7 @@ struct VncDisplay
>
>      struct VncSurface guest;   /* guest visible surface (aka ds->surface)
> */
>      pixman_image_t *server;    /* vnc server surface */
> +    int true_width; /* server surface width before rounding up */
>
>      const char *id;
>      QTAILQ_ENTRY(VncDisplay) next;
> --
> 2.29.2
>
>
>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>


-- 
Marc-André Lureau

[-- Attachment #2: Type: text/html, Size: 8352 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] ui: improve precision of VNC desktop resizing
  2021-03-11 18:29 [PATCH 0/4] ui: improve precision of VNC desktop resizing Daniel P. Berrangé
                   ` (3 preceding siblings ...)
  2021-03-11 18:29 ` [PATCH 4/4] ui: honour the actual guest display dimensions without rounding Daniel P. Berrangé
@ 2021-03-12 10:36 ` Gerd Hoffmann
  4 siblings, 0 replies; 10+ messages in thread
From: Gerd Hoffmann @ 2021-03-12 10:36 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: qemu-devel

On Thu, Mar 11, 2021 at 06:29:53PM +0000, Daniel P. Berrangé wrote:
> Currently when resizing the VNC desktop we get a thin black bar down the
> right hand side of the screen 93% of the time, because the VNC server
> rounds up the display to a multiple of 16. This series solves this
> problem by fixing the separation between the server surface dimensions
> (which are important for dirty bitmap tracking) and the client desktop
> size (which is what the client actually renders).
> 
> Daniel P. Berrangé (4):
>   ui: add more trace points for VNC client/server messages
>   ui: avoid sending framebuffer updates outside client desktop bounds
>   ui: use client width/height in WMVi message
>   ui: honour the actual guest display dimensions without rounding

Added to ui patch queue.

thanks,
  Gerd



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-03-12 10:54 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-11 18:29 [PATCH 0/4] ui: improve precision of VNC desktop resizing Daniel P. Berrangé
2021-03-11 18:29 ` [PATCH 1/4] ui: add more trace points for VNC client/server messages Daniel P. Berrangé
2021-03-11 21:12   ` Marc-André Lureau
2021-03-11 18:29 ` [PATCH 2/4] ui: avoid sending framebuffer updates outside client desktop bounds Daniel P. Berrangé
2021-03-11 21:15   ` Marc-André Lureau
2021-03-11 18:29 ` [PATCH 3/4] ui: use client width/height in WMVi message Daniel P. Berrangé
2021-03-11 21:19   ` Marc-André Lureau
2021-03-11 18:29 ` [PATCH 4/4] ui: honour the actual guest display dimensions without rounding Daniel P. Berrangé
2021-03-12  6:48   ` Marc-André Lureau
2021-03-12 10:36 ` [PATCH 0/4] ui: improve precision of VNC desktop resizing Gerd Hoffmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.