From ec8138773a417976a260619099a1649306a0a495 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 28 Apr 2018 18:10:49 +0200 Subject: [PATCH 1/3] compositor: Do not optimize obscured areas away in paint volumes This optimization was presumably added before Clutter was able to invalidate selected regions of an actor. Paint volumes are supposed to be invariable as long as the actor conditions don't change. Stacking of other actors shouldn't affect the paint volume, so it's actually wrong to optimize those areas away here. --- src/compositor/meta-shaped-texture.c | 37 +--------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 0240c067ce3..6f4d3acbb62 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -694,46 +694,11 @@ effective_unobscured_region (MetaShapedTexture *self) return priv->unobscured_region; } -static gboolean -get_unobscured_bounds (MetaShapedTexture *self, - cairo_rectangle_int_t *unobscured_bounds) -{ - cairo_region_t *unobscured_region = effective_unobscured_region (self); - - if (unobscured_region) - { - cairo_region_get_extents (unobscured_region, unobscured_bounds); - return TRUE; - } - else - return FALSE; -} - static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *actor, ClutterPaintVolume *volume) { - MetaShapedTexture *self = META_SHAPED_TEXTURE (actor); - ClutterActorBox box; - cairo_rectangle_int_t unobscured_bounds; - - if (!clutter_actor_has_allocation (actor)) - return FALSE; - - clutter_actor_get_allocation_box (actor, &box); - - if (get_unobscured_bounds (self, &unobscured_bounds)) - { - box.x1 = MAX (unobscured_bounds.x, box.x1); - box.x2 = MIN (unobscured_bounds.x + unobscured_bounds.width, box.x2); - box.y1 = MAX (unobscured_bounds.y, box.y1); - box.y2 = MIN (unobscured_bounds.y + unobscured_bounds.height, box.y2); - } - box.x2 = MAX (box.x2, box.x1); - box.y2 = MAX (box.y2, box.y1); - - clutter_paint_volume_union_box (volume, &box); - return TRUE; + return clutter_paint_volume_set_from_allocation (volume, actor); } void -- GitLab From 94f400988220eae76a1fb30390a62104da8f7b8f Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 28 Apr 2018 18:14:34 +0200 Subject: [PATCH 2/3] compositor: Add get_paint_volume() implementation to MetaSurfaceActor The special ::pick implementation there makes clutter fall into paths that do require a get_paint_volume() implementation, or an infinite area will be used. Providing a paint volume here is easier on the invalidation mechanism. --- src/compositor/meta-surface-actor.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index bf8c76f39b6..9acfab1f084 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -101,6 +101,13 @@ meta_surface_actor_pick (ClutterActor *actor, clutter_actor_paint (child); } +static gboolean +meta_surface_actor_get_paint_volume (ClutterActor *actor, + ClutterPaintVolume *volume) +{ + return clutter_paint_volume_set_from_allocation (volume, actor); +} + static void meta_surface_actor_dispose (GObject *object) { @@ -120,6 +127,7 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass) object_class->dispose = meta_surface_actor_dispose; actor_class->pick = meta_surface_actor_pick; + actor_class->get_paint_volume = meta_surface_actor_get_paint_volume; signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled", G_TYPE_FROM_CLASS (object_class), -- GitLab From 161d2540e659fa8ed5efc74f350a741b2430417d Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 29 Apr 2017 13:43:33 +0200 Subject: [PATCH 3/3] ClutterActor: Preserve valid paint volumes till the next relayout/repaint Cuts down approximately all paint volume calculations when there's windows that redraw frequently, but don't move. https://bugzilla.gnome.org/show_bug.cgi?id=782344 --- clutter/clutter/clutter-actor.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 3e00a11db3c..2ba61ba9e24 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -840,6 +840,7 @@ struct _ClutterActorPrivate guint needs_compute_expand : 1; guint needs_x_expand : 1; guint needs_y_expand : 1; + guint needs_paint_volume_update : 1; }; enum @@ -1504,6 +1505,8 @@ clutter_actor_real_map (ClutterActor *self) CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED); + self->priv->needs_paint_volume_update = TRUE; + stage = _clutter_actor_get_stage_internal (self); priv->pick_id = _clutter_stage_acquire_pick_id (CLUTTER_STAGE (stage), self); @@ -2737,6 +2740,7 @@ clutter_actor_real_queue_relayout (ClutterActor *self) priv->needs_width_request = TRUE; priv->needs_height_request = TRUE; priv->needs_allocation = TRUE; + priv->needs_paint_volume_update = TRUE; /* reset the cached size requests */ memset (priv->width_requests, 0, @@ -8518,6 +8522,7 @@ clutter_actor_init (ClutterActor *self) priv->needs_width_request = TRUE; priv->needs_height_request = TRUE; priv->needs_allocation = TRUE; + priv->needs_paint_volume_update = TRUE; priv->cached_width_age = 1; priv->cached_height_age = 1; @@ -10084,6 +10089,9 @@ clutter_actor_allocate (ClutterActor *self, return; } + if (CLUTTER_ACTOR_IS_MAPPED (self)) + self->priv->needs_paint_volume_update = TRUE; + if (!stage_allocation_changed) { /* If the actor didn't move but needs_allocation is set, we just @@ -12972,6 +12980,9 @@ clutter_actor_add_child_internal (ClutterActor *self, child->priv->needs_height_request = TRUE; child->priv->needs_allocation = TRUE; + if (CLUTTER_ACTOR_IS_MAPPED (child)) + child->priv->needs_paint_volume_update = TRUE; + /* we only queue a relayout here, because any possible * redraw has already been queued either by show() or * by our call to queue_redraw() above @@ -17514,11 +17525,16 @@ _clutter_actor_get_paint_volume_mutable (ClutterActor *self) priv = self->priv; if (priv->paint_volume_valid) - clutter_paint_volume_free (&priv->paint_volume); + { + if (!priv->needs_paint_volume_update) + return &priv->paint_volume; + clutter_paint_volume_free (&priv->paint_volume); + } if (_clutter_actor_get_paint_volume_real (self, &priv->paint_volume)) { priv->paint_volume_valid = TRUE; + priv->needs_paint_volume_update = FALSE; return &priv->paint_volume; } else -- GitLab