mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
clutter/actor: Add API to get the stage-views an actor is painted on
There are certain rendering techniques and optimizations, for example the unredirection of non-fullscreen windows, where information about the output/stage-view an actor is on is needed to determine whether the optimization can be enabled. So add a new method to ClutterActor that allows listing the stage-views the actor is being painted on: clutter_actor_peek_stage_views() With the way Clutter works, the only point where we can reliably get this information is during or right before the paint phase, when the layout phase of the stage has been completed and no more changes to the actors transformation matrices happen. So to get the stage views the actor is on, introduce a new step that's done on every master clock tick between layout and paint cycle: Traversing through the actor tree and updating the stage-views the mapped actors are going to be painted on. We're doing this in a separate step instead of inside clutter_actor_paint() itself for a few reasons: It keeps the code separate from the painting code, making profiling easier and issues easier to track down (hopefully), it allows for a new "stage-views-changed" signal that doesn't interfere with painting, and finally, it will make it very easy to update the resource scales in the same step in the future. Currently, this list is only invalidated on allocation changes of actors, but not on changes to the transformation matrices. That's because there's no proper API to invalidate the transformation matrices ClutterActor implementations can apply through the apply_transform() vfunc. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
This commit is contained in:
parent
8127494e52
commit
675a97d58e
@ -321,6 +321,8 @@ gboolean _clutter_actor_get_real_resource_scale
|
|||||||
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
|
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
|
||||||
CoglTexture *texture);
|
CoglTexture *texture);
|
||||||
|
|
||||||
|
void clutter_actor_update_stage_views (ClutterActor *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
|
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
|
||||||
|
@ -813,6 +813,8 @@ struct _ClutterActorPrivate
|
|||||||
gulong font_changed_id;
|
gulong font_changed_id;
|
||||||
gulong layout_changed_id;
|
gulong layout_changed_id;
|
||||||
|
|
||||||
|
GList *stage_views;
|
||||||
|
|
||||||
/* bitfields: KEEP AT THE END */
|
/* bitfields: KEEP AT THE END */
|
||||||
|
|
||||||
/* fixed position and sizes */
|
/* fixed position and sizes */
|
||||||
@ -855,6 +857,7 @@ struct _ClutterActorPrivate
|
|||||||
guint had_effects_on_last_paint_volume_update : 1;
|
guint had_effects_on_last_paint_volume_update : 1;
|
||||||
guint needs_compute_resource_scale : 1;
|
guint needs_compute_resource_scale : 1;
|
||||||
guint absolute_origin_changed : 1;
|
guint absolute_origin_changed : 1;
|
||||||
|
guint needs_update_stage_views : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -2565,6 +2568,7 @@ static void
|
|||||||
absolute_allocation_changed (ClutterActor *actor)
|
absolute_allocation_changed (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
actor->priv->needs_compute_resource_scale = TRUE;
|
actor->priv->needs_compute_resource_scale = TRUE;
|
||||||
|
actor->priv->needs_update_stage_views = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterActorTraverseVisitFlags
|
static ClutterActorTraverseVisitFlags
|
||||||
@ -4282,6 +4286,7 @@ typedef enum
|
|||||||
REMOVE_CHILD_FLUSH_QUEUE = 1 << 4,
|
REMOVE_CHILD_FLUSH_QUEUE = 1 << 4,
|
||||||
REMOVE_CHILD_NOTIFY_FIRST_LAST = 1 << 5,
|
REMOVE_CHILD_NOTIFY_FIRST_LAST = 1 << 5,
|
||||||
REMOVE_CHILD_STOP_TRANSITIONS = 1 << 6,
|
REMOVE_CHILD_STOP_TRANSITIONS = 1 << 6,
|
||||||
|
REMOVE_CHILD_CLEAR_STAGE_VIEWS = 1 << 7,
|
||||||
|
|
||||||
/* default flags for public API */
|
/* default flags for public API */
|
||||||
REMOVE_CHILD_DEFAULT_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS |
|
REMOVE_CHILD_DEFAULT_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS |
|
||||||
@ -4290,14 +4295,16 @@ typedef enum
|
|||||||
REMOVE_CHILD_EMIT_ACTOR_REMOVED |
|
REMOVE_CHILD_EMIT_ACTOR_REMOVED |
|
||||||
REMOVE_CHILD_CHECK_STATE |
|
REMOVE_CHILD_CHECK_STATE |
|
||||||
REMOVE_CHILD_FLUSH_QUEUE |
|
REMOVE_CHILD_FLUSH_QUEUE |
|
||||||
REMOVE_CHILD_NOTIFY_FIRST_LAST,
|
REMOVE_CHILD_NOTIFY_FIRST_LAST |
|
||||||
|
REMOVE_CHILD_CLEAR_STAGE_VIEWS,
|
||||||
|
|
||||||
/* flags for legacy/deprecated API */
|
/* flags for legacy/deprecated API */
|
||||||
REMOVE_CHILD_LEGACY_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS |
|
REMOVE_CHILD_LEGACY_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS |
|
||||||
REMOVE_CHILD_CHECK_STATE |
|
REMOVE_CHILD_CHECK_STATE |
|
||||||
REMOVE_CHILD_FLUSH_QUEUE |
|
REMOVE_CHILD_FLUSH_QUEUE |
|
||||||
REMOVE_CHILD_EMIT_PARENT_SET |
|
REMOVE_CHILD_EMIT_PARENT_SET |
|
||||||
REMOVE_CHILD_NOTIFY_FIRST_LAST
|
REMOVE_CHILD_NOTIFY_FIRST_LAST |
|
||||||
|
REMOVE_CHILD_CLEAR_STAGE_VIEWS
|
||||||
} ClutterActorRemoveChildFlags;
|
} ClutterActorRemoveChildFlags;
|
||||||
|
|
||||||
/*< private >
|
/*< private >
|
||||||
@ -4319,6 +4326,7 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
|||||||
gboolean notify_first_last;
|
gboolean notify_first_last;
|
||||||
gboolean was_mapped;
|
gboolean was_mapped;
|
||||||
gboolean stop_transitions;
|
gboolean stop_transitions;
|
||||||
|
gboolean clear_stage_views;
|
||||||
GObject *obj;
|
GObject *obj;
|
||||||
|
|
||||||
if (self == child)
|
if (self == child)
|
||||||
@ -4335,6 +4343,7 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
|||||||
flush_queue = (flags & REMOVE_CHILD_FLUSH_QUEUE) != 0;
|
flush_queue = (flags & REMOVE_CHILD_FLUSH_QUEUE) != 0;
|
||||||
notify_first_last = (flags & REMOVE_CHILD_NOTIFY_FIRST_LAST) != 0;
|
notify_first_last = (flags & REMOVE_CHILD_NOTIFY_FIRST_LAST) != 0;
|
||||||
stop_transitions = (flags & REMOVE_CHILD_STOP_TRANSITIONS) != 0;
|
stop_transitions = (flags & REMOVE_CHILD_STOP_TRANSITIONS) != 0;
|
||||||
|
clear_stage_views = (flags & REMOVE_CHILD_CLEAR_STAGE_VIEWS) != 0;
|
||||||
|
|
||||||
obj = G_OBJECT (self);
|
obj = G_OBJECT (self);
|
||||||
g_object_freeze_notify (obj);
|
g_object_freeze_notify (obj);
|
||||||
@ -4408,6 +4417,13 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
|||||||
clutter_actor_queue_compute_expand (self);
|
clutter_actor_queue_compute_expand (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only actors which are attached to a stage get notified about changes
|
||||||
|
* to the stage views, so make sure all the stage-views lists are
|
||||||
|
* cleared as the child and its children leave the actor tree.
|
||||||
|
*/
|
||||||
|
if (clear_stage_views)
|
||||||
|
clutter_actor_clear_stage_views_recursive (child);
|
||||||
|
|
||||||
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
|
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
|
||||||
{
|
{
|
||||||
child->priv->needs_compute_resource_scale = TRUE;
|
child->priv->needs_compute_resource_scale = TRUE;
|
||||||
@ -6080,6 +6096,8 @@ clutter_actor_dispose (GObject *object)
|
|||||||
priv->clones = NULL;
|
priv->clones = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->stage_views, g_list_free);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
|
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8634,6 +8652,7 @@ clutter_actor_init (ClutterActor *self)
|
|||||||
priv->needs_allocation = TRUE;
|
priv->needs_allocation = TRUE;
|
||||||
priv->needs_paint_volume_update = TRUE;
|
priv->needs_paint_volume_update = TRUE;
|
||||||
priv->needs_compute_resource_scale = TRUE;
|
priv->needs_compute_resource_scale = TRUE;
|
||||||
|
priv->needs_update_stage_views = TRUE;
|
||||||
|
|
||||||
priv->cached_width_age = 1;
|
priv->cached_width_age = 1;
|
||||||
priv->cached_height_age = 1;
|
priv->cached_height_age = 1;
|
||||||
@ -17521,7 +17540,11 @@ clear_stage_views_cb (ClutterActor *actor,
|
|||||||
int depth,
|
int depth,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
actor->priv->needs_update_stage_views = TRUE;
|
||||||
actor->priv->needs_compute_resource_scale = TRUE;
|
actor->priv->needs_compute_resource_scale = TRUE;
|
||||||
|
|
||||||
|
g_clear_pointer (&actor->priv->stage_views, g_list_free);
|
||||||
|
|
||||||
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
|
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17622,6 +17645,93 @@ clutter_actor_get_resource_scale (ClutterActor *self,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_stage_views (ClutterActor *self)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
ClutterStage *stage;
|
||||||
|
graphene_rect_t bounding_rect;
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->stage_views, g_list_free);
|
||||||
|
|
||||||
|
if (priv->needs_allocation)
|
||||||
|
{
|
||||||
|
g_warning ("Can't update stage views actor %s is on because it needs an "
|
||||||
|
"allocation.", _clutter_actor_get_debug_name (self));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
|
||||||
|
g_return_if_fail (stage);
|
||||||
|
|
||||||
|
clutter_actor_get_transformed_position (self,
|
||||||
|
&bounding_rect.origin.x,
|
||||||
|
&bounding_rect.origin.y);
|
||||||
|
clutter_actor_get_transformed_size (self,
|
||||||
|
&bounding_rect.size.width,
|
||||||
|
&bounding_rect.size.height);
|
||||||
|
|
||||||
|
if (bounding_rect.size.width == 0.0 ||
|
||||||
|
bounding_rect.size.height == 0.0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->stage_views = clutter_stage_get_views_for_rect (stage,
|
||||||
|
&bounding_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_actor_update_stage_views (ClutterActor *self)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
ClutterActor *child;
|
||||||
|
|
||||||
|
if (!CLUTTER_ACTOR_IS_MAPPED (self) ||
|
||||||
|
CLUTTER_ACTOR_IN_DESTRUCTION (self))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->needs_update_stage_views)
|
||||||
|
{
|
||||||
|
update_stage_views (self);
|
||||||
|
|
||||||
|
priv->needs_update_stage_views = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (child = priv->first_child; child; child = child->priv->next_sibling)
|
||||||
|
clutter_actor_update_stage_views (child);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_actor_peek_stage_views:
|
||||||
|
* @self: A #ClutterActor
|
||||||
|
*
|
||||||
|
* Retrieves the list of #ClutterStageView<!-- -->s the actor is being
|
||||||
|
* painted on.
|
||||||
|
*
|
||||||
|
* If this function is called during the paint cycle, the list is guaranteed
|
||||||
|
* to be up-to-date, if called outside the paint cycle, the list will
|
||||||
|
* contain the views the actor was painted on last.
|
||||||
|
*
|
||||||
|
* The list returned by this function is not updated when the actors
|
||||||
|
* visibility changes: If an actor gets hidden and is not being painted
|
||||||
|
* anymore, this function will return the list of views the actor was
|
||||||
|
* painted on last.
|
||||||
|
*
|
||||||
|
* If an actor is not attached to a stage (realized), this function will
|
||||||
|
* always return an empty list.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (element-type Clutter.StageView): The list of
|
||||||
|
* #ClutterStageView<!-- -->s the actor is being painted on. The list and
|
||||||
|
* its contents are owned by the #ClutterActor and the list may not be
|
||||||
|
* freed or modified.
|
||||||
|
*/
|
||||||
|
GList *
|
||||||
|
clutter_actor_peek_stage_views (ClutterActor *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||||
|
|
||||||
|
return self->priv->stage_views;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_has_overlaps:
|
* clutter_actor_has_overlaps:
|
||||||
* @self: A #ClutterActor
|
* @self: A #ClutterActor
|
||||||
|
@ -919,6 +919,9 @@ void clutter_actor_pick_box (ClutterActor *self,
|
|||||||
ClutterPickContext *pick_context,
|
ClutterPickContext *pick_context,
|
||||||
const ClutterActorBox *box);
|
const ClutterActorBox *box);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
GList * clutter_actor_peek_stage_views (ClutterActor *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_ACTOR_H__ */
|
#endif /* __CLUTTER_ACTOR_H__ */
|
||||||
|
@ -1469,6 +1469,14 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
|
|||||||
return updating;
|
return updating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_actor_stage_views (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
ClutterActor *actor = CLUTTER_ACTOR (stage);
|
||||||
|
|
||||||
|
clutter_actor_update_stage_views (actor);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _clutter_stage_do_update:
|
* _clutter_stage_do_update:
|
||||||
* @stage: A #ClutterStage
|
* @stage: A #ClutterStage
|
||||||
@ -1516,6 +1524,10 @@ _clutter_stage_do_update (ClutterStage *stage)
|
|||||||
if (stage_was_relayout)
|
if (stage_was_relayout)
|
||||||
pointers = _clutter_stage_check_updated_pointers (stage);
|
pointers = _clutter_stage_check_updated_pointers (stage);
|
||||||
|
|
||||||
|
COGL_TRACE_BEGIN (ClutterStageUpdateActorStageViews, "Actor stage-views");
|
||||||
|
update_actor_stage_views (stage);
|
||||||
|
COGL_TRACE_END (ClutterStageUpdateActorStageViews);
|
||||||
|
|
||||||
COGL_TRACE_BEGIN (ClutterStagePaint, "Paint");
|
COGL_TRACE_BEGIN (ClutterStagePaint, "Paint");
|
||||||
|
|
||||||
clutter_stage_maybe_finish_queue_redraws (stage);
|
clutter_stage_maybe_finish_queue_redraws (stage);
|
||||||
|
Loading…
Reference in New Issue
Block a user