/* * _clutter_master_clock_advance: * @master_clock: a #ClutterMasterClock * * Advances all the timelines held by the master clock. This function * should be called before calling clutter_redraw() to make sure that * all the timelines are advanced and the scene is updated. */ void _clutter_master_clock_advance (ClutterMasterClock *master_clock) { GSList *timelines, *l; CLUTTER_STATIC_TIMER (master_timeline_advance, "Master Clock", "Timelines Advancement", "The time spent advancing all timelines", 0); g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); CLUTTER_TIMER_START (_clutter_uprof_context, master_timeline_advance); /* we protect ourselves from timelines being removed during * the advancement by other timelines by copying the list of * timelines, taking a reference on them, iterating over the * copied list and then releasing the reference. * * we cannot simply take a reference on the timelines and still * use the list held by the master clock because the do_tick() * might result in the creation of a new timeline, which gets * added at the end of the list with no reference increase and * thus gets disposed at the end of the iteration. * * this implies that a newly added timeline will not be advanced * by this clock iteration, which is perfectly fine since we're * in its first cycle. * * we also cannot steal the master clock timelines list because * a timeline might be removed as the direct result of do_tick() * and remove_timeline() would not find the timeline, failing * and leaving a dangling pointer behind. */ timelines = g_slist_copy (master_clock->timelines); g_slist_foreach (timelines, (GFunc) g_object_ref, NULL); for (l = timelines; l != NULL; l = l->next) _clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000); g_slist_foreach (timelines, (GFunc) g_object_unref, NULL); g_slist_free (timelines); CLUTTER_TIMER_STOP (_clutter_uprof_context, master_timeline_advance); }
/* * master_clock_advance_timelines: * @master_clock: a #ClutterMasterClock * * Advances all the timelines held by the master clock. This function * should be called before calling _clutter_stage_do_update() to * make sure that all the timelines are advanced and the scene is updated. */ static void master_clock_advance_timelines (ClutterMasterClockDefault *master_clock) { GSList *timelines, *l; #ifdef CLUTTER_ENABLE_DEBUG gint64 start = g_get_monotonic_time (); #endif /* we protect ourselves from timelines being removed during * the advancement by other timelines by copying the list of * timelines, taking a reference on them, iterating over the * copied list and then releasing the reference. * * we cannot simply take a reference on the timelines and still * use the list held by the master clock because the do_tick() * might result in the creation of a new timeline, which gets * added at the end of the list with no reference increase and * thus gets disposed at the end of the iteration. * * this implies that a newly added timeline will not be advanced * by this clock iteration, which is perfectly fine since we're * in its first cycle. * * we also cannot steal the master clock timelines list because * a timeline might be removed as the direct result of do_tick() * and remove_timeline() would not find the timeline, failing * and leaving a dangling pointer behind. */ timelines = g_slist_copy (master_clock->timelines); g_slist_foreach (timelines, (GFunc) g_object_ref, NULL); for (l = timelines; l != NULL; l = l->next) _clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000); g_slist_foreach (timelines, (GFunc) g_object_unref, NULL); g_slist_free (timelines); #ifdef CLUTTER_ENABLE_DEBUG if (_clutter_diagnostic_enabled ()) clutter_warn_if_over_budget (master_clock, start, "Animations"); master_clock->remaining_budget -= (g_get_monotonic_time () - start); #endif }