From: Benjamin Otte Date: Fri, 30 Mar 2018 14:47:52 +0000 (+0200) Subject: demos: Improve frame rate tracking for fishbowl demo X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~22^2~722 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=89f6a4ede4c10db1bc74227ddf84f47b8ecf527b;p=gtk4.git demos: Improve frame rate tracking for fishbowl demo We now properly use GdkFrameTimings and can therefor check for dropping even a single frame in the history (of 16 frames or 1/4 of a second). Once that happens, we immediately stop adding new items to the bowl. A side effect is that the number of icons is now a *lot* smaller. --- diff --git a/demos/gtk-demo/fishbowl.c b/demos/gtk-demo/fishbowl.c index bd288aa26a..b9de77118e 100644 --- a/demos/gtk-demo/fishbowl.c +++ b/demos/gtk-demo/fishbowl.c @@ -9,6 +9,7 @@ #include "gtkfishbowl.h" +GtkWidget *info_label; GtkWidget *allow_changes; #define N_STATS 5 @@ -17,14 +18,7 @@ GtkWidget *allow_changes; typedef struct _Stats Stats; struct _Stats { - gint64 last_stats; - gint64 last_frame; gint last_suggestion; - guint frame_counter_max; - - guint stats_index; - guint frame_counter[N_STATS]; - guint item_counter[N_STATS]; }; static Stats * @@ -41,8 +35,6 @@ get_stats (GtkWidget *widget) { stats = g_new0 (Stats, 1); g_object_set_qdata_full (G_OBJECT (widget), stats_quark, stats, g_free); - stats->last_frame = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget)); - stats->last_stats = stats->last_frame; } return stats; @@ -50,93 +42,85 @@ get_stats (GtkWidget *widget) static void do_stats (GtkWidget *widget, - GtkWidget *info_label, gint *suggested_change) { + GdkFrameClock *frame_clock; Stats *stats; - gint64 frame_time; + GdkFrameTimings *start, *end; + gint64 start_counter, end_counter; + gint64 n_frames, expected_frames; + gint64 start_timestamp, end_timestamp; + gint64 interval; + char *new_label; stats = get_stats (widget); - frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget)); + frame_clock = gtk_widget_get_frame_clock (widget); + if (frame_clock == NULL) + return; + + start_counter = gdk_frame_clock_get_history_start (frame_clock); + end_counter = gdk_frame_clock_get_frame_counter (frame_clock); + start = gdk_frame_clock_get_timings (frame_clock, start_counter); + for (end = gdk_frame_clock_get_timings (frame_clock, end_counter); + end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end); + end = gdk_frame_clock_get_timings (frame_clock, end_counter)) + end_counter--; + if (start_counter == end_counter) + return; + + start_timestamp = gdk_frame_timings_get_presentation_time (start); + end_timestamp = gdk_frame_timings_get_presentation_time (end); + if (start_timestamp == 0 || end_timestamp == 0) + { + start_timestamp = gdk_frame_timings_get_frame_time (start); + end_timestamp = gdk_frame_timings_get_frame_time (end); + } + + interval = gdk_frame_timings_get_refresh_interval (end); + n_frames = end_counter - start_counter; + expected_frames = round ((double) (end_timestamp - start_timestamp) / interval); - if (stats->last_stats + STATS_UPDATE_TIME < frame_time) + new_label = g_strdup_printf ("icons - %.1f fps", + ((double) n_frames) * G_USEC_PER_SEC / (end_timestamp - start_timestamp)); + gtk_label_set_label (GTK_LABEL (info_label), new_label); + g_free (new_label); + + if (n_frames >= expected_frames) { - char *new_label; - guint i, n_frames; - - n_frames = 0; - for (i = 0; i < N_STATS; i++) - { - n_frames += stats->frame_counter[i]; - } - - new_label = g_strdup_printf ("icons - %.1f fps", - (double) G_USEC_PER_SEC * n_frames - / (N_STATS * STATS_UPDATE_TIME)); - gtk_label_set_label (GTK_LABEL (info_label), new_label); - g_free (new_label); - - if (stats->frame_counter[stats->stats_index] >= 19 * stats->frame_counter_max / 20) - { - if (stats->last_suggestion > 0) - stats->last_suggestion *= 2; - else - stats->last_suggestion = 1; - } + if (stats->last_suggestion > 0) + stats->last_suggestion *= 2; else - { - if (stats->last_suggestion < 0) - stats->last_suggestion--; - else - stats->last_suggestion = -1; - stats->last_suggestion = MAX (stats->last_suggestion, 1 - (int) stats->item_counter[stats->stats_index]); - } - - stats->stats_index = (stats->stats_index + 1) % N_STATS; - stats->frame_counter[stats->stats_index] = 0; - stats->item_counter[stats->stats_index] = stats->item_counter[(stats->stats_index + N_STATS - 1) % N_STATS]; - stats->last_stats = frame_time; - - if (suggested_change) - *suggested_change = stats->last_suggestion; + stats->last_suggestion = 1; + } + else if (n_frames + 1 < expected_frames) + { + if (stats->last_suggestion < 0) + stats->last_suggestion--; else - stats->last_suggestion = 0; + stats->last_suggestion = -1; } else { - if (suggested_change) - *suggested_change = 0; + stats->last_suggestion = 0; } - stats->last_frame = frame_time; - stats->frame_counter[stats->stats_index]++; - stats->frame_counter_max = MAX (stats->frame_counter_max, stats->frame_counter[stats->stats_index]); -} - -static void -stats_update (GtkWidget *widget) -{ - Stats *stats; - - stats = get_stats (widget); - - stats->item_counter[stats->stats_index] = gtk_fishbowl_get_count (GTK_FISHBOWL (widget)); + if (suggested_change) + *suggested_change = stats->last_suggestion; + else + stats->last_suggestion = 0; } static gboolean -move_fish (GtkWidget *bowl, - GdkFrameClock *frame_clock, - gpointer info_label) +move_fish (gpointer bowl) { - gint suggested_change = 0; + gint suggested_change = 0, new_count; do_stats (bowl, - info_label, !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (allow_changes)) ? &suggested_change : NULL); - gtk_fishbowl_set_count (GTK_FISHBOWL (bowl), - gtk_fishbowl_get_count (GTK_FISHBOWL (bowl)) + suggested_change); - stats_update (bowl); + new_count = gtk_fishbowl_get_count (GTK_FISHBOWL (bowl)) + suggested_change; + new_count = MAX (1, new_count); + gtk_fishbowl_set_count (GTK_FISHBOWL (bowl), new_count); return G_SOURCE_CONTINUE; } @@ -149,7 +133,7 @@ do_fishbowl (GtkWidget *do_widget) if (!window) { GtkBuilder *builder; - GtkWidget *bowl, *info_label; + GtkWidget *bowl; g_type_ensure (GTK_TYPE_FISHBOWL); @@ -166,7 +150,9 @@ do_fishbowl (GtkWidget *do_widget) G_CALLBACK (gtk_widget_destroyed), &window); gtk_widget_realize (window); - gtk_widget_add_tick_callback (bowl, move_fish, info_label, NULL); + g_timeout_add_seconds (1, + move_fish, + bowl); } if (!gtk_widget_get_visible (window))