diff mbox series

[1/3] ui/gtk: adds status bar for expressing ups and fps

Message ID 20210726222551.28795-1-dongwon.kim@intel.com (mailing list archive)
State New, archived
Headers show
Series [1/3] ui/gtk: adds status bar for expressing ups and fps | expand

Commit Message

Kim, Dongwon July 26, 2021, 10:25 p.m. UTC
With a display option, "show-fps=on", qemu adds a status bar and print
following performance numbers on the bar,

ups = update per seconds - the rate the guest scanout is updated.
fps = frame per seconds - the frame rate of VC's GL drawing area

One function, gd_gl_count_frame is added to count # frames
and calculate ups and fps every 100 frames or guest scanout updates.

Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
---
 include/ui/console.h |  4 +++-
 include/ui/gtk.h     |  2 ++
 qapi/ui.json         |  6 +++++-
 ui/console.c         |  6 ++++++
 ui/gtk.c             | 51 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 67 insertions(+), 2 deletions(-)

Comments

Daniel P. Berrangé July 27, 2021, 8:24 a.m. UTC | #1
On Mon, Jul 26, 2021 at 03:25:49PM -0700, Dongwon Kim wrote:
> With a display option, "show-fps=on", qemu adds a status bar and print
> following performance numbers on the bar,
> 
> ups = update per seconds - the rate the guest scanout is updated.
> fps = frame per seconds - the frame rate of VC's GL drawing area
> 
> One function, gd_gl_count_frame is added to count # frames
> and calculate ups and fps every 100 frames or guest scanout updates.

This feels like a pretty niche/novelty feature. Is this really
something we can justify adding to the UI, considering that it
means we will be maintaining this UI and supporting code long
term. 


Regards,
Daniel
Kim, Dongwon July 27, 2021, 6:46 p.m. UTC | #2
I found there are no such performance indicators available in Qemu/GTK.
I thought this was the gap as in many fields, users want to check fps or
ups to evaluate graphic or display performance in their use-cases.

Thanks for your feedback!. 

On Tue, Jul 27, 2021 at 09:24:44AM +0100, Daniel P. Berrangé wrote:
> On Mon, Jul 26, 2021 at 03:25:49PM -0700, Dongwon Kim wrote:
> > With a display option, "show-fps=on", qemu adds a status bar and print
> > following performance numbers on the bar,
> > 
> > ups = update per seconds - the rate the guest scanout is updated.
> > fps = frame per seconds - the frame rate of VC's GL drawing area
> > 
> > One function, gd_gl_count_frame is added to count # frames
> > and calculate ups and fps every 100 frames or guest scanout updates.
> 
> This feels like a pretty niche/novelty feature. Is this really
> something we can justify adding to the UI, considering that it
> means we will be maintaining this UI and supporting code long
> term. 
> 
> 
> Regards,
> Daniel
> -- 
> |: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org         -o-            https://fstop138.berrange.com :|
> |: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
>
Eric Blake July 29, 2021, 11:47 p.m. UTC | #3
On Mon, Jul 26, 2021 at 03:25:49PM -0700, Dongwon Kim wrote:

[meta-comment] When sending a patch series, remember to include a 0/3
cover letter, as it makes it easier to distinguish replies about the
series as a whole from review of the first patch.

> With a display option, "show-fps=on", qemu adds a status bar and print
> following performance numbers on the bar,
> 
> ups = update per seconds - the rate the guest scanout is updated.
> fps = frame per seconds - the frame rate of VC's GL drawing area
> 
> One function, gd_gl_count_frame is added to count # frames
> and calculate ups and fps every 100 frames or guest scanout updates.
> 
> Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
> ---
>  include/ui/console.h |  4 +++-
>  include/ui/gtk.h     |  2 ++
>  qapi/ui.json         |  6 +++++-
>  ui/console.c         |  6 ++++++
>  ui/gtk.c             | 51 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 67 insertions(+), 2 deletions(-)

> +++ b/qapi/ui.json
> @@ -1035,13 +1035,17 @@
>  #               assuming the guest will resize the display to match
>  #               the window size then.  Otherwise it defaults to "off".
>  #               Since 3.1
> +# @show-fps:    Enable showing Guest Scanout's update rate (UPS) and
> +#               Surface render swap rate (FPS) on a status bar (default: off).
> +#               Since 6.0

This is too late to make the 6.1 release; at best, it should read
'since 6.2'
diff mbox series

Patch

diff --git a/include/ui/console.h b/include/ui/console.h
index b30b63976a..3ca8d07220 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -243,7 +243,8 @@  typedef struct DisplayChangeListenerOps {
     /* required if GL */
     void (*dpy_gl_update)(DisplayChangeListener *dcl,
                           uint32_t x, uint32_t y, uint32_t w, uint32_t h);
-
+    /* optional */
+    void (*dpy_gl_count_frame)(DisplayChangeListener *dcl, bool ups);
 } DisplayChangeListenerOps;
 
 struct DisplayChangeListener {
@@ -314,6 +315,7 @@  void dpy_gl_release_dmabuf(QemuConsole *con,
                            QemuDmaBuf *dmabuf);
 void dpy_gl_update(QemuConsole *con,
                    uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+void dpy_gl_count_frame(QemuConsole *con, bool ups);
 
 QEMUGLContext dpy_gl_ctx_create(QemuConsole *con,
                                 QEMUGLParams *params);
diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 9516670ebc..8d1a6c2cef 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -118,6 +118,7 @@  struct GtkDisplayState {
     GtkWidget *show_tabs_item;
     GtkWidget *untabify_item;
     GtkWidget *show_menubar_item;
+    GtkWidget *status_bar;
 
     GtkWidget *vbox;
     GtkWidget *notebook;
@@ -152,6 +153,7 @@  extern bool gtk_use_gl_area;
 /* ui/gtk.c */
 void gd_update_windowsize(VirtualConsole *vc);
 int gd_monitor_update_interval(GtkWidget *widget);
+void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups);
 
 /* ui/gtk-egl.c */
 void gd_egl_init(VirtualConsole *vc);
diff --git a/qapi/ui.json b/qapi/ui.json
index 1052ca9c38..a0882d6428 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1035,13 +1035,17 @@ 
 #               assuming the guest will resize the display to match
 #               the window size then.  Otherwise it defaults to "off".
 #               Since 3.1
+# @show-fps:    Enable showing Guest Scanout's update rate (UPS) and
+#               Surface render swap rate (FPS) on a status bar (default: off).
+#               Since 6.0
 #
 # Since: 2.12
 #
 ##
 { 'struct'  : 'DisplayGTK',
   'data'    : { '*grab-on-hover' : 'bool',
-                '*zoom-to-fit'   : 'bool'  } }
+                '*zoom-to-fit'   : 'bool',
+                '*show-fps'      : 'bool'  } }
 
 ##
 # @DisplayEGLHeadless:
diff --git a/ui/console.c b/ui/console.c
index 2de5f4105b..31efdb0512 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1924,6 +1924,12 @@  void dpy_gl_update(QemuConsole *con,
     con->gl->ops->dpy_gl_update(con->gl, x, y, w, h);
 }
 
+void dpy_gl_count_frame(QemuConsole *con, bool ups)
+{
+    assert(con->gl);
+    con->gl->ops->dpy_gl_count_frame(con->gl, ups);
+}
+
 /***********************************************************/
 /* register display */
 
diff --git a/ui/gtk.c b/ui/gtk.c
index 98046f577b..091da08028 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -549,6 +549,47 @@  static void gd_switch(DisplayChangeListener *dcl,
     }
 }
 
+void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups)
+{
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+    gchar ups_fps_str[100];
+    static guint prev, curr;
+    static guint ups_cnt, fps_cnt, status_bar_id;
+    struct timeval tv;
+
+    if (!vc->s->opts->show_fps) {
+        return;
+    }
+
+    if (prev == 0) {
+        gettimeofday(&tv, NULL);
+        prev = tv.tv_sec * 1000000 + tv.tv_usec;
+    }
+
+    if (ups) {
+        ups_cnt++;
+    } else {
+        fps_cnt++;
+    }
+
+    /* update rate is calculated for every 200 frames */
+    if (ups_cnt == 200 || fps_cnt == 200) {
+        gettimeofday(&tv, NULL);
+        curr = tv.tv_sec * 1000000 + tv.tv_usec;
+        prev = curr - prev;
+        sprintf(ups_fps_str, "UPS : %0.2f u/s  FPS : %0.2f f/s",
+                ups_cnt * 1000000/(gfloat)prev, fps_cnt * 1000000/(gfloat)prev);
+
+        status_bar_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(vc->s->status_bar),
+                                                     "ups_fps_info");
+        gtk_statusbar_pop(GTK_STATUSBAR(vc->s->status_bar), status_bar_id);
+        gtk_statusbar_push(GTK_STATUSBAR(vc->s->status_bar), status_bar_id, ups_fps_str);
+        prev = curr;
+        fps_cnt = 0;
+        ups_cnt = 0;
+     }
+}
+
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name             = "gtk",
     .dpy_gfx_update       = gd_update,
@@ -594,6 +635,7 @@  static const DisplayChangeListenerOps dcl_gl_area_ops = {
     .dpy_gl_update           = gd_gl_area_scanout_flush,
     .dpy_gl_scanout_dmabuf   = gd_gl_area_scanout_dmabuf,
     .dpy_has_dmabuf          = gd_has_dmabuf,
+    .dpy_gl_count_frame      = gd_gl_count_frame,
 };
 
 #ifdef CONFIG_X11
@@ -618,6 +660,7 @@  static const DisplayChangeListenerOps dcl_egl_ops = {
     .dpy_gl_release_dmabuf   = gd_egl_release_dmabuf,
     .dpy_gl_update           = gd_egl_scanout_flush,
     .dpy_has_dmabuf          = gd_has_dmabuf,
+    .dpy_gl_count_frame      = gd_gl_count_frame,
 };
 
 #endif
@@ -2208,6 +2251,10 @@  static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
     s->notebook = gtk_notebook_new();
     s->menu_bar = gtk_menu_bar_new();
 
+    if (opts->show_fps) {
+        s->status_bar = gtk_statusbar_new();
+    }
+
     s->free_scale = FALSE;
 
     /* Mostly LC_MESSAGES only. See early_gtk_display_init() for details. For
@@ -2248,6 +2295,10 @@  static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
     gtk_box_pack_start(GTK_BOX(s->vbox), s->menu_bar, FALSE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(s->vbox), s->notebook, TRUE, TRUE, 0);
 
+    if (opts->show_fps) {
+        gtk_box_pack_start(GTK_BOX(s->vbox), s->status_bar, FALSE, TRUE, 0);
+    }
+
     gtk_container_add(GTK_CONTAINER(s->window), s->vbox);
 
     gtk_widget_show_all(s->window);