[mutter/wayland] meta-shaped-texture: Don't queue redraws for obscured regions
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wayland] meta-shaped-texture: Don't queue redraws for obscured regions
- Date: Thu, 29 Aug 2013 21:06:07 +0000 (UTC)
commit f08921bd0c1eb7df47755e725aa480cb2d60b9eb
Author: Adel Gadllah <adel gadllah gmail com>
Date: Tue Aug 27 16:45:15 2013 +0200
meta-shaped-texture: Don't queue redraws for obscured regions
When we get a damage event we update the window by calling
meta_shaped_texture_update_area which queues a redraw on the actor.
We can avoid that for obscured regions by comparing the damage area to
our visible area.
This patch causes _NET_WM_FRAME_DRAWN messages to be not sent in some cases
where they should be sent; they will be added back in a later commit.
https://bugzilla.gnome.org/show_bug.cgi?id=703332
src/compositor/meta-shaped-texture.c | 60 ++++++++++++++++++++++---
src/compositor/meta-window-actor-private.h | 13 +++--
src/compositor/meta-window-actor.c | 67 +++++++++++++++++++++-------
src/compositor/meta-window-group.c | 67 ++++++++++++++++++++--------
src/meta/meta-shaped-texture.h | 11 +++--
5 files changed, 165 insertions(+), 53 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 838e3fe..01ff5f7 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -738,19 +738,38 @@ queue_damage_redraw_with_clip (MetaShapedTexture *stex,
clutter_actor_queue_redraw_with_clip (self, &clip);
}
-void
+/**
+ * meta_shaped_texture_update_area:
+ * @stex: #MetaShapedTexture
+ * @x: the x coordinate of the damaged area
+ * @y: the y coordinate of the damaged area
+ * @width: the width of the damaged area
+ * @height: the height of the damaged area
+ * @unobscured_region: The unobscured region of the window or %NULL if
+ * there is no valid one (like when the actor is transformed or
+ * has a mapped clone)
+ *
+ * Repairs the damaged area indicated by @x, @y, @width and @height
+ * and queues a redraw for the intersection @visibible_region and
+ * the damage area. If @visibible_region is %NULL a redraw will always
+ * get queued.
+ *
+ * Return value: Whether a redraw have been queued or not
+ */
+gboolean
meta_shaped_texture_update_area (MetaShapedTexture *stex,
- int x,
- int y,
- int width,
- int height)
+ int x,
+ int y,
+ int width,
+ int height,
+ cairo_region_t *unobscured_region)
{
MetaShapedTexturePrivate *priv;
priv = stex->priv;
if (priv->texture == NULL)
- return;
+ return FALSE;
switch (priv->type)
{
@@ -765,7 +784,34 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
- queue_damage_redraw_with_clip (stex, x, y, width, height);
+ if (unobscured_region)
+ {
+ cairo_region_t *intersection;
+
+ if (cairo_region_is_empty (unobscured_region))
+ return FALSE;
+
+ intersection = cairo_region_copy (unobscured_region);
+ cairo_region_intersect_rectangle (intersection, &clip);
+
+ if (!cairo_region_is_empty (intersection))
+ {
+ cairo_rectangle_int_t damage_rect;
+ cairo_region_get_extents (intersection, &damage_rect);
+ clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
+ cairo_region_destroy (intersection);
+
+ return TRUE;
+ }
+
+ cairo_region_destroy (intersection);
+
+ return FALSE;
+ }
+
+ clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
+
+ return TRUE;
}
/**
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
index cfe6c9d..235e221 100644
--- a/src/compositor/meta-window-actor-private.h
+++ b/src/compositor/meta-window-actor-private.h
@@ -70,11 +70,14 @@ void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
-void meta_window_actor_set_visible_region (MetaWindowActor *self,
- cairo_region_t *visible_region);
-void meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
- cairo_region_t *beneath_region);
-void meta_window_actor_reset_visible_regions (MetaWindowActor *self);
+void meta_window_actor_set_clip_region (MetaWindowActor *self,
+ cairo_region_t *clip_region);
+void meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
+ cairo_region_t *beneath_region);
+void meta_window_actor_reset_clip_regions (MetaWindowActor *self);
+
+void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
+ cairo_region_t *unobscured_region);
void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 1204322..537fded 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -77,6 +77,9 @@ struct _MetaWindowActorPrivate
/* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip;
+ /* The region that is visible, used to optimize out redraws */
+ cairo_region_t *unobscured_region;
+
/* Extracted size-invariant shape used for shadows */
MetaWindowShape *shadow_shape;
@@ -445,6 +448,7 @@ meta_window_actor_dispose (GObject *object)
meta_window_actor_detach_x11_pixmap (self);
}
+ g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
g_clear_pointer (&priv->input_region, cairo_region_destroy);
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
@@ -948,7 +952,8 @@ meta_window_actor_damage_all (MetaWindowActor *self)
meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
0, 0,
cogl_texture_get_width (texture),
- cogl_texture_get_height (texture));
+ cogl_texture_get_height (texture),
+ clutter_actor_has_mapped_clones (priv->actor) ? NULL :
priv->unobscured_region);
priv->needs_damage_all = FALSE;
priv->repaint_scheduled = TRUE;
@@ -1734,40 +1739,67 @@ see_region (cairo_region_t *region,
#endif
/**
- * meta_window_actor_set_visible_region:
+ * meta_window_actor_set_unobscured_region:
+ * @self: a #MetaWindowActor
+ * @unobscured_region: the region of the screen that isn't completely
+ * obscured.
+ *
+ * Provides a hint as to what areas of the window need to queue
+ * redraws when damaged. Regions not in @unobscured_region are completely obscured.
+ * Unlike meta_window_actor_set_clip_region(), the region here
+ * doesn't take into account any clipping that is in effect while drawing.
+ */
+void
+meta_window_actor_set_unobscured_region (MetaWindowActor *self,
+ cairo_region_t *unobscured_region)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+
+ if (priv->unobscured_region)
+ cairo_region_destroy (priv->unobscured_region);
+
+ if (unobscured_region)
+ priv->unobscured_region = cairo_region_copy (unobscured_region);
+ else
+ priv->unobscured_region = NULL;
+}
+
+/**
+ * meta_window_actor_set_clip_region:
* @self: a #MetaWindowActor
- * @visible_region: the region of the screen that isn't completely
+ * @clip_region: the region of the screen that isn't completely
* obscured.
*
* Provides a hint as to what areas of the window need to be
- * drawn. Regions not in @visible_region are completely obscured.
+ * drawn. Regions not in @clip_region are completely obscured or
+ * not drawn in this frame.
* This will be set before painting then unset afterwards.
*/
void
-meta_window_actor_set_visible_region (MetaWindowActor *self,
- cairo_region_t *visible_region)
+meta_window_actor_set_clip_region (MetaWindowActor *self,
+ cairo_region_t *clip_region)
{
MetaWindowActorPrivate *priv = self->priv;
meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
- visible_region);
+ clip_region);
}
/**
- * meta_window_actor_set_visible_region_beneath:
+ * meta_window_actor_set_clip_region_beneath:
* @self: a #MetaWindowActor
- * @visible_region: the region of the screen that isn't completely
+ * @clip_region: the region of the screen that isn't completely
* obscured beneath the main window texture.
*
* Provides a hint as to what areas need to be drawn *beneath*
- * the main window texture. This is the relevant visible region
+ * the main window texture. This is the relevant clip region
* when drawing the shadow, properly accounting for areas of the
* shadow hid by the window itself. This will be set before painting
* then unset afterwards.
*/
void
-meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
- cairo_region_t *beneath_region)
+meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
+ cairo_region_t *beneath_region)
{
MetaWindowActorPrivate *priv = self->priv;
gboolean appears_focused = meta_window_appears_focused (priv->window);
@@ -1786,14 +1818,14 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
}
/**
- * meta_window_actor_reset_visible_regions:
+ * meta_window_actor_reset_clip_regions:
* @self: a #MetaWindowActor
*
- * Unsets the regions set by meta_window_actor_set_visible_region() and
- * meta_window_actor_set_visible_region_beneath()
+ * Unsets the regions set by meta_window_actor_set_clip_region() and
+ * meta_window_actor_set_clip_region_beneath()
*/
void
-meta_window_actor_reset_visible_regions (MetaWindowActor *self)
+meta_window_actor_reset_clip_regions (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
@@ -2019,7 +2051,8 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
event->area.x,
event->area.y,
event->area.width,
- event->area.height);
+ event->area.height,
+ clutter_actor_has_mapped_clones (priv->actor) ? NULL :
priv->unobscured_region);
priv->repaint_scheduled = TRUE;
}
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index 65771f7..4acb588 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -90,17 +90,30 @@ painting_untransformed (MetaWindowGroup *window_group,
static void
meta_window_group_paint (ClutterActor *actor)
{
- cairo_region_t *visible_region;
- ClutterActor *stage;
+ cairo_region_t *clip_region;
+ cairo_region_t *unobscured_region;
ClutterActorIter iter;
ClutterActor *child;
- cairo_rectangle_int_t visible_rect;
+ cairo_rectangle_int_t visible_rect, clip_rect;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int paint_x_offset, paint_y_offset;
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
- MetaCompScreen *info;
+ MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
+ ClutterActor *stage = clutter_actor_get_stage (actor);
+
+ /* Start off by treating all windows as completely unobscured, so damage anywhere
+ * in a window queues redraws, but confine it more below. */
+ 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_set_unobscured_region (window_actor, NULL);
+ }
+ }
/* Normally we expect an actor to be drawn at it's position on the screen.
* However, if we're inside the paint of a ClutterClone, that won't be the
@@ -125,17 +138,22 @@ meta_window_group_paint (ClutterActor *actor)
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
+ 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);
+
/* 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. */
- stage = clutter_actor_get_stage (actor);
clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage),
- &visible_rect);
+ &clip_rect);
- visible_region = cairo_region_create_rectangle (&visible_rect);
+ clip_region = cairo_region_create_rectangle (&clip_rect);
if (!meta_is_wayland_compositor ())
{
@@ -146,7 +164,8 @@ meta_window_group_paint (ClutterActor *actor)
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
- cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
+ cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
+ cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
}
}
@@ -195,20 +214,28 @@ meta_window_group_paint (ClutterActor *actor)
x += paint_x_offset;
y += paint_y_offset;
+
/* Temporarily move to the coordinate system of the actor */
- cairo_region_translate (visible_region, - x, - y);
+ cairo_region_translate (unobscured_region, - x, - y);
+ cairo_region_translate (clip_region, - x, - y);
- meta_window_actor_set_visible_region (window_actor, visible_region);
+ meta_window_actor_set_unobscured_region (window_actor, unobscured_region);
+ meta_window_actor_set_clip_region (window_actor, clip_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
- cairo_region_subtract (visible_region, obscured_region);
+ {
+ cairo_region_subtract (unobscured_region, obscured_region);
+ cairo_region_subtract (clip_region, obscured_region);
+ }
}
- meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
- cairo_region_translate (visible_region, x, y);
+ meta_window_actor_set_clip_region_beneath (window_actor, 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))
@@ -221,17 +248,19 @@ meta_window_group_paint (ClutterActor *actor)
x += paint_x_offset;
y += paint_y_offset;
- cairo_region_translate (visible_region, - x, - y);
+ cairo_region_translate (clip_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (child))
- meta_background_group_set_visible_region (META_BACKGROUND_GROUP (child), visible_region);
+ meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region);
else
- meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), visible_region);
- cairo_region_translate (visible_region, x, y);
+ meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region);
+
+ cairo_region_translate (clip_region, x, y);
}
}
- cairo_region_destroy (visible_region);
+ cairo_region_destroy (unobscured_region);
+ cairo_region_destroy (clip_region);
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
@@ -244,7 +273,7 @@ meta_window_group_paint (ClutterActor *actor)
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
- meta_window_actor_reset_visible_regions (window_actor);
+ meta_window_actor_reset_clip_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (child))
{
diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h
index 2b6d325..d757ced 100644
--- a/src/meta/meta-shaped-texture.h
+++ b/src/meta/meta-shaped-texture.h
@@ -67,11 +67,12 @@ GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps);
-void meta_shaped_texture_update_area (MetaShapedTexture *stex,
- int x,
- int y,
- int width,
- int height);
+gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
+ int x,
+ int y,
+ int width,
+ int height,
+ cairo_region_t *unobscured_region);
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]