diff --git a/src/Makefile.am b/src/Makefile.am index 8759f766c..2d6baaa95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,7 +52,6 @@ libmutter_la_SOURCES = \ compositor/meta-shadow-factory.c \ compositor/meta-shadow-factory-private.h \ compositor/meta-shaped-texture.c \ - compositor/meta-shaped-texture.h \ compositor/meta-texture-rectangle.c \ compositor/meta-texture-rectangle.h \ compositor/meta-texture-tower.c \ @@ -172,6 +171,7 @@ libmutterinclude_base_headers = \ meta/main.h \ meta/meta-background-actor.h \ meta/meta-plugin.h \ + meta/meta-shaped-texture.h \ meta/meta-shadow-factory.h \ meta/meta-window-actor.h \ meta/prefs.h \ diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 7aa8f9e4f..0e48cdb46 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -25,32 +25,36 @@ #include -#include "meta-shaped-texture.h" +#include #include "meta-texture-tower.h" #include "meta-texture-rectangle.h" #include #include +#define COGL_ENABLE_EXPERIMENTAL_API +#include #include static void meta_shaped_texture_dispose (GObject *object); -static void meta_shaped_texture_notify (GObject *object, - GParamSpec *pspec); static void meta_shaped_texture_paint (ClutterActor *actor); static void meta_shaped_texture_pick (ClutterActor *actor, const ClutterColor *color); -static void meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture, - int x, - int y, - int width, - int height); +static void meta_shaped_texture_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p); + +static void meta_shaped_texture_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p); static void meta_shaped_texture_dirty_mask (MetaShapedTexture *stex); G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture, - CLUTTER_X11_TYPE_TEXTURE_PIXMAP); + CLUTTER_TYPE_ACTOR); #define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \ @@ -59,6 +63,8 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture, struct _MetaShapedTexturePrivate { MetaTextureTower *paint_tower; + Pixmap pixmap; + CoglHandle texture; CoglHandle mask_texture; CoglHandle material; CoglHandle material_unshaped; @@ -71,6 +77,7 @@ struct _MetaShapedTexturePrivate cairo_region_t *visible_pixels_region; + guint tex_width, tex_height; guint mask_width, mask_height; guint create_mipmaps : 1; @@ -81,16 +88,14 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; ClutterActorClass *actor_class = (ClutterActorClass *) klass; - ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass; gobject_class->dispose = meta_shaped_texture_dispose; - gobject_class->notify = meta_shaped_texture_notify; + actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width; + actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height; actor_class->paint = meta_shaped_texture_paint; actor_class->pick = meta_shaped_texture_pick; - x11_texture_class->update_area = meta_shaped_texture_update_area; - g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate)); } @@ -106,6 +111,7 @@ meta_shaped_texture_init (MetaShapedTexture *self) priv->overlay_region = NULL; priv->visible_pixels_region = NULL; priv->paint_tower = meta_texture_tower_new (); + priv->texture = COGL_INVALID_HANDLE; priv->mask_texture = COGL_INVALID_HANDLE; priv->create_mipmaps = TRUE; } @@ -132,6 +138,11 @@ meta_shaped_texture_dispose (GObject *object) cogl_handle_unref (priv->material_unshaped); priv->material_unshaped = COGL_INVALID_HANDLE; } + if (priv->texture != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->texture); + priv->texture = COGL_INVALID_HANDLE; + } meta_shaped_texture_set_shape_region (self, NULL); meta_shaped_texture_set_clip_region (self, NULL); @@ -140,31 +151,6 @@ meta_shaped_texture_dispose (GObject *object) G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); } -static void -meta_shaped_texture_notify (GObject *object, - GParamSpec *pspec) -{ - if (G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify) - G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify (object, pspec); - - /* It seems like we could just do this out of update_area(), but unfortunately, - * clutter_glx_texture_pixmap() doesn't call through the vtable on the - * initial update_area, so we need to look for changes to the texture - * explicitly. - */ - if (strcmp (pspec->name, "cogl-texture") == 0) - { - MetaShapedTexture *stex = (MetaShapedTexture *) object; - MetaShapedTexturePrivate *priv = stex->priv; - - meta_shaped_texture_clear (stex); - - if (priv->create_mipmaps) - meta_texture_tower_set_base_texture (priv->paint_tower, - clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex))); - } -} - static void meta_shaped_texture_dirty_mask (MetaShapedTexture *stex) { @@ -310,7 +296,7 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex) CoglHandle paint_tex; guint tex_width, tex_height; - paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)); + paint_tex = priv->texture; if (paint_tex == COGL_INVALID_HANDLE) return; @@ -451,13 +437,13 @@ meta_shaped_texture_paint (ClutterActor *actor) if (priv->create_mipmaps) paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower); else - paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)); + paint_tex = priv->texture; if (paint_tex == COGL_INVALID_HANDLE) return; - tex_width = cogl_texture_get_width (paint_tex); - tex_height = cogl_texture_get_height (paint_tex); + tex_width = priv->tex_width; + tex_height = priv->tex_height; if (tex_width == 0 || tex_height == 0) /* no contents yet */ return; @@ -574,7 +560,7 @@ meta_shaped_texture_pick (ClutterActor *actor, ClutterActorBox alloc; guint tex_width, tex_height; - paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)); + paint_tex = priv->texture; if (paint_tex == COGL_INVALID_HANDLE) return; @@ -602,19 +588,41 @@ meta_shaped_texture_pick (ClutterActor *actor, } static void -meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture, - int x, - int y, - int width, - int height) +meta_shaped_texture_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) { - MetaShapedTexture *stex = (MetaShapedTexture *) texture; - MetaShapedTexturePrivate *priv = stex->priv; + MetaShapedTexturePrivate *priv; - CLUTTER_X11_TEXTURE_PIXMAP_CLASS (meta_shaped_texture_parent_class)->update_area (texture, - x, y, width, height); + g_return_if_fail (META_IS_SHAPED_TEXTURE (self)); - meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); + priv = META_SHAPED_TEXTURE (self)->priv; + + if (min_width_p) + *min_width_p = 0; + + if (natural_width_p) + *natural_width_p = priv->tex_width; +} + +static void +meta_shaped_texture_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + MetaShapedTexturePrivate *priv; + + g_return_if_fail (META_IS_SHAPED_TEXTURE (self)); + + priv = META_SHAPED_TEXTURE (self)->priv; + + if (min_height_p) + *min_height_p = 0; + + if (natural_height_p) + *natural_height_p = priv->tex_height; } ClutterActor * @@ -640,50 +648,13 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, if (create_mipmaps != priv->create_mipmaps) { CoglHandle base_texture; - priv->create_mipmaps = create_mipmaps; - base_texture = create_mipmaps ? - clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)) : COGL_INVALID_HANDLE; - + priv->texture : COGL_INVALID_HANDLE; meta_texture_tower_set_base_texture (priv->paint_tower, base_texture); } } -/* This is a workaround for deficiencies in the hack tower: - * - * When we call clutter_x11_texture_pixmap_set_pixmap(tp, None), - * ClutterX11TexturePixmap knows that it has to get rid of the old texture, but - * clutter_texture_set_cogl_texture(texture, COGL_INVALID_HANDLE) isn't allowed, so - * it grabs the material for the texture and manually sets the texture in it. This means - * that the "cogl-texture" property isn't notified, so we don't find out about it. - * - * And if we keep the CoglX11TexturePixmap around after the X pixmap is freed, then - * we'll trigger X errors when we actually try to free it. - * - * The only correct thing to do here is to change our code to derive - * from ClutterActor and get rid of the inheritance hack tower. Once - * we want to depend on Clutter-1.4 (which has CoglTexturePixmapX11), - * that will be very easy to do. - */ -void -meta_shaped_texture_clear (MetaShapedTexture *stex) -{ - MetaShapedTexturePrivate *priv; - - g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - - priv = stex->priv; - - meta_texture_tower_set_base_texture (priv->paint_tower, COGL_INVALID_HANDLE); - - if (priv->material != COGL_INVALID_HANDLE) - cogl_material_set_layer (priv->material, 0, COGL_INVALID_HANDLE); - - if (priv->material_unshaped != COGL_INVALID_HANDLE) - cogl_material_set_layer (priv->material_unshaped, 0, COGL_INVALID_HANDLE); -} - void meta_shaped_texture_set_shape_region (MetaShapedTexture *stex, cairo_region_t *region) @@ -710,6 +681,75 @@ meta_shaped_texture_set_shape_region (MetaShapedTexture *stex, clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); } +void +meta_shaped_texture_update_area (MetaShapedTexture *stex, + int x, + int y, + int width, + int height) +{ + MetaShapedTexturePrivate *priv; + const cairo_rectangle_int_t clip = { x, y, width, height }; + + priv = stex->priv; + + if (priv->texture == COGL_INVALID_HANDLE) + return; + + cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height); + + meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); + + clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); +} + +static void +set_cogl_texture (MetaShapedTexture *stex, + CoglHandle cogl_tex) +{ + MetaShapedTexturePrivate *priv; + guint width, height; + + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + + priv = stex->priv; + + if (priv->texture != COGL_INVALID_HANDLE) + cogl_handle_unref (priv->texture); + + priv->texture = cogl_tex; + + if (priv->material != COGL_INVALID_HANDLE) + cogl_material_set_layer (priv->material, 0, cogl_tex); + + if (priv->material_unshaped != COGL_INVALID_HANDLE) + cogl_material_set_layer (priv->material_unshaped, 0, cogl_tex); + + if (cogl_tex != COGL_INVALID_HANDLE) + { + width = cogl_texture_get_width (cogl_tex); + height = cogl_texture_get_height (cogl_tex); + + if (width != priv->tex_width || + height != priv->tex_height) + { + priv->tex_width = width; + priv->tex_height = height; + + clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); + } + } + else + { + /* size changed to 0 going to an invalid handle */ + priv->tex_width = 0; + priv->tex_height = 0; + clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); + } + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); +} + /** * meta_shaped_texture_get_visible_pixels_region: * @stex: a #MetaShapedTexture @@ -728,13 +768,55 @@ meta_shaped_texture_get_visible_pixels_region (MetaShapedTexture *stex) return stex->priv->visible_pixels_region; } +/** + * meta_shaped_texture_set_pixmap: + * @stex: The #MetaShapedTexture + * @pixmap: The pixmap you want the stex to assume + */ +void +meta_shaped_texture_set_pixmap (MetaShapedTexture *stex, + Pixmap pixmap) +{ + MetaShapedTexturePrivate *priv; + + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + + priv = stex->priv; + + if (priv->pixmap == pixmap) + return; + + priv->pixmap = pixmap; + + if (pixmap != None) + set_cogl_texture (stex, cogl_texture_pixmap_x11_new (pixmap, FALSE)); + else + set_cogl_texture (stex, COGL_INVALID_HANDLE); + + if (priv->create_mipmaps) + meta_texture_tower_set_base_texture (priv->paint_tower, priv->texture); +} + +/** + * meta_shaped_texture_get_texture: + * @stex: The #MetaShapedTexture + * + * Returns: (transfer none): the unshaped texture + */ +CoglHandle +meta_shaped_texture_get_texture (MetaShapedTexture *stex) +{ + g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), COGL_INVALID_HANDLE); + return stex->priv->texture; +} + /** * meta_shaped_texture_set_overlay_path: * @stex: a #MetaShapedTexture * @overlay_region: A region containing the parts of the mask to overlay. * All rectangles in this region are wiped clear to full transparency, * and the overlay path is clipped to this region. - * @overlay_path (transfer full): This path will be painted onto the mask + * @overlay_path: (transfer full): This path will be painted onto the mask * texture with a fully opaque source. Due to the lack of refcounting * in #cairo_path_t, ownership of the path is assumed. */ @@ -772,7 +854,7 @@ meta_shaped_texture_set_overlay_path (MetaShapedTexture *stex, /** * meta_shaped_texture_set_clip_region: - * @frame: a #MetaShapedTexture + * @stex: a #MetaShapedTexture * @clip_region: (transfer full): the region of the texture that * is visible and should be painted. OWNERSHIP IS ASSUMED BY * THE FUNCTION (for efficiency to avoid a copy.) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 16d136fcc..0904205e2 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -18,11 +18,11 @@ #include #include "frame.h" #include +#include #include "xprops.h" #include "compositor-private.h" #include "meta-shadow-factory-private.h" -#include "meta-shaped-texture.h" #include "meta-window-actor-private.h" enum { @@ -944,26 +944,20 @@ static void meta_window_actor_damage_all (MetaWindowActor *self) { MetaWindowActorPrivate *priv = self->priv; - ClutterX11TexturePixmap *texture_x11 = CLUTTER_X11_TEXTURE_PIXMAP (priv->actor); - guint pixmap_width = 0; - guint pixmap_height = 0; + CoglHandle texture; if (!priv->needs_damage_all) return; - g_object_get (texture_x11, - "pixmap-width", &pixmap_width, - "pixmap-height", &pixmap_height, - NULL); + texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor)); if (!priv->mapped || priv->needs_pixmap) return; - clutter_x11_texture_pixmap_update_area (texture_x11, - 0, - 0, - pixmap_width, - pixmap_height); + meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), + 0, 0, + cogl_texture_get_width (texture), + cogl_texture_get_height (texture)); priv->needs_damage_all = FALSE; } @@ -1202,9 +1196,8 @@ meta_window_actor_detach (MetaWindowActor *self) * you are supposed to be able to free a GLXPixmap after freeing the underlying * pixmap, but it certainly doesn't work with current DRI/Mesa */ - clutter_x11_texture_pixmap_set_pixmap (CLUTTER_X11_TEXTURE_PIXMAP (priv->actor), - None); - meta_shaped_texture_clear (META_SHAPED_TEXTURE (priv->actor)); + meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor), + None); cogl_flush(); XFreePixmap (xdisplay, priv->back_pixmap); @@ -1823,19 +1816,6 @@ meta_window_actor_reset_visible_regions (MetaWindowActor *self) meta_window_actor_clear_shadow_clip (self); } -static gboolean -texture_pixmap_using_extension (ClutterX11TexturePixmap *texture) -{ - ClutterTexture *self = CLUTTER_TEXTURE (texture); - CoglHandle handle; - - handle = clutter_texture_get_cogl_texture (self); - - return handle != NULL && - cogl_is_texture_pixmap_x11 (handle) && - cogl_texture_pixmap_x11_is_using_tfp_extension (handle); -} - static void check_needs_pixmap (MetaWindowActor *self) { @@ -1869,7 +1849,7 @@ check_needs_pixmap (MetaWindowActor *self) if (priv->back_pixmap == None) { - gint pxm_width, pxm_height; + CoglHandle texture; meta_error_trap_push (display); @@ -1898,23 +1878,22 @@ check_needs_pixmap (MetaWindowActor *self) meta_shaped_texture_set_create_mipmaps (META_SHAPED_TEXTURE (priv->actor), FALSE); - clutter_x11_texture_pixmap_set_pixmap - (CLUTTER_X11_TEXTURE_PIXMAP (priv->actor), - priv->back_pixmap); + meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor), + priv->back_pixmap); + + texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor)); + /* * This only works *after* actually setting the pixmap, so we have to * do it here. * See: http://bugzilla.clutter-project.org/show_bug.cgi?id=2236 */ - if (G_UNLIKELY (!texture_pixmap_using_extension (CLUTTER_X11_TEXTURE_PIXMAP (priv->actor)))) + if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (texture))) g_warning ("NOTE: Not using GLX TFP!\n"); - g_object_get (priv->actor, - "pixmap-width", &pxm_width, - "pixmap-height", &pxm_height, - NULL); - - meta_window_actor_update_bounding_region_and_borders (self, pxm_width, pxm_height); + meta_window_actor_update_bounding_region_and_borders (self, + cogl_texture_get_width (texture), + cogl_texture_get_height (texture)); } priv->needs_pixmap = FALSE; @@ -2007,7 +1986,6 @@ meta_window_actor_process_damage (MetaWindowActor *self, XDamageNotifyEvent *event) { MetaWindowActorPrivate *priv = self->priv; - ClutterX11TexturePixmap *texture_x11 = CLUTTER_X11_TEXTURE_PIXMAP (priv->actor); priv->received_damage = TRUE; @@ -2038,11 +2016,11 @@ meta_window_actor_process_damage (MetaWindowActor *self, if (!priv->mapped || priv->needs_pixmap) return; - clutter_x11_texture_pixmap_update_area (texture_x11, - event->area.x, - event->area.y, - event->area.width, - event->area.height); + meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), + event->area.x, + event->area.y, + event->area.width, + event->area.height); } void diff --git a/src/compositor/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h similarity index 82% rename from src/compositor/meta-shaped-texture.h rename to src/meta/meta-shaped-texture.h index a36fe6bce..cb2526b2a 100644 --- a/src/compositor/meta-shaped-texture.h +++ b/src/meta/meta-shaped-texture.h @@ -26,10 +26,8 @@ #ifndef __META_SHAPED_TEXTURE_H__ #define __META_SHAPED_TEXTURE_H__ -#include - #include -#include +#include G_BEGIN_DECLS @@ -46,12 +44,12 @@ typedef struct _MetaShapedTexturePrivate MetaShapedTexturePrivate; struct _MetaShapedTextureClass { - ClutterX11TexturePixmapClass parent_class; + ClutterActorClass parent_class; }; struct _MetaShapedTexture { - ClutterX11TexturePixmap parent; + ClutterActor parent; MetaShapedTexturePrivate *priv; }; @@ -63,7 +61,16 @@ ClutterActor *meta_shaped_texture_new (void); void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, gboolean create_mipmaps); -void meta_shaped_texture_clear (MetaShapedTexture *stex); +void meta_shaped_texture_update_area (MetaShapedTexture *stex, + int x, + int y, + int width, + int height); + +void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex, + Pixmap pixmap); + +CoglHandle meta_shaped_texture_get_texture (MetaShapedTexture *stex); void meta_shaped_texture_set_shape_region (MetaShapedTexture *stex, cairo_region_t *region);