From d9d8732096792be0efd495d7373b25ec71386700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 28 Apr 2020 18:13:23 +0200 Subject: [PATCH] clutter/stage: Use new paint API to implement capture() This changes the semantics a bit, e.g. we will never include the pointer cursor sprite, as there is no way to know whether the caller wants to or not. We also change things a bit so that when we render to an offscreen paint context, we don't emit the "paint" signal on actors, as doing so would end up recursing in gnome-shell's screenshot and screencast code. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2567 https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1222 --- clutter/clutter/clutter-actor.c | 4 +- .../clutter/clutter-paint-context-private.h | 1 + clutter/clutter/clutter-paint-context.c | 3 +- clutter/clutter/clutter-stage.c | 45 +++---------------- src/backends/meta-stage.c | 4 +- 5 files changed, 15 insertions(+), 42 deletions(-) diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index b82d847a4..1cf09ac11 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -4194,7 +4194,9 @@ clutter_actor_continue_paint (ClutterActor *self, clutter_paint_node_unref (dummy); /* XXX:2.0 - Call the paint() virtual directly */ - if (g_signal_has_handler_pending (self, actor_signals[PAINT], + if (!(clutter_paint_context_get_paint_flags (paint_context) & + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL) && + g_signal_has_handler_pending (self, actor_signals[PAINT], 0, TRUE)) g_signal_emit (self, actor_signals[PAINT], 0, paint_context); else diff --git a/clutter/clutter/clutter-paint-context-private.h b/clutter/clutter/clutter-paint-context-private.h index 4cc72043e..132238cb9 100644 --- a/clutter/clutter/clutter-paint-context-private.h +++ b/clutter/clutter/clutter-paint-context-private.h @@ -24,6 +24,7 @@ typedef enum _ClutterPaintFlag { CLUTTER_PAINT_FLAG_NONE = 0, CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0, + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL = 1 << 0, } ClutterPaintFlag; ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view, diff --git a/clutter/clutter/clutter-paint-context.c b/clutter/clutter/clutter-paint-context.c index fc519c058..6787a5b5c 100644 --- a/clutter/clutter/clutter-paint-context.c +++ b/clutter/clutter/clutter-paint-context.c @@ -66,7 +66,8 @@ clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer) paint_context = g_new0 (ClutterPaintContext, 1); g_ref_count_init (&paint_context->ref_count); - paint_context->paint_flags = CLUTTER_PAINT_FLAG_NO_CURSORS; + paint_context->paint_flags = (CLUTTER_PAINT_FLAG_NO_CURSORS | + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL); clutter_paint_context_push_framebuffer (paint_context, framebuffer); diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 92f3dd759..82565c6b5 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -4575,50 +4575,17 @@ capture_view_into (ClutterStage *stage, uint8_t *data, int stride) { - CoglFramebuffer *framebuffer; - ClutterBackend *backend; - CoglContext *context; - CoglBitmap *bitmap; - cairo_rectangle_int_t view_layout; + g_autoptr (GError) error = NULL; float view_scale; - float texture_width; - float texture_height; g_return_if_fail (CLUTTER_IS_STAGE (stage)); - framebuffer = clutter_stage_view_get_framebuffer (view); - - if (paint) - { - cairo_region_t *region; - - _clutter_stage_maybe_setup_viewport (stage, view); - region = cairo_region_create_rectangle (rect); - clutter_stage_do_paint_view (stage, view, region); - cairo_region_destroy (region); - } - view_scale = clutter_stage_view_get_scale (view); - texture_width = roundf (rect->width * view_scale); - texture_height = roundf (rect->height * view_scale); - - backend = clutter_get_default_backend (); - context = clutter_backend_get_cogl_context (backend); - bitmap = cogl_bitmap_new_for_data (context, - texture_width, texture_height, - CLUTTER_CAIRO_FORMAT_ARGB32, - stride, - data); - - clutter_stage_view_get_layout (view, &view_layout); - - cogl_framebuffer_read_pixels_into_bitmap (framebuffer, - roundf ((rect->x - view_layout.x) * view_scale), - roundf ((rect->y - view_layout.y) * view_scale), - COGL_READ_PIXELS_COLOR_BUFFER, - bitmap); - - cogl_object_unref (bitmap); + if (!clutter_stage_paint_to_buffer (stage, rect, view_scale, data, stride, + CLUTTER_CAIRO_FORMAT_ARGB32, + CLUTTER_PAINT_FLAG_NO_CURSORS, + &error)) + g_warning ("Failed to capture stage: %s", error->message); } void diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c index 43b0ecb2a..3f7dd55ca 100644 --- a/src/backends/meta-stage.c +++ b/src/backends/meta-stage.c @@ -204,7 +204,9 @@ meta_stage_paint (ClutterActor *actor, META_STAGE_WATCH_AFTER_ACTOR_PAINT); } - g_signal_emit (stage, signals[ACTORS_PAINTED], 0); + if (!(clutter_paint_context_get_paint_flags (paint_context) & + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL)) + g_signal_emit (stage, signals[ACTORS_PAINTED], 0); if (!(clutter_paint_context_get_paint_flags (paint_context) & CLUTTER_PAINT_FLAG_NO_CURSORS))