qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] gtk: sync guest display updates to host display


From: Chen Zhang
Subject: Re: [Qemu-devel] [PATCH] gtk: sync guest display updates to host display refresh
Date: Mon, 26 Nov 2018 11:24:52 +0800

Update refresh interval upon frame tick;
Add callback of window state events to adjust refresh rate during iconified.
The callback handle is saved in struct VirtualConsole for its removal when the 
window is iconified.

Signed-off-by: Chen Zhang <address@hidden>
---
 include/ui/gtk.h |  1 +
 ui/gtk.c         | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 99edd3c..c1f7655 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -76,6 +76,7 @@ typedef struct VirtualConsole {
     GtkWidget *tab_item;
     GtkWidget *focus;
     VirtualConsoleType type;
+    guint frame_tick_cb;
     union {
         VirtualGfxConsole gfx;
 #if defined(CONFIG_VTE)
diff --git a/ui/gtk.c b/ui/gtk.c
index 579990b..9bc5812 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1661,6 +1661,43 @@ static gboolean gd_configure(GtkWidget *widget,
     return FALSE;
 }
 
+static gboolean gd_frame_tick(GtkWidget *widget,
+                              GdkFrameClock *frame_clock,
+                              gpointer opaque)
+{
+    VirtualConsole *vc = opaque;
+    gint64 interval;
+    gdk_frame_clock_get_refresh_info(frame_clock,
+            0,
+            &interval,
+            NULL);
+    interval = interval / 1000;
+    if (vc->gfx.dcl.update_interval != interval) {
+        update_displaychangelistener(&vc->gfx.dcl, interval);
+    }
+    return G_SOURCE_CONTINUE;
+}
+
+static void gd_window_state_event(GtkWidget *widget,
+                           GdkEventWindowState *event,
+                           GtkDisplayState *s)
+{
+    if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) {
+        bool iconified = (event->new_window_state & 
GDK_WINDOW_STATE_ICONIFIED) != 0;
+        VirtualConsole *vc = gd_vc_find_current(s);
+        if (iconified) {
+            gtk_widget_remove_tick_callback(vc->gfx.drawing_area,
+                                            vc->frame_tick_cb);
+            update_displaychangelistener(&vc->gfx.dcl, 
GUI_REFRESH_INTERVAL_IDLE);
+        } else {
+            vc->frame_tick_cb =
+                gtk_widget_add_tick_callback(vc->gfx.drawing_area,
+                                             gd_frame_tick, vc, NULL);
+            update_displaychangelistener(&vc->gfx.dcl, 
GUI_REFRESH_INTERVAL_DEFAULT);
+        }
+    }
+}
+
 /** Virtual Console Callbacks **/
 
 static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc,
@@ -1911,6 +1948,17 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc)
                          G_CALLBACK(gd_focus_out_event), vc);
         g_signal_connect(vc->gfx.drawing_area, "configure-event",
                          G_CALLBACK(gd_configure), vc);
+        if (1 /* make that a config option ??? */) {
+            update_displaychangelistener(&vc->gfx.dcl,
+                                         GUI_REFRESH_INTERVAL_IDLE);
+            vc->frame_tick_cb =
+                    gtk_widget_add_tick_callback(vc->gfx.drawing_area,
+                                                 gd_frame_tick, vc, NULL);
+
+            gtk_widget_add_events(vc->s->window, GDK_STRUCTURE_MASK);
+            g_signal_connect(vc->s->window, "window-state-event",
+                             G_CALLBACK(gd_window_state_event), vc->s);
+        }
     } else {
         g_signal_connect(vc->gfx.drawing_area, "key-press-event",
                          G_CALLBACK(gd_text_key_down), vc);
-- 
2.7.4


> On Nov 14, 2018, at 5:40 PM, Chen Zhang <address@hidden> wrote:
> 
> Additionally, the aforementioned patch performs OK for non-vfio OpenGL 
> enabled GTK displays, and fails DMA Buf iGVT-g display only, so far as I 
> could tell.
> 
> Perhaps a change like the following is better?
> 
>  static gboolean gd_frame_tick(GtkWidget *widget,
>                                GdkFrameClock *frame_clock,
>                                gpointer opaque)
>  {
>      VirtualConsole *vc = opaque;
> -
> -    vc->gfx.dcl.ops->dpy_refresh(&vc->gfx.dcl);
> +    gint64 interval;
> +    gdk_frame_clock_get_refresh_info(frame_clock,
> +            0,
> +            &interval,
> +            NULL);
> +    interval /= 1000;
> +    if (vc->gfx.dcl.update_interval != interval) {
> +        update_displaychangelistener(&vc->gfx.dcl, interval);
> +    }
>      return G_SOURCE_CONTINUE;
>  }
> 
> 
>> On Nov 14, 2018, at 11:10 AM, Chen Zhang <address@hidden 
>> <mailto:address@hidden>> wrote:
>> 
>> Hi,
>> 
>> I have briefly tested this patch. Unfortunately, it apparently caused 
>> deteriorated performance on a previously working Windows 10 guest with DMA 
>> Buf.
>> 
>> The patched qemu not only clogged up graphics drawing, but also obstructed 
>> the guest OS. The boot time and latency for guest operations (e.g. clicking 
>> Start menu in guest) dramatically increased. My best guess would be that GTK 
>> update events messed up with some polling in main_loop_wait(false), leading 
>> to blocked IO, or conversely the GUI being blocked by IO.
>> 
>> Best regards,
>> 
>> --
>> P.S:
>> 
>> The arguments for qemu:
>> 
>> /tmp/qemu-system-x86_64 -nodefaults -machine 
>> pc,accel=kvm,usb=off,kernel_irqchip=on \
>>  -vga none -display gtk,gl=on  -rtc base=localtime \
>>  -device 
>> vfio-pci,sysfsdev=/sys/bus/pci/devices/0000:00:02.0/{UUID-FOR-MDEV},x-igd-opregion=on,display=on,rombar=0
>>  \
>>  -m 3000 -realtime mlock=off -smp 3,sockets=1,cores=1 \
>>  -drive file=/home/user/disk.img,format=qcow2,media=disk,if=ide \
>>  -usb -device qemu-xhci,id=xhci -device usb-tablet,bus=xhci.0 \
>>  -cpu host -monitor stdio
>> 
>> The host runs a Ubuntu 18.04 desktop.
>> 
>>> On Nov 13, 2018, at 5:02 PM, Gerd Hoffmann <address@hidden 
>>> <mailto:address@hidden>> wrote:
>>> 
>>> Reduce console refresh timer to idle refresh rate.  Register a frame
>>> tick callback (called by gtk on each display frame) and use that to kick
>>> display updates instead.
>>> 
>>> That should sync qemu refresh rate to display refresh rate.  It'll also
>>> stop updating the qemu display in case the qemu is not visible (gtk
>>> stops calling the frame tick callback then).
>>> 
>>> Buglink: https://bugs.launchpad.net/bugs/1802915 
>>> <https://bugs.launchpad.net/bugs/1802915>
>>> Suggested-by: Chen Zhang <address@hidden <mailto:address@hidden>>
>>> Signed-off-by: Gerd Hoffmann <address@hidden <mailto:address@hidden>>
>>> ---
>>> ui/gtk.c | 16 ++++++++++++++++
>>> 1 file changed, 16 insertions(+)
>>> 
>>> diff --git a/ui/gtk.c b/ui/gtk.c
>>> index 579990b865..8f79dfe42c 100644
>>> --- a/ui/gtk.c
>>> +++ b/ui/gtk.c
>>> @@ -1661,6 +1661,16 @@ static gboolean gd_configure(GtkWidget *widget,
>>>    return FALSE;
>>> }
>>> 
>>> +static gboolean gd_frame_tick(GtkWidget *widget,
>>> +                              GdkFrameClock *frame_clock,
>>> +                              gpointer opaque)
>>> +{
>>> +    VirtualConsole *vc = opaque;
>>> +
>>> +    vc->gfx.dcl.ops->dpy_refresh(&vc->gfx.dcl);
>>> +    return G_SOURCE_CONTINUE;
>>> +}
>>> +
>>> /** Virtual Console Callbacks **/
>>> 
>>> static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc,
>>> @@ -1911,6 +1921,12 @@ static void gd_connect_vc_gfx_signals(VirtualConsole 
>>> *vc)
>>>                         G_CALLBACK(gd_focus_out_event), vc);
>>>        g_signal_connect(vc->gfx.drawing_area, "configure-event",
>>>                         G_CALLBACK(gd_configure), vc);
>>> +        if (1 /* make that a config option ??? */) {
>>> +            update_displaychangelistener(&vc->gfx.dcl,
>>> +                                         GUI_REFRESH_INTERVAL_IDLE);
>>> +            gtk_widget_add_tick_callback(vc->gfx.drawing_area,
>>> +                                         gd_frame_tick, vc, NULL);
>>> +        }
>>>    } else {
>>>        g_signal_connect(vc->gfx.drawing_area, "key-press-event",
>>>                         G_CALLBACK(gd_text_key_down), vc);
>>> -- 
>>> 2.9.3
>>> 
>> 
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]