From dd39d7a06008cba613e0b20ed08c1ae42d6da638 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Wed, 26 Dec 2018 13:41:26 -0200 Subject: [PATCH] shaped-texture: Implement ClutterContent MetaWindowActor is the compositor-side representative of a MetaWindow. Specifically it represents the geometry of the window under Clutter scene graph. MetaWindowActors are backed by MetaSurfaceActors, that represent the windowing system's surfaces themselves. Naturally, these surfaces have textures with the pixel content of the clients associated with them. These textures are represented by MetaShapedTexture. MetaShapedTextures are currently implemented as ClutterActor subclasses that override the paint function to paint the textures it holds. Conceptually, however, Clutter has an abstraction layer for contents of actors: ClutterContent. Which MetaShapedTexture fits nicely, in fact. Make MetaShapedTexture a ClutterContent implementation. This forces a few changes in the stack: * MetaShapedTexture now manually tracks the content scale. * We now paint into ClutterPaintNode instead of the direct framebuffer. * Various pieces of Wayland code now use MetaSurfaceActor instead of MetaShapedTexture. * MetaSurfaceActorWayland doesn't override size negotiation vfuncs anymore --- src/compositor/meta-shaped-texture-private.h | 8 + src/compositor/meta-shaped-texture.c | 540 +++++++++++++------ src/compositor/meta-surface-actor-wayland.c | 50 -- src/compositor/meta-surface-actor.c | 16 +- src/compositor/meta-window-actor.c | 16 +- src/meta/meta-window-actor.h | 3 +- src/wayland/meta-wayland-actor-surface.c | 2 +- src/wayland/meta-wayland-data-device.c | 2 +- src/wayland/meta-wayland-surface.c | 4 +- src/wayland/meta-wayland-tablet-tool.c | 2 +- 10 files changed, 423 insertions(+), 220 deletions(-) diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index 44816a14d..f926a272c 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -44,5 +44,13 @@ gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex); void meta_shaped_texture_set_transform (MetaShapedTexture *stex, MetaMonitorTransform transform); +void meta_shaped_texture_cull_out (MetaShapedTexture *stex, + cairo_region_t *unobscured_region, + cairo_region_t *clip_region, + uint8_t opacity); +void meta_shaped_texture_reset_culling (MetaShapedTexture *stex); +void meta_shaped_texture_set_scale (MetaShapedTexture *stex, + double scale); +double meta_shaped_texture_get_scale (MetaShapedTexture *stex); #endif diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 9f96d6718..f915dfac0 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -57,21 +57,7 @@ static void meta_shaped_texture_dispose (GObject *object); -static void meta_shaped_texture_paint (ClutterActor *actor); - -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 gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume); - -static void cullable_iface_init (MetaCullableInterface *iface); +static void clutter_content_iface_init (ClutterContentIface *iface); enum { SIZE_CHANGED, @@ -83,7 +69,7 @@ static guint signals[LAST_SIGNAL]; struct _MetaShapedTexture { - ClutterActor parent; + GObject parent; MetaTextureTower *paint_tower; @@ -116,25 +102,21 @@ struct _MetaShapedTexture guint remipmap_timeout_id; gint64 earliest_remipmap; + double scale; + guint create_mipmaps : 1; }; -G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); +G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, clutter_content_iface_init)); static void meta_shaped_texture_class_init (MetaShapedTextureClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; - ClutterActorClass *actor_class = (ClutterActorClass *) klass; gobject_class->dispose = meta_shaped_texture_dispose; - 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->get_paint_volume = meta_shaped_texture_get_paint_volume; - signals[SIZE_CHANGED] = g_signal_new ("size-changed", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, @@ -154,16 +136,12 @@ meta_shaped_texture_init (MetaShapedTexture *stex) { stex->paint_tower = meta_texture_tower_new (); + stex->scale = 1.0; stex->texture = NULL; stex->mask_texture = NULL; stex->create_mipmaps = TRUE; stex->is_y_inverted = TRUE; stex->transform = META_MONITOR_TRANSFORM_NORMAL; - - g_signal_connect (stex, - "notify::scale-x", - G_CALLBACK (invalidate_size), - stex); } static void @@ -207,7 +185,7 @@ update_size (MetaShapedTexture *stex) stex->dst_width = dst_width; stex->dst_height = dst_height; meta_shaped_texture_set_mask_texture (stex, NULL); - clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); + clutter_content_invalidate_size (CLUTTER_CONTENT (stex)); g_signal_emit (stex, signals[SIZE_CHANGED], 0); } } @@ -436,6 +414,40 @@ paint_clipped_rectangle (CoglFramebuffer *fb, &coords[0], 8); } +static void +paint_clipped_rectangle_node (ClutterPaintNode *root_node, + CoglPipeline *pipeline, + cairo_rectangle_int_t *rect, + ClutterActorBox *alloc) +{ + g_autoptr(ClutterPaintNode) node = NULL; + float coords[8]; + + coords[0] = rect->x / (alloc->x2 - alloc->x1); + coords[1] = rect->y / (alloc->y2 - alloc->y1); + coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1); + coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1); + + coords[4] = coords[0]; + coords[5] = coords[1]; + coords[6] = coords[2]; + coords[7] = coords[3]; + + node = clutter_pipeline_node_new (pipeline); + clutter_paint_node_set_name (node, "MetaShapedTexture (clipped)"); + clutter_paint_node_add_child (root_node, node); + + clutter_paint_node_add_multitexture_rectangle (node, + &(ClutterActorBox) + { + .x1 = rect->x, + .x2 = rect->x + rect->width, + .y1 = rect->y, + .y2 = rect->y + rect->height, + }, + coords, 8); +} + static void set_cogl_texture (MetaShapedTexture *stex, CoglTexture *cogl_tex) @@ -476,6 +488,8 @@ set_cogl_texture (MetaShapedTexture *stex, if (stex->create_mipmaps) meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); + + clutter_content_invalidate (CLUTTER_CONTENT (stex)); } static gboolean @@ -486,12 +500,31 @@ texture_is_idle_and_not_mipmapped (gpointer user_data) if ((g_get_monotonic_time () - stex->earliest_remipmap) < 0) return G_SOURCE_CONTINUE; - clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); + clutter_content_invalidate (CLUTTER_CONTENT (stex)); stex->remipmap_timeout_id = 0; return G_SOURCE_REMOVE; } +static cairo_region_t * +effective_unobscured_region (MetaShapedTexture *stex) +{ + /* + ClutterActor *actor; + + actor = CLUTTER_ACTOR (stex); + do + { + if (clutter_actor_has_mapped_clones (actor)) + return NULL; + actor = clutter_actor_get_parent (actor); + } + while (actor != NULL); + */ + + return stex->unobscured_region; +} + static void do_paint (MetaShapedTexture *stex, CoglFramebuffer *fb, @@ -696,21 +729,262 @@ do_paint (MetaShapedTexture *stex, } static void -meta_shaped_texture_paint (ClutterActor *actor) -{ - MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); - CoglTexture *paint_tex; - CoglFramebuffer *fb; +do_paint_content (MetaShapedTexture *stex, + ClutterPaintNode *root_node, + CoglTexture *paint_tex, + ClutterActorBox *alloc, + double tex_scale, + guchar opacity) - if (!stex->texture) +{ + int dst_width, dst_height; + cairo_rectangle_int_t tex_rect; + gboolean use_opaque_region; + cairo_region_t *clip_tex_region; + cairo_region_t *opaque_tex_region; + cairo_region_t *blended_tex_region; + CoglContext *ctx; + CoglPipelineFilter filter; + + ensure_size_valid (stex); + + dst_width = stex->dst_width; + dst_height = stex->dst_height; + + if (dst_width == 0 || dst_height == 0) /* no contents yet */ return; + tex_rect = (cairo_rectangle_int_t) { 0, 0, dst_width, dst_height }; + + /* Use nearest-pixel interpolation if the texture is unscaled. This + * improves performance, especially with software rendering. + */ + + filter = COGL_PIPELINE_FILTER_LINEAR; + + /* FIXME: evil cogl_get_draw_framebuffer() */ + if (meta_actor_painting_untransformed (cogl_get_draw_framebuffer (), + dst_width, dst_height, + NULL, NULL)) + filter = COGL_PIPELINE_FILTER_NEAREST; + + ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + if (stex->opaque_region && opacity == 255) + { + opaque_tex_region = + meta_region_scale_double (stex->opaque_region, + 1.0 / tex_scale, + META_ROUNDING_STRATEGY_SHRINK); + use_opaque_region = TRUE; + } + else + { + opaque_tex_region = NULL; + use_opaque_region = FALSE; + } + + if (stex->clip_region) + { + clip_tex_region = + meta_region_scale_double (stex->clip_region, + 1.0 / tex_scale, + META_ROUNDING_STRATEGY_GROW); + } + else + { + clip_tex_region = NULL; + } + + if (use_opaque_region) + { + if (clip_tex_region) + blended_tex_region = cairo_region_copy (clip_tex_region); + else + blended_tex_region = cairo_region_create_rectangle (&tex_rect); + + cairo_region_subtract (blended_tex_region, opaque_tex_region); + } + else + { + if (clip_tex_region) + blended_tex_region = cairo_region_reference (clip_tex_region); + else + blended_tex_region = NULL; + } + + /* Limit to how many separate rectangles we'll draw; beyond this just + * fall back and draw the whole thing */ +#define MAX_RECTS 16 + + if (blended_tex_region) + { + int n_rects = cairo_region_num_rectangles (blended_tex_region); + if (n_rects > MAX_RECTS) + { + /* Fall back to taking the fully blended path. */ + use_opaque_region = FALSE; + + g_clear_pointer (&blended_tex_region, cairo_region_destroy); + } + } + + /* First, paint the unblended parts, which are part of the opaque region. */ + if (use_opaque_region) + { + cairo_region_t *region; + int n_rects; + int i; + + if (clip_tex_region) + { + region = cairo_region_copy (clip_tex_region); + cairo_region_intersect (region, opaque_tex_region); + } + else + { + region = cairo_region_reference (opaque_tex_region); + } + + if (!cairo_region_is_empty (region)) + { + CoglPipeline *opaque_pipeline; + + opaque_pipeline = get_unblended_pipeline (stex, ctx); + cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); + cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); + + n_rects = cairo_region_num_rectangles (region); + for (i = 0; i < n_rects; i++) + { + cairo_rectangle_int_t rect; + cairo_region_get_rectangle (region, i, &rect); + paint_clipped_rectangle_node (root_node, opaque_pipeline, &rect, alloc); + } + } + + cairo_region_destroy (region); + } + + /* Now, go ahead and paint the blended parts. */ + + /* We have three cases: + * 1) blended_tex_region has rectangles - paint the rectangles. + * 2) blended_tex_region is empty - don't paint anything + * 3) blended_tex_region is NULL - paint fully-blended. + * + * 1) and 3) are the times where we have to paint stuff. This tests + * for 1) and 3). + */ + if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region)) + { + CoglPipeline *blended_pipeline; + + if (stex->mask_texture == NULL) + { + blended_pipeline = get_unmasked_pipeline (stex, ctx); + } + else + { + blended_pipeline = get_masked_pipeline (stex, ctx); + cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); + cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); + } + + cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); + cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); + + CoglColor color; + cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); + cogl_pipeline_set_color (blended_pipeline, &color); + + if (blended_tex_region) + { + /* 1) blended_tex_region is not empty. Paint the rectangles. */ + int i; + int n_rects = cairo_region_num_rectangles (blended_tex_region); + + for (i = 0; i < n_rects; i++) + { + cairo_rectangle_int_t rect; + cairo_region_get_rectangle (blended_tex_region, i, &rect); + + if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect)) + continue; + + paint_clipped_rectangle_node (root_node, blended_pipeline, &rect, alloc); + } + } + else + { + g_autoptr(ClutterPaintNode) node = NULL; + + node = clutter_pipeline_node_new (blended_pipeline); + clutter_paint_node_set_name (node, "MetaShapedTexture (unclipped)"); + clutter_paint_node_add_child (root_node, node); + + /* 3) blended_tex_region is NULL. Do a full paint. */ + clutter_paint_node_add_rectangle (node, alloc); + } + } + + g_clear_pointer (&clip_tex_region, cairo_region_destroy); + g_clear_pointer (&opaque_tex_region, cairo_region_destroy); + g_clear_pointer (&blended_tex_region, cairo_region_destroy); +} + +static CoglTexture * +select_texture_for_paint (MetaShapedTexture *stex) +{ + CoglTexture *texture = NULL; + gint64 now = g_get_monotonic_time (); + + if (stex->create_mipmaps && stex->last_invalidation) + { + gint64 age = now - stex->last_invalidation; + + if (age >= MIN_MIPMAP_AGE_USEC || + stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP) + texture = meta_texture_tower_get_paint_texture (stex->paint_tower); + } + + if (texture == NULL) + { + texture = COGL_TEXTURE (stex->texture); + + if (texture == NULL) + return NULL; + + if (stex->create_mipmaps) + { + /* Minus 1000 to ensure we don't fail the age test in timeout */ + stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000; + + if (!stex->remipmap_timeout_id) + stex->remipmap_timeout_id = + g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000, + texture_is_idle_and_not_mipmapped, + stex); + } + } + + return texture; +} + +static void +meta_shaped_texture_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root_node) +{ + MetaShapedTexture *stex = META_SHAPED_TEXTURE (content); + ClutterActorBox alloc; + CoglTexture *paint_tex = NULL; + double tex_scale; + guchar opacity; + if (stex->clip_region && cairo_region_is_empty (stex->clip_region)) return; - if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) - clutter_actor_realize (CLUTTER_ACTOR (stex)); - /* The GL EXT_texture_from_pixmap extension does allow for it to be * used together with SGIS_generate_mipmap, however this is very * rarely supported. Also, even when it is supported there @@ -726,100 +1000,40 @@ meta_shaped_texture_paint (ClutterActor *actor) * Setting the texture quality to high without SGIS_generate_mipmap * support for TFP textures will result in fallbacks to XGetImage. */ - if (stex->create_mipmaps) - { - int64_t now = g_get_monotonic_time (); - int64_t age = now - stex->last_invalidation; - - if (age >= MIN_MIPMAP_AGE_USEC || - stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP) - { - paint_tex = meta_texture_tower_get_paint_texture (stex->paint_tower); - if (!paint_tex) - paint_tex = stex->texture; - } - else - { - paint_tex = stex->texture; - - /* Minus 1000 to ensure we don't fail the age test in timeout */ - stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000; - - if (!stex->remipmap_timeout_id) - stex->remipmap_timeout_id = - g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000, - texture_is_idle_and_not_mipmapped, - stex); - } - } - else - { - paint_tex = COGL_TEXTURE (stex->texture); - } - - if (cogl_texture_get_width (paint_tex) == 0 || - cogl_texture_get_height (paint_tex) == 0) + paint_tex = select_texture_for_paint (stex); + if (!paint_tex) return; - fb = cogl_get_draw_framebuffer (); - do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region); -} + clutter_actor_get_scale (actor, &tex_scale, NULL); + opacity = clutter_actor_get_paint_opacity (actor); + clutter_actor_get_content_box (actor, &alloc); -static void -meta_shaped_texture_get_preferred_width (ClutterActor *self, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) -{ - MetaShapedTexture *stex = META_SHAPED_TEXTURE (self); - - ensure_size_valid (stex); - - if (min_width_p) - *min_width_p = stex->dst_width; - if (natural_width_p) - *natural_width_p = stex->dst_width; -} - -static void -meta_shaped_texture_get_preferred_height (ClutterActor *self, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) -{ - MetaShapedTexture *stex = META_SHAPED_TEXTURE (self); - - ensure_size_valid (stex); - - if (min_height_p) - *min_height_p = stex->dst_height; - if (natural_height_p) - *natural_height_p = stex->dst_height; -} - -static cairo_region_t * -effective_unobscured_region (MetaShapedTexture *stex) -{ - ClutterActor *actor; - - /* Fail if we have any mapped clones. */ - actor = CLUTTER_ACTOR (stex); - do - { - if (clutter_actor_has_mapped_clones (actor)) - return NULL; - actor = clutter_actor_get_parent (actor); - } - while (actor != NULL); - - return stex->unobscured_region; + do_paint_content (stex, root_node, paint_tex, &alloc, tex_scale, opacity); } static gboolean -meta_shaped_texture_get_paint_volume (ClutterActor *actor, - ClutterPaintVolume *volume) +meta_shaped_texture_get_preferred_size (ClutterContent *content, + float *width, + float *height) { - return clutter_paint_volume_set_from_allocation (volume, actor); + MetaShapedTexture *stex = META_SHAPED_TEXTURE (content); + + ensure_size_valid (stex); + + if (width) + *width = stex->dst_width * stex->scale; + + if (height) + *height = stex->dst_height * stex->scale; + + return TRUE; +} + +static void +clutter_content_iface_init (ClutterContentIface *iface) +{ + iface->paint_content = meta_shaped_texture_paint_content; + iface->get_preferred_size = meta_shaped_texture_get_preferred_size; } void @@ -853,7 +1067,7 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, cogl_object_ref (stex->mask_texture); } - clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); + clutter_content_invalidate (CLUTTER_CONTENT (stex)); } gboolean @@ -944,7 +1158,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, { cairo_rectangle_int_t damage_rect; cairo_region_get_extents (intersection, &damage_rect); - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect); + clutter_content_invalidate (CLUTTER_CONTENT (stex)); + //clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect); cairo_region_destroy (intersection); return TRUE; } @@ -954,7 +1169,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, } else { - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); + clutter_content_invalidate (CLUTTER_CONTENT (stex)); + //clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); return TRUE; } } @@ -1230,7 +1446,7 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, transformed_clip = alloca (sizeof (cairo_rectangle_int_t)); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); + tex_scale = stex->scale; meta_rectangle_scale_double (clip, 1.0 / tex_scale, META_ROUNDING_STRATEGY_GROW, transformed_clip); @@ -1318,17 +1534,47 @@ meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, invalidate_size (stex); } -static void -meta_shaped_texture_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) +ClutterActor * +meta_shaped_texture_new (void) { - MetaShapedTexture *stex = META_SHAPED_TEXTURE (cullable); + return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); +} + +void +meta_shaped_texture_set_scale (MetaShapedTexture *stex, + double scale) +{ + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + + if (scale == stex->scale) + return; + + stex->scale = scale; + + invalidate_size (stex); + clutter_content_invalidate_size (CLUTTER_CONTENT (stex)); +} + +double +meta_shaped_texture_get_scale (MetaShapedTexture *stex) +{ + g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0.0); + + return stex->scale; +} + +void +meta_shaped_texture_cull_out (MetaShapedTexture *stex, + cairo_region_t *unobscured_region, + cairo_region_t *clip_region, + uint8_t opacity) +{ + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); set_unobscured_region (stex, unobscured_region); set_clip_region (stex, clip_region); - if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex)) == 0xff) + if (opacity == 0xff) { if (stex->opaque_region) { @@ -1340,22 +1586,10 @@ meta_shaped_texture_cull_out (MetaCullable *cullable, } } -static void -meta_shaped_texture_reset_culling (MetaCullable *cullable) +void +meta_shaped_texture_reset_culling (MetaShapedTexture *stex) { - MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable); - set_clip_region (self, NULL); -} + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - iface->cull_out = meta_shaped_texture_cull_out; - iface->reset_culling = meta_shaped_texture_reset_culling; -} - -ClutterActor * -meta_shaped_texture_new (void) -{ - return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); + set_clip_region (stex, NULL); } diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index f8d6c32b7..27c600c59 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -110,54 +110,6 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) return surface->window; } -static void -meta_surface_actor_wayland_get_preferred_width (ClutterActor *actor, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) -{ - MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); - MetaShapedTexture *stex; - double scale; - - stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL); - clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), - for_height, - min_width_p, - natural_width_p); - - if (min_width_p) - *min_width_p *= scale; - - if (natural_width_p) - *natural_width_p *= scale; -} - -static void -meta_surface_actor_wayland_get_preferred_height (ClutterActor *actor, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) -{ - MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); - MetaShapedTexture *stex; - double scale; - - stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale); - clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), - for_width, - min_height_p, - natural_height_p); - - if (min_height_p) - *min_height_p *= scale; - - if (natural_height_p) - *natural_height_p *= scale; -} - static void meta_surface_actor_wayland_paint (ClutterActor *actor) { @@ -203,8 +155,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); - actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width; - actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height; actor_class->paint = meta_surface_actor_wayland_paint; surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 6edf7c22d..ffd631863 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -158,13 +158,22 @@ meta_surface_actor_cull_out (MetaCullable *cullable, cairo_region_t *unobscured_region, cairo_region_t *clip_region) { - meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); + MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); + MetaSurfaceActorPrivate *priv = + meta_surface_actor_get_instance_private (surface_actor); + uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable)); + + meta_shaped_texture_cull_out (priv->texture, unobscured_region, clip_region, opacity); } static void meta_surface_actor_reset_culling (MetaCullable *cullable) { - meta_cullable_reset_culling_children (cullable); + MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); + MetaSurfaceActorPrivate *priv = + meta_surface_actor_get_instance_private (surface_actor); + + meta_shaped_texture_reset_culling (priv->texture); } static void @@ -191,7 +200,8 @@ meta_surface_actor_init (MetaSurfaceActor *self) priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); g_signal_connect_object (priv->texture, "size-changed", G_CALLBACK (texture_size_changed), self, 0); - clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture)); + clutter_actor_set_content (CLUTTER_ACTOR (self), CLUTTER_CONTENT (priv->texture)); + clutter_actor_set_request_mode (CLUTTER_ACTOR (self), CLUTTER_REQUEST_CONTENT_SIZE); } cairo_surface_t * diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 20a22062f..d471f622a 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -829,14 +829,14 @@ meta_window_actor_get_meta_window (MetaWindowActor *self) * * Return value: (transfer none): the #ClutterActor for the contents */ -ClutterActor * +MetaShapedTexture * meta_window_actor_get_texture (MetaWindowActor *self) { MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); if (priv->surface) - return CLUTTER_ACTOR (meta_surface_actor_get_texture (priv->surface)); + return meta_surface_actor_get_texture (priv->surface); else return NULL; } @@ -1875,19 +1875,19 @@ meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, MetaShapedTexture *stex; MetaRectangle buffer_rect; MetaRectangle frame_rect; - double scale_x, scale_y; + double scale; stex = meta_surface_actor_get_texture (priv->surface); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y); + scale = meta_shaped_texture_get_scale (stex); window = priv->window; meta_window_get_buffer_rect (window, &buffer_rect); meta_window_get_frame_rect (window, &frame_rect); - bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale_x); - bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale_y); - bounds->width = (int) ceil (frame_rect.width / scale_x); - bounds->height = (int) ceil (frame_rect.height / scale_y); + bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale); + bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale); + bounds->width = (int) ceil (frame_rect.width / scale); + bounds->height = (int) ceil (frame_rect.height / scale); } static void diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h index 09f73bcb0..55e2e7b27 100644 --- a/src/meta/meta-window-actor.h +++ b/src/meta/meta-window-actor.h @@ -27,6 +27,7 @@ #include "clutter/clutter.h" #include "meta/compositor.h" +#include "meta/meta-shaped-texture.h" #define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ()) @@ -43,7 +44,7 @@ META_EXPORT MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self); META_EXPORT -ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self); +MetaShapedTexture *meta_window_actor_get_texture (MetaWindowActor *self); META_EXPORT void meta_window_actor_sync_visibility (MetaWindowActor *self); diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index 56ea66e1e..a85fde49f 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -163,7 +163,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor stex = meta_surface_actor_get_texture (surface_actor); actor_scale = meta_wayland_actor_surface_calculate_scale (actor_surface); - clutter_actor_set_scale (CLUTTER_ACTOR (stex), actor_scale, actor_scale); + meta_shaped_texture_set_scale (stex, actor_scale); /* Wayland surface coordinate space -> stage coordinate space */ geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface); diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index 122604965..447ebbda5 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -1123,7 +1123,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data surface_actor = meta_wayland_surface_get_actor (surface); - clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)), + clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor), seat->pointer->grab_x, seat->pointer->grab_y, &surface_pos.x, &surface_pos.y); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index f75fefd87..2d0f05703 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1514,7 +1514,7 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface, else { ClutterActor *actor = - CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface))); + CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); clutter_actor_transform_stage_point (actor, abs_x, abs_y, sx, sy); *sx /= surface->scale; @@ -1530,7 +1530,7 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface, float *y) { ClutterActor *actor = - CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface))); + CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); ClutterVertex sv = { .x = sx * surface->scale, .y = sy * surface->scale, diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c index 222b46633..abfe533ff 100644 --- a/src/wayland/meta-wayland-tablet-tool.c +++ b/src/wayland/meta-wayland-tablet-tool.c @@ -640,7 +640,7 @@ meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool, surface_actor = meta_wayland_surface_get_actor (surface); clutter_event_get_coords (event, &xf, &yf); - clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)), + clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor), xf, yf, &xf, &yf); *sx = wl_fixed_from_double (xf) / surface->scale;