[mutter/gbsneto/split-pick-paint: 1/4] clutter: Split pick and paint
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/gbsneto/split-pick-paint: 1/4] clutter: Split pick and paint
- Date: Fri, 18 Oct 2019 12:31:33 +0000 (UTC)
commit 9d668628cb553a977af89d6ee127b53db20f1e9d
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Oct 17 17:01:25 2019 +0200
clutter: Split pick and paint
Add the corresponding clutter_actor_pick() and
clutter_actor_continue_pick() as public APIs,
and use them in pick overrides and ClutterEffect.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/865
clutter/clutter/clutter-actor.c | 187 +++++++++++++++++++++++++++++++++++-
clutter/clutter/clutter-actor.h | 4 +
clutter/clutter/clutter-effect.c | 2 +-
clutter/clutter/clutter-private.h | 4 +-
src/compositor/meta-surface-actor.c | 2 +-
5 files changed, 195 insertions(+), 4 deletions(-)
---
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index 62a28e945..5f7a0e99c 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -2373,7 +2373,7 @@ clutter_actor_real_pick (ClutterActor *self)
for (iter = self->priv->first_child;
iter != NULL;
iter = iter->priv->next_sibling)
- clutter_actor_paint (iter);
+ clutter_actor_pick (iter);
}
}
@@ -4215,6 +4215,191 @@ clutter_actor_continue_paint (ClutterActor *self)
}
}
+/**
+ * clutter_actor_pick:
+ * @actor: A #ClutterActor
+ *
+ * Asks @actor to perform a pick.
+ */
+void
+clutter_actor_pick (ClutterActor *actor)
+{
+ ClutterCullResult result = CLUTTER_CULL_RESULT_IN;
+ ClutterActorPrivate *priv;
+ gboolean success;
+ ClutterActorBox clip;
+ gboolean clip_set = FALSE;
+
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
+ return;
+
+ priv = actor->priv;
+
+ /* if we aren't paintable (not in a toplevel with all
+ * parents paintable) then do nothing.
+ */
+ if (!CLUTTER_ACTOR_IS_MAPPED (actor))
+ return;
+
+ clutter_actor_ensure_resource_scale (actor);
+
+ /* mark that we are in the paint process */
+ CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK);
+
+ cogl_push_matrix ();
+
+ if (priv->enable_model_view_transform)
+ {
+ CoglMatrix matrix;
+
+ cogl_get_modelview_matrix (&matrix);
+ _clutter_actor_apply_modelview_transform (actor, &matrix);
+ cogl_set_modelview_matrix (&matrix);
+ }
+
+ if (priv->has_clip)
+ {
+ clip.x1 = priv->clip.origin.x;
+ clip.y1 = priv->clip.origin.y;
+ clip.x2 = priv->clip.origin.x + priv->clip.size.width;
+ clip.y2 = priv->clip.origin.y + priv->clip.size.height;
+ clip_set = TRUE;
+ }
+ else if (priv->clip_to_allocation)
+ {
+ clip.x1 = 0.f;
+ clip.y1 = 0.f;
+ clip.x2 = priv->allocation.x2 - priv->allocation.x1;
+ clip.y2 = priv->allocation.y2 - priv->allocation.y1;
+ clip_set = TRUE;
+ }
+
+ if (clip_set)
+ clip_set = _clutter_actor_push_pick_clip (actor, &clip);
+
+ /* We save the current paint volume so that the next time the
+ * actor queues a redraw we can constrain the redraw to just
+ * cover the union of the new bounding box and the old.
+ *
+ * We also fetch the current paint volume to perform culling so
+ * we can avoid painting actors outside the current clip region.
+ *
+ * If we are painting inside a clone, we should neither update
+ * the paint volume or use it to cull painting, since the paint
+ * box represents the location of the source actor on the
+ * screen.
+ *
+ * XXX: We are starting to do a lot of vertex transforms on
+ * the CPU in a typical paint, so at some point we should
+ * audit these and consider caching some things.
+ *
+ * NB: We don't perform culling while picking at this point because
+ * clutter-stage.c doesn't setup the clipping planes appropriately.
+ *
+ * NB: We don't want to update the last-paint-volume during picking
+ * because the last-paint-volume is used to determine the old screen
+ * space location of an actor that has moved so we can know the
+ * minimal region to redraw to clear an old view of the actor. If we
+ * update this during picking then by the time we come around to
+ * paint then the last-paint-volume would likely represent the new
+ * actor position not the old.
+ */
+ if (G_LIKELY ((clutter_paint_debug_flags &
+ (CLUTTER_DEBUG_DISABLE_CULLING |
+ CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)) !=
+ (CLUTTER_DEBUG_DISABLE_CULLING |
+ CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
+ _clutter_actor_update_last_paint_volume (actor);
+
+ success = cull_actor (actor, &result);
+
+ if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS))
+ _clutter_actor_paint_cull_result (actor, success, result);
+ else if (result == CLUTTER_CULL_RESULT_OUT && success)
+ goto done;
+
+ if (priv->effects == NULL)
+ priv->next_effect_to_paint = NULL;
+ else
+ priv->next_effect_to_paint =
+ _clutter_meta_group_peek_metas (priv->effects);
+
+ clutter_actor_continue_pick (actor);
+
+done:
+ if (clip_set)
+ _clutter_actor_pop_pick_clip (actor);
+
+ cogl_pop_matrix ();
+
+ /* paint sequence complete */
+ CLUTTER_UNSET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK);
+}
+
+/**
+ * clutter_actor_continue_pick:
+ * @actor: A #ClutterActor
+ *
+ * Run the next stage of the pick sequence. This function should only
+ * be called within the implementation of the ‘pick’ virtual of a
+ * #ClutterEffect. It will cause the run method of the next effect to
+ * be applied, or it will pick the actual actor if the current effect
+ * is the last effect in the chain.
+ *
+ * Since: 1.8
+ */
+void
+clutter_actor_continue_pick (ClutterActor *actor)
+{
+ ClutterActorPrivate *priv;
+
+ g_return_if_fail (CLUTTER_IS_ACTOR (actor));
+
+ g_return_if_fail (CLUTTER_ACTOR_IN_PICK (actor));
+
+ priv = actor->priv;
+
+ /* Skip any effects that are disabled */
+ while (priv->next_effect_to_paint &&
+ !clutter_actor_meta_get_enabled (priv->next_effect_to_paint->data))
+ priv->next_effect_to_paint = priv->next_effect_to_paint->next;
+
+ /* If this has come from the last effect then we'll just paint the
+ actual actor */
+ if (priv->next_effect_to_paint == NULL)
+ {
+ /* The actor will log a silhouette of itself to the stage pick log.
+ *
+ * XXX:2.0 - Call the pick() virtual directly
+ */
+ if (g_signal_has_handler_pending (actor, actor_signals[PICK],
+ 0, TRUE))
+ g_signal_emit (actor, actor_signals[PICK], 0);
+ else
+ CLUTTER_ACTOR_GET_CLASS (actor)->pick (actor);
+ }
+ else
+ {
+ ClutterEffect *old_current_effect;
+ ClutterEffectPaintFlags run_flags = 0;
+
+ /* Cache the current effect so that we can put it back before
+ returning */
+ old_current_effect = priv->current_effect;
+
+ priv->current_effect = priv->next_effect_to_paint->data;
+ priv->next_effect_to_paint = priv->next_effect_to_paint->next;
+
+ /* We can't determine when an actor has been modified since
+ its last pick so lets just assume it has always been
+ modified */
+ run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY;
+ _clutter_effect_pick (priv->current_effect, run_flags);
+
+ priv->current_effect = old_current_effect;
+ }
+}
+
static void
_clutter_actor_stop_transitions (ClutterActor *self)
{
diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h
index d7382c776..efe919ec8 100644
--- a/clutter/clutter/clutter-actor.h
+++ b/clutter/clutter/clutter-actor.h
@@ -353,6 +353,10 @@ void clutter_actor_paint
CLUTTER_EXPORT
void clutter_actor_continue_paint (ClutterActor
*self);
CLUTTER_EXPORT
+void clutter_actor_pick (ClutterActor
*actor);
+CLUTTER_EXPORT
+void clutter_actor_continue_pick (ClutterActor
*actor);
+CLUTTER_EXPORT
void clutter_actor_queue_redraw (ClutterActor
*self);
CLUTTER_EXPORT
void clutter_actor_queue_redraw_with_clip (ClutterActor
*self,
diff --git a/clutter/clutter/clutter-effect.c b/clutter/clutter/clutter-effect.c
index 47c11a53a..5a4c7aa87 100644
--- a/clutter/clutter/clutter-effect.c
+++ b/clutter/clutter/clutter-effect.c
@@ -223,7 +223,7 @@ clutter_effect_real_pick (ClutterEffect *effect,
ClutterActor *actor;
actor = clutter_actor_meta_get_actor (actor_meta);
- clutter_actor_continue_paint (actor);
+ clutter_actor_continue_pick (actor);
}
static void
diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h
index 28c56c0d0..94575f06b 100644
--- a/clutter/clutter/clutter-private.h
+++ b/clutter/clutter/clutter-private.h
@@ -67,6 +67,7 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) !=
FALSE)
#define CLUTTER_ACTOR_IN_REPARENT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_REPARENT) != FALSE)
#define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE)
+#define CLUTTER_ACTOR_IN_PICK(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PICK) != FALSE)
#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_WIDTH(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_WIDTH) !=
FALSE)
#define CLUTTER_ACTOR_IN_PREF_HEIGHT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_HEIGHT) !=
FALSE)
@@ -104,9 +105,10 @@ typedef enum
/* Used to avoid recursion */
CLUTTER_IN_PAINT = 1 << 5,
+ CLUTTER_IN_PICK = 1 << 6,
/* Used to avoid recursion */
- CLUTTER_IN_RELAYOUT = 1 << 6,
+ CLUTTER_IN_RELAYOUT = 1 << 7,
} ClutterPrivateFlags;
/*
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 19e775dc9..5046a70fa 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -168,7 +168,7 @@ meta_surface_actor_pick (ClutterActor *actor)
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
- clutter_actor_paint (child);
+ clutter_actor_pick (child);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]