mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
picking: Fix tracking of pick buffer validity
We have an optimization to track when there are multiple picks per frame so we can do a full render of the pick buffer to reduce the number of pick renders for a static scene. There was a problem though in that we were tracking this information in the ClutterMainContext, but conceptually this doesn't really make sense because the pick buffer is associated with a stage framebuffer and there can be multiple stages for one context. This patch moves the state tracking to ClutterStage.
This commit is contained in:
parent
b2a56c9cda
commit
56929942a8
@ -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;
|
||||
|
@ -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 ();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user