diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 944c0a465..fb7baeca5 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -1780,7 +1780,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self, ClutterActor *origin) { ClutterActor *parent; - ClutterMainContext *context; + ClutterActor *stage; CLUTTER_NOTE (PAINT, "Redraw queued on '%s' (from: '%s')", get_actor_debug_name (self), @@ -1798,16 +1798,11 @@ clutter_actor_real_queue_redraw (ClutterActor *self, if (!CLUTTER_ACTOR_IS_VISIBLE (self)) return; - /* We have an optimization in _clutter_do_pick to detect when the scene is - * static so we can cache a full, un-clipped pick buffer to avoid continuous - * pick renders. - * - * Currently the assumption is that actors queue a redraw when some state - * changes that affects painting *or* picking so we can use this point - * to invalidate any currently cached pick buffer. + /* XXX: when we merge the paint-box branch we should only need to + * invalidate the pick buffer in _clutter_stage_queue_actor_redraw */ - context = _clutter_context_get_default (); - context->have_complete_pick_buffer = FALSE; + stage = _clutter_actor_get_stage_internal (self); + _clutter_stage_set_pick_buffer_valid (CLUTTER_STAGE (stage), FALSE); /* Although we could determine here that a full stage redraw * has already been queued and immediately bail out, we actually @@ -1818,8 +1813,6 @@ clutter_actor_real_queue_redraw (ClutterActor *self, */ if (self->priv->propagated_one_redraw) { - ClutterActor *stage = _clutter_actor_get_stage_internal (self); - if (stage != NULL && _clutter_stage_has_full_redraw_queued (CLUTTER_STAGE (stage))) return; diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 0768833d6..7ed35d822 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -274,12 +274,8 @@ _clutter_do_redraw (ClutterStage *stage) ctx = _clutter_context_get_default (); - /* We have an optimization to avoid pick renders while scene is static. - * This is implied by seeing multiple picks per frame so we have to - * reset a pick counter each frame and also invalidate any current pick - * buffer. */ - ctx->picks_per_frame = 0; - ctx->have_complete_pick_buffer = FALSE; + _clutter_stage_set_pick_buffer_valid (stage, FALSE); + _clutter_stage_reset_picks_per_frame_counter (stage); /* Before we can paint, we have to be sure we have the latest layout */ _clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage)); @@ -601,7 +597,7 @@ _clutter_do_pick (ClutterStage *stage, /* It's possible that we currently have a static scene and have renderered a * full, unclipped pick buffer. If so we can simply continue to read from * this cached buffer until the scene next changes. */ - if (context->have_complete_pick_buffer) + if (_clutter_stage_get_pick_buffer_valid (stage)) { CLUTTER_TIMER_START (_clutter_uprof_context, pick_read); cogl_read_pixels (x, y, 1, 1, @@ -628,7 +624,7 @@ _clutter_do_pick (ClutterStage *stage, goto result; } - context->picks_per_frame++; + _clutter_stage_increment_picks_per_frame_counter (stage); _clutter_backend_ensure_context (context->backend, stage); @@ -638,7 +634,7 @@ _clutter_do_pick (ClutterStage *stage, /* If we are seeing multiple picks per frame that means the scene is static * so we promote to doing a non-scissored pick render so that all subsequent * picks for the same static scene won't require additional renders */ - if (context->picks_per_frame < 2) + if (_clutter_stage_get_picks_per_frame_counter (stage) < 2) { if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) @@ -680,7 +676,7 @@ _clutter_do_pick (ClutterStage *stage, cogl_clip_pop (); } else - context->have_complete_pick_buffer = TRUE; + _clutter_stage_set_pick_buffer_valid (stage, TRUE); /* Make sure Cogl flushes any batched geometry to the GPU driver */ cogl_flush (); diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 7c460d393..56221c630 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -183,9 +183,6 @@ struct _ClutterMainContext GList *repaint_funcs; ClutterSettings *settings; - - gint picks_per_frame; - gboolean have_complete_pick_buffer; }; #define CLUTTER_CONTEXT() (_clutter_context_get_default ()) @@ -279,6 +276,12 @@ int _clutter_stage_get_pending_swaps (ClutterStage *stage); gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage); +void _clutter_stage_set_pick_buffer_valid (ClutterStage *stage, gboolean valid); +gboolean _clutter_stage_get_pick_buffer_valid (ClutterStage *stage); +void _clutter_stage_increment_picks_per_frame_counter (ClutterStage *stage); +void _clutter_stage_reset_picks_per_frame_counter (ClutterStage *stage); +guint _clutter_stage_get_picks_per_frame_counter (ClutterStage *stage); + /* vfuncs implemented by backend */ GType _clutter_backend_impl_get_type (void); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 7b7c8c867..87ddc1dbc 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -116,6 +116,8 @@ struct _ClutterStagePrivate ClutterStageHint stage_hints; + gint picks_per_frame; + guint redraw_pending : 1; guint is_fullscreen : 1; guint is_cursor_visible : 1; @@ -126,6 +128,7 @@ struct _ClutterStagePrivate guint min_size_changed : 1; guint dirty_viewport : 1; guint dirty_projection : 1; + guint have_valid_pick_buffer : 1; }; enum @@ -734,6 +737,16 @@ clutter_stage_real_queue_redraw (ClutterActor *actor, else CLUTTER_CONTEXT ()->redraw_count += 1; + /* We have an optimization in _clutter_do_pick to detect when the + * scene is static so we can cache a full, un-clipped pick buffer to + * avoid continuous pick renders. + * + * Currently the assumption is that actors queue a redraw when some + * state changes that affects painting *or* picking so we can use + * this point to invalidate any currently cached pick buffer. + */ + _clutter_stage_set_pick_buffer_valid (stage, FALSE); + /* If the backend can't do anything with redraw clips (e.g. it already knows * it needs to redraw everything anyway) then don't spend time transforming * any clip regions into stage coordinates... */ @@ -1452,6 +1465,9 @@ clutter_stage_init (ClutterStage *self) _clutter_stage_window_get_geometry (priv->impl, &geom); _clutter_stage_set_viewport (self, 0, 0, geom.width, geom.height); + + _clutter_stage_set_pick_buffer_valid (self, FALSE); + _clutter_stage_reset_picks_per_frame_counter (self); } /** @@ -2929,3 +2945,33 @@ clutter_stage_get_no_clear_hint (ClutterStage *stage) return (stage->priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0; } + +gboolean +_clutter_stage_get_pick_buffer_valid (ClutterStage *stage) +{ + return stage->priv->have_valid_pick_buffer; +} + +void +_clutter_stage_set_pick_buffer_valid (ClutterStage *stage, gboolean valid) +{ + stage->priv->have_valid_pick_buffer = valid; +} + +void +_clutter_stage_increment_picks_per_frame_counter (ClutterStage *stage) +{ + stage->priv->picks_per_frame++; +} + +void +_clutter_stage_reset_picks_per_frame_counter (ClutterStage *stage) +{ + stage->priv->picks_per_frame = 0; +} + +guint +_clutter_stage_get_picks_per_frame_counter (ClutterStage *stage) +{ + return stage->priv->picks_per_frame; +}