Port MetaShapedTexture/MetaWindowActor to use cairo regions instead of XRects
https://bugzilla.gnome.org/show_bug.cgi?id=644930
This commit is contained in:
parent
183bcd6fc7
commit
65e1b416ef
@ -34,7 +34,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void meta_shaped_texture_dispose (GObject *object);
|
static void meta_shaped_texture_dispose (GObject *object);
|
||||||
static void meta_shaped_texture_finalize (GObject *object);
|
|
||||||
static void meta_shaped_texture_notify (GObject *object,
|
static void meta_shaped_texture_notify (GObject *object,
|
||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
|
|
||||||
@ -65,11 +64,10 @@ struct _MetaShapedTexturePrivate
|
|||||||
CoglHandle material_unshaped;
|
CoglHandle material_unshaped;
|
||||||
|
|
||||||
cairo_region_t *clip_region;
|
cairo_region_t *clip_region;
|
||||||
|
cairo_region_t *shape_region;
|
||||||
|
|
||||||
guint mask_width, mask_height;
|
guint mask_width, mask_height;
|
||||||
|
|
||||||
GArray *rectangles;
|
|
||||||
|
|
||||||
guint create_mipmaps : 1;
|
guint create_mipmaps : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,7 +79,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
|||||||
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
|
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
|
||||||
|
|
||||||
gobject_class->dispose = meta_shaped_texture_dispose;
|
gobject_class->dispose = meta_shaped_texture_dispose;
|
||||||
gobject_class->finalize = meta_shaped_texture_finalize;
|
|
||||||
gobject_class->notify = meta_shaped_texture_notify;
|
gobject_class->notify = meta_shaped_texture_notify;
|
||||||
|
|
||||||
actor_class->paint = meta_shaped_texture_paint;
|
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 = 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->paint_tower = meta_texture_tower_new ();
|
||||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||||
priv->create_mipmaps = TRUE;
|
priv->create_mipmaps = TRUE;
|
||||||
@ -129,22 +125,12 @@ meta_shaped_texture_dispose (GObject *object)
|
|||||||
priv->material_unshaped = COGL_INVALID_HANDLE;
|
priv->material_unshaped = COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_shaped_texture_set_shape_region (self, NULL);
|
||||||
meta_shaped_texture_set_clip_region (self, NULL);
|
meta_shaped_texture_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
static void
|
||||||
meta_shaped_texture_notify (GObject *object,
|
meta_shaped_texture_notify (GObject *object,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
@ -210,19 +196,23 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
|
|||||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
guchar *mask_data;
|
guchar *mask_data;
|
||||||
const XRectangle *rect;
|
int i;
|
||||||
|
int n_rects;
|
||||||
GLenum paint_gl_target;
|
GLenum paint_gl_target;
|
||||||
|
|
||||||
/* Create data for an empty image */
|
/* Create data for an empty image */
|
||||||
mask_data = g_malloc0 (tex_width * tex_height);
|
mask_data = g_malloc0 (tex_width * tex_height);
|
||||||
|
|
||||||
/* Cut out a hole for each rectangle */
|
n_rects = cairo_region_num_rectangles (priv->shape_region);
|
||||||
for (rect = (XRectangle *) priv->rectangles->data
|
|
||||||
+ priv->rectangles->len;
|
/* Fill in each rectangle. */
|
||||||
rect-- > (XRectangle *) priv->rectangles->data;)
|
for (i = 0; i < n_rects; i ++)
|
||||||
{
|
{
|
||||||
gint x1 = rect->x, x2 = x1 + rect->width;
|
cairo_rectangle_int_t rect;
|
||||||
gint y1 = rect->y, y2 = y1 + rect->height;
|
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;
|
guchar *p;
|
||||||
|
|
||||||
/* Clip the rectangle to the size of the texture */
|
/* 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 */
|
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||||
return;
|
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)
|
if (priv->material_unshaped == COGL_INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
@ -423,8 +413,8 @@ meta_shaped_texture_pick (ClutterActor *actor,
|
|||||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||||
MetaShapedTexturePrivate *priv = stex->priv;
|
MetaShapedTexturePrivate *priv = stex->priv;
|
||||||
|
|
||||||
/* If there are no rectangles then use the regular pick */
|
/* If there is no region then use the regular pick */
|
||||||
if (priv->rectangles->len < 1)
|
if (priv->shape_region == NULL)
|
||||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
|
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
|
||||||
->pick (actor, color);
|
->pick (actor, color);
|
||||||
else if (clutter_actor_should_pick_paint (actor))
|
else if (clutter_actor_should_pick_paint (actor))
|
||||||
@ -544,7 +534,8 @@ meta_shaped_texture_clear (MetaShapedTexture *stex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
|
meta_shaped_texture_set_shape_region (MetaShapedTexture *stex,
|
||||||
|
cairo_region_t *region)
|
||||||
{
|
{
|
||||||
MetaShapedTexturePrivate *priv;
|
MetaShapedTexturePrivate *priv;
|
||||||
|
|
||||||
@ -552,33 +543,18 @@ meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
|
|||||||
|
|
||||||
priv = stex->priv;
|
priv = stex->priv;
|
||||||
|
|
||||||
g_array_set_size (priv->rectangles, 0);
|
if (priv->shape_region != NULL)
|
||||||
meta_shaped_texture_dirty_mask (stex);
|
{
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
cairo_region_destroy (priv->shape_region);
|
||||||
|
priv->shape_region = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
if (region != NULL)
|
||||||
meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
|
|
||||||
const XRectangle *rect)
|
|
||||||
{
|
{
|
||||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
cairo_region_reference (region);
|
||||||
|
priv->shape_region = region;
|
||||||
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);
|
|
||||||
|
|
||||||
meta_shaped_texture_dirty_mask (stex);
|
meta_shaped_texture_dirty_mask (stex);
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||||
}
|
}
|
||||||
|
@ -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 (MetaShapedTexture *stex);
|
||||||
|
|
||||||
void meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex);
|
void meta_shaped_texture_set_shape_region (MetaShapedTexture *stex,
|
||||||
|
cairo_region_t *region);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Assumes ownership of clip_region */
|
/* Assumes ownership of clip_region */
|
||||||
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||||
|
@ -1701,20 +1701,15 @@ meta_window_actor_update_bounding_region (MetaWindowActor *self,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||||
int n_rects,
|
cairo_region_t *region)
|
||||||
XRectangle *rects)
|
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
int i;
|
|
||||||
|
|
||||||
meta_window_actor_clear_shape_region (self);
|
meta_window_actor_clear_shape_region (self);
|
||||||
|
|
||||||
priv->shape_region = cairo_region_create ();
|
/* region must be non-null */
|
||||||
for (i = 0; i < n_rects; i++)
|
priv->shape_region = region;
|
||||||
{
|
cairo_region_reference (region);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our "shape_region" is called the "bounding region" in the X Shape
|
/* Our "shape_region" is called the "bounding region" in the X Shape
|
||||||
* Extension Documentation.
|
* Extension Documentation.
|
||||||
@ -2106,12 +2101,12 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaScreen *screen = priv->screen;
|
MetaScreen *screen = priv->screen;
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
|
cairo_region_t *region;
|
||||||
|
|
||||||
if (!priv->needs_reshape)
|
if (!priv->needs_reshape)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_shaped_texture_clear_rectangles (META_SHAPED_TEXTURE (priv->actor));
|
region = NULL;
|
||||||
meta_window_actor_clear_shape_region (self);
|
|
||||||
|
|
||||||
#ifdef HAVE_SHAPE
|
#ifdef HAVE_SHAPE
|
||||||
if (priv->shaped)
|
if (priv->shaped)
|
||||||
@ -2130,16 +2125,30 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
|
|
||||||
if (rects)
|
if (rects)
|
||||||
{
|
{
|
||||||
meta_shaped_texture_add_rectangles (META_SHAPED_TEXTURE (priv->actor),
|
int i;
|
||||||
n_rects, rects);
|
|
||||||
|
|
||||||
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);
|
XFree (rects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
priv->needs_reshape = FALSE;
|
||||||
meta_window_actor_invalidate_shadow (self);
|
meta_window_actor_invalidate_shadow (self);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user