mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
picking: Fix tracking of pick buffer validity
We have an optimization to track when there are multiple picks per frames so we can do a full render of the pick buffer to reduce the number of pick renders for a static scene. There were two problems with how we were tracking this state though. Firstly 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. Secondly - since the change to how redraws are queued - we weren't marking the pick buffer as invalid when a queuing a redraw, we were only marking the buffer invalid when signaling/finishing the queue-redraw process, which is now deferred until just before a paint. This meant using clutter_stage_get_actor_at_pos after a scenegraph change could give a wrong result if it just read from an existing (but technically invalid) pick buffer. This patch moves the state tracking to ClutterStage, and ensures the buffer is invalidated in _clutter_stage_queue_actor_redraw. http://bugzilla.clutter-project.org/show_bug.cgi?id=2283 Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
This commit is contained in:
parent
60c9dc25df
commit
d7e86e2696
@ -1780,7 +1780,6 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *origin)
|
||||
{
|
||||
ClutterActor *parent;
|
||||
ClutterMainContext *context;
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Redraw queued on '%s' (from: '%s')",
|
||||
get_actor_debug_name (self),
|
||||
@ -1798,17 +1797,6 @@ 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.
|
||||
*/
|
||||
context = _clutter_context_get_default ();
|
||||
context->have_complete_pick_buffer = FALSE;
|
||||
|
||||
/* Although we could determine here that a full stage redraw
|
||||
* has already been queued and immediately bail out, we actually
|
||||
* guarantee that we will propagate a queue-redraw signal to our
|
||||
|
@ -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_unset_pick_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_pick_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_pick_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,13 @@ 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_pick_counter (ClutterStage *stage);
|
||||
void _clutter_stage_unset_pick_counter (ClutterStage *stage);
|
||||
guint _clutter_stage_get_pick_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... */
|
||||
@ -2929,3 +2942,36 @@ 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)
|
||||
{
|
||||
valid = !!valid;
|
||||
|
||||
stage->priv->have_valid_pick_buffer = valid;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_increment_pick_counter (ClutterStage *stage)
|
||||
{
|
||||
stage->priv->picks_per_frame += 1;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_unset_pick_counter (ClutterStage *stage)
|
||||
{
|
||||
stage->priv->picks_per_frame = 0;
|
||||
}
|
||||
|
||||
guint
|
||||
_clutter_stage_get_pick_counter (ClutterStage *stage)
|
||||
{
|
||||
return stage->priv->picks_per_frame;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user