diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index 18d61a728..48ae0dfbd 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -32,5 +32,8 @@ ClutterActor *meta_shaped_texture_new (void); void meta_shaped_texture_set_texture (MetaShapedTexture *stex, CoglTexture *texture); +gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *stex, + cairo_rectangle_int_t *unobscured_bounds); +gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); #endif diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 985859bba..d1d205314 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -72,10 +72,15 @@ struct _MetaShapedTexturePrivate CoglTexture *texture; CoglTexture *mask_texture; - cairo_region_t *clip_region; - cairo_region_t *opaque_region; cairo_region_t *input_shape_region; + /* The region containing only fully opaque pixels */ + cairo_region_t *opaque_region; + + /* MetaCullable regions, see that documentation for more details */ + cairo_region_t *clip_region; + cairo_region_t *unobscured_region; + guint tex_width, tex_height; guint create_mipmaps : 1; @@ -112,6 +117,21 @@ meta_shaped_texture_init (MetaShapedTexture *self) priv->create_mipmaps = TRUE; } +static void +set_unobscured_region (MetaShapedTexture *self, + cairo_region_t *unobscured_region) +{ + MetaShapedTexturePrivate *priv = self->priv; + + g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy); + if (unobscured_region) + { + cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height }; + priv->unobscured_region = cairo_region_copy (unobscured_region); + cairo_region_intersect_rectangle (priv->unobscured_region, &bounds); + } +} + static void set_clip_region (MetaShapedTexture *self, cairo_region_t *clip_region) @@ -137,6 +157,7 @@ meta_shaped_texture_dispose (GObject *object) g_clear_pointer (&priv->opaque_region, cairo_region_destroy); meta_shaped_texture_set_mask_texture (self, NULL); + set_unobscured_region (self, NULL); set_clip_region (self, NULL); G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); @@ -497,10 +518,37 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self, } static gboolean -meta_shaped_texture_get_paint_volume (ClutterActor *self, +meta_shaped_texture_get_paint_volume (ClutterActor *actor, ClutterPaintVolume *volume) { - return clutter_paint_volume_set_from_allocation (volume, self); + MetaShapedTexture *self = META_SHAPED_TEXTURE (actor); + cairo_rectangle_int_t unobscured_bounds; + + if (!clutter_paint_volume_set_from_allocation (volume, actor)) + return FALSE; + + if (meta_shaped_texture_get_unobscured_bounds (self, &unobscured_bounds)) + { + ClutterVertex origin; + cairo_rectangle_int_t 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); + + 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; } void @@ -546,6 +594,40 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); } +static cairo_region_t * +effective_unobscured_region (MetaShapedTexture *self) +{ + MetaShapedTexturePrivate *priv = self->priv; + + return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region; +} + +gboolean +meta_shaped_texture_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; +} + +gboolean +meta_shaped_texture_is_obscured (MetaShapedTexture *self) +{ + MetaShapedTexturePrivate *priv = self->priv; + cairo_region_t *unobscured_region = effective_unobscured_region (self); + + if (unobscured_region) + return cairo_region_is_empty (unobscured_region); + else + return FALSE; +} /** * meta_shaped_texture_update_area: @@ -554,14 +636,9 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, * @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. + * and potentially queues a redraw. * * Return value: Whether a redraw have been queued or not */ @@ -570,10 +647,10 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, int x, int y, int width, - int height, - cairo_region_t *unobscured_region) + int height) { MetaShapedTexturePrivate *priv; + cairo_region_t *unobscured_region; const cairo_rectangle_int_t clip = { x, y, width, height }; priv = stex->priv; @@ -583,6 +660,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); + unobscured_region = effective_unobscured_region (stex); if (unobscured_region) { cairo_region_t *intersection; @@ -851,6 +929,7 @@ meta_shaped_texture_cull_out (MetaCullable *cullable, MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable); MetaShapedTexturePrivate *priv = self->priv; + set_unobscured_region (self, unobscured_region); set_clip_region (self, clip_region); if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 00a005eb4..8fb621fa4 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -74,9 +74,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; @@ -395,7 +392,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); @@ -663,7 +659,7 @@ meta_window_actor_get_paint_volume (ClutterActor *actor, { MetaWindowActor *self = META_WINDOW_ACTOR (actor); MetaWindowActorPrivate *priv = self->priv; - cairo_rectangle_int_t bounds; + cairo_rectangle_int_t unobscured_bounds, bounds; gboolean appears_focused = meta_window_appears_focused (priv->window); ClutterVertex origin; @@ -688,12 +684,8 @@ meta_window_actor_get_paint_volume (ClutterActor *actor, gdk_rectangle_union (&bounds, &shadow_bounds, &bounds); } - if (priv->unobscured_region && !clutter_actor_has_mapped_clones (actor)) - { - cairo_rectangle_int_t unobscured_bounds; - cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds); - gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); - } + if (meta_shaped_texture_get_unobscured_bounds (META_SHAPED_TEXTURE (priv->actor), &unobscured_bounds)) + gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); origin.x = bounds.x; origin.y = bounds.y; @@ -905,9 +897,7 @@ meta_window_actor_damage_all (MetaWindowActor *self) redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), 0, 0, cogl_texture_get_width (texture), - cogl_texture_get_height (texture), - clutter_actor_has_mapped_clones (priv->actor) ? - NULL : priv->unobscured_region); + cogl_texture_get_height (texture)); priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; priv->needs_damage_all = FALSE; } @@ -962,17 +952,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_shaped_texture_is_obscured (META_SHAPED_TEXTURE (priv->actor)); /* A frame was marked by the client without actually doing any * damage or any unobscured, or while we had the window frozen @@ -1641,30 +1621,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. - */ -static 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 @@ -1715,7 +1671,6 @@ meta_window_actor_cull_out (MetaCullable *cullable, if (priv->unredirected) 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); } @@ -1947,9 +1902,7 @@ meta_window_actor_process_damage (MetaWindowActor *self, event->area.x, event->area.y, event->area.width, - event->area.height, - clutter_actor_has_mapped_clones (priv->actor) ? - NULL : priv->unobscured_region); + event->area.height); priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; } diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h index 9eea4b8d9..b0870bf95 100644 --- a/src/meta/meta-shaped-texture.h +++ b/src/meta/meta-shaped-texture.h @@ -69,8 +69,7 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex, int x, int y, int width, - int height, - cairo_region_t *unobscured_region); + int height); CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);