shaped-texture: Move unobscured_region processing here

We want to remove a bunch of auxilliary duties from the MetaWindowActor
and MetaSurfaceActor, including some details of how culling is done.
Move the unobscured region culling code to the MetaShapedTexture, which
helps the actor become "more independent".

https://bugzilla.gnome.org/show_bug.cgi?id=720631
This commit is contained in:
Jasper St. Pierre 2014-02-05 14:06:32 -05:00
parent b580ccfe56
commit 8daefd92df
4 changed files with 101 additions and 67 deletions

View File

@ -32,5 +32,8 @@
ClutterActor *meta_shaped_texture_new (void); ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_texture (MetaShapedTexture *stex, void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture); 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 #endif

View File

@ -72,10 +72,15 @@ struct _MetaShapedTexturePrivate
CoglTexture *texture; CoglTexture *texture;
CoglTexture *mask_texture; CoglTexture *mask_texture;
cairo_region_t *clip_region;
cairo_region_t *opaque_region;
cairo_region_t *input_shape_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 tex_width, tex_height;
guint create_mipmaps : 1; guint create_mipmaps : 1;
@ -112,6 +117,21 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv->create_mipmaps = TRUE; 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 static void
set_clip_region (MetaShapedTexture *self, set_clip_region (MetaShapedTexture *self,
cairo_region_t *clip_region) cairo_region_t *clip_region)
@ -137,6 +157,7 @@ meta_shaped_texture_dispose (GObject *object)
g_clear_pointer (&priv->opaque_region, cairo_region_destroy); g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
meta_shaped_texture_set_mask_texture (self, NULL); meta_shaped_texture_set_mask_texture (self, NULL);
set_unobscured_region (self, NULL);
set_clip_region (self, NULL); set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
@ -497,10 +518,37 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
} }
static gboolean static gboolean
meta_shaped_texture_get_paint_volume (ClutterActor *self, meta_shaped_texture_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume) 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 void
@ -546,6 +594,40 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (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: * 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 * @y: the y coordinate of the damaged area
* @width: the width of the damaged area * @width: the width of the damaged area
* @height: the height 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 * Repairs the damaged area indicated by @x, @y, @width and @height
* and queues a redraw for the intersection @visibible_region and * and potentially queues a redraw.
* the damage area. If @visibible_region is %NULL a redraw will always
* get queued.
* *
* Return value: Whether a redraw have been queued or not * Return value: Whether a redraw have been queued or not
*/ */
@ -570,10 +647,10 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x, int x,
int y, int y,
int width, int width,
int height, int height)
cairo_region_t *unobscured_region)
{ {
MetaShapedTexturePrivate *priv; MetaShapedTexturePrivate *priv;
cairo_region_t *unobscured_region;
const cairo_rectangle_int_t clip = { x, y, width, height }; const cairo_rectangle_int_t clip = { x, y, width, height };
priv = stex->priv; 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); meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
unobscured_region = effective_unobscured_region (stex);
if (unobscured_region) if (unobscured_region)
{ {
cairo_region_t *intersection; cairo_region_t *intersection;
@ -851,6 +929,7 @@ meta_shaped_texture_cull_out (MetaCullable *cullable,
MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable); MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable);
MetaShapedTexturePrivate *priv = self->priv; MetaShapedTexturePrivate *priv = self->priv;
set_unobscured_region (self, unobscured_region);
set_clip_region (self, clip_region); set_clip_region (self, clip_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff) if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff)

View File

@ -74,9 +74,6 @@ struct _MetaWindowActorPrivate
/* The region we should clip to when painting the shadow */ /* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip; 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; guint send_frame_messages_timer;
gint64 frame_drawn_time; gint64 frame_drawn_time;
@ -395,7 +392,6 @@ meta_window_actor_dispose (GObject *object)
priv->send_frame_messages_timer = 0; 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->shape_region, cairo_region_destroy);
g_clear_pointer (&priv->shadow_clip, 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); MetaWindowActor *self = META_WINDOW_ACTOR (actor);
MetaWindowActorPrivate *priv = self->priv; 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); gboolean appears_focused = meta_window_appears_focused (priv->window);
ClutterVertex origin; ClutterVertex origin;
@ -688,12 +684,8 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds); gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
} }
if (priv->unobscured_region && !clutter_actor_has_mapped_clones (actor)) if (meta_shaped_texture_get_unobscured_bounds (META_SHAPED_TEXTURE (priv->actor), &unobscured_bounds))
{
cairo_rectangle_int_t unobscured_bounds;
cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds);
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
}
origin.x = bounds.x; origin.x = bounds.x;
origin.y = bounds.y; 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), redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
0, 0, 0, 0,
cogl_texture_get_width (texture), 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->repaint_scheduled = priv->repaint_scheduled || redraw_queued; priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
priv->needs_damage_all = FALSE; priv->needs_damage_all = FALSE;
} }
@ -962,17 +952,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
if (!priv->repaint_scheduled) if (!priv->repaint_scheduled)
{ {
gboolean is_obscured = FALSE; gboolean is_obscured = meta_shaped_texture_is_obscured (META_SHAPED_TEXTURE (priv->actor));
/* 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);
}
/* A frame was marked by the client without actually doing any /* A frame was marked by the client without actually doing any
* damage or any unobscured, or while we had the window frozen * damage or any unobscured, or while we had the window frozen
@ -1641,30 +1621,6 @@ see_region (cairo_region_t *region,
} }
#endif #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: * meta_window_actor_set_clip_region_beneath:
* @self: a #MetaWindowActor * @self: a #MetaWindowActor
@ -1715,7 +1671,6 @@ meta_window_actor_cull_out (MetaCullable *cullable,
if (priv->unredirected) if (priv->unredirected)
return; return;
meta_window_actor_set_unobscured_region (self, unobscured_region);
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
meta_window_actor_set_clip_region_beneath (self, 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.x,
event->area.y, event->area.y,
event->area.width, event->area.width,
event->area.height, event->area.height);
clutter_actor_has_mapped_clones (priv->actor) ?
NULL : priv->unobscured_region);
priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
} }

View File

@ -69,8 +69,7 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x, int x,
int y, int y,
int width, int width,
int height, int height);
cairo_region_t *unobscured_region);
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);