mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -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)
|
||||
{
|
||||
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,
|
||||
delay);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user