#include "config.h"
+#include "gdkinternals.h"
#include "gdkframeclockidle.h"
#include "gdk.h"
guint64 timer_base;
guint64 frame_time;
guint64 min_next_frame_time;
+ gint64 sleep_serial;
guint flush_idle_id;
guint paint_idle_id;
GdkFrameClockPhase requested;
GdkFrameClockPhase phase;
+
+ guint in_paint_idle : 1;
};
static gboolean gdk_frame_clock_flush_idle (void *data);
G_IMPLEMENT_INTERFACE (GDK_TYPE_FRAME_CLOCK,
gdk_frame_clock_idle_interface_init))
+static gint64 sleep_serial;
+static gint64 sleep_source_prepare_time;
+static GSource *sleep_source;
+
+gboolean
+sleep_source_prepare (GSource *source,
+ gint *timeout)
+{
+ sleep_source_prepare_time = g_source_get_time (source);
+ *timeout = -1;
+ return FALSE;
+}
+
+gboolean
+sleep_source_check (GSource *source)
+{
+ if (g_source_get_time (source) != sleep_source_prepare_time)
+ sleep_serial++;
+
+ return FALSE;
+}
+
+gboolean
+sleep_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ return TRUE;
+}
+
+static GSourceFuncs sleep_source_funcs = {
+ sleep_source_prepare,
+ sleep_source_check,
+ sleep_source_dispatch,
+ NULL /* finalize */
+};
+
+static gint64
+get_sleep_serial (void)
+{
+ if (sleep_source == NULL)
+ {
+ sleep_source = g_source_new (&sleep_source_funcs, sizeof (GSource));
+
+ g_source_set_priority (sleep_source, G_PRIORITY_HIGH);
+ g_source_attach (sleep_source, NULL);
+ g_source_unref (sleep_source);
+ }
+
+ return sleep_serial;
+}
+
static void
gdk_frame_clock_idle_class_init (GdkFrameClockIdleClass *klass)
{
}
if (priv->paint_idle_id == 0 &&
+ !priv->in_paint_idle &&
(priv->requested & ~GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0)
{
priv->paint_idle_id = gdk_threads_add_timeout_full (GDK_PRIORITY_REDRAW,
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
gboolean skip_to_resume_events;
+ GdkFrameTimings *timings = NULL;
+ gint64 frame_counter = 0;
priv->paint_idle_id = 0;
+ priv->in_paint_idle = TRUE;
skip_to_resume_events =
(priv->requested & ~(GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS | GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS)) == 0;
+ if (priv->phase > GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT)
+ {
+ frame_counter = gdk_frame_history_get_frame_counter (priv->history);
+ timings = gdk_frame_history_get_timings (priv->history, frame_counter);
+ }
+
if (!skip_to_resume_events)
{
switch (priv->phase)
case GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT:
if (priv->freeze_count == 0)
{
- GdkFrameTimings *timings;
- gint64 frame_counter;
-
priv->frame_time = compute_frame_time (clock_idle);
+
gdk_frame_history_begin_frame (priv->history);
frame_counter = gdk_frame_history_get_frame_counter (priv->history);
timings = gdk_frame_history_get_timings (priv->history, frame_counter);
+
gdk_frame_timings_set_frame_time (timings, priv->frame_time);
+ gdk_frame_timings_set_slept_before (timings,
+ priv->sleep_serial != get_sleep_serial ());
+
priv->phase = GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT;
/* We always emit ::before-paint and ::after-paint if
case GDK_FRAME_CLOCK_PHASE_LAYOUT:
if (priv->freeze_count == 0)
{
+#ifdef G_ENABLE_DEBUG
+ if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
+ {
+ if (priv->phase != GDK_FRAME_CLOCK_PHASE_LAYOUT &&
+ (priv->requested & GDK_FRAME_CLOCK_PHASE_LAYOUT))
+ _gdk_frame_timings_set_layout_start_time (timings, g_get_monotonic_time ());
+ }
+#endif /* G_ENABLE_DEBUG */
+
priv->phase = GDK_FRAME_CLOCK_PHASE_LAYOUT;
if (priv->requested & GDK_FRAME_CLOCK_PHASE_LAYOUT)
{
case GDK_FRAME_CLOCK_PHASE_PAINT:
if (priv->freeze_count == 0)
{
+#ifdef G_ENABLE_DEBUG
+ if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
+ {
+ if (priv->phase != GDK_FRAME_CLOCK_PHASE_PAINT &&
+ (priv->requested & GDK_FRAME_CLOCK_PHASE_PAINT))
+ _gdk_frame_timings_set_paint_start_time (timings, g_get_monotonic_time ());
+ }
+#endif /* G_ENABLE_DEBUG */
+
priv->phase = GDK_FRAME_CLOCK_PHASE_PAINT;
if (priv->requested & GDK_FRAME_CLOCK_PHASE_PAINT)
{
/* the ::after-paint phase doesn't get repeated on freeze/thaw,
*/
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
+
+#ifdef G_ENABLE_DEBUG
+ if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
+ _gdk_frame_timings_set_frame_end_time (timings, g_get_monotonic_time ());
+#endif /* G_ENABLE_DEBUG */
}
case GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS:
;
}
}
+#ifdef G_ENABLE_DEBUG
+ if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
+ {
+ if (gdk_frame_timings_get_complete (timings))
+ _gdk_frame_history_debug_print (priv->history, timings);
+ }
+#endif /* G_ENABLE_DEBUG */
+
if (priv->requested & GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS)
{
priv->requested &= ~GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS;
g_signal_emit_by_name (G_OBJECT (clock), "resume-events");
}
- priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
+ if (priv->freeze_count == 0)
+ priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
+
+ priv->in_paint_idle = FALSE;
if (priv->freeze_count == 0 && priv->requested != 0)
{
priv->min_next_frame_time = 0;
}
+ if (priv->freeze_count == 0)
+ priv->sleep_serial = get_sleep_serial ();
+
return FALSE;
}
* run and do it for us. */
if (priv->paint_idle_id == 0)
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
+
+ priv->sleep_serial = get_sleep_serial ();
}
}