From a0fe3926657611f687c3befffce3c07f17071444 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Fri, 6 Dec 2013 11:57:40 -0500 Subject: [PATCH] surface-actor: Move unobscured_region processing here https://bugzilla.gnome.org/show_bug.cgi?id=720631 --- src/compositor/meta-surface-actor.c | 105 +++++++++++++++++++-- src/compositor/meta-surface-actor.h | 9 +- src/compositor/meta-window-actor-private.h | 3 - src/compositor/meta-window-actor.c | 70 +++----------- src/compositor/meta-window-group.c | 14 --- src/wayland/meta-wayland-surface.c | 6 +- 6 files changed, 116 insertions(+), 91 deletions(-) diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 37b87b03a..8d3f5b4d5 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -24,6 +24,9 @@ struct _MetaSurfaceActorPrivate { MetaShapedTexture *texture; MetaWaylandBuffer *buffer; + + /* The region that is visible, used to optimize out redraws */ + cairo_region_t *unobscured_region; }; static void cullable_iface_init (MetaCullableInterface *iface); @@ -31,23 +34,96 @@ static void cullable_iface_init (MetaCullableInterface *iface); G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); +static gboolean +meta_surface_actor_get_paint_volume (ClutterActor *actor, + ClutterPaintVolume *volume) +{ + MetaSurfaceActor *self = META_SURFACE_ACTOR (actor); + MetaSurfaceActorPrivate *priv = self->priv; + + if (!CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->get_paint_volume (actor, volume)) + return FALSE; + + if (priv->unobscured_region) + { + ClutterVertex origin; + cairo_rectangle_int_t bounds, unobscured_bounds; + + /* I hate ClutterPaintVolume so much... */ + clutter_paint_volume_get_origin (volume, &origin); + bounds.x = origin.x; + bounds.y = origin.y; + bounds.width = clutter_paint_volume_get_width (volume); + bounds.height = clutter_paint_volume_get_height (volume); + + cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds); + gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); + + origin.x = bounds.x; + origin.y = bounds.y; + clutter_paint_volume_set_origin (volume, &origin); + clutter_paint_volume_set_width (volume, bounds.width); + clutter_paint_volume_set_height (volume, bounds.height); + } + + return TRUE; +} + +static void +meta_surface_actor_dispose (GObject *object) +{ + MetaSurfaceActor *self = META_SURFACE_ACTOR (object); + MetaSurfaceActorPrivate *priv = self->priv; + + g_clear_pointer (&priv->unobscured_region, cairo_region_destroy); + + G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object); +} + static void meta_surface_actor_class_init (MetaSurfaceActorClass *klass) { + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + actor_class->get_paint_volume = meta_surface_actor_get_paint_volume; + object_class->dispose = meta_surface_actor_dispose; + g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate)); } +static void +set_unobscured_region (MetaSurfaceActor *self, + cairo_region_t *unobscured_region) +{ + MetaSurfaceActorPrivate *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; +} + static void meta_surface_actor_cull_out (MetaCullable *cullable, cairo_region_t *unobscured_region, cairo_region_t *clip_region) { + MetaSurfaceActor *self = META_SURFACE_ACTOR (cullable); + + set_unobscured_region (self, unobscured_region); meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); } static void meta_surface_actor_reset_culling (MetaCullable *cullable) { + MetaSurfaceActor *self = META_SURFACE_ACTOR (cullable); + + set_unobscured_region (self, NULL); meta_cullable_reset_culling_children (cullable); } @@ -108,9 +184,16 @@ update_area (MetaSurfaceActor *self, } } +static cairo_region_t * +effective_unobscured_region (MetaSurfaceActor *self) +{ + MetaSurfaceActorPrivate *priv = self->priv; + + return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region; +} + gboolean -meta_surface_actor_damage_all (MetaSurfaceActor *self, - cairo_region_t *unobscured_region) +meta_surface_actor_damage_all (MetaSurfaceActor *self) { MetaSurfaceActorPrivate *priv = self->priv; CoglTexture *texture = meta_shaped_texture_get_texture (priv->texture); @@ -120,7 +203,7 @@ meta_surface_actor_damage_all (MetaSurfaceActor *self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture), - unobscured_region); + effective_unobscured_region (self)); } gboolean @@ -128,15 +211,25 @@ meta_surface_actor_damage_area (MetaSurfaceActor *self, int x, int y, int width, - int height, - cairo_region_t *unobscured_region) + int height) { MetaSurfaceActorPrivate *priv = self->priv; update_area (self, x, y, width, height); return meta_shaped_texture_update_area (priv->texture, x, y, width, height, - unobscured_region); + effective_unobscured_region (self)); +} + +gboolean +meta_surface_actor_is_obscured (MetaSurfaceActor *self) +{ + MetaSurfaceActorPrivate *priv = self->priv; + + if (priv->unobscured_region) + return cairo_region_is_empty (priv->unobscured_region); + else + return FALSE; } void diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h index 484877b73..0f5fd8f04 100644 --- a/src/compositor/meta-surface-actor.h +++ b/src/compositor/meta-surface-actor.h @@ -43,15 +43,14 @@ cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self, MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); -gboolean meta_surface_actor_damage_all (MetaSurfaceActor *self, - cairo_region_t *unobscured_region); - +gboolean meta_surface_actor_damage_all (MetaSurfaceActor *self); gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self, int x, int y, int width, - int height, - cairo_region_t *unobscured_region); + int height); + +gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); void meta_surface_actor_set_texture (MetaSurfaceActor *self, CoglTexture *texture); diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h index 82326d29b..e3d239d2e 100644 --- a/src/compositor/meta-window-actor-private.h +++ b/src/compositor/meta-window-actor-private.h @@ -59,9 +59,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_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 e9cecfc2c..652ce04f5 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -72,9 +72,6 @@ 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; - guint send_frame_messages_timer; gint64 frame_drawn_time; @@ -424,7 +421,6 @@ meta_window_actor_dispose (GObject *object) priv->send_frame_messages_timer = 0; } - g_clear_pointer (&priv->unobscured_region, cairo_region_destroy); g_clear_pointer (&priv->shape_region, cairo_region_destroy); g_clear_pointer (&priv->shadow_clip, cairo_region_destroy); @@ -720,12 +716,15 @@ meta_window_actor_get_paint_volume (ClutterActor *actor, gdk_rectangle_union (&bounds, &shadow_bounds, &bounds); } - if (priv->unobscured_region) - { - cairo_rectangle_int_t unobscured_bounds; - cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds); - gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); - } + { + const ClutterPaintVolume *child_volume; + + child_volume = clutter_actor_get_transformed_paint_volume (CLUTTER_ACTOR (priv->surface), actor); + if (!child_volume) + return FALSE; + + clutter_paint_volume_union (volume, child_volume); + } origin.x = bounds.x; origin.y = bounds.y; @@ -977,7 +976,6 @@ static void meta_window_actor_damage_all (MetaWindowActor *self) { MetaWindowActorPrivate *priv = self->priv; - cairo_region_t *unobscured_region; gboolean redraw_queued; if (!priv->needs_damage_all) @@ -986,11 +984,7 @@ meta_window_actor_damage_all (MetaWindowActor *self) if (priv->needs_pixmap) return; - unobscured_region = - clutter_actor_has_mapped_clones (CLUTTER_ACTOR (priv->surface)) - ? NULL : priv->unobscured_region; - - redraw_queued = meta_surface_actor_damage_all (priv->surface, unobscured_region); + redraw_queued = meta_surface_actor_damage_all (priv->surface); priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; priv->needs_damage_all = FALSE; @@ -1049,17 +1043,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self, if (!priv->repaint_scheduled) { - gboolean is_obscured = FALSE; - - /* Find out whether the window is completly obscured */ - if (priv->unobscured_region) - { - cairo_region_t *unobscured_window_region; - unobscured_window_region = cairo_region_copy (priv->shape_region); - cairo_region_intersect (unobscured_window_region, priv->unobscured_region); - is_obscured = cairo_region_is_empty (unobscured_window_region); - cairo_region_destroy (unobscured_window_region); - } + gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface); /* A frame was marked by the client without actually doing any * damage or any unobscured, or while we had the window frozen @@ -1703,30 +1687,6 @@ see_region (cairo_region_t *region, } #endif -/** - * 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. - */ -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_beneath: * @self: a #MetaWindowActor @@ -1775,7 +1735,6 @@ meta_window_actor_cull_out (MetaCullable *cullable, return; } - meta_window_actor_set_unobscured_region (self, unobscured_region); meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); meta_window_actor_set_clip_region_beneath (self, clip_region); } @@ -1946,7 +1905,6 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self, MetaWindowActorPrivate *priv = self->priv; MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen); gboolean redraw_queued; - cairo_region_t *unobscured_region; priv->received_x11_damage = TRUE; @@ -1994,15 +1952,11 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self, if (priv->needs_pixmap) return; - unobscured_region = - clutter_actor_has_mapped_clones (CLUTTER_ACTOR (priv->surface)) - ? NULL : priv->unobscured_region; redraw_queued = meta_surface_actor_damage_area (priv->surface, event->area.x, event->area.y, event->area.width, - event->area.height, - unobscured_region); + event->area.height); priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c index 9554571b0..11445543e 100644 --- a/src/compositor/meta-window-group.c +++ b/src/compositor/meta-window-group.c @@ -115,8 +115,6 @@ meta_window_group_paint (ClutterActor *actor) { cairo_region_t *clip_region; cairo_region_t *unobscured_region; - ClutterActorIter iter; - ClutterActor *child; cairo_rectangle_int_t visible_rect, clip_rect; int paint_x_offset, paint_y_offset; int paint_x_origin, paint_y_origin; @@ -125,18 +123,6 @@ meta_window_group_paint (ClutterActor *actor) MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); 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 * case and we need to compensate. We look at the position of the window diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 1ca38e564..f31f3cef2 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -69,11 +69,7 @@ surface_process_damage (MetaWaylandSurface *surface, cairo_rectangle_int_t rect; cairo_region_get_rectangle (region, i, &rect); meta_surface_actor_damage_area (surface->surface_actor, - rect.x, - rect.y, - rect.width, - rect.height, - NULL); + rect.x, rect.y, rect.width, rect.height); } }