Move away from GTimeVal

GLib 2.28 will deprecate GTimeVal and related API in favour of
standardizing on microseconds granularity for all time-based API.

Clutter should switch too.

All of the current users of GTimeVal convert to milliseconds when
doing time operations, and use GTimeVal only as storage. This can
effectively be replaced by a gint64.

The Master Clock uses a microsecond resolution, except when interacting
with the main loop itself, since the main loop has a millisecond
resolution - at least until Ryan Lortie manages to switch that too to
microseconds on Linux.

The clutter_timeline_do_tick() function was erroneously not privatized,
but it was still assumed to be private; we should just remove it from
the public symbols.
This commit is contained in:
Emmanuele Bassi 2010-11-07 15:57:33 +00:00
parent 8b047d0bc9
commit 68d7a5e847
7 changed files with 79 additions and 78 deletions

View File

@ -144,11 +144,13 @@ clutter_frame_source_prepare (GSource *source,
gint *delay)
{
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
GTimeVal current_time;
GTimeVal source_time;
gint64 current_time;
g_source_get_current_time (source, &current_time);
g_source_get_current_time (source, &source_time);
current_time = source_time.tv_sec * 1000 + source_time.tv_usec / 1000;
return _clutter_timeout_interval_prepare (&current_time,
return _clutter_timeout_interval_prepare (current_time,
&frame_source->timeout,
delay);
}

View File

@ -56,21 +56,18 @@ struct _ClutterMasterClock
/* the list of timelines handled by the clock */
GSList *timelines;
/* the current state of the clock
*/
GTimeVal cur_tick;
/* the current state of the clock, in usecs */
gint64 cur_tick;
/* the previous state of the clock, used to compute
* the delta
*/
GTimeVal prev_tick;
/* the previous state of the clock, in usecs, used to compute the delta */
gint64 prev_tick;
/* an idle source, used by the Master Clock to queue
* a redraw on the stage and drive the animations
*/
GSource *source;
/* If the master clock is idle that means it's
/* If the master clock is idle that means it has
* fallen back to idle polling for timeline
* progressions and it may have been some time since
* the last real stage update.
@ -173,8 +170,8 @@ master_clock_is_running (ClutterMasterClock *master_clock)
static gint
master_clock_next_frame_delay (ClutterMasterClock *master_clock)
{
GTimeVal now;
GTimeVal next;
GTimeVal source_time;
gint64 now, next;
if (!master_clock_is_running (master_clock))
return -1;
@ -198,7 +195,7 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock)
return 0;
}
if (master_clock->prev_tick.tv_sec == 0)
if (master_clock->prev_tick == 0)
{
/* If we weren't previously running, then draw the next frame
* immediately
@ -210,24 +207,22 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock)
/* Otherwise, wait at least 1/frame_rate seconds since we last
* started a frame
*/
g_source_get_current_time (master_clock->source, &now);
g_source_get_current_time (master_clock->source, &source_time);
now = source_time.tv_sec * 1000000L + source_time.tv_usec;
next = master_clock->prev_tick;
/* If time has gone backwards then there's no way of knowing how
long we should wait so let's just dispatch immediately */
if (now.tv_sec < next.tv_sec ||
(now.tv_sec == next.tv_sec && now.tv_usec <= next.tv_usec))
if (now <= next)
{
CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
return 0;
}
g_time_val_add (&next, 1000000L / (gulong) clutter_get_default_frame_rate ());
next += (1000000L / clutter_get_default_frame_rate ());
if (next.tv_sec < now.tv_sec ||
(next.tv_sec == now.tv_sec && next.tv_usec <= now.tv_usec))
if (next <= now)
{
CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
1000000L / (gulong) clutter_get_default_frame_rate ());
@ -236,12 +231,10 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock)
}
else
{
CLUTTER_NOTE (SCHEDULER, "Waiting %lu msecs",
(next.tv_sec - now.tv_sec) * 1000 +
(next.tv_usec - now.tv_usec) / 1000);
CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
(next - now) / 1000);
return ((next.tv_sec - now.tv_sec) * 1000 +
(next.tv_usec - now.tv_usec) / 1000);
return (next - now) / 1000;
}
}
@ -307,8 +300,9 @@ clutter_clock_dispatch (GSource *source,
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterMasterClock *master_clock = clock_source->master_clock;
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
GSList *stages, *l;
gboolean stages_updated = FALSE;
GTimeVal source_time;
GSList *stages, *l;
CLUTTER_STATIC_TIMER (master_dispatch_timer,
"Mainloop",
@ -327,9 +321,10 @@ clutter_clock_dispatch (GSource *source,
clutter_threads_enter ();
/* Get the time to use for this frame.
*/
g_source_get_current_time (source, &master_clock->cur_tick);
/* Get the time to use for this frame */
g_source_get_current_time (source, &source_time);
master_clock->cur_tick = source_time.tv_sec * 1000000L
+ source_time.tv_usec;
/* We need to protect ourselves against stages being destroyed during
* event handling
@ -552,7 +547,7 @@ _clutter_master_clock_advance (ClutterMasterClock *master_clock)
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);
_clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000);
g_slist_foreach (timelines, (GFunc) g_object_unref, NULL);
g_slist_free (timelines);

View File

@ -64,7 +64,7 @@ struct _ClutterTimelinePrivate
GHashTable *markers_by_name;
/* Time we last advanced the elapsed time and showed a frame */
GTimeVal last_frame_time;
gint64 last_frame_time;
guint loop : 1;
guint is_playing : 1;
@ -1205,14 +1205,14 @@ clutter_timeline_get_delta (ClutterTimeline *timeline)
* @timeline: a #ClutterTimeline
* @tick_time: time of advance
*
* Advances @timeline based on the time passed in @msecs. This
* Advances @timeline based on the time passed in @tick_time. 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_do_tick (ClutterTimeline *timeline,
GTimeVal *tick_time)
_clutter_timeline_do_tick (ClutterTimeline *timeline,
gint64 tick_time)
{
ClutterTimelinePrivate *priv;
@ -1222,15 +1222,14 @@ clutter_timeline_do_tick (ClutterTimeline *timeline,
if (priv->waiting_first_tick)
{
priv->last_frame_time = *tick_time;
priv->last_frame_time = tick_time;
priv->waiting_first_tick = FALSE;
}
else
{
gint64 msecs;
msecs = (tick_time->tv_sec - priv->last_frame_time.tv_sec) * 1000
+ (tick_time->tv_usec - priv->last_frame_time.tv_usec) / 1000;
msecs = tick_time - priv->last_frame_time;
/* if the clock rolled back between ticks we need to
* account for it; the best course of action, since the
@ -1239,14 +1238,14 @@ clutter_timeline_do_tick (ClutterTimeline *timeline,
*/
if (msecs < 0)
{
priv->last_frame_time = *tick_time;
priv->last_frame_time = tick_time;
return;
}
if (msecs != 0)
{
/* Avoid accumulating error */
g_time_val_add (&priv->last_frame_time, msecs * 1000L);
priv->last_frame_time += msecs;
priv->msecs_delta = msecs;
clutter_timeline_do_frame (timeline);
}

View File

@ -154,8 +154,8 @@ void clutter_timeline_advance_to_marker (ClutterTimeline *timeli
const gchar *marker_name);
/*< private >*/
void clutter_timeline_do_tick (ClutterTimeline *timeline,
GTimeVal *tick_time);
void _clutter_timeline_do_tick (ClutterTimeline *timeline,
gint64 tick_time);
G_END_DECLS

View File

@ -34,30 +34,32 @@ void
_clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
guint fps)
{
g_get_current_time (&interval->start_time);
GTimeVal start_time;
g_get_current_time (&start_time);
interval->start_time = start_time.tv_sec * 1000
+ start_time.tv_usec / 1000;
interval->fps = fps;
interval->frame_count = 0;
}
static guint
_clutter_timeout_interval_get_ticks (const GTimeVal *current_time,
static gint64
_clutter_timeout_interval_get_ticks (gint64 current_time,
ClutterTimeoutInterval *interval)
{
return ((current_time->tv_sec - interval->start_time.tv_sec) * 1000
+ (current_time->tv_usec - interval->start_time.tv_usec) / 1000);
return MAX (current_time - interval->start_time, 0);
}
gboolean
_clutter_timeout_interval_prepare (const GTimeVal *current_time,
_clutter_timeout_interval_prepare (gint64 current_time,
ClutterTimeoutInterval *interval,
gint *delay)
{
guint elapsed_time, new_frame_num;
gint elapsed_time, new_frame_num;
elapsed_time = _clutter_timeout_interval_get_ticks (current_time,
interval);
new_frame_num = elapsed_time * interval->fps
/ 1000;
elapsed_time = _clutter_timeout_interval_get_ticks (current_time, interval);
new_frame_num = elapsed_time * interval->fps / 1000;
/* If time has gone backwards or the time since the last frame is
greater than the two frames worth then reset the time and do a
@ -69,10 +71,10 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
guint frame_time = (1000 + interval->fps - 1) / interval->fps;
/* Reset the start time */
interval->start_time = *current_time;
interval->start_time = current_time;
/* Move the start time as if one whole frame has elapsed */
g_time_val_add (&interval->start_time, -(gint) frame_time * 1000);
interval->start_time -= frame_time;
interval->frame_count = 0;
@ -119,11 +121,10 @@ _clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
{
guint a_delay = 1000 / a->fps;
guint b_delay = 1000 / b->fps;
glong b_difference;
gint64 b_difference;
gint comparison;
b_difference = ((a->start_time.tv_sec - b->start_time.tv_sec) * 1000
+ (a->start_time.tv_usec - b->start_time.tv_usec) / 1000);
b_difference = a->start_time - b->start_time;
comparison = ((gint) ((a->frame_count + 1) * a_delay)
- (gint) ((b->frame_count + 1) * b_delay + b_difference));

View File

@ -32,24 +32,26 @@ typedef struct _ClutterTimeoutInterval ClutterTimeoutInterval;
struct _ClutterTimeoutInterval
{
GTimeVal start_time;
guint frame_count, fps;
/* milliseconds */
gint64 start_time;
guint frame_count;
guint fps;
};
void _clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
guint fps);
void _clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
guint fps);
gboolean _clutter_timeout_interval_prepare (const GTimeVal *current_time,
ClutterTimeoutInterval *interval,
gint *delay);
gboolean _clutter_timeout_interval_prepare (gint64 current_time,
ClutterTimeoutInterval *interval,
gint *delay);
gboolean _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
GSourceFunc callback,
gpointer user_data);
gboolean _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
GSourceFunc callback,
gpointer user_data);
gint _clutter_timeout_interval_compare_expiration
(const ClutterTimeoutInterval *a,
const ClutterTimeoutInterval *b);
gint _clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
const ClutterTimeoutInterval *b);
G_END_DECLS

View File

@ -65,8 +65,9 @@ struct _ClutterTimeoutPool
guint next_id;
GTimeVal start_time;
GList *timeouts, *dispatched_timeouts;
GList *timeouts;
GList *dispatched_timeouts;
gint ready;
guint id;
@ -135,11 +136,14 @@ clutter_timeout_prepare (ClutterTimeoutPool *pool,
ClutterTimeout *timeout,
gint *next_timeout)
{
GTimeVal now;
GTimeVal source_time;
gint64 now;
g_source_get_current_time (&pool->source, &now);
g_source_get_current_time (&pool->source, &source_time);
now = source_time.tv_sec * 1000 + source_time.tv_usec / 1000;
return _clutter_timeout_interval_prepare (&now, &timeout->interval,
return _clutter_timeout_interval_prepare (now,
&timeout->interval,
next_timeout);
}
@ -387,8 +391,6 @@ clutter_timeout_pool_new (gint priority)
g_source_set_priority (source, priority);
pool = (ClutterTimeoutPool *) source;
g_get_current_time (&pool->start_time);
pool->next_id = 1;
pool->id = g_source_attach (source, NULL);