From 3073aee7c86ce06cefe391242f443fefb8c28996 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 22 Oct 2020 19:34:26 -0300 Subject: [PATCH 1/5] clutter/pick-stack: Add autoptr support It'll allow us use g_autoptr (ClutterPickStack) when removing the pick stack cache, making the code a bit more modern. Part-of: --- clutter/clutter/clutter-pick-stack-private.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clutter/clutter/clutter-pick-stack-private.h b/clutter/clutter/clutter-pick-stack-private.h index 159b8c4ebba..0523fcafe69 100644 --- a/clutter/clutter/clutter-pick-stack-private.h +++ b/clutter/clutter/clutter-pick-stack-private.h @@ -61,6 +61,8 @@ clutter_pick_stack_search_actor (ClutterPickStack *pick_stack, const graphene_point3d_t *point, const graphene_ray_t *ray); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPickStack, clutter_pick_stack_unref) + G_END_DECLS #endif /* CLUTTER_PICK_STACK_PRIVATE_H */ -- GitLab From 1b29d265a8506ffeb0f0d01199ffa962c29d51d0 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 22 Oct 2020 19:34:51 -0300 Subject: [PATCH 2/5] clutter/stage: Remove cached pick mode The cached pick mode never actually cached anything, since it is always, unconditionally reset when painting. Furthermore, next commits will cull out actors during pick, which makes the pick stack uncacheable. Remove the cached pick mode. Part-of: --- clutter/clutter/clutter-stage.c | 52 +++++---------------------------- 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 430233534eb..3d2edf95eeb 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -124,9 +124,6 @@ struct _ClutterStagePrivate GTimer *fps_timer; gint32 timer_n_frames; - ClutterPickStack *pick_stack; - ClutterPickMode cached_pick_mode; - ClutterStageState current_state; int update_freeze_count; @@ -228,15 +225,6 @@ clutter_stage_get_preferred_height (ClutterActor *self, *natural_height_p = geom.height; } -static void -_clutter_stage_clear_pick_stack (ClutterStage *stage) -{ - ClutterStagePrivate *priv = stage->priv; - - g_clear_pointer (&priv->pick_stack, clutter_pick_stack_unref); - priv->cached_pick_mode = CLUTTER_PICK_NONE; -} - static void clutter_stage_add_redraw_clip (ClutterStage *stage, cairo_rectangle_int_t *clip) @@ -457,19 +445,12 @@ clutter_stage_do_paint_view (ClutterStage *stage, ClutterStageView *view, const cairo_region_t *redraw_clip) { - ClutterStagePrivate *priv = stage->priv; ClutterPaintContext *paint_context; cairo_rectangle_int_t clip_rect; g_autoptr (GArray) clip_frusta = NULL; graphene_frustum_t clip_frustum; int n_rectangles; - /* Any mode of painting/picking invalidates the pick cache, unless we're - * in the middle of building it. So we reset the cached flag but don't - * completely clear the pick stack. - */ - priv->cached_pick_mode = CLUTTER_PICK_NONE; - n_rectangles = redraw_clip ? cairo_region_num_rectangles (redraw_clip) : 0; if (redraw_clip && n_rectangles < MAX_FRUSTA) { @@ -632,7 +613,6 @@ clutter_stage_hide (ClutterActor *self) ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; g_assert (priv->impl != NULL); - _clutter_stage_clear_pick_stack (CLUTTER_STAGE (self)); _clutter_stage_window_hide (priv->impl); CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self); @@ -1100,31 +1080,23 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage, ClutterPickMode mode, ClutterStageView *view) { - ClutterStagePrivate *priv = stage->priv; + g_autoptr (ClutterPickStack) pick_stack = NULL; + ClutterPickContext *pick_context; graphene_point3d_t p; graphene_ray_t ray; ClutterActor *actor; COGL_TRACE_BEGIN_SCOPED (ClutterStagePickView, "Pick (view)"); - if (!priv->pick_stack || mode != priv->cached_pick_mode) - { - ClutterPickContext *pick_context; - - _clutter_stage_clear_pick_stack (stage); - - pick_context = clutter_pick_context_new_for_view (view, mode); - - clutter_actor_pick (CLUTTER_ACTOR (stage), pick_context); - priv->pick_stack = clutter_pick_context_steal_stack (pick_context); - priv->cached_pick_mode = mode; + pick_context = clutter_pick_context_new_for_view (view, mode); - clutter_pick_context_destroy (pick_context); - } + clutter_actor_pick (CLUTTER_ACTOR (stage), pick_context); + pick_stack = clutter_pick_context_steal_stack (pick_context); + clutter_pick_context_destroy (pick_context); setup_ray_for_coordinates (stage, x, y, &p, &ray); - actor = clutter_pick_stack_search_actor (priv->pick_stack, &p, &ray); + actor = clutter_pick_stack_search_actor (pick_stack, &p, &ray); return actor ? actor : CLUTTER_ACTOR (stage); } @@ -1334,8 +1306,6 @@ clutter_stage_finalize (GObject *object) g_array_free (priv->paint_volume_stack, TRUE); - _clutter_stage_clear_pick_stack (stage); - if (priv->fps_timer != NULL) g_timer_destroy (priv->fps_timer); @@ -1653,8 +1623,6 @@ clutter_stage_init (ClutterStage *self) priv->paint_volume_stack = g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume)); - - priv->cached_pick_mode = CLUTTER_PICK_NONE; } static void @@ -2727,12 +2695,6 @@ clutter_stage_queue_actor_redraw (ClutterStage *stage, CLUTTER_NOTE (CLIPPING, "stage_queue_actor_redraw (actor=%s, clip=%p): ", _clutter_actor_get_debug_name (actor), clip); - /* Queuing a redraw or clip change invalidates the pick cache, unless we're - * in the middle of building it. So we reset the cached flag but don't - * completely clear the pick stack... - */ - priv->cached_pick_mode = CLUTTER_PICK_NONE; - if (!priv->pending_finish_queue_redraws) { GList *l; -- GitLab From c3534d339008f65ba35ded2686ffa94e2bf23ffc Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 22 Oct 2020 21:10:33 -0300 Subject: [PATCH 3/5] clutter/pick-context: Store point and ray on construction It'll be used to do a quick box test to cull out while picking. Part-of: --- clutter/clutter/clutter-pick-context-private.h | 7 +++++-- clutter/clutter/clutter-pick-context.c | 11 +++++++++-- clutter/clutter/clutter-stage.c | 6 +++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/clutter/clutter/clutter-pick-context-private.h b/clutter/clutter/clutter-pick-context-private.h index cfbfce6eb49..cc8baf88144 100644 --- a/clutter/clutter/clutter-pick-context-private.h +++ b/clutter/clutter/clutter-pick-context-private.h @@ -21,8 +21,11 @@ #include "clutter-pick-context.h" #include "clutter-pick-stack-private.h" -ClutterPickContext * clutter_pick_context_new_for_view (ClutterStageView *view, - ClutterPickMode mode); +ClutterPickContext * +clutter_pick_context_new_for_view (ClutterStageView *view, + ClutterPickMode mode, + const graphene_point3d_t *point, + const graphene_ray_t *ray); ClutterPickStack * clutter_pick_context_steal_stack (ClutterPickContext *pick_context); diff --git a/clutter/clutter/clutter-pick-context.c b/clutter/clutter/clutter-pick-context.c index 4e6fb7a8821..b9758366d41 100644 --- a/clutter/clutter/clutter-pick-context.c +++ b/clutter/clutter/clutter-pick-context.c @@ -26,6 +26,9 @@ struct _ClutterPickContext ClutterPickMode mode; ClutterPickStack *pick_stack; + + graphene_ray_t ray; + graphene_point3d_t point; }; G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context, @@ -33,8 +36,10 @@ G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context, clutter_pick_context_unref) ClutterPickContext * -clutter_pick_context_new_for_view (ClutterStageView *view, - ClutterPickMode mode) +clutter_pick_context_new_for_view (ClutterStageView *view, + ClutterPickMode mode, + const graphene_point3d_t *point, + const graphene_ray_t *ray) { ClutterPickContext *pick_context; CoglContext *context; @@ -42,6 +47,8 @@ clutter_pick_context_new_for_view (ClutterStageView *view, pick_context = g_new0 (ClutterPickContext, 1); g_ref_count_init (&pick_context->ref_count); pick_context->mode = mode; + graphene_ray_init_from_ray (&pick_context->ray, ray); + graphene_point3d_init_from_point (&pick_context->point, point); context = clutter_backend_get_cogl_context (clutter_get_default_backend ()); pick_context->pick_stack = clutter_pick_stack_new (context); diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 3d2edf95eeb..f520e3b23a6 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -1088,14 +1088,14 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage, COGL_TRACE_BEGIN_SCOPED (ClutterStagePickView, "Pick (view)"); - pick_context = clutter_pick_context_new_for_view (view, mode); + setup_ray_for_coordinates (stage, x, y, &p, &ray); + + pick_context = clutter_pick_context_new_for_view (view, mode, &p, &ray); clutter_actor_pick (CLUTTER_ACTOR (stage), pick_context); pick_stack = clutter_pick_context_steal_stack (pick_context); clutter_pick_context_destroy (pick_context); - setup_ray_for_coordinates (stage, x, y, &p, &ray); - actor = clutter_pick_stack_search_actor (pick_stack, &p, &ray); return actor ? actor : CLUTTER_ACTOR (stage); } -- GitLab From 1fdde25b3e385602f1843b0eb068859164d7d350 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 22 Oct 2020 21:11:48 -0300 Subject: [PATCH 4/5] clutter/paint-volume: Add new API to convert to graphene_box_t Will be used to cull when picking based on the actor's projected paint volume. Part-of: --- .../clutter/clutter-paint-volume-private.h | 3 +++ clutter/clutter/clutter-paint-volume.c | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/clutter/clutter/clutter-paint-volume-private.h b/clutter/clutter/clutter-paint-volume-private.h index 5d51e5bf31b..0a52b60c4be 100644 --- a/clutter/clutter/clutter-paint-volume-private.h +++ b/clutter/clutter/clutter-paint-volume-private.h @@ -133,6 +133,9 @@ void _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolu void _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv, ClutterActor *relative_to_ancestor); +void clutter_paint_volume_to_box (ClutterPaintVolume *pv, + graphene_box_t *box); + G_END_DECLS #endif /* __CLUTTER_PAINT_VOLUME_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-paint-volume.c b/clutter/clutter/clutter-paint-volume.c index 97077f7d1d2..a55c5a8e4e4 100644 --- a/clutter/clutter/clutter-paint-volume.c +++ b/clutter/clutter/clutter-paint-volume.c @@ -1131,3 +1131,25 @@ _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv, _clutter_paint_volume_transform (pv, &matrix); } + +void +clutter_paint_volume_to_box (ClutterPaintVolume *pv, + graphene_box_t *box) +{ + int vertex_count; + + if (pv->is_empty) + { + graphene_box_init_from_box (box, graphene_box_empty ()); + return; + } + + _clutter_paint_volume_complete (pv); + + if (G_LIKELY (pv->is_2d)) + vertex_count = 4; + else + vertex_count = 8; + + graphene_box_init_from_points (box, vertex_count, pv->vertices); +} -- GitLab From 6c4b897d74522b4a45689c5529e7afdbab3e2509 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 22 Oct 2020 21:12:10 -0300 Subject: [PATCH 5/5] clutter/actor: Cull out when picking Testing points and rays against boxes is substantially cheaper - in fact, almost trivial - compared to triangles. Check if the actor's paint volume doesn't intersect with the current pick point / ray, and skip recursing altogether in those cases. Part-of: --- clutter/clutter/clutter-actor.c | 11 +++++++++++ clutter/clutter/clutter-pick-context-private.h | 4 ++++ clutter/clutter/clutter-pick-context.c | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 20070df4e4f..0d5eae78248 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -635,6 +635,7 @@ #include "clutter-paint-nodes.h" #include "clutter-paint-node-private.h" #include "clutter-paint-volume-private.h" +#include "clutter-pick-context-private.h" #include "clutter-private.h" #include "clutter-property-transition.h" #include "clutter-scriptable.h" @@ -3959,6 +3960,15 @@ clutter_actor_pick (ClutterActor *actor, /* mark that we are in the paint process */ CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK); + if (priv->paint_volume_valid && priv->last_paint_volume_valid) + { + graphene_box_t box; + + clutter_paint_volume_to_box (&priv->last_paint_volume, &box); + if (!clutter_pick_context_intersects_box (pick_context, &box)) + goto out; + } + if (priv->enable_model_view_transform) { graphene_matrix_t matrix; @@ -4007,6 +4017,7 @@ clutter_actor_pick (ClutterActor *actor, if (transform_pushed) clutter_pick_context_pop_transform (pick_context); +out: /* paint sequence complete */ CLUTTER_UNSET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK); } diff --git a/clutter/clutter/clutter-pick-context-private.h b/clutter/clutter/clutter-pick-context-private.h index cc8baf88144..f40de6f3dfe 100644 --- a/clutter/clutter/clutter-pick-context-private.h +++ b/clutter/clutter/clutter-pick-context-private.h @@ -30,4 +30,8 @@ clutter_pick_context_new_for_view (ClutterStageView *view, ClutterPickStack * clutter_pick_context_steal_stack (ClutterPickContext *pick_context); +gboolean +clutter_pick_context_intersects_box (ClutterPickContext *pick_context, + const graphene_box_t *box); + #endif /* CLUTTER_PICK_CONTEXT_PRIVATE_H */ diff --git a/clutter/clutter/clutter-pick-context.c b/clutter/clutter/clutter-pick-context.c index b9758366d41..2f054d318fc 100644 --- a/clutter/clutter/clutter-pick-context.c +++ b/clutter/clutter/clutter-pick-context.c @@ -189,3 +189,11 @@ clutter_pick_context_pop_transform (ClutterPickContext *pick_context) { clutter_pick_stack_pop_transform (pick_context->pick_stack); } + +gboolean +clutter_pick_context_intersects_box (ClutterPickContext *pick_context, + const graphene_box_t *box) +{ + return graphene_box_contains_point (box, &pick_context->point) || + graphene_ray_intersects_box (&pick_context->ray, box); +} -- GitLab