mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
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:
parent
8b047d0bc9
commit
68d7a5e847
@ -144,11 +144,13 @@ clutter_frame_source_prepare (GSource *source,
|
|||||||
gint *delay)
|
gint *delay)
|
||||||
{
|
{
|
||||||
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
|
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
|
||||||
GTimeVal current_time;
|
GTimeVal source_time;
|
||||||
|
gint64 current_time;
|
||||||
|
|
||||||
g_source_get_current_time (source, ¤t_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 (¤t_time,
|
return _clutter_timeout_interval_prepare (current_time,
|
||||||
&frame_source->timeout,
|
&frame_source->timeout,
|
||||||
delay);
|
delay);
|
||||||
}
|
}
|
||||||
|
@ -56,21 +56,18 @@ struct _ClutterMasterClock
|
|||||||
/* the list of timelines handled by the clock */
|
/* the list of timelines handled by the clock */
|
||||||
GSList *timelines;
|
GSList *timelines;
|
||||||
|
|
||||||
/* the current state of the clock
|
/* the current state of the clock, in usecs */
|
||||||
*/
|
gint64 cur_tick;
|
||||||
GTimeVal cur_tick;
|
|
||||||
|
|
||||||
/* the previous state of the clock, used to compute
|
/* the previous state of the clock, in usecs, used to compute the delta */
|
||||||
* the delta
|
gint64 prev_tick;
|
||||||
*/
|
|
||||||
GTimeVal prev_tick;
|
|
||||||
|
|
||||||
/* an idle source, used by the Master Clock to queue
|
/* an idle source, used by the Master Clock to queue
|
||||||
* a redraw on the stage and drive the animations
|
* a redraw on the stage and drive the animations
|
||||||
*/
|
*/
|
||||||
GSource *source;
|
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
|
* fallen back to idle polling for timeline
|
||||||
* progressions and it may have been some time since
|
* progressions and it may have been some time since
|
||||||
* the last real stage update.
|
* the last real stage update.
|
||||||
@ -173,8 +170,8 @@ master_clock_is_running (ClutterMasterClock *master_clock)
|
|||||||
static gint
|
static gint
|
||||||
master_clock_next_frame_delay (ClutterMasterClock *master_clock)
|
master_clock_next_frame_delay (ClutterMasterClock *master_clock)
|
||||||
{
|
{
|
||||||
GTimeVal now;
|
GTimeVal source_time;
|
||||||
GTimeVal next;
|
gint64 now, next;
|
||||||
|
|
||||||
if (!master_clock_is_running (master_clock))
|
if (!master_clock_is_running (master_clock))
|
||||||
return -1;
|
return -1;
|
||||||
@ -198,7 +195,7 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock)
|
|||||||
return 0;
|
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
|
/* If we weren't previously running, then draw the next frame
|
||||||
* immediately
|
* immediately
|
||||||
@ -210,24 +207,22 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock)
|
|||||||
/* Otherwise, wait at least 1/frame_rate seconds since we last
|
/* Otherwise, wait at least 1/frame_rate seconds since we last
|
||||||
* started a frame
|
* 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;
|
next = master_clock->prev_tick;
|
||||||
|
|
||||||
/* If time has gone backwards then there's no way of knowing how
|
/* If time has gone backwards then there's no way of knowing how
|
||||||
long we should wait so let's just dispatch immediately */
|
long we should wait so let's just dispatch immediately */
|
||||||
if (now.tv_sec < next.tv_sec ||
|
if (now <= next)
|
||||||
(now.tv_sec == next.tv_sec && now.tv_usec <= next.tv_usec))
|
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
|
CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
|
||||||
|
|
||||||
return 0;
|
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 ||
|
if (next <= now)
|
||||||
(next.tv_sec == now.tv_sec && next.tv_usec <= now.tv_usec))
|
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
|
CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
|
||||||
1000000L / (gulong) clutter_get_default_frame_rate ());
|
1000000L / (gulong) clutter_get_default_frame_rate ());
|
||||||
@ -236,12 +231,10 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (SCHEDULER, "Waiting %lu msecs",
|
CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
|
||||||
(next.tv_sec - now.tv_sec) * 1000 +
|
(next - now) / 1000);
|
||||||
(next.tv_usec - now.tv_usec) / 1000);
|
|
||||||
|
|
||||||
return ((next.tv_sec - now.tv_sec) * 1000 +
|
return (next - now) / 1000;
|
||||||
(next.tv_usec - now.tv_usec) / 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,8 +300,9 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||||
ClutterMasterClock *master_clock = clock_source->master_clock;
|
ClutterMasterClock *master_clock = clock_source->master_clock;
|
||||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||||
GSList *stages, *l;
|
|
||||||
gboolean stages_updated = FALSE;
|
gboolean stages_updated = FALSE;
|
||||||
|
GTimeVal source_time;
|
||||||
|
GSList *stages, *l;
|
||||||
|
|
||||||
CLUTTER_STATIC_TIMER (master_dispatch_timer,
|
CLUTTER_STATIC_TIMER (master_dispatch_timer,
|
||||||
"Mainloop",
|
"Mainloop",
|
||||||
@ -327,9 +321,10 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
|
|
||||||
clutter_threads_enter ();
|
clutter_threads_enter ();
|
||||||
|
|
||||||
/* Get the time to use for this frame.
|
/* Get the time to use for this frame */
|
||||||
*/
|
g_source_get_current_time (source, &source_time);
|
||||||
g_source_get_current_time (source, &master_clock->cur_tick);
|
master_clock->cur_tick = source_time.tv_sec * 1000000L
|
||||||
|
+ source_time.tv_usec;
|
||||||
|
|
||||||
/* We need to protect ourselves against stages being destroyed during
|
/* We need to protect ourselves against stages being destroyed during
|
||||||
* event handling
|
* event handling
|
||||||
@ -552,7 +547,7 @@ _clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
|||||||
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
|
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
|
||||||
|
|
||||||
for (l = timelines; l != NULL; l = l->next)
|
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_foreach (timelines, (GFunc) g_object_unref, NULL);
|
||||||
g_slist_free (timelines);
|
g_slist_free (timelines);
|
||||||
|
@ -64,7 +64,7 @@ struct _ClutterTimelinePrivate
|
|||||||
GHashTable *markers_by_name;
|
GHashTable *markers_by_name;
|
||||||
|
|
||||||
/* Time we last advanced the elapsed time and showed a frame */
|
/* Time we last advanced the elapsed time and showed a frame */
|
||||||
GTimeVal last_frame_time;
|
gint64 last_frame_time;
|
||||||
|
|
||||||
guint loop : 1;
|
guint loop : 1;
|
||||||
guint is_playing : 1;
|
guint is_playing : 1;
|
||||||
@ -1205,14 +1205,14 @@ clutter_timeline_get_delta (ClutterTimeline *timeline)
|
|||||||
* @timeline: a #ClutterTimeline
|
* @timeline: a #ClutterTimeline
|
||||||
* @tick_time: time of advance
|
* @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
|
* function is called by the master clock. The @timeline will use this
|
||||||
* interval to emit the #ClutterTimeline::new-frame signal and
|
* interval to emit the #ClutterTimeline::new-frame signal and
|
||||||
* eventually skip frames.
|
* eventually skip frames.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_timeline_do_tick (ClutterTimeline *timeline,
|
_clutter_timeline_do_tick (ClutterTimeline *timeline,
|
||||||
GTimeVal *tick_time)
|
gint64 tick_time)
|
||||||
{
|
{
|
||||||
ClutterTimelinePrivate *priv;
|
ClutterTimelinePrivate *priv;
|
||||||
|
|
||||||
@ -1222,15 +1222,14 @@ clutter_timeline_do_tick (ClutterTimeline *timeline,
|
|||||||
|
|
||||||
if (priv->waiting_first_tick)
|
if (priv->waiting_first_tick)
|
||||||
{
|
{
|
||||||
priv->last_frame_time = *tick_time;
|
priv->last_frame_time = tick_time;
|
||||||
priv->waiting_first_tick = FALSE;
|
priv->waiting_first_tick = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gint64 msecs;
|
gint64 msecs;
|
||||||
|
|
||||||
msecs = (tick_time->tv_sec - priv->last_frame_time.tv_sec) * 1000
|
msecs = tick_time - priv->last_frame_time;
|
||||||
+ (tick_time->tv_usec - priv->last_frame_time.tv_usec) / 1000;
|
|
||||||
|
|
||||||
/* if the clock rolled back between ticks we need to
|
/* if the clock rolled back between ticks we need to
|
||||||
* account for it; the best course of action, since the
|
* account for it; the best course of action, since the
|
||||||
@ -1239,14 +1238,14 @@ clutter_timeline_do_tick (ClutterTimeline *timeline,
|
|||||||
*/
|
*/
|
||||||
if (msecs < 0)
|
if (msecs < 0)
|
||||||
{
|
{
|
||||||
priv->last_frame_time = *tick_time;
|
priv->last_frame_time = tick_time;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msecs != 0)
|
if (msecs != 0)
|
||||||
{
|
{
|
||||||
/* Avoid accumulating error */
|
/* Avoid accumulating error */
|
||||||
g_time_val_add (&priv->last_frame_time, msecs * 1000L);
|
priv->last_frame_time += msecs;
|
||||||
priv->msecs_delta = msecs;
|
priv->msecs_delta = msecs;
|
||||||
clutter_timeline_do_frame (timeline);
|
clutter_timeline_do_frame (timeline);
|
||||||
}
|
}
|
||||||
|
@ -154,8 +154,8 @@ void clutter_timeline_advance_to_marker (ClutterTimeline *timeli
|
|||||||
const gchar *marker_name);
|
const gchar *marker_name);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
void clutter_timeline_do_tick (ClutterTimeline *timeline,
|
void _clutter_timeline_do_tick (ClutterTimeline *timeline,
|
||||||
GTimeVal *tick_time);
|
gint64 tick_time);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -34,30 +34,32 @@ void
|
|||||||
_clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
|
_clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
|
||||||
guint fps)
|
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->fps = fps;
|
||||||
interval->frame_count = 0;
|
interval->frame_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static gint64
|
||||||
_clutter_timeout_interval_get_ticks (const GTimeVal *current_time,
|
_clutter_timeout_interval_get_ticks (gint64 current_time,
|
||||||
ClutterTimeoutInterval *interval)
|
ClutterTimeoutInterval *interval)
|
||||||
{
|
{
|
||||||
return ((current_time->tv_sec - interval->start_time.tv_sec) * 1000
|
return MAX (current_time - interval->start_time, 0);
|
||||||
+ (current_time->tv_usec - interval->start_time.tv_usec) / 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
_clutter_timeout_interval_prepare (gint64 current_time,
|
||||||
ClutterTimeoutInterval *interval,
|
ClutterTimeoutInterval *interval,
|
||||||
gint *delay)
|
gint *delay)
|
||||||
{
|
{
|
||||||
guint elapsed_time, new_frame_num;
|
gint elapsed_time, new_frame_num;
|
||||||
|
|
||||||
elapsed_time = _clutter_timeout_interval_get_ticks (current_time,
|
elapsed_time = _clutter_timeout_interval_get_ticks (current_time, interval);
|
||||||
interval);
|
new_frame_num = elapsed_time * interval->fps / 1000;
|
||||||
new_frame_num = elapsed_time * interval->fps
|
|
||||||
/ 1000;
|
|
||||||
|
|
||||||
/* If time has gone backwards or the time since the last frame is
|
/* 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
|
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;
|
guint frame_time = (1000 + interval->fps - 1) / interval->fps;
|
||||||
|
|
||||||
/* Reset the start time */
|
/* 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 */
|
/* 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;
|
interval->frame_count = 0;
|
||||||
|
|
||||||
@ -119,11 +121,10 @@ _clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
|
|||||||
{
|
{
|
||||||
guint a_delay = 1000 / a->fps;
|
guint a_delay = 1000 / a->fps;
|
||||||
guint b_delay = 1000 / b->fps;
|
guint b_delay = 1000 / b->fps;
|
||||||
glong b_difference;
|
gint64 b_difference;
|
||||||
gint comparison;
|
gint comparison;
|
||||||
|
|
||||||
b_difference = ((a->start_time.tv_sec - b->start_time.tv_sec) * 1000
|
b_difference = a->start_time - b->start_time;
|
||||||
+ (a->start_time.tv_usec - b->start_time.tv_usec) / 1000);
|
|
||||||
|
|
||||||
comparison = ((gint) ((a->frame_count + 1) * a_delay)
|
comparison = ((gint) ((a->frame_count + 1) * a_delay)
|
||||||
- (gint) ((b->frame_count + 1) * b_delay + b_difference));
|
- (gint) ((b->frame_count + 1) * b_delay + b_difference));
|
||||||
|
@ -32,24 +32,26 @@ typedef struct _ClutterTimeoutInterval ClutterTimeoutInterval;
|
|||||||
|
|
||||||
struct _ClutterTimeoutInterval
|
struct _ClutterTimeoutInterval
|
||||||
{
|
{
|
||||||
GTimeVal start_time;
|
/* milliseconds */
|
||||||
guint frame_count, fps;
|
gint64 start_time;
|
||||||
|
|
||||||
|
guint frame_count;
|
||||||
|
guint fps;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
|
void _clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
|
||||||
guint fps);
|
guint fps);
|
||||||
|
|
||||||
gboolean _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
gboolean _clutter_timeout_interval_prepare (gint64 current_time,
|
||||||
ClutterTimeoutInterval *interval,
|
ClutterTimeoutInterval *interval,
|
||||||
gint *delay);
|
gint *delay);
|
||||||
|
|
||||||
gboolean _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
|
gboolean _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
|
||||||
GSourceFunc callback,
|
GSourceFunc callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
gint _clutter_timeout_interval_compare_expiration
|
gint _clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
|
||||||
(const ClutterTimeoutInterval *a,
|
const ClutterTimeoutInterval *b);
|
||||||
const ClutterTimeoutInterval *b);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -65,8 +65,9 @@ struct _ClutterTimeoutPool
|
|||||||
|
|
||||||
guint next_id;
|
guint next_id;
|
||||||
|
|
||||||
GTimeVal start_time;
|
GList *timeouts;
|
||||||
GList *timeouts, *dispatched_timeouts;
|
GList *dispatched_timeouts;
|
||||||
|
|
||||||
gint ready;
|
gint ready;
|
||||||
|
|
||||||
guint id;
|
guint id;
|
||||||
@ -135,11 +136,14 @@ clutter_timeout_prepare (ClutterTimeoutPool *pool,
|
|||||||
ClutterTimeout *timeout,
|
ClutterTimeout *timeout,
|
||||||
gint *next_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);
|
next_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,8 +391,6 @@ clutter_timeout_pool_new (gint priority)
|
|||||||
g_source_set_priority (source, priority);
|
g_source_set_priority (source, priority);
|
||||||
|
|
||||||
pool = (ClutterTimeoutPool *) source;
|
pool = (ClutterTimeoutPool *) source;
|
||||||
|
|
||||||
g_get_current_time (&pool->start_time);
|
|
||||||
pool->next_id = 1;
|
pool->next_id = 1;
|
||||||
pool->id = g_source_attach (source, NULL);
|
pool->id = g_source_attach (source, NULL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user