forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
0032b2dc5a
commit
b7063509f8
@ -263,6 +263,8 @@ testrevealer_DEPENDENCIES = $(TEST_DEPS)
|
||||
|
||||
animated_resizing_SOURCES = \
|
||||
animated-resizing.c \
|
||||
frame-stats.c \
|
||||
frame-stats.h \
|
||||
variable.c \
|
||||
variable.h
|
||||
|
||||
|
@ -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;
|
||||
|
||||
@ -113,115 +110,11 @@ on_window_draw (GtkWidget *widget,
|
||||
g_rand_free(rand);
|
||||
}
|
||||
|
||||
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);
|
||||
|
182
tests/frame-stats.c
Normal file
182
tests/frame-stats.c
Normal file
@ -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);
|
||||
}
|
9
tests/frame-stats.h
Normal file
9
tests/frame-stats.h
Normal file
@ -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__ */
|
@ -3,6 +3,14 @@
|
||||
#include <math.h>
|
||||
#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,
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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__ */
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user