[mutter/wip/culling: 3/8] cullable: Turn cull_out / reset_culling into a separate interface
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/culling: 3/8] cullable: Turn cull_out / reset_culling into a separate interface
- Date: Fri, 22 Nov 2013 20:32:30 +0000 (UTC)
commit f8ad133c4986ef9ac2ca23925d435640c19ebc72
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Thu Nov 21 15:25:08 2013 -0500
cullable: Turn cull_out / reset_culling into a separate interface
Instead of hardcoded knowledge of certain classes in MetaWindowGroup,
create a generic interface that all actors can implement to get parts
of their regions culled out during redraw, without needing any special
knowledge of how to handle a specific actor.
https://bugzilla.gnome.org/show_bug.cgi?id=714706
doc/reference/meta-sections.txt | 17 ++
src/Makefile.am | 3 +-
src/compositor/meta-background-actor-private.h | 3 -
src/compositor/meta-background-actor.c | 59 +++++---
src/compositor/meta-background-group-private.h | 11 --
src/compositor/meta-background-group.c | 59 +++-----
src/compositor/meta-cullable.c | 191 ++++++++++++++++++++++++
src/compositor/meta-cullable.h | 68 +++++++++
src/compositor/meta-window-actor-private.h | 5 -
src/compositor/meta-window-actor.c | 35 +++--
src/compositor/meta-window-group.c | 68 +++------
src/compositor/meta-window-group.h | 26 +---
12 files changed, 379 insertions(+), 166 deletions(-)
---
diff --git a/doc/reference/meta-sections.txt b/doc/reference/meta-sections.txt
index 90f8152..7aa8931 100644
--- a/doc/reference/meta-sections.txt
+++ b/doc/reference/meta-sections.txt
@@ -389,6 +389,23 @@ meta_window_actor_get_type
</SECTION>
<SECTION>
+<FILE>meta-cullable</FILE>
+<TITLE>MetaCullable</TITLE>
+MetaCullable
+MetaCullableInterface
+meta_cullable_cull_out
+meta_cullable_reset_culling
+meta_cullable_cull_out_children
+meta_cullable_reset_culling_children
+<SUBSECTION Standard>
+META_TYPE_CULLABLE
+META_CULLABLE
+META_IS_CULLABLE
+META_CULLABLE_GET_IFACE
+meta_cullable_get_type
+</SECTION>
+
+<SECTION>
<FILE>prefs</FILE>
MetaPreference
MetaPrefsChangedFunc
diff --git a/src/Makefile.am b/src/Makefile.am
index 52adec3..ba4122e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,7 +55,8 @@ libmutter_la_SOURCES = \
compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \
compositor/meta-background-group.c \
- compositor/meta-background-group-private.h \
+ compositor/meta-cullable.c \
+ compositor/meta-cullable.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
diff --git a/src/compositor/meta-background-actor-private.h b/src/compositor/meta-background-actor-private.h
index 9ab074e..d48fb03 100644
--- a/src/compositor/meta-background-actor-private.h
+++ b/src/compositor/meta-background-actor-private.h
@@ -6,9 +6,6 @@
#include <meta/screen.h>
#include <meta/meta-background-actor.h>
-void meta_background_actor_set_clip_region (MetaBackgroundActor *self,
- cairo_region_t *clip_region);
-
cairo_region_t *meta_background_actor_get_clip_region (MetaBackgroundActor *self);
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */
diff --git a/src/compositor/meta-background-actor.c b/src/compositor/meta-background-actor.c
index 32b6007..2074458 100644
--- a/src/compositor/meta-background-actor.c
+++ b/src/compositor/meta-background-actor.c
@@ -41,20 +41,35 @@
#include <meta/errors.h>
#include <meta/meta-background.h>
#include "meta-background-actor-private.h"
+#include "meta-cullable.h"
struct _MetaBackgroundActorPrivate
{
cairo_region_t *clip_region;
};
-G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
+static void cullable_iface_init (MetaCullableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR,
+ G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
+
+static void
+set_clip_region (MetaBackgroundActor *self,
+ cairo_region_t *clip_region)
+{
+ MetaBackgroundActorPrivate *priv = self->priv;
+
+ g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy);
+ if (clip_region)
+ priv->clip_region = cairo_region_copy (clip_region);
+}
static void
meta_background_actor_dispose (GObject *object)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
- meta_background_actor_set_clip_region (self, NULL);
+ set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
}
@@ -166,31 +181,27 @@ meta_background_actor_new (void)
return CLUTTER_ACTOR (self);
}
-/**
- * meta_background_actor_set_clip_region:
- * @self: a #MetaBackgroundActor
- * @clip_region: (allow-none): the area of the actor (in allocate-relative
- * coordinates) that is visible.
- *
- * Sets the area of the background that is unobscured by overlapping windows.
- * This is used to optimize and only paint the visible portions.
- */
-void
-meta_background_actor_set_clip_region (MetaBackgroundActor *self,
- cairo_region_t *clip_region)
+static void
+meta_background_actor_cull_out (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region)
{
- MetaBackgroundActorPrivate *priv;
-
- g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
-
- priv = self->priv;
+ MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
+ set_clip_region (self, clip_region);
+}
- g_clear_pointer (&priv->clip_region,
- (GDestroyNotify)
- cairo_region_destroy);
+static void
+meta_background_actor_reset_culling (MetaCullable *cullable)
+{
+ MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
+ set_clip_region (self, NULL);
+}
- if (clip_region)
- priv->clip_region = cairo_region_copy (clip_region);
+static void
+cullable_iface_init (MetaCullableInterface *iface)
+{
+ iface->cull_out = meta_background_actor_cull_out;
+ iface->reset_culling = meta_background_actor_reset_culling;
}
/**
diff --git a/src/compositor/meta-background-group.c b/src/compositor/meta-background-group.c
index 092dd18..2ff01d3 100644
--- a/src/compositor/meta-background-group.c
+++ b/src/compositor/meta-background-group.c
@@ -16,12 +16,13 @@
#include <config.h>
-#include "compositor-private.h"
-#include "clutter-utils.h"
-#include "meta-background-actor-private.h"
-#include "meta-background-group-private.h"
+#include <meta/meta-background-group.h>
+#include "meta-cullable.h"
-G_DEFINE_TYPE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR);
+static void cullable_iface_init (MetaCullableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR,
+ G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
meta_background_group_class_init (MetaBackgroundGroupClass *klass)
@@ -29,43 +30,29 @@ meta_background_group_class_init (MetaBackgroundGroupClass *klass)
}
static void
-meta_background_group_init (MetaBackgroundGroup *self)
+meta_background_group_cull_out (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region)
{
+ meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
-/**
- * meta_background_group_set_clip_region:
- * @self: a #MetaBackgroundGroup
- * @region: (allow-none): the parts of the background to paint
- *
- * Sets the area of the backgrounds that is unobscured by overlapping windows.
- * This is used to optimize and only paint the visible portions.
- */
-void
-meta_background_group_set_clip_region (MetaBackgroundGroup *self,
- cairo_region_t *region)
+static void
+meta_background_group_reset_culling (MetaCullable *cullable)
{
- ClutterActor *child;
- for (child = clutter_actor_get_first_child (CLUTTER_ACTOR (self));
- child != NULL;
- child = clutter_actor_get_next_sibling (child))
- {
- if (META_IS_BACKGROUND_ACTOR (child))
- {
- meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), region);
- }
- else if (META_IS_BACKGROUND_GROUP (child))
- {
- int x, y;
+ meta_cullable_reset_culling_children (cullable);
+}
- if (!meta_actor_is_untransformed (child, &x, &y))
- continue;
+static void
+cullable_iface_init (MetaCullableInterface *iface)
+{
+ iface->cull_out = meta_background_group_cull_out;
+ iface->reset_culling = meta_background_group_reset_culling;
+}
- cairo_region_translate (region, -x, -y);
- meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), region);
- cairo_region_translate (region, x, y);
- }
- }
+static void
+meta_background_group_init (MetaBackgroundGroup *self)
+{
}
ClutterActor *
diff --git a/src/compositor/meta-cullable.c b/src/compositor/meta-cullable.c
new file mode 100644
index 0000000..a139166
--- /dev/null
+++ b/src/compositor/meta-cullable.c
@@ -0,0 +1,191 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ * Owen Taylor <otaylor redhat com>
+ * Ray Strode <rstrode redhat com>
+ * Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+#include "meta-cullable.h"
+#include "clutter-utils.h"
+
+G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR);
+
+/**
+ * SECTION:meta-cullable
+ * @title: MetaCullable
+ * @short_description: CPU culling operations for efficient drawing
+ *
+ * When we are painting a stack of 5-10 large actors, the standard
+ * bottom-to-top method of drawing every actor results in a tremendous
+ * amount of overdraw. If these actors are painting textures like
+ * windows, it can easily max out the available memory bandwidth on a
+ * low-end graphics chipset. It's even worse if window textures are
+ * being accessed over the AGP bus.
+ *
+ * #MetaCullable is our solution. The basic technique applied here is to
+ * do a pre-pass before painting where we walk each actor from top to bottom
+ * and ask each actor to "cull itself out". We pass in a region it can copy
+ * to clip its drawing to, and the actor can subtract its fully opaque pixels
+ * so that actors underneath know not to draw there as well.
+ */
+
+/**
+ * meta_cullable_cull_out_children:
+ * @cullable: The #MetaCullable
+ * @unobscured_region: The unobscured region, as passed into cull_out()
+ * @clip_region: The clip region, as passed into cull_out()
+ *
+ * This is a helper method for actors that want to recurse over their
+ * child actors, and cull them out.
+ *
+ * See #MetaCullable and meta_cullable_cull_out() for more details.
+ */
+void
+meta_cullable_cull_out_children (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region)
+{
+ ClutterActor *actor = CLUTTER_ACTOR (cullable);
+ ClutterActor *child;
+ ClutterActorIter iter;
+
+ clutter_actor_iter_init (&iter, actor);
+ while (clutter_actor_iter_prev (&iter, &child))
+ {
+ int x, y;
+
+ if (!CLUTTER_ACTOR_IS_VISIBLE (child))
+ continue;
+
+ /* If an actor has effects applied, then that can change the area
+ * it paints and the opacity, so we no longer can figure out what
+ * portion of the actor is obscured and what portion of the screen
+ * it obscures, so we skip the actor.
+ *
+ * This has a secondary beneficial effect: if a ClutterOffscreenEffect
+ * is applied to an actor, then our clipped redraws interfere with the
+ * caching of the FBO - even if we only need to draw a small portion
+ * of the window right now, ClutterOffscreenEffect may use other portions
+ * of the FBO later. So, skipping actors with effects applied also
+ * prevents these bugs.
+ *
+ * Theoretically, we should check clutter_actor_get_offscreen_redirect()
+ * as well for the same reason, but omitted for simplicity in the
+ * hopes that no-one will do that.
+ */
+ if (clutter_actor_has_effects (child))
+ continue;
+
+ if (!META_IS_CULLABLE (child))
+ continue;
+
+ if (!meta_actor_is_untransformed (child, &x, &y))
+ continue;
+
+ /* Temporarily move to the coordinate system of the actor */
+ cairo_region_translate (unobscured_region, - x, - y);
+ cairo_region_translate (clip_region, - x, - y);
+
+ meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
+
+ cairo_region_translate (unobscured_region, x, y);
+ cairo_region_translate (clip_region, x, y);
+ }
+}
+
+/**
+ * meta_cullable_reset_culling_children:
+ * @cullable: The #MetaCullable
+ *
+ * This is a helper method for actors that want to recurse over their
+ * child actors, and cull them out.
+ *
+ * See #MetaCullable and meta_cullable_reset_culling() for more details.
+ */
+void
+meta_cullable_reset_culling_children (MetaCullable *cullable)
+{
+ ClutterActor *actor = CLUTTER_ACTOR (cullable);
+ ClutterActor *child;
+ ClutterActorIter iter;
+
+ clutter_actor_iter_init (&iter, actor);
+ while (clutter_actor_iter_next (&iter, &child))
+ {
+ if (!META_IS_CULLABLE (child))
+ continue;
+
+ meta_cullable_reset_culling (META_CULLABLE (child));
+ }
+}
+
+static void
+meta_cullable_default_init (MetaCullableInterface *iface)
+{
+}
+
+/**
+ * meta_cullable_cull_out:
+ * @cullable: The #MetaCullable
+ * @unobscured_region: The unobscured region, in @cullable's space.
+ * @clip_region: The clip region, in @cullable's space.
+ *
+ * When #MetaWindowGroup is painted, we walk over its direct cullable
+ * children from top to bottom and ask themselves to "cull out". Cullables
+ * can use @unobscured_region and @clip_region to clip their drawing. Actors
+ * interested in eliminating overdraw should copy the @clip_region and only
+ * paint those parts, as everything else has been obscured by actors above it.
+ *
+ * Actors that may have fully opaque parts should also subtract out a region
+ * that is fully opaque from @unobscured_region and @clip_region.
+ *
+ * @unobscured_region and @clip_region are extremely similar. The difference
+ * is that @clip_region starts off with the stage's clip, if Clutter detects
+ * that we're doing a clipped redraw. @unobscured_region, however, starts off
+ * with the full stage size, so actors that may want to record what parts of
+ * their window are unobscured for e.g. scheduling repaints can do so.
+ *
+ * Actors that have children can also use the meta_cullable_cull_out_children()
+ * helper method to do a simple cull across all their children.
+ */
+void
+meta_cullable_cull_out (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region)
+{
+ META_CULLABLE_GET_IFACE (cullable)->cull_out (cullable, unobscured_region, clip_region);
+}
+
+/**
+ * meta_cullable_reset_culling:
+ * @cullable: The #MetaCullable
+ *
+ * Actors that copied data in their cull_out() implementation can now
+ * reset their data, as the paint is now over. Additional paints may be
+ * done by #ClutterClone or similar, and they should not be affected by
+ * the culling operation.
+ */
+void
+meta_cullable_reset_culling (MetaCullable *cullable)
+{
+ META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable);
+}
diff --git a/src/compositor/meta-cullable.h b/src/compositor/meta-cullable.h
new file mode 100644
index 0000000..5a8c215
--- /dev/null
+++ b/src/compositor/meta-cullable.h
@@ -0,0 +1,68 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ * Owen Taylor <otaylor redhat com>
+ * Ray Strode <rstrode redhat com>
+ * Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef __META_CULLABLE_H__
+#define __META_CULLABLE_H__
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define META_TYPE_CULLABLE (meta_cullable_get_type ())
+#define META_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CULLABLE, MetaCullable))
+#define META_IS_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CULLABLE))
+#define META_CULLABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_CULLABLE,
MetaCullableInterface))
+
+typedef struct _MetaCullable MetaCullable;
+typedef struct _MetaCullableInterface MetaCullableInterface;
+
+struct _MetaCullableInterface
+{
+ GTypeInterface g_iface;
+
+ void (* cull_out) (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region);
+ void (* reset_culling) (MetaCullable *cullable);
+};
+
+GType meta_cullable_get_type (void);
+
+void meta_cullable_cull_out (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region);
+void meta_cullable_reset_culling (MetaCullable *cullable);
+
+/* Utility methods for implementations */
+void meta_cullable_cull_out_children (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region);
+void meta_cullable_reset_culling_children (MetaCullable *cullable);
+
+G_END_DECLS
+
+#endif /* __META_CULLABLE_H__ */
+
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
index f10276b..441f05b 100644
--- a/src/compositor/meta-window-actor-private.h
+++ b/src/compositor/meta-window-actor-private.h
@@ -55,11 +55,6 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);
-void meta_window_actor_cull_out (MetaWindowActor *self,
- cairo_region_t *unobscured_region,
- cairo_region_t *clip_region);
-void meta_window_actor_reset_culling (MetaWindowActor *self);
-
void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
cairo_region_t *unobscured_region);
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 153b303..7d52c24 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -32,6 +32,7 @@
#include "meta-texture-rectangle.h"
#include "region-utils.h"
#include "monitor-private.h"
+#include "meta-cullable.h"
enum {
POSITION_CHANGED,
@@ -191,7 +192,10 @@ static void do_send_frame_timings (MetaWindowActor *self,
gint refresh_interval,
gint64 presentation_time);
-G_DEFINE_TYPE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR);
+static void cullable_iface_init (MetaCullableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR,
+ G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
frame_data_free (FrameData *frame)
@@ -1848,11 +1852,13 @@ meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
}
}
-void
-meta_window_actor_cull_out (MetaWindowActor *self,
- cairo_region_t *unobscured_region,
- cairo_region_t *clip_region)
+static void
+meta_window_actor_cull_out (MetaCullable *cullable,
+ cairo_region_t *unobscured_region,
+ cairo_region_t *clip_region)
{
+ MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
+
meta_window_actor_set_unobscured_region (self, unobscured_region);
meta_window_actor_set_clip_region (self, clip_region);
@@ -1869,16 +1875,10 @@ meta_window_actor_cull_out (MetaWindowActor *self,
meta_window_actor_set_clip_region_beneath (self, clip_region);
}
-/**
- * meta_window_actor_reset_culling:
- * @self: a #MetaWindowActor
- *
- * Unsets the regions set by meta_window_actor_set_clip_region() and
- * meta_window_actor_set_clip_region_beneath()
- */
-void
-meta_window_actor_reset_culling (MetaWindowActor *self)
+static void
+meta_window_actor_reset_culling (MetaCullable *cullable)
{
+ MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
MetaWindowActorPrivate *priv = self->priv;
meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
@@ -1887,6 +1887,13 @@ meta_window_actor_reset_culling (MetaWindowActor *self)
}
static void
+cullable_iface_init (MetaCullableInterface *iface)
+{
+ iface->cull_out = meta_window_actor_cull_out;
+ iface->reset_culling = meta_window_actor_reset_culling;
+}
+
+static void
check_needs_pixmap (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index ea23e1d..1b08aa1 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -11,8 +11,8 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
-#include "meta-background-actor-private.h"
-#include "meta-background-group-private.h"
+#include "window-private.h"
+#include "meta-cullable.h"
struct _MetaWindowGroupClass
{
@@ -126,6 +126,7 @@ meta_window_group_cull_out (MetaWindowGroup *group,
while (clutter_actor_iter_prev (&iter, &child))
{
MetaCompScreen *info = meta_screen_get_compositor_data (group->screen);
+ int x, y;
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
@@ -153,45 +154,23 @@ meta_window_group_cull_out (MetaWindowGroup *group,
if (clutter_actor_has_effects (child))
continue;
- if (META_IS_WINDOW_ACTOR (child))
- {
- int x, y;
-
- if (!meta_actor_is_untransformed (child, &x, &y))
- continue;
-
- x += paint_x_offset;
- y += paint_y_offset;
-
- /* Temporarily move to the coordinate system of the actor */
- cairo_region_translate (unobscured_region, - x, - y);
- cairo_region_translate (clip_region, - x, - y);
-
- meta_window_actor_cull_out (META_WINDOW_ACTOR (child), unobscured_region, clip_region);
-
- cairo_region_translate (unobscured_region, x, y);
- cairo_region_translate (clip_region, x, y);
- }
- else if (META_IS_BACKGROUND_ACTOR (child) ||
- META_IS_BACKGROUND_GROUP (child))
- {
- int x, y;
+ if (!META_IS_CULLABLE (child))
+ continue;
- if (!meta_actor_is_untransformed (child, &x, &y))
- continue;
+ if (!meta_actor_is_untransformed (child, &x, &y))
+ continue;
- x += paint_x_offset;
- y += paint_y_offset;
+ x += paint_x_offset;
+ y += paint_y_offset;
- cairo_region_translate (clip_region, - x, - y);
+ /* Temporarily move to the coordinate system of the actor */
+ cairo_region_translate (unobscured_region, - x, - y);
+ cairo_region_translate (clip_region, - x, - y);
- if (META_IS_BACKGROUND_GROUP (child))
- meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region);
- else
- meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region);
+ meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
- cairo_region_translate (clip_region, x, y);
- }
+ cairo_region_translate (unobscured_region, x, y);
+ cairo_region_translate (clip_region, x, y);
}
}
@@ -202,22 +181,13 @@ meta_window_group_reset_culling (MetaWindowGroup *group)
ClutterActor *child;
ClutterActorIter iter;
- /* Now that we are done painting, unset the visible regions (they will
- * mess up painting clones of our actors)
- */
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
- if (META_IS_WINDOW_ACTOR (child))
- {
- MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
- meta_window_actor_reset_culling (window_actor);
- }
- else if (META_IS_BACKGROUND_ACTOR (child))
- {
- MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
- meta_background_actor_set_clip_region (background_actor, NULL);
- }
+ if (!META_IS_CULLABLE (child))
+ continue;
+
+ meta_cullable_reset_culling (META_CULLABLE (child));
}
}
diff --git a/src/compositor/meta-window-group.h b/src/compositor/meta-window-group.h
index 1c3eebf..d624ac6 100644
--- a/src/compositor/meta-window-group.h
+++ b/src/compositor/meta-window-group.h
@@ -11,29 +11,9 @@
* MetaWindowGroup:
*
* This class is a subclass of ClutterActor with special handling for
- * MetaWindowActor/MetaBackgroundActor/MetaBackgroundGroup when painting
- * children.
- *
- * When we are painting a stack of 5-10 maximized windows, the
- * standard bottom-to-top method of drawing every actor results in a
- * tremendous amount of overdraw and can easily max out the available
- * memory bandwidth on a low-end graphics chipset. It's even worse if
- * window textures are being accessed over the AGP bus.
- *
- * The basic technique applied here is to do a pre-pass before painting
- * where we walk window from top to bottom and compute the visible area
- * at each step by subtracting out the windows above it. The visible
- * area is passed to MetaWindowActor which uses it to clip the portion of
- * the window which drawn and avoid redrawing the shadow if it is completely
- * obscured.
- *
- * A caveat is that this is ineffective if applications are using ARGB
- * visuals, since we have no way of knowing whether a window obscures
- * the windows behind it or not. Alternate approaches using the depth
- * or stencil buffer rather than client side regions might be able to
- * handle alpha windows, but the combination of glAlphaFunc and stenciling
- * tends not to be efficient except on newer cards. (And on newer cards
- * we have lots of memory and bandwidth.)
+ * #MetaCullable when painting children. It uses code similar to
+ * meta_cullable_cull_out_children(), but also has additional special
+ * cases for the undirected window, and similar.
*/
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]