[mutter/wip/carlosg/clip-me-harder: 548/548] compositor: Cache culling info across repaints



commit 19d4ea14f1dd45600d62d31508152b45a4ccdb8f
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri May 10 12:39:27 2019 +0200

    compositor: Cache culling info across repaints
    
    Add an explicit call to have the topmost MetaCullable invalidate
    the culling information. And have MetaWindowGroup (the topmost
    MetaCullable) be more selective about creating and throwing away
    the information, instead of doing it at every repaint.
    
    The cullable info is invalidated whenever 1) Anything triggers
    ::queue-relayout on a child, 2) window opacity changes.
    
    The obvious benefit of this is avoiding 2 recursive operations
    surrounding the already recursive paint(), as window repositions
    and opacity changes are a lot less frequent.

 src/compositor/meta-cullable.c     | 22 +++++++++++++++
 src/compositor/meta-cullable.h     |  2 ++
 src/compositor/meta-window-actor.c |  9 +++++++
 src/compositor/meta-window-group.c | 55 +++++++++++++++++++++++++-------------
 4 files changed, 69 insertions(+), 19 deletions(-)
---
diff --git a/src/compositor/meta-cullable.c b/src/compositor/meta-cullable.c
index 5cdc03a6d..a57481d04 100644
--- a/src/compositor/meta-cullable.c
+++ b/src/compositor/meta-cullable.c
@@ -200,3 +200,25 @@ meta_cullable_reset_culling (MetaCullable *cullable)
 {
   META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable);
 }
+
+/**
+ * meta_cullable_invalidate:
+ * @cullable: The #MetaCullable
+ *
+ * Invalidates the culling information.
+ **/
+void
+meta_cullable_invalidate (MetaCullable *cullable)
+{
+  ClutterActor *actor = CLUTTER_ACTOR (cullable);
+  MetaCullable *topmost_cullable = NULL;
+
+  while (actor && META_IS_CULLABLE (actor))
+    {
+      topmost_cullable = META_CULLABLE (actor);
+      actor = clutter_actor_get_parent (actor);
+    }
+
+  if (topmost_cullable)
+    meta_cullable_reset_culling (topmost_cullable);
+}
diff --git a/src/compositor/meta-cullable.h b/src/compositor/meta-cullable.h
index fc1720c8d..f37362da4 100644
--- a/src/compositor/meta-cullable.h
+++ b/src/compositor/meta-cullable.h
@@ -53,6 +53,8 @@ void meta_cullable_cull_out_children (MetaCullable   *cullable,
                                       cairo_region_t *clip_region);
 void meta_cullable_reset_culling_children (MetaCullable *cullable);
 
+void meta_cullable_invalidate (MetaCullable *cullable);
+
 G_END_DECLS
 
 #endif /* __META_CULLABLE_H__ */
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 9b5bad188..62daf49e0 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -168,6 +168,13 @@ meta_window_actor_real_set_surface_actor (MetaWindowActor  *actor,
   set_surface (actor, surface);
 }
 
+static void
+meta_window_actor_queue_relayout (ClutterActor *actor)
+{
+  meta_cullable_invalidate (META_CULLABLE (actor));
+  CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->queue_relayout (actor);
+}
+
 static void
 meta_window_actor_class_init (MetaWindowActorClass *klass)
 {
@@ -182,6 +189,7 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
 
   actor_class->paint = meta_window_actor_paint;
   actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
+  actor_class->queue_relayout = meta_window_actor_queue_relayout;
 
   klass->set_surface_actor = meta_window_actor_real_set_surface_actor;
 
@@ -1687,6 +1695,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
 
   meta_surface_actor_set_opaque_region (priv->surface, opaque_region);
   cairo_region_destroy (opaque_region);
+  meta_cullable_invalidate (META_CULLABLE (self));
 }
 
 static void
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index 29ec1e742..ee6680a5e 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -23,6 +23,7 @@ struct _MetaWindowGroup
   ClutterActor parent;
 
   MetaDisplay *display;
+  guint need_culling : 1;
 };
 
 static void cullable_iface_init (MetaCullableInterface *iface);
@@ -41,7 +42,10 @@ meta_window_group_cull_out (MetaCullable   *cullable,
 static void
 meta_window_group_reset_culling (MetaCullable *cullable)
 {
+  MetaWindowGroup *window_group = META_WINDOW_GROUP (cullable);
+
   meta_cullable_reset_culling_children (cullable);
+  window_group->need_culling = TRUE;
 }
 
 static void
@@ -100,33 +104,35 @@ meta_window_group_paint (ClutterActor *actor)
       paint_y_origin = 0;
     }
 
-  visible_rect.x = visible_rect.y = 0;
-  visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
-  visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
+  if (window_group->need_culling)
+    {
+      visible_rect.x = visible_rect.y = 0;
+      visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
+      visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
 
-  unobscured_region = cairo_region_create_rectangle (&visible_rect);
+      unobscured_region = cairo_region_create_rectangle (&visible_rect);
 
-  /* Get the clipped redraw bounds from Clutter so that we can avoid
-   * painting shadows on windows that don't need to be painted in this
-   * frame. In the case of a multihead setup with mismatched monitor
-   * sizes, we could intersect this with an accurate union of the
-   * monitors to avoid painting shadows that are visible only in the
-   * holes. */
-  clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage),
-                                        &clip_rect);
+      /* Get the clipped redraw bounds from Clutter so that we can avoid
+       * painting shadows on windows that don't need to be painted in this
+       * frame. In the case of a multihead setup with mismatched monitor
+       * sizes, we could intersect this with an accurate union of the
+       * monitors to avoid painting shadows that are visible only in the
+       * holes. */
+      clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage),
+                                            &clip_rect);
 
-  clip_region = cairo_region_create_rectangle (&clip_rect);
+      clip_region = cairo_region_create_rectangle (&clip_rect);
 
-  cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin);
+      cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin);
 
-  meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
+      meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
 
-  cairo_region_destroy (unobscured_region);
-  cairo_region_destroy (clip_region);
+      cairo_region_destroy (unobscured_region);
+      cairo_region_destroy (clip_region);
+      window_group->need_culling = FALSE;
+    }
 
   CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
-
-  meta_cullable_reset_culling (META_CULLABLE (window_group));
 }
 
 /* Adapted from clutter_actor_update_default_paint_volume() */
@@ -185,6 +191,15 @@ meta_window_group_get_preferred_height (ClutterActor *actor,
   *nat_height = 0;
 }
 
+static void
+meta_window_group_queue_relayout (ClutterActor *actor)
+{
+  MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
+
+  meta_cullable_reset_culling (META_CULLABLE (window_group));
+  CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->queue_relayout (actor);
+}
+
 static void
 meta_window_group_class_init (MetaWindowGroupClass *klass)
 {
@@ -194,11 +209,13 @@ meta_window_group_class_init (MetaWindowGroupClass *klass)
   actor_class->get_paint_volume = meta_window_group_get_paint_volume;
   actor_class->get_preferred_width = meta_window_group_get_preferred_width;
   actor_class->get_preferred_height = meta_window_group_get_preferred_height;
+  actor_class->queue_relayout = meta_window_group_queue_relayout;
 }
 
 static void
 meta_window_group_init (MetaWindowGroup *window_group)
 {
+  window_group->need_culling = TRUE;
 }
 
 ClutterActor *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]