[master clock] Avoid excessive redraws
Currently, the clock source spins a redraw every time there is at least a timeline running. If the timelines were not advanced in the previous frame, though, because their interval is larger than the vblanking interval then this will lead to excessive redraws of the scenegraph even if nothing has changed. To avoid this a simple guard should be set by the MasterClock::advance method in case no timeline was effectively advanced, and checked before dispatching the stage redraws.
This commit is contained in:
parent
b6f1322e07
commit
762873e79e
@ -68,6 +68,11 @@ struct _ClutterMasterClock
|
|||||||
* after the last timeline has been completed
|
* after the last timeline has been completed
|
||||||
*/
|
*/
|
||||||
guint last_advance : 1;
|
guint last_advance : 1;
|
||||||
|
|
||||||
|
/* a guard, so that we dispatch the redraws only if
|
||||||
|
* any timeline did advance
|
||||||
|
*/
|
||||||
|
guint has_advanced : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterMasterClockClass
|
struct _ClutterMasterClockClass
|
||||||
@ -208,6 +213,17 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
|
|
||||||
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
|
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
|
||||||
|
|
||||||
|
/* do not force a redraw if no timeline has advanced; this might
|
||||||
|
* happen if we only have timelines with intervals smaller than
|
||||||
|
* the vblank interval
|
||||||
|
*/
|
||||||
|
if (master_clock->has_advanced)
|
||||||
|
{
|
||||||
|
master_clock->has_advanced = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||||
|
|
||||||
/* queue a redraw for each stage; this will advance each timeline
|
/* queue a redraw for each stage; this will advance each timeline
|
||||||
@ -438,6 +454,7 @@ void
|
|||||||
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
||||||
{
|
{
|
||||||
GTimeVal cur_tick = { 0, };
|
GTimeVal cur_tick = { 0, };
|
||||||
|
gboolean has_advanced;
|
||||||
gulong msecs;
|
gulong msecs;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
|
|
||||||
@ -461,12 +478,13 @@ _clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
|||||||
g_slist_length (master_clock->timelines),
|
g_slist_length (master_clock->timelines),
|
||||||
msecs);
|
msecs);
|
||||||
|
|
||||||
|
has_advanced = FALSE;
|
||||||
for (l = master_clock->timelines; l != NULL; l = l->next)
|
for (l = master_clock->timelines; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
ClutterTimeline *timeline = l->data;
|
ClutterTimeline *timeline = l->data;
|
||||||
|
|
||||||
if (clutter_timeline_is_playing (timeline))
|
if (clutter_timeline_is_playing (timeline))
|
||||||
clutter_timeline_advance_delta (timeline, msecs);
|
has_advanced = clutter_timeline_advance_delta (timeline, msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store the previous state so that we can use
|
/* store the previous state so that we can use
|
||||||
@ -474,4 +492,5 @@ _clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
|||||||
*/
|
*/
|
||||||
master_clock->msecs_delta = msecs;
|
master_clock->msecs_delta = msecs;
|
||||||
master_clock->prev_tick = cur_tick;
|
master_clock->prev_tick = cur_tick;
|
||||||
|
master_clock->has_advanced = has_advanced;
|
||||||
}
|
}
|
||||||
|
@ -1381,21 +1381,23 @@ clutter_timeline_get_delta (ClutterTimeline *timeline,
|
|||||||
* elapsed since the last redraw operation. The @timeline will use this
|
* elapsed since the last redraw operation. The @timeline will use this
|
||||||
* interval to emit the #ClutterTimeline::new-frame signal and eventually
|
* interval to emit the #ClutterTimeline::new-frame signal and eventually
|
||||||
* skip frames.
|
* skip frames.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the timeline advanced
|
||||||
*/
|
*/
|
||||||
void
|
gboolean
|
||||||
clutter_timeline_advance_delta (ClutterTimeline *timeline,
|
clutter_timeline_advance_delta (ClutterTimeline *timeline,
|
||||||
guint msecs)
|
guint msecs)
|
||||||
{
|
{
|
||||||
ClutterTimelinePrivate *priv;
|
ClutterTimelinePrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
|
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE);
|
||||||
|
|
||||||
priv = timeline->priv;
|
priv = timeline->priv;
|
||||||
|
|
||||||
priv->msecs_delta += msecs;
|
priv->msecs_delta += msecs;
|
||||||
|
|
||||||
if (priv->msecs_delta < priv->frame_interval)
|
if (priv->msecs_delta < priv->frame_interval)
|
||||||
return;
|
return FALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clutter_timeline_advance_internal (timeline);
|
clutter_timeline_advance_internal (timeline);
|
||||||
@ -1403,6 +1405,8 @@ clutter_timeline_advance_delta (ClutterTimeline *timeline,
|
|||||||
/* Keep the remainder of the frame time so that it will be
|
/* Keep the remainder of the frame time so that it will be
|
||||||
counted towards the next time if the delta is short */
|
counted towards the next time if the delta is short */
|
||||||
priv->msecs_delta %= priv->frame_interval;
|
priv->msecs_delta %= priv->frame_interval;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ void clutter_timeline_advance_to_marker (ClutterTimeline *timeli
|
|||||||
const gchar *marker_name);
|
const gchar *marker_name);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
void clutter_timeline_advance_delta (ClutterTimeline *timeline,
|
gboolean clutter_timeline_advance_delta (ClutterTimeline *timeline,
|
||||||
guint msecs);
|
guint msecs);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
Loading…
Reference in New Issue
Block a user