* a redraw on the stage and drive the animations
*/
GSource *source;
-
- guint timelines_running : 1;
};
struct _ClutterMasterClockClass
{
master_clock->timelines = g_slist_remove (master_clock->timelines,
timeline);
- if (master_clock->timelines == NULL)
- master_clock->timelines_running = FALSE;
}
/*
void
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
{
- gulong msecs;
- GSList *l;
+ GSList *l, *next;
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
- if (master_clock->timelines == NULL)
- return;
-
- if (!master_clock->timelines_running)
- {
- /* When we start running, we count the first frame as time 0,
- * so we don't need an advance. (And master_clock->prev_tick
- * doesn't meaningfully relate to these timelines.)
- */
- master_clock->timelines_running = TRUE;
- return;
- }
-
- msecs = (master_clock->cur_tick.tv_sec - master_clock->prev_tick.tv_sec) * 1000
- + (master_clock->cur_tick.tv_usec - master_clock->prev_tick.tv_usec) / 1000;
-
- if (msecs == 0)
- return;
-
- CLUTTER_NOTE (SCHEDULER, "Advancing %d timelines by %lu milliseconds",
- g_slist_length (master_clock->timelines),
- msecs);
-
- for (l = master_clock->timelines; l != NULL; l = l->next)
+ for (l = master_clock->timelines; l != NULL; l = next)
{
- ClutterTimeline *timeline = l->data;
+ next = l->next;
- if (clutter_timeline_is_playing (timeline))
- clutter_timeline_advance_delta (timeline, msecs);
+ clutter_timeline_do_tick (l->data, &master_clock->cur_tick);
}
}
GHashTable *markers_by_name;
+ /* Time we last advanced the elapsed time and showed a frame */
+ GTimeVal last_frame_time;
+
guint loop : 1;
guint is_playing : 1;
+ /* If we've just started playing and haven't yet gotten a tick from the master clock */
+ guint waiting_first_tick : 1;
};
typedef struct {
priv->is_playing = is_playing;
master_clock = _clutter_master_clock_get_default ();
if (priv->is_playing)
- _clutter_master_clock_add_timeline (master_clock, timeline);
+ {
+ _clutter_master_clock_add_timeline (master_clock, timeline);
+ priv->waiting_first_tick = TRUE;
+ }
else
- _clutter_master_clock_remove_timeline (master_clock, timeline);
+ {
+ _clutter_master_clock_remove_timeline (master_clock, timeline);
+ }
}
static gboolean
-clutter_timeline_advance_internal (ClutterTimeline *timeline)
+clutter_timeline_do_frame (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv;
}
/*
- * clutter_timeline_advance_delta:
+ * clutter_timeline_do_tick
* @timeline: a #ClutterTimeline
- * @msecs: advance in milliseconds
+ * @tick_time: time of advance
*
- * Advances @timeline by @msecs. This function is called by the master
- * clock and it is used to advance a timeline by the amount of milliseconds
- * elapsed since the last redraw operation. The @timeline will use this
- * interval to emit the #ClutterTimeline::new-frame signal and eventually
- * skip frames.
+ * Advances @timeline based on the time passed in @msecs. This
+ * function is called by the master clock. The @timeline will use this
+ * interval to emit the #ClutterTimeline::new-frame signal and
+ * eventually skip frames.
*/
void
-clutter_timeline_advance_delta (ClutterTimeline *timeline,
- guint msecs)
+clutter_timeline_do_tick (ClutterTimeline *timeline,
+ GTimeVal *tick_time)
{
ClutterTimelinePrivate *priv;
priv = timeline->priv;
- priv->msecs_delta = msecs;
+ if (priv->waiting_first_tick)
+ {
+ priv->last_frame_time = *tick_time;
+ priv->waiting_first_tick = FALSE;
+ }
+ else
+ {
+ gint msecs =
+ (tick_time->tv_sec - priv->last_frame_time.tv_sec) * 1000
+ + (tick_time->tv_usec - priv->last_frame_time.tv_usec) / 1000;
- clutter_timeline_advance_internal (timeline);
+ if (msecs != 0)
+ {
+ /* Avoid accumulating error */
+ g_time_val_add (&priv->last_frame_time, msecs * 1000L);
+ priv->msecs_delta = msecs;
+ clutter_timeline_do_frame (timeline);
+ }
+ }
}
static inline void
const gchar *marker_name);
/*< private >*/
-void clutter_timeline_advance_delta (ClutterTimeline *timeline,
- guint msecs);
+void clutter_timeline_do_tick (ClutterTimeline *timeline,
+ GTimeVal *tick_time);
G_END_DECLS
gint completion_count;
gboolean passed;
guint source_id;
- GTimeVal prev_tick;
- gulong msecs_delta;
} TestState;
{
TestState *state = data;
GTimeVal cur_tick = { 0, };
- gulong msecs;
g_get_current_time (&cur_tick);
- if (state->prev_tick.tv_sec == 0)
- state->prev_tick = cur_tick;
-
- msecs = (cur_tick.tv_sec - state->prev_tick.tv_sec) * 1000
- + (cur_tick.tv_usec - state->prev_tick.tv_usec) / 1000;
-
if (clutter_timeline_is_playing (state->timeline))
- clutter_timeline_advance_delta (state->timeline, msecs);
-
- state->msecs_delta = msecs;
- state->prev_tick = cur_tick;
+ clutter_timeline_do_tick (state->timeline, &cur_tick);
return TRUE;
}
state.new_frame_counter = 0;
state.passed = TRUE;
state.expected_frame = 0;
- state.prev_tick.tv_sec = 0;
- state.prev_tick.tv_usec = 0;
- state.msecs_delta = 0;
state.source_id =
clutter_threads_add_frame_source (60, frame_tick, &state);
ClutterTimeline *timeline;
gint rewind_count;
guint source_id;
- GTimeVal prev_tick;
- gulong msecs_delta;
} TestState;
static gboolean
{
TestState *state = data;
GTimeVal cur_tick = { 0, };
- gulong msecs;
g_get_current_time (&cur_tick);
- if (state->prev_tick.tv_sec == 0)
- state->prev_tick = cur_tick;
-
- msecs = (cur_tick.tv_sec - state->prev_tick.tv_sec) * 1000
- + (cur_tick.tv_usec - state->prev_tick.tv_usec) / 1000;
-
if (clutter_timeline_is_playing (state->timeline))
- clutter_timeline_advance_delta (state->timeline, msecs);
-
- state->msecs_delta = msecs;
- state->prev_tick = cur_tick;
+ clutter_timeline_do_tick (state->timeline, &cur_tick);
return TRUE;
}
(GSourceFunc)watchdog_timeout,
&state);
state.rewind_count = 0;
- state.prev_tick.tv_sec = 0;
- state.prev_tick.tv_usec = 0;
- state.msecs_delta = 0;
state.source_id =
clutter_threads_add_frame_source (60, frame_tick, &state);
struct _FrameCounter
{
- GTimeVal prev_tick;
- gulong msecs_delta;
-
GSList *timelines;
};
FrameCounter *counter = data;
GTimeVal cur_tick = { 0, };
GSList *l;
- gulong msecs;
g_get_current_time (&cur_tick);
- if (counter->prev_tick.tv_sec == 0)
- counter->prev_tick = cur_tick;
-
- msecs = (cur_tick.tv_sec - counter->prev_tick.tv_sec) * 1000
- + (cur_tick.tv_usec - counter->prev_tick.tv_usec) / 1000;
-
for (l = counter->timelines; l != NULL; l = l->next)
{
ClutterTimeline *timeline = l->data;
if (clutter_timeline_is_playing (timeline))
- clutter_timeline_advance_delta (timeline, msecs);
+ clutter_timeline_do_tick (timeline, &cur_tick);
}
- counter->msecs_delta = msecs;
- counter->prev_tick = cur_tick;
-
return TRUE;
}