[gtk+] tests/animated-resizing: Split frame statistics out into a separate file



commit b7063509f8cac919490d4f907ece5ec8d7e3f127
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sun Apr 21 18:31:36 2013 -0400

    tests/animated-resizing: Split frame statistics out into a separate file
    
    Split the code for computing frame rate and latency into a separate file
    so we can use it from multiple tests.

 tests/Makefile.am         |    2 +
 tests/animated-resizing.c |  129 +++-----------------------------
 tests/frame-stats.c       |  182 +++++++++++++++++++++++++++++++++++++++++++++
 tests/frame-stats.h       |    9 ++
 tests/variable.c          |   17 ++--
 tests/variable.h          |    5 +-
 tests/video-timer.c       |    4 +-
 7 files changed, 218 insertions(+), 130 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dac59ae..1dd397d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -263,6 +263,8 @@ testrevealer_DEPENDENCIES = $(TEST_DEPS)
 
 animated_resizing_SOURCES =    \
        animated-resizing.c     \
+       frame-stats.c           \
+       frame-stats.h           \
        variable.c              \
        variable.h
 
diff --git a/tests/animated-resizing.c b/tests/animated-resizing.c
index 8a34d9f..c37106d 100644
--- a/tests/animated-resizing.c
+++ b/tests/animated-resizing.c
@@ -4,7 +4,7 @@
 #include <math.h>
 #include <string.h>
 
-#include "variable.h"
+#include "frame-stats.h"
 
 #define RADIUS 64
 #define DIAMETER (2*RADIUS)
@@ -19,11 +19,8 @@ static int window_width = WIDTH, window_height = HEIGHT;
 gint64 start_frame_time;
 static double angle;
 
-static int max_stats = -1;
-static double statistics_time = 5.;
 static double load_factor = 1.0;
 static double cb_no_resize = FALSE;
-static gboolean machine_readable = FALSE;
 
 static cairo_surface_t *source_surface;
 
@@ -114,114 +111,10 @@ on_window_draw (GtkWidget *widget,
 }
 
 static void
-print_double (const char *description,
-              double      value)
-{
-  if (machine_readable)
-    g_print ("%g\t", value);
-  else
-    g_print ("%s: %g\n", description, value);
-}
-
-static void
-print_variable (const char *description,
-                Variable *variable)
-{
-  if (variable->weight != 0)
-    {
-      if (machine_readable)
-        g_print ("%g\t%g\t",
-                 variable_mean (variable),
-                 variable_standard_deviation (variable));
-      else
-        g_print ("%s: %g +/- %g\n", description,
-                 variable_mean (variable),
-                 variable_standard_deviation (variable));
-    }
-  else
-    {
-      if (machine_readable)
-        g_print ("-\t-\t");
-      else
-        g_print ("%s: <n/a>\n", description);
-    }
-}
-
-static void
-handle_frame_stats (GdkFrameClock *frame_clock)
-{
-  static int num_stats = 0;
-  static double last_print_time = 0;
-  static int frames_since_last_print = 0;
-  static gint64 frame_counter;
-  static gint64 last_handled_frame = -1;
-
-  static Variable latency = VARIABLE_INIT;
-
-  double current_time;
-
-  current_time = g_get_monotonic_time ();
-  if (current_time >= last_print_time + 1000000 * statistics_time)
-    {
-      if (frames_since_last_print)
-        {
-          if (num_stats == 0 && machine_readable)
-            {
-              g_print ("# load_factor frame_rate latency\n");
-            }
-
-          num_stats++;
-          if (machine_readable)
-            g_print ("%g       ", load_factor);
-          print_double ("Frame rate ",
-                        frames_since_last_print / ((current_time - last_print_time) / 1000000.));
-
-          print_variable ("Latency", &latency);
-
-          g_print ("\n");
-        }
-
-      last_print_time = current_time;
-      frames_since_last_print = 0;
-      variable_reset (&latency);
-
-      if (num_stats == max_stats)
-        gtk_main_quit ();
-    }
-
-  frames_since_last_print++;
-
-  for (frame_counter = last_handled_frame;
-       frame_counter < gdk_frame_clock_get_frame_counter (frame_clock);
-       frame_counter++)
-    {
-      GdkFrameTimings *timings = gdk_frame_clock_get_timings (frame_clock, frame_counter);
-      GdkFrameTimings *previous_timings = gdk_frame_clock_get_timings (frame_clock, frame_counter - 1);
-
-      if (!timings || gdk_frame_timings_get_complete (timings))
-        last_handled_frame = frame_counter;
-
-      if (timings && gdk_frame_timings_get_complete (timings) && previous_timings &&
-          gdk_frame_timings_get_presentation_time (timings) != 0 &&
-          gdk_frame_timings_get_presentation_time (previous_timings) != 0)
-        {
-          double display_time = (gdk_frame_timings_get_presentation_time (timings) - 
gdk_frame_timings_get_presentation_time (previous_timings)) / 1000.;
-          double frame_latency = (gdk_frame_timings_get_presentation_time (previous_timings) - 
gdk_frame_timings_get_frame_time (previous_timings)) / 1000. + display_time / 2;
-
-          variable_add_weighted (&latency, frame_latency, display_time);
-        }
-    }
-}
-
-static void
 on_frame (double progress)
 {
-  GdkFrameClock *frame_clock = gtk_widget_get_frame_clock (window);
   int jitter;
 
-  if (frame_clock)
-    handle_frame_stats (frame_clock);
-
   angle = 2 * M_PI * progress;
   jitter = WINDOW_SIZE_JITTER * sin(angle);
 
@@ -265,10 +158,7 @@ on_map_event (GtkWidget      *widget,
 
 static GOptionEntry options[] = {
   { "factor", 'f', 0, G_OPTION_ARG_DOUBLE, &load_factor, "Load factor", "FACTOR" },
-  { "max-statistics", 'm', 0, G_OPTION_ARG_INT, &max_stats, "Maximum statistics printed", NULL },
-  { "machine-readable", 0, 0, G_OPTION_ARG_NONE, &machine_readable, "Print statistics in columns", NULL },
   { "no-resize", 'n', 0, G_OPTION_ARG_NONE, &cb_no_resize, "No Resize", NULL },
-  { "statistics-time", 's', 0, G_OPTION_ARG_DOUBLE, &statistics_time, "Statistics accumulation time", "TIME" 
},
   { NULL }
 };
 
@@ -279,21 +169,26 @@ main(int argc, char **argv)
   GdkScreen *screen;
   GdkRectangle monitor_bounds;
 
-  if (!gtk_init_with_args (&argc, &argv, "",
-                           options, NULL, &error))
+  GOptionContext *context = g_option_context_new (NULL);
+  g_option_context_add_main_entries (context, options, NULL);
+  frame_stats_add_options (g_option_context_get_main_group (context));
+  g_option_context_add_group (context,
+                              gtk_get_option_group (TRUE));
+
+  if (!g_option_context_parse (context, &argc, &argv, &error))
     {
       g_printerr ("Option parsing failed: %s\n", error->message);
       return 1;
     }
 
-  g_print ("%sLoad factor: %g\n",
-           machine_readable ? "# " : "",
+  g_print ("# Load factor: %g\n",
            load_factor);
-  g_print ("%sResizing?: %s\n",
-           machine_readable ? "# " : "",
+  g_print ("# Resizing?: %s\n",
            cb_no_resize ? "no" : "yes");
 
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  frame_stats_ensure (GTK_WINDOW (window));
+
   gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
   gtk_window_set_gravity (GTK_WINDOW (window), GDK_GRAVITY_CENTER);
   gtk_widget_set_app_paintable (window, TRUE);
diff --git a/tests/frame-stats.c b/tests/frame-stats.c
new file mode 100644
index 0000000..5d888d2
--- /dev/null
+++ b/tests/frame-stats.c
@@ -0,0 +1,182 @@
+/* -*- mode: C; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+
+#include <gtk/gtk.h>
+
+#include "frame-stats.h"
+#include "variable.h"
+
+typedef struct FrameStats FrameStats;
+
+struct FrameStats
+{
+  GdkFrameClock *frame_clock;
+
+  int num_stats;
+  double last_print_time;
+  int frames_since_last_print;
+  gint64 last_handled_frame;
+
+  Variable latency;
+};
+
+static int max_stats = -1;
+static double statistics_time = 5.;
+static gboolean machine_readable = FALSE;
+
+static GOptionEntry frame_sync_options[] = {
+  { "max-statistics", 'm', 0, G_OPTION_ARG_INT, &max_stats, "Maximum statistics printed", NULL },
+  { "machine-readable", 0, 0, G_OPTION_ARG_NONE, &machine_readable, "Print statistics in columns", NULL },
+  { "statistics-time", 's', 0, G_OPTION_ARG_DOUBLE, &statistics_time, "Statistics accumulation time", "TIME" 
},
+  { NULL }
+};
+
+void
+frame_stats_add_options (GOptionGroup *group)
+{
+  g_option_group_add_entries (group, frame_sync_options);
+}
+
+static void
+print_double (const char *description,
+              double      value)
+{
+  if (machine_readable)
+    g_print ("%g\t", value);
+  else
+    g_print ("%s: %g\n", description, value);
+}
+
+static void
+print_variable (const char *description,
+                Variable *variable)
+{
+  if (variable->weight != 0)
+    {
+      if (machine_readable)
+        g_print ("%g\t%g\t",
+                 variable_mean (variable),
+                 variable_standard_deviation (variable));
+      else
+        g_print ("%s: %g +/- %g\n", description,
+                 variable_mean (variable),
+                 variable_standard_deviation (variable));
+    }
+  else
+    {
+      if (machine_readable)
+        g_print ("-\t-\t");
+      else
+        g_print ("%s: <n/a>\n", description);
+    }
+}
+
+static void
+on_frame_clock_after_paint (GdkFrameClock *frame_clock,
+                            FrameStats    *frame_stats)
+{
+  gint64 frame_counter;
+  gint64 current_time;
+
+  current_time = g_get_monotonic_time ();
+  if (current_time >= frame_stats->last_print_time + 1000000 * statistics_time)
+    {
+      if (frame_stats->frames_since_last_print)
+        {
+          if (frame_stats->num_stats == 0 && machine_readable)
+            {
+              g_print ("# load_factor frame_rate latency\n");
+            }
+
+          frame_stats->num_stats++;
+          print_double ("Frame rate ",
+                        frame_stats->frames_since_last_print /
+                        ((current_time - frame_stats->last_print_time) / 1000000.));
+
+          print_variable ("Latency", &frame_stats->latency);
+
+          g_print ("\n");
+        }
+
+      frame_stats->last_print_time = current_time;
+      frame_stats->frames_since_last_print = 0;
+      variable_init (&frame_stats->latency);
+
+      if (frame_stats->num_stats == max_stats)
+        gtk_main_quit ();
+    }
+
+  frame_stats->frames_since_last_print++;
+
+  for (frame_counter = frame_stats->last_handled_frame;
+       frame_counter < gdk_frame_clock_get_frame_counter (frame_clock);
+       frame_counter++)
+    {
+      GdkFrameTimings *timings = gdk_frame_clock_get_timings (frame_clock, frame_counter);
+      GdkFrameTimings *previous_timings = gdk_frame_clock_get_timings (frame_clock, frame_counter - 1);
+
+      if (!timings || gdk_frame_timings_get_complete (timings))
+        frame_stats->last_handled_frame = frame_counter;
+
+      if (timings && gdk_frame_timings_get_complete (timings) && previous_timings &&
+          gdk_frame_timings_get_presentation_time (timings) != 0 &&
+          gdk_frame_timings_get_presentation_time (previous_timings) != 0)
+        {
+          double display_time = (gdk_frame_timings_get_presentation_time (timings) - 
gdk_frame_timings_get_presentation_time (previous_timings)) / 1000.;
+          double frame_latency = (gdk_frame_timings_get_presentation_time (previous_timings) - 
gdk_frame_timings_get_frame_time (previous_timings)) / 1000. + display_time / 2;
+
+          variable_add_weighted (&frame_stats->latency, frame_latency, display_time);
+        }
+    }
+}
+
+void
+on_window_realize (GtkWidget  *window,
+                   FrameStats *frame_stats)
+{
+  frame_stats->frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (window));
+  g_signal_connect (frame_stats->frame_clock, "after-paint",
+                    G_CALLBACK (on_frame_clock_after_paint), frame_stats);
+}
+
+void
+on_window_unrealize (GtkWidget  *window,
+                     FrameStats *frame_stats)
+{
+  g_signal_handlers_disconnect_by_func (frame_stats->frame_clock,
+                                        (gpointer) on_frame_clock_after_paint,
+                                        frame_stats);
+  frame_stats->frame_clock = NULL;
+}
+
+void
+on_window_destroy (GtkWidget  *window,
+                   FrameStats *stats)
+{
+  g_free (stats);
+}
+
+void
+frame_stats_ensure (GtkWindow *window)
+{
+  FrameStats *frame_stats;
+
+  frame_stats = g_object_get_data (G_OBJECT (window), "frame-stats");
+  if (frame_stats != NULL)
+    return;
+
+  frame_stats = g_new0 (FrameStats, 1);
+  g_object_set_data (G_OBJECT (window), "frame-stats", frame_stats);
+
+  variable_init (&frame_stats->latency);
+  frame_stats->last_handled_frame = -1;
+
+  g_signal_connect (window, "realize",
+                    G_CALLBACK (on_window_realize), frame_stats);
+  g_signal_connect (window, "unrealize",
+                    G_CALLBACK (on_window_unrealize), frame_stats);
+  g_signal_connect (window, "destroy",
+                    G_CALLBACK (on_window_destroy), frame_stats);
+
+  if (gtk_widget_get_realized (GTK_WIDGET (window)))
+    on_window_realize (GTK_WIDGET (window), frame_stats);
+}
diff --git a/tests/frame-stats.h b/tests/frame-stats.h
new file mode 100644
index 0000000..9c046a7
--- /dev/null
+++ b/tests/frame-stats.h
@@ -0,0 +1,9 @@
+#ifndef __FRAME_STATS_H__
+#define __FRAME_STATS_H__
+
+#include <gtk/gtk.h>
+
+void frame_stats_add_options (GOptionGroup *group);
+void frame_stats_ensure      (GtkWindow    *window);
+
+#endif /* __FRAME_STATS_H__ */
diff --git a/tests/variable.c b/tests/variable.c
index 9ce5d5d..097d3a4 100644
--- a/tests/variable.c
+++ b/tests/variable.c
@@ -4,6 +4,14 @@
 #include "variable.h"
 
 void
+variable_init (Variable *variable)
+{
+  variable->weight = 0.0;
+  variable->sum = 0.0;
+  variable->sum2 = 0.0;
+}
+
+void
 variable_add_weighted (Variable *variable,
                        double    value,
                        double    weight)
@@ -32,12 +40,3 @@ variable_standard_deviation (Variable *variable)
   double mean = variable_mean (variable);
   return sqrt (variable->sum2 / variable->weight - mean * mean);
 }
-
-void
-variable_reset (Variable *variable)
-{
-  variable->weight = 0;
-  variable->sum = 0;
-  variable->sum2 = 0;
-}
-
diff --git a/tests/variable.h b/tests/variable.h
index d53dd58..7246689 100644
--- a/tests/variable.h
+++ b/tests/variable.h
@@ -8,8 +8,9 @@ typedef struct
   double sum2;
 } Variable;
 
-#define VARIABLE_INIT { 0, 0.0, 0.0 }
+#define VARIABLE_INIT { 0.0, 0.0, 0.0 }
 
+void   variable_init               (Variable *variable);
 void   variable_add_weighted       (Variable *variable,
                                     double    value,
                                     double    weight);
@@ -19,5 +20,5 @@ double variable_mean               (Variable *variable);
 double variable_standard_deviation (Variable *variable);
 void   variable_reset              (Variable *variable);
 
-#endif /* __VARAIBLE_H__ */
+#endif /* __VARIABLE_H__ */
 
diff --git a/tests/video-timer.c b/tests/video-timer.c
index f858240..e665c6d 100644
--- a/tests/video-timer.c
+++ b/tests/video-timer.c
@@ -291,8 +291,8 @@ print_statistics (void)
         g_print ("playback rate adjustment: %g +/- %g %%\n",
                  (variable_mean (&time_factor_stats) - 1) * 100,
                  variable_standard_deviation (&time_factor_stats) * 100);
-      variable_reset (&latency_error);
-      variable_reset (&time_factor_stats);
+      variable_init (&latency_error);
+      variable_init (&time_factor_stats);
       dropped_frames = 0;
       n_frames = 0;
       last_print_time = now;


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