From acf7722a41dc5c568f895166cc471f53f3546926 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 10 Jun 2009 15:50:27 +0100 Subject: [PATCH] [master-clock] Throttle if no redraw was performed A flag in the master clock is now set whenever the dispatch caused an actual redraw of a stage. If this flag is not set during the prepare and check functions then it will resort to limiting the redraw attempts to the default frame rate as if vblank syncing was disabled. Otherwise if a timeline is running that does not cause the scene to change then it would busy-wait with 100% CPU until the next frame. This fix was suggested by Owen Taylor in: http://bugzilla.openedhand.com/show_bug.cgi?id=1637 Signed-off-by: Emmanuele Bassi --- clutter/clutter-master-clock.c | 11 +++++++++-- clutter/clutter-private.h | 2 +- clutter/clutter-stage.c | 12 ++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/clutter/clutter-master-clock.c b/clutter/clutter-master-clock.c index 661a4987a..2d3c87f73 100644 --- a/clutter/clutter-master-clock.c +++ b/clutter/clutter-master-clock.c @@ -66,6 +66,8 @@ struct _ClutterMasterClock * a redraw on the stage and drive the animations */ GSource *source; + + guint updated_stages : 1; }; struct _ClutterMasterClockClass @@ -144,7 +146,8 @@ master_clock_next_frame_delay (ClutterMasterClock *master_clock) if (!master_clock_is_running (master_clock)) return -1; - if (clutter_feature_available (CLUTTER_FEATURE_SYNC_TO_VBLANK)) + if (clutter_feature_available (CLUTTER_FEATURE_SYNC_TO_VBLANK) && + master_clock->updated_stages) { /* When we have sync-to-vblank, we count on that to throttle * our frame rate, and otherwise draw frames as fast as possible. @@ -250,6 +253,8 @@ clutter_clock_dispatch (GSource *source, stages = clutter_stage_manager_list_stages (stage_manager); g_slist_foreach (stages, (GFunc)g_object_ref, NULL); + master_clock->updated_stages = FALSE; + /* Process queued events */ for (l = stages; l != NULL; l = l->next) @@ -262,7 +267,7 @@ clutter_clock_dispatch (GSource *source, * is advanced. */ for (l = stages; l != NULL; l = l->next) - _clutter_stage_do_update (l->data); + master_clock->updated_stages |= _clutter_stage_do_update (l->data); g_slist_foreach (stages, (GFunc)g_object_unref, NULL); g_slist_free (stages); @@ -298,6 +303,8 @@ clutter_master_clock_init (ClutterMasterClock *self) source = clutter_clock_source_new (self); self->source = source; + self->updated_stages = TRUE; + g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW); g_source_set_can_recurse (source, FALSE); g_source_attach (source, NULL); diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 340cc75c6..0b96018b0 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -174,7 +174,7 @@ ClutterStageWindow *_clutter_stage_get_default_window (void); void _clutter_stage_maybe_setup_viewport (ClutterStage *stage); void _clutter_stage_maybe_relayout (ClutterActor *stage); gboolean _clutter_stage_needs_update (ClutterStage *stage); -void _clutter_stage_do_update (ClutterStage *stage); +gboolean _clutter_stage_do_update (ClutterStage *stage); void _clutter_stage_queue_event (ClutterStage *stage, ClutterEvent *event); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 7fdb98164..746d49468 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -486,7 +486,7 @@ _clutter_stage_process_queued_events (ClutterStage *stage) * * Determines if _clutter_stage_do_update() needs to be called. * - * Return value: %TRUE if the stages need layout or painting + * Return value: %TRUE if the stage need layout or painting */ gboolean _clutter_stage_needs_update (ClutterStage *stage) @@ -505,18 +505,20 @@ _clutter_stage_needs_update (ClutterStage *stage) * @stage: A #ClutterStage * * Handles per-frame layout and repaint for the stage. + * + * Return value: %TRUE if the stage was updated */ -void +gboolean _clutter_stage_do_update (ClutterStage *stage) { ClutterStagePrivate *priv; - g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); priv = stage->priv; if (!priv->redraw_pending) - return; + return FALSE; /* clutter_do_redraw() will also call maybe_relayout(), but since a relayout * can queue a redraw, we want to do the relayout before we clear the @@ -539,6 +541,8 @@ _clutter_stage_do_update (ClutterStage *stage) CLUTTER_CONTEXT ()->redraw_count = 0; } + + return TRUE; } static void