glx/dri3: Implement LIBGL_SHOW_FPS=1 for DRI3/Present.
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 15 Mar 2014 01:53:42 +0000 (18:53 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 29 Oct 2014 22:13:58 +0000 (15:13 -0700)
v2: Use the UST value provided in the PRESENT_COMPLETE_NOTIFY event
    rather than gettimeofday(), which gives us the presentation time
    instead of the time when SwapBuffers was called.  Suggested by
    Keith Packard.  This relies on the fact that the X DRI3/Present
    implementations use microseconds for UST.

v3: Properly ignore PresentCompleteKindMSCNotify; multiply in 64 bits
    (caught by Keith Packard).

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Keith Packard <keithp@keithp.com> [v3]
Reviewed-by: Marek Olšák <marek.olsak@amd.com> [v1]
src/glx/dri3_glx.c
src/glx/dri3_priv.h

index e8e5c4ab28a720bd8ab3cff511b490e19b307173..a9ff73b36f4c75ef09fbe26f4272b34eee5342c7 100644 (file)
@@ -361,12 +361,34 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,
    return &pdraw->base;
 }
 
+static void
+show_fps(struct dri3_drawable *draw, uint64_t current_ust)
+{
+   const uint64_t interval =
+      ((struct dri3_screen *) draw->base.psc)->show_fps_interval;
+
+   draw->frames++;
+
+   /* DRI3+Present together uses microseconds for UST. */
+   if (draw->previous_ust + interval * 1000000 <= current_ust) {
+      if (draw->previous_ust) {
+         fprintf(stderr, "libGL: FPS = %.1f\n",
+                 ((uint64_t) draw->frames * 1000000) /
+                 (double)(current_ust - draw->previous_ust));
+      }
+      draw->frames = 0;
+      draw->previous_ust = current_ust;
+   }
+}
+
 /*
  * Process one Present event
  */
 static void
 dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_t *ge)
 {
+   struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+
    switch (ge->evtype) {
    case XCB_PRESENT_CONFIGURE_NOTIFY: {
       xcb_present_configure_notify_event_t *ce = (void *) ge;
@@ -395,6 +417,9 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_
             break;
          }
          dri3_update_num_back(priv);
+
+         if (psc->show_fps_interval)
+            show_fps(priv, ce->ust);
       } else {
          priv->recv_msc_serial = ce->serial;
       }
@@ -1830,7 +1855,7 @@ dri3_create_screen(int screen, struct glx_display * priv)
    struct dri3_screen *psc;
    __GLXDRIscreen *psp;
    struct glx_config *configs = NULL, *visuals = NULL;
-   char *driverName, *deviceName;
+   char *driverName, *deviceName, *tmp;
    int i;
 
    psc = calloc(1, sizeof *psc);
@@ -1969,6 +1994,11 @@ dri3_create_screen(int screen, struct glx_display * priv)
    free(driverName);
    free(deviceName);
 
+   tmp = getenv("LIBGL_SHOW_FPS");
+   psc->show_fps_interval = tmp ? atoi(tmp) : 0;
+   if (psc->show_fps_interval < 0)
+      psc->show_fps_interval = 0;
+
    return &psc->base;
 
 handle_error:
index bdfe224fed02ef60aec912a2793707cb612c3acf..8e466407b892c14c0830b29fcb525966300f4321 100644 (file)
@@ -138,7 +138,7 @@ struct dri3_screen {
    int fd;
    int is_different_gpu;
 
-   Bool show_fps;
+   int show_fps_interval;
 };
 
 struct dri3_context
@@ -198,6 +198,10 @@ struct dri3_drawable {
    xcb_present_event_t eid;
    xcb_gcontext_t gc;
    xcb_special_event_t *special_event;
+
+   /* LIBGL_SHOW_FPS support */
+   uint64_t previous_ust;
+   unsigned frames;
 };