static gboolean gtk_gears_tick (GtkWidget *widget, GdkFrameClock *frame_clock, gpointer user_data) { GtkGears *gears = GTK_GEARS (widget); GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears); GdkFrameTimings *timings, *previous_timings; gint64 previous_frame_time = 0; gint64 frame_time; gint64 history_start, history_len; gint64 frame; char *s; frame = gdk_frame_clock_get_frame_counter (frame_clock); frame_time = gdk_frame_clock_get_frame_time (frame_clock); if (priv->first_frame_time == 0) { /* No need for changes on first frame */ priv->first_frame_time = frame_time; if (priv->fps_label) gtk_label_set_label (priv->fps_label, "FPS: ---"); return G_SOURCE_CONTINUE; } /* glxgears advances 70 degrees per second, so do the same */ priv->angle = fmod ((frame_time - priv->first_frame_time) / (double)G_USEC_PER_SEC * 70.0, 360.0); gtk_widget_queue_draw (widget); history_start = gdk_frame_clock_get_history_start (frame_clock); if (priv->fps_label && frame % 60 == 0) { history_len = frame - history_start; if (history_len > 0) { previous_timings = gdk_frame_clock_get_timings (frame_clock, frame - history_len); previous_frame_time = gdk_frame_timings_get_frame_time (previous_timings); s = g_strdup_printf ("FPS: %-4.1f", (G_USEC_PER_SEC * history_len) / (double)(frame_time - previous_frame_time)); gtk_label_set_label (priv->fps_label, s); g_free (s); } } timings = gdk_frame_clock_get_current_timings (frame_clock); previous_timings = gdk_frame_clock_get_timings (frame_clock, gdk_frame_timings_get_frame_counter (timings) - 1); if (previous_timings != NULL) previous_frame_time = gdk_frame_timings_get_frame_time (previous_timings); return G_SOURCE_CONTINUE; }
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock, GdkFrameTimings *timings) { gint64 previous_frame_time = 0; GdkFrameTimings *previous_timings = gdk_frame_clock_get_timings (clock, timings->frame_counter - 1); if (previous_timings != NULL) previous_frame_time = previous_timings->frame_time; g_print ("%5" G_GINT64_FORMAT ":", timings->frame_counter); if (previous_frame_time != 0) { g_print (" interval=%-4.1f", (timings->frame_time - previous_frame_time) / 1000.); g_print (timings->slept_before ? " (sleep)" : " "); } if (timings->layout_start_time != 0) g_print (" layout_start=%-4.1f", (timings->layout_start_time - timings->frame_time) / 1000.); if (timings->paint_start_time != 0) g_print (" paint_start=%-4.1f", (timings->paint_start_time - timings->frame_time) / 1000.); if (timings->frame_end_time != 0) g_print (" frame_end=%-4.1f", (timings->frame_end_time - timings->frame_time) / 1000.); if (timings->presentation_time != 0) g_print (" present=%-4.1f", (timings->presentation_time - timings->frame_time) / 1000.); if (timings->predicted_presentation_time != 0) g_print (" predicted=%-4.1f", (timings->predicted_presentation_time - timings->frame_time) / 1000.); if (timings->refresh_interval != 0) g_print (" refresh_interval=%-4.1f", timings->refresh_interval / 1000.); g_print ("\n"); }
/** * gdk_frame_clock_get_current_timings: * @frame_clock: a #GdkFrameClock * * Gets the frame timings for the current frame. * * Returns: the #GdkFrameTimings for the frame currently being * processed, or even no frame is being processed, for the * previous frame. Before any frames have been procesed, * returns %NULL. * Since: 3.8 */ GdkFrameTimings * gdk_frame_clock_get_current_timings (GdkFrameClock *frame_clock) { GdkFrameClockPrivate *priv; g_return_val_if_fail (GDK_IS_FRAME_CLOCK (frame_clock), 0); priv = frame_clock->priv; return gdk_frame_clock_get_timings (frame_clock, priv->frame_counter); }
/** * gdk_frame_clock_get_refresh_info: * @frame_clock: a #GdkFrameClock * @base_time: base time for determining a presentaton time * @refresh_interval_return: a location to store the determined refresh * interval, or %NULL. A default refresh interval of 1/60th of * a second will be stored if no history is present. * @presentation_time_return: a location to store the next * candidate presentation time after the given base time. * 0 will be will be stored if no history is present. * * Using the frame history stored in the frame clock, finds the last * known presentation time and refresh interval, and assuming that * presentation times are separated by the refresh interval, * predicts a presentation time that is a multiple of the refresh * interval after the last presentation time, and later than @base_time. * * Since: 3.8 */ void gdk_frame_clock_get_refresh_info (GdkFrameClock *frame_clock, gint64 base_time, gint64 *refresh_interval_return, gint64 *presentation_time_return) { gint64 frame_counter; g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock)); frame_counter = gdk_frame_clock_get_frame_counter (frame_clock); if (presentation_time_return) *presentation_time_return = 0; if (refresh_interval_return) *refresh_interval_return = DEFAULT_REFRESH_INTERVAL; while (TRUE) { GdkFrameTimings *timings = gdk_frame_clock_get_timings (frame_clock, frame_counter); gint64 presentation_time; gint64 refresh_interval; if (timings == NULL) return; refresh_interval = timings->refresh_interval; presentation_time = timings->presentation_time; if (presentation_time != 0) { if (presentation_time > base_time - MAX_HISTORY_AGE && presentation_time_return) { if (refresh_interval == 0) refresh_interval = DEFAULT_REFRESH_INTERVAL; if (refresh_interval_return) *refresh_interval_return = refresh_interval; while (presentation_time < base_time) presentation_time += refresh_interval; if (presentation_time_return) *presentation_time_return = presentation_time; } return; } frame_counter--; } }
static void collect_old_frames (void) { GdkFrameClock *frame_clock = gtk_widget_get_frame_clock (window); GList *l, *l_next; for (l = past_frames; l; l = l_next) { FrameData *frame_data = l->data; gboolean remove = FALSE; l_next = l->next; GdkFrameTimings *timings = gdk_frame_clock_get_timings (frame_clock, frame_data->frame_counter); if (timings == NULL) { remove = TRUE; } else if (gdk_frame_timings_get_complete (timings)) { gint64 presentation_time = gdk_frame_timings_get_predicted_presentation_time (timings); gint64 refresh_interval = gdk_frame_timings_get_refresh_interval (timings); if (pll && presentation_time && refresh_interval && presentation_time > frame_data->clock_time - refresh_interval / 2 && presentation_time < frame_data->clock_time + refresh_interval / 2) adjust_clock_for_phase (frame_data->clock_time, presentation_time); if (presentation_time) variable_add (&latency_error, presentation_time - frame_data->clock_time); remove = TRUE; } if (remove) { past_frames = g_list_delete_link (past_frames, l); g_slice_free (FrameData, frame_data); } } }
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); } } }