From b1c8510a95dfe7c4bdf7835cdccd25ac2c11b491 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Sun, 22 Aug 2021 13:21:56 +0200 Subject: [PATCH] window-actor: Add paint_to_content() function Analogous to `get_image()` this returns a `ClutterContent` for a given `MetaWindowActor`. This can be used to implement window effects without a roundtrip from GPU to CPU memory. Part-of: --- src/compositor/meta-window-actor.c | 68 ++++++++++++++++++++++++++++++ src/meta/meta-window-actor.h | 5 +++ 2 files changed, 73 insertions(+) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index c284a6cd5..cbc0c96a8 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1575,3 +1575,71 @@ out: clutter_actor_uninhibit_culling (actor); return surface; } + +/** + * meta_window_actor_paint_to_content: + * @self: A #MetaWindowActor + * @clip: (nullable): A clipping rectangle, in actor coordinates, to help + * prevent extra processing. + * In the case that the clipping rectangle is partially or fully + * outside the bounds of the actor, the rectangle will be clipped. + * @error: A #GError to catch exceptional errors or %NULL. + * + * Returns: (nullable) (transfer full): a new #ClutterContent + */ +ClutterContent * +meta_window_actor_paint_to_content (MetaWindowActor *self, + MetaRectangle *clip, + GError **error) +{ + MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterContent *content = NULL; + CoglFramebuffer *framebuffer; + CoglTexture *texture; + MetaRectangle framebuffer_clip; + float x, y, width, height; + + if (!priv->surface) + return NULL; + + clutter_actor_inhibit_culling (actor); + + clutter_actor_get_position (actor, &x, &y); + clutter_actor_get_size (actor, &width, &height); + + if (width == 0 || height == 0) + goto out; + + framebuffer_clip = (MetaRectangle) { + .x = floorf (x), + .y = floorf (y), + .width = ceilf (width), + .height = ceilf (height), + }; + + if (clip) + { + MetaRectangle tmp_clip; + + if (!meta_rectangle_intersect (&framebuffer_clip, clip, &tmp_clip)) + goto out; + + framebuffer_clip = tmp_clip; + } + + framebuffer = create_framebuffer_from_window_actor (self, + &framebuffer_clip, + error); + if (!framebuffer) + goto out; + + texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer)); + content = clutter_texture_content_new_from_texture (texture, NULL); + + g_object_unref (framebuffer); + +out: + clutter_actor_uninhibit_culling (actor); + return content; +} diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h index 6e18683a2..342995fb0 100644 --- a/src/meta/meta-window-actor.h +++ b/src/meta/meta-window-actor.h @@ -51,6 +51,11 @@ META_EXPORT cairo_surface_t * meta_window_actor_get_image (MetaWindowActor *self, cairo_rectangle_int_t *clip); +META_EXPORT +ClutterContent * meta_window_actor_paint_to_content (MetaWindowActor *self, + MetaRectangle *clip, + GError **error); + META_EXPORT void meta_window_actor_freeze (MetaWindowActor *self);