]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
ui/vnc: Update display update interval when VM state changes to RUNNING
authorJuraj Marcin <jmarcin@redhat.com>
Wed, 21 May 2025 15:16:13 +0000 (17:16 +0200)
committerPeter Xu <peterx@redhat.com>
Mon, 23 Jun 2025 20:03:59 +0000 (16:03 -0400)
If a virtual machine is paused for an extended period time, for example,
due to an incoming migration, there are also no changes on the screen.
VNC in such case increases the display update interval by
VNC_REFRESH_INTERVAL_INC (50 ms). The update interval can then grow up
to VNC_REFRESH_INTERVAL_MAX (3000 ms).

When the machine resumes, it can then take up to 3 seconds for the first
display update. Furthermore, the update interval is then halved with
each display update with changes on the screen. If there are moving
elements on the screen, such as a video, this can be perceived as
freezing and stuttering for few seconds before the movement is smooth
again.

This patch resolves this issue, by adding a listener to VM state changes
and changing the update interval when the VM state changes to RUNNING.
The update_displaychangelistener() function updates the internal timer,
and the display is refreshed immediately if the timer is expired.

Signed-off-by: Juraj Marcin <jmarcin@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Link: https://lore.kernel.org/r/20250521151616.3951178-1-jmarcin@redhat.com
Signed-off-by: Peter Xu <peterx@redhat.com>
ui/vnc.c
ui/vnc.h

index d095cd7da31e2fe0d7241894b7ed5d2cbb21f72c..e9c30aad62c254f2281eada4a83f0ec4942e740c 100644 (file)
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3385,6 +3385,16 @@ static const DisplayChangeListenerOps dcl_ops = {
     .dpy_cursor_define    = vnc_dpy_cursor_define,
 };
 
+static void vmstate_change_handler(void *opaque, bool running, RunState state)
+{
+    VncDisplay *vd = opaque;
+
+    if (state != RUN_STATE_RUNNING) {
+        return;
+    }
+    update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
+}
+
 void vnc_display_init(const char *id, Error **errp)
 {
     VncDisplay *vd;
@@ -3421,6 +3431,8 @@ void vnc_display_init(const char *id, Error **errp)
     vd->dcl.ops = &dcl_ops;
     register_displaychangelistener(&vd->dcl);
     vd->kbd = qkbd_state_init(vd->dcl.con);
+    vd->vmstate_handler_entry = qemu_add_vm_change_state_handler(
+        &vmstate_change_handler, vd);
 }
 
 
index 02613aa63a170901734a04aee84abff7b58d8736..b3e07269bb4322c8a51bf36b1df292a92f5654af 100644 (file)
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -185,6 +185,8 @@ struct VncDisplay
 #endif
 
     AudioState *audio_state;
+
+    VMChangeStateEntry *vmstate_handler_entry;
 };
 
 typedef struct VncTight {