Port MetaShapedTexture/MetaWindowActor to use cairo regions instead of XRects

https://bugzilla.gnome.org/show_bug.cgi?id=644930
This commit is contained in:
Jasper St. Pierre 2011-07-08 15:06:13 -04:00
parent 183bcd6fc7
commit 65e1b416ef
3 changed files with 55 additions and 75 deletions

View File

@ -34,7 +34,6 @@
#include <string.h>
static void meta_shaped_texture_dispose (GObject *object);
static void meta_shaped_texture_finalize (GObject *object);
static void meta_shaped_texture_notify (GObject *object,
GParamSpec *pspec);
@ -65,11 +64,10 @@ struct _MetaShapedTexturePrivate
CoglHandle material_unshaped;
cairo_region_t *clip_region;
cairo_region_t *shape_region;
guint mask_width, mask_height;
GArray *rectangles;
guint create_mipmaps : 1;
};
@ -81,7 +79,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
gobject_class->dispose = meta_shaped_texture_dispose;
gobject_class->finalize = meta_shaped_texture_finalize;
gobject_class->notify = meta_shaped_texture_notify;
actor_class->paint = meta_shaped_texture_paint;
@ -99,8 +96,7 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
priv->shape_region = NULL;
priv->paint_tower = meta_texture_tower_new ();
priv->mask_texture = COGL_INVALID_HANDLE;
priv->create_mipmaps = TRUE;
@ -129,22 +125,12 @@ meta_shaped_texture_dispose (GObject *object)
priv->material_unshaped = COGL_INVALID_HANDLE;
}
meta_shaped_texture_set_shape_region (self, NULL);
meta_shaped_texture_set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
static void
meta_shaped_texture_finalize (GObject *object)
{
MetaShapedTexture *self = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = self->priv;
g_array_free (priv->rectangles, TRUE);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->finalize (object);
}
static void
meta_shaped_texture_notify (GObject *object,
GParamSpec *pspec)
@ -210,19 +196,23 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
if (priv->mask_texture == COGL_INVALID_HANDLE)
{
guchar *mask_data;
const XRectangle *rect;
int i;
int n_rects;
GLenum paint_gl_target;
/* Create data for an empty image */
mask_data = g_malloc0 (tex_width * tex_height);
/* Cut out a hole for each rectangle */
for (rect = (XRectangle *) priv->rectangles->data
+ priv->rectangles->len;
rect-- > (XRectangle *) priv->rectangles->data;)
n_rects = cairo_region_num_rectangles (priv->shape_region);
/* Fill in each rectangle. */
for (i = 0; i < n_rects; i ++)
{
gint x1 = rect->x, x2 = x1 + rect->width;
gint y1 = rect->y, y2 = y1 + rect->height;
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (priv->shape_region, i, &rect);
gint x1 = rect.x, x2 = x1 + rect.width;
gint y1 = rect.y, y2 = y1 + rect.height;
guchar *p;
/* Clip the rectangle to the size of the texture */
@ -321,9 +311,9 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
if (priv->rectangles->len < 1)
if (priv->shape_region == NULL)
{
/* If there are no rectangles use a single-layer texture */
/* No region means an unclipped shape. Use a single-layer texture. */
if (priv->material_unshaped == COGL_INVALID_HANDLE)
{
@ -423,8 +413,8 @@ meta_shaped_texture_pick (ClutterActor *actor,
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
/* If there are no rectangles then use the regular pick */
if (priv->rectangles->len < 1)
/* If there is no region then use the regular pick */
if (priv->shape_region == NULL)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
@ -544,7 +534,8 @@ meta_shaped_texture_clear (MetaShapedTexture *stex)
}
void
meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
meta_shaped_texture_set_shape_region (MetaShapedTexture *stex,
cairo_region_t *region)
{
MetaShapedTexturePrivate *priv;
@ -552,32 +543,17 @@ meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
priv = stex->priv;
g_array_set_size (priv->rectangles, 0);
meta_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
if (priv->shape_region != NULL)
{
cairo_region_destroy (priv->shape_region);
priv->shape_region = NULL;
}
void
meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
const XRectangle *rect)
{
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
meta_shaped_texture_add_rectangles (stex, 1, rect);
}
void
meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
size_t num_rects,
const XRectangle *rects)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
g_array_append_vals (priv->rectangles, rects, num_rects);
if (region != NULL)
{
cairo_region_reference (region);
priv->shape_region = region;
}
meta_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));

View File

@ -65,13 +65,8 @@ void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
void meta_shaped_texture_clear (MetaShapedTexture *stex);
void meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex);
void meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
const XRectangle *rect);
void meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
size_t num_rects,
const XRectangle *rects);
void meta_shaped_texture_set_shape_region (MetaShapedTexture *stex,
cairo_region_t *region);
/* Assumes ownership of clip_region */
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,

View File

@ -1701,20 +1701,15 @@ meta_window_actor_update_bounding_region (MetaWindowActor *self,
static void
meta_window_actor_update_shape_region (MetaWindowActor *self,
int n_rects,
XRectangle *rects)
cairo_region_t *region)
{
MetaWindowActorPrivate *priv = self->priv;
int i;
meta_window_actor_clear_shape_region (self);
priv->shape_region = cairo_region_create ();
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect = { rects[i].x, rects[i].y, rects[i].width, rects[i].height };
cairo_region_union_rectangle (priv->shape_region, &rect);
}
/* region must be non-null */
priv->shape_region = region;
cairo_region_reference (region);
/* Our "shape_region" is called the "bounding region" in the X Shape
* Extension Documentation.
@ -2106,12 +2101,12 @@ check_needs_reshape (MetaWindowActor *self)
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
cairo_region_t *region;
if (!priv->needs_reshape)
return;
meta_shaped_texture_clear_rectangles (META_SHAPED_TEXTURE (priv->actor));
meta_window_actor_clear_shape_region (self);
region = NULL;
#ifdef HAVE_SHAPE
if (priv->shaped)
@ -2130,16 +2125,30 @@ check_needs_reshape (MetaWindowActor *self)
if (rects)
{
meta_shaped_texture_add_rectangles (META_SHAPED_TEXTURE (priv->actor),
n_rects, rects);
int i;
meta_window_actor_update_shape_region (self, n_rects, rects);
region = cairo_region_create ();
for (i = 0; i < n_rects; i ++)
{
cairo_rectangle_int_t rect = { rects[i].x,
rects[i].y,
rects[i].width,
rects[i].height };
cairo_region_union_rectangle (region, &rect);
}
XFree (rects);
}
}
#endif
meta_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor),
region);
meta_window_actor_update_shape_region (self, region);
cairo_region_destroy (region);
priv->needs_reshape = FALSE;
meta_window_actor_invalidate_shadow (self);
}