diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index a86a2bff0..42458daa2 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -30,7 +30,7 @@ #include "backends/meta-monitor-manager-private.h" #include "meta/meta-shaped-texture.h" -ClutterActor *meta_shaped_texture_new (void); +MetaShapedTexture *meta_shaped_texture_new (void); void meta_shaped_texture_set_texture (MetaShapedTexture *stex, CoglTexture *texture); void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, @@ -51,5 +51,13 @@ void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex, int dst_width, int dst_height); void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex); +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_buffer_scale (MetaShapedTexture *stex, + int buffer_scale); +int meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex); #endif diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 90a02210d..667d43d56 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -58,21 +58,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 (ClutterContentInterface *iface); enum { @@ -85,7 +71,7 @@ static guint signals[LAST_SIGNAL]; struct _MetaShapedTexture { - ClutterActor parent; + GObject parent; MetaTextureTower *paint_tower; @@ -123,25 +109,22 @@ struct _MetaShapedTexture guint remipmap_timeout_id; gint64 earliest_remipmap; + int buffer_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, @@ -161,40 +144,30 @@ meta_shaped_texture_init (MetaShapedTexture *stex) { stex->paint_tower = meta_texture_tower_new (); + stex->buffer_scale = 1; 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 update_size (MetaShapedTexture *stex) { - ClutterActor *actor = CLUTTER_ACTOR (stex); + int buffer_scale = stex->buffer_scale; int dst_width; int dst_height; if (stex->has_viewport_dst_size) { - double tex_scale; - - clutter_actor_get_scale (actor, &tex_scale, NULL); - dst_width = ceil (stex->viewport_dst_width / tex_scale); - dst_height = ceil (stex->viewport_dst_height / tex_scale); + dst_width = stex->viewport_dst_width; + dst_height = stex->viewport_dst_height; } else if (stex->has_viewport_src_rect) { - double tex_scale; - - clutter_actor_get_scale (actor, &tex_scale, NULL); - dst_width = ceil (stex->viewport_src_rect.size.width / tex_scale); - dst_height = ceil (stex->viewport_src_rect.size.height / tex_scale); + dst_width = stex->viewport_src_rect.size.width; + dst_height = stex->viewport_src_rect.size.height; } else { @@ -202,26 +175,26 @@ update_size (MetaShapedTexture *stex) { if (stex->texture) { - dst_width = stex->tex_height; - dst_height = stex->tex_width; + dst_width = stex->tex_height / buffer_scale; + dst_height = stex->tex_width / buffer_scale; } else { - dst_width = stex->fallback_height; - dst_height = stex->fallback_width; + dst_width = stex->fallback_height / buffer_scale; + dst_height = stex->fallback_width / buffer_scale; } } else { if (stex->texture) { - dst_width = stex->tex_width; - dst_height = stex->tex_height; + dst_width = stex->tex_width / buffer_scale; + dst_height = stex->tex_height / buffer_scale; } else { - dst_width = stex->fallback_width; - dst_height = stex->fallback_height; + dst_width = stex->fallback_width / buffer_scale; + dst_height = stex->fallback_height / buffer_scale; } } } @@ -234,7 +207,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); } } @@ -377,27 +350,25 @@ get_base_pipeline (MetaShapedTexture *stex, if (stex->has_viewport_src_rect) { - ClutterActor *actor = CLUTTER_ACTOR (stex); - double tex_scale; - - clutter_actor_get_scale (actor, &tex_scale, NULL); + float scaled_tex_width = stex->tex_width / (float) stex->buffer_scale; + float scaled_tex_height = stex->tex_height / (float) stex->buffer_scale; if (meta_monitor_transform_is_rotated (stex->transform)) { cogl_matrix_scale (&matrix, stex->viewport_src_rect.size.width / - (stex->tex_height * tex_scale), + scaled_tex_height, stex->viewport_src_rect.size.height / - (stex->tex_width * tex_scale), + scaled_tex_width, 1); } else { cogl_matrix_scale (&matrix, stex->viewport_src_rect.size.width / - (stex->tex_width * tex_scale), + scaled_tex_width, stex->viewport_src_rect.size.height / - (stex->tex_height * tex_scale), + scaled_tex_height, 1); } @@ -469,21 +440,17 @@ get_unblended_pipeline (MetaShapedTexture *stex, } static void -paint_clipped_rectangle (MetaShapedTexture *stex, - CoglFramebuffer *fb, - CoglPipeline *pipeline, - cairo_rectangle_int_t *rect, - ClutterActorBox *alloc) +paint_clipped_rectangle_node (MetaShapedTexture *stex, + ClutterPaintNode *root_node, + CoglPipeline *pipeline, + cairo_rectangle_int_t *rect, + ClutterActorBox *alloc) { + g_autoptr (ClutterPaintNode) node = NULL; float coords[8]; - float x1, y1, x2, y2; float alloc_width; float alloc_height; - x1 = rect->x; - y1 = rect->y; - x2 = rect->x + rect->width; - y2 = rect->y + rect->height; alloc_width = alloc->x2 - alloc->x1; alloc_height = alloc->y2 - alloc->y1; @@ -497,9 +464,18 @@ paint_clipped_rectangle (MetaShapedTexture *stex, coords[6] = coords[2]; coords[7] = coords[3]; - cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline, - x1, y1, x2, y2, - &coords[0], 8); + 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 @@ -542,6 +518,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 @@ -552,39 +530,47 @@ 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 void -do_paint (MetaShapedTexture *stex, - CoglFramebuffer *fb, - CoglTexture *paint_tex, - cairo_region_t *clip_region) +static cairo_region_t * +effective_unobscured_region (MetaShapedTexture *stex) +{ + return stex->unobscured_region; +} + +static void +do_paint_content (MetaShapedTexture *stex, + ClutterPaintNode *root_node, + CoglTexture *paint_tex, + ClutterActorBox *alloc, + uint8_t opacity) + { - double tex_scale; int dst_width, dst_height; - cairo_rectangle_int_t tex_rect; - guchar opacity; + cairo_rectangle_int_t content_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; - ClutterActorBox alloc; CoglPipelineFilter filter; - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); ensure_size_valid (stex); - dst_width = stex->dst_width; + 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 }; + content_rect = (cairo_rectangle_int_t) { + .x = 0, + .y = 0, + .width = dst_width, + .height = dst_height, + }; /* Use nearest-pixel interpolation if the texture is unscaled. This * improves performance, especially with software rendering. @@ -592,55 +578,28 @@ do_paint (MetaShapedTexture *stex, filter = COGL_PIPELINE_FILTER_LINEAR; - if (meta_actor_painting_untransformed (fb, + if (meta_actor_painting_untransformed (clutter_paint_node_get_framebuffer (root_node), dst_width, dst_height, NULL, NULL)) filter = COGL_PIPELINE_FILTER_NEAREST; ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); - opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex)); - clutter_actor_get_allocation_box (CLUTTER_ACTOR (stex), &alloc); - - 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 (clip_region) - { - clip_tex_region = - meta_region_scale_double (clip_region, - 1.0 / tex_scale, - META_ROUNDING_STRATEGY_GROW); - } - else - { - clip_tex_region = NULL; - } + use_opaque_region = stex->opaque_region && opacity == 255; if (use_opaque_region) { - if (clip_tex_region) - blended_tex_region = cairo_region_copy (clip_tex_region); + if (stex->clip_region) + blended_tex_region = cairo_region_copy (stex->clip_region); else - blended_tex_region = cairo_region_create_rectangle (&tex_rect); + blended_tex_region = cairo_region_create_rectangle (&content_rect); - cairo_region_subtract (blended_tex_region, opaque_tex_region); + cairo_region_subtract (blended_tex_region, stex->opaque_region); } else { - if (clip_tex_region) - blended_tex_region = cairo_region_reference (clip_tex_region); + if (stex->clip_region) + blended_tex_region = cairo_region_reference (stex->clip_region); else blended_tex_region = NULL; } @@ -664,23 +623,24 @@ do_paint (MetaShapedTexture *stex, /* First, paint the unblended parts, which are part of the opaque region. */ if (use_opaque_region) { - CoglPipeline *opaque_pipeline; cairo_region_t *region; int n_rects; int i; - if (clip_tex_region) + if (stex->clip_region) { - region = cairo_region_copy (clip_tex_region); - cairo_region_intersect (region, opaque_tex_region); + region = cairo_region_copy (stex->clip_region); + cairo_region_intersect (region, stex->opaque_region); } else { - region = cairo_region_reference (opaque_tex_region); + region = cairo_region_reference (stex->opaque_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); @@ -690,11 +650,9 @@ do_paint (MetaShapedTexture *stex, { cairo_rectangle_int_t rect; cairo_region_get_rectangle (region, i, &rect); - paint_clipped_rectangle (stex, - fb, - opaque_pipeline, - &rect, - &alloc); + paint_clipped_rectangle_node (stex, root_node, + opaque_pipeline, + &rect, alloc); } } @@ -744,47 +702,83 @@ do_paint (MetaShapedTexture *stex, cairo_rectangle_int_t rect; cairo_region_get_rectangle (blended_tex_region, i, &rect); - if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect)) + if (!gdk_rectangle_intersect (&content_rect, &rect, &rect)) continue; - paint_clipped_rectangle (stex, - fb, - blended_pipeline, - &rect, - &alloc); + paint_clipped_rectangle_node (stex, 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. */ - cogl_framebuffer_draw_rectangle (fb, blended_pipeline, - 0, 0, - alloc.x2 - alloc.x1, - alloc.y2 - alloc.y1); + 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 void -meta_shaped_texture_paint (ClutterActor *actor) +static CoglTexture * +select_texture_for_paint (MetaShapedTexture *stex) { - MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); - CoglTexture *paint_tex; - CoglFramebuffer *fb; + CoglTexture *texture = NULL; + int64_t now; if (!stex->texture) - return; + return NULL; + + now = g_get_monotonic_time (); + + if (stex->create_mipmaps && stex->last_invalidation) + { + int64_t 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) + { + texture = stex->texture; + + 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; + uint8_t 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 @@ -800,100 +794,39 @@ 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); -} + 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, 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; + + if (height) + *height = stex->dst_height; + + return TRUE; +} + +static void +clutter_content_iface_init (ClutterContentInterface *iface) +{ + iface->paint_content = meta_shaped_texture_paint_content; + iface->get_preferred_size = meta_shaped_texture_get_preferred_size; } void @@ -927,7 +860,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 @@ -987,14 +920,11 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, { ClutterRect viewport; ClutterRect inverted_viewport; - double tex_scale; float dst_width; float dst_height; int inverted_dst_width; int inverted_dst_height; - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); - if (stex->has_viewport_src_rect) { viewport = stex->viewport_src_rect; @@ -1004,8 +934,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, viewport = (ClutterRect) { .origin.x = 0, .origin.y = 0, - .size.width = stex->tex_width * tex_scale, - .size.height = stex->tex_height * tex_scale + .size.width = stex->tex_width, + .size.height = stex->tex_height, }; } @@ -1016,13 +946,13 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, } else { - dst_width = (float) stex->tex_width * tex_scale; - dst_height = (float) stex->tex_height * tex_scale; + dst_width = (float) stex->tex_width; + dst_height = (float) stex->tex_height; } inverted_viewport = (ClutterRect) { - .origin.x = -((viewport.origin.x * (dst_width / viewport.size.width)) / tex_scale), - .origin.y = -((viewport.origin.y * (dst_height / viewport.size.height)) / tex_scale), + .origin.x = -(viewport.origin.x * (dst_width / viewport.size.width)), + .origin.y = -(viewport.origin.y * (dst_height / viewport.size.height)), .size.width = dst_width, .size.height = dst_height }; @@ -1037,10 +967,10 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, } meta_texture_tower_update_area (stex->paint_tower, - clip.x, - clip.y, - clip.width, - clip.height); + x, + y, + width, + height); stex->prev_invalidation = stex->last_invalidation; stex->last_invalidation = g_get_monotonic_time (); @@ -1059,6 +989,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, unobscured_region = effective_unobscured_region (stex); if (unobscured_region) { + cairo_rectangle_int_t extents; + cairo_region_t *scaled_unobscured_region; cairo_region_t *intersection; if (cairo_region_is_empty (unobscured_region)) @@ -1071,7 +1003,7 @@ 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)); cairo_region_destroy (intersection); return TRUE; } @@ -1081,7 +1013,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, } else { - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); + clutter_content_invalidate (CLUTTER_CONTENT (stex)); return TRUE; } } @@ -1274,6 +1206,7 @@ static cairo_surface_t * get_image_via_offscreen (MetaShapedTexture *stex, cairo_rectangle_int_t *clip) { + g_autoptr (ClutterPaintNode) root_node = NULL; ClutterBackend *clutter_backend = clutter_get_default_backend (); CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); @@ -1283,7 +1216,7 @@ get_image_via_offscreen (MetaShapedTexture *stex, CoglFramebuffer *fb; CoglMatrix projection_matrix; cairo_rectangle_int_t fallback_clip; - CoglColor clear_color; + ClutterColor clear_color; cairo_surface_t *surface; if (!clip) @@ -1329,12 +1262,20 @@ get_image_via_offscreen (MetaShapedTexture *stex, cogl_framebuffer_set_projection_matrix (fb, &projection_matrix); - cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); - cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color); + clear_color = (ClutterColor) { 0, 0, 0, 0 }; - do_paint (stex, fb, stex->texture, NULL); + root_node = clutter_root_node_new (fb, &clear_color, COGL_BUFFER_BIT_COLOR); + clutter_paint_node_set_name (root_node, "MetaShapedTexture.offscreen"); - cogl_framebuffer_pop_matrix (fb); + do_paint_content (stex, root_node, + stex->texture, + &(ClutterActorBox) { + clip->x, clip->y, + clip->width, clip->height, + }, + 255); + + clutter_paint_node_paint (root_node); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, clip->width, clip->height); @@ -1386,13 +1327,11 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, if (clip != NULL) { - double tex_scale; cairo_rectangle_int_t dst_rect; transformed_clip = alloca (sizeof (cairo_rectangle_int_t)); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); - meta_rectangle_scale_double (clip, 1.0 / tex_scale, + meta_rectangle_scale_double (clip, stex->buffer_scale, META_ROUNDING_STRATEGY_GROW, transformed_clip); @@ -1479,17 +1418,46 @@ 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) +MetaShapedTexture * +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_buffer_scale (MetaShapedTexture *stex, + int buffer_scale) +{ + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + + if (buffer_scale == stex->buffer_scale) + return; + + stex->buffer_scale = buffer_scale; + + invalidate_size (stex); +} + +int +meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex) +{ + g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 1.0); + + return stex->buffer_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) { @@ -1501,22 +1469,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 ca4ca19a9..e50eb8018 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -159,13 +159,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 @@ -189,10 +198,13 @@ meta_surface_actor_init (MetaSurfaceActor *self) MetaSurfaceActorPrivate *priv = meta_surface_actor_get_instance_private (self); - priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); + priv->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 375d7bc0a..81aaf4e2e 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -833,14 +833,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; } @@ -1902,19 +1902,19 @@ meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, MetaShapedTexture *stex; MetaRectangle buffer_rect; MetaRectangle frame_rect; - double scale_x, scale_y; + int buffer_scale; stex = meta_surface_actor_get_texture (priv->surface); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y); + buffer_scale = meta_shaped_texture_get_buffer_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) / (float) buffer_scale); + bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / (float) buffer_scale); + bounds->width = (int) ceil (frame_rect.width / (float) buffer_scale); + bounds->height = (int) ceil (frame_rect.height / (float) buffer_scale); } static void @@ -1928,7 +1928,6 @@ meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (window_actor); - MetaShapedTexture *stex; MetaRectangle bounds; ClutterVertex v1 = { 0.f, }, v2 = { 0.f, }; @@ -1941,8 +1940,9 @@ meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast bounds.y, bounds.y + bounds.height); - stex = meta_surface_actor_get_texture (priv->surface); - clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (stex), &v1, &v2); + clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (priv->surface), + &v1, + &v2); *x_out = (double) v2.x; *y_out = (double) v2.y; @@ -1969,22 +1969,19 @@ meta_window_actor_transform_cursor_position (MetaScreenCastWindow *screen_cast_w out_cursor_scale) { MetaShapedTexture *stex; - double actor_scale; + double texture_scale; float cursor_texture_scale; stex = meta_surface_actor_get_texture (priv->surface); - clutter_actor_get_scale (CLUTTER_ACTOR (stex), &actor_scale, NULL); + texture_scale = meta_shaped_texture_get_buffer_scale (stex); cursor_texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - *out_cursor_scale = actor_scale / cursor_texture_scale; + *out_cursor_scale = texture_scale / cursor_texture_scale; } if (out_relative_cursor_position) { - MetaShapedTexture *stex; - - stex = meta_surface_actor_get_texture (priv->surface); - clutter_actor_transform_stage_point (CLUTTER_ACTOR (stex), + clutter_actor_transform_stage_point (CLUTTER_ACTOR (priv->surface), cursor_position->x, cursor_position->y, &out_relative_cursor_position->x, diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h index 9ba164910..ad4b7bf1d 100644 --- a/src/meta/meta-window-actor.h +++ b/src/meta/meta-window-actor.h @@ -25,6 +25,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 ()) @@ -38,7 +39,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 bd987e970..979422bae 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -154,16 +154,13 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor meta_wayland_surface_role_get_surface (surface_role); MetaSurfaceActor *surface_actor; MetaShapedTexture *stex; - double actor_scale; GList *l; cairo_rectangle_int_t surface_rect; int geometry_scale; surface_actor = priv->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_buffer_scale (stex, surface->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 ba9591ec1..7eeac7e31 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -1197,7 +1197,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 3bf9bc9ce..f9cc118b6 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1581,7 +1581,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; @@ -1597,7 +1597,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 d243608cf..a149b1e67 100644 --- a/src/wayland/meta-wayland-tablet-tool.c +++ b/src/wayland/meta-wayland-tablet-tool.c @@ -663,7 +663,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;