From 12710dc6448f9a5bb2b3bcba406f4ce74ef204e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 16 May 2017 23:09:27 +0800 Subject: [PATCH] clutter/stage: Add capture_into API Add API similar to clutter_stage_capture() but that draws into externally allocated memory. It is assumed that the pixel format is ARGB32, and the memory is structured in a way that the width of the passed rectangle is identical to the stride divided by 4. https://bugzilla.gnome.org/show_bug.cgi?id=784199 --- clutter/clutter/clutter-mutter.h | 6 +++ clutter/clutter/clutter-stage.c | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h index b820e6b84..034e5d0f2 100644 --- a/clutter/clutter/clutter-mutter.h +++ b/clutter/clutter/clutter-mutter.h @@ -40,6 +40,12 @@ gboolean _clutter_get_sync_to_vblank (void); CLUTTER_AVAILABLE_IN_MUTTER int64_t clutter_stage_get_frame_counter (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_MUTTER +void clutter_stage_capture_into (ClutterStage *stage, + gboolean paint, + cairo_rectangle_int_t *rect, + uint8_t *data); + #undef __CLUTTER_H_INSIDE__ #endif /* __CLUTTER_MUTTER_H__ */ diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 1fa762630..29406112a 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -4810,3 +4810,82 @@ clutter_stage_capture (ClutterStage *stage, return TRUE; } + +static void +capture_view_into (ClutterStage *stage, + gboolean paint, + ClutterStageView *view, + cairo_rectangle_int_t *rect, + uint8_t *data, + int stride) +{ + CoglFramebuffer *framebuffer; + ClutterBackend *backend; + CoglContext *context; + CoglBitmap *bitmap; + cairo_rectangle_int_t view_layout; + + framebuffer = clutter_stage_view_get_framebuffer (view); + + if (paint) + { + _clutter_stage_maybe_setup_viewport (stage, view); + cogl_push_framebuffer (framebuffer); + clutter_stage_do_paint_view (stage, view, rect); + } + + backend = clutter_get_default_backend (); + context = clutter_backend_get_cogl_context (backend); + bitmap = cogl_bitmap_new_for_data (context, + rect->width, rect->height, + CLUTTER_CAIRO_FORMAT_ARGB32, + stride, + data); + + clutter_stage_view_get_layout (view, &view_layout); + + cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + rect->x - view_layout.x, + rect->y - view_layout.y, + COGL_READ_PIXELS_COLOR_BUFFER, + bitmap); + + if (paint) + cogl_pop_framebuffer (); + + cogl_object_unref (bitmap); +} + +void +clutter_stage_capture_into (ClutterStage *stage, + gboolean paint, + cairo_rectangle_int_t *rect, + uint8_t *data) +{ + ClutterStagePrivate *priv = stage->priv; + GList *views = _clutter_stage_window_get_views (priv->impl); + GList *l; + + for (l = views; l; l = l->next) + { + ClutterStageView *view = l->data; + cairo_rectangle_int_t view_layout; + cairo_region_t *region; + cairo_rectangle_int_t view_capture_rect; + int offset; + const int bpp = 4; + + clutter_stage_view_get_layout (view, &view_layout); + region = cairo_region_create_rectangle (&view_layout); + cairo_region_intersect_rectangle (region, rect); + cairo_region_get_extents (region, &view_capture_rect); + cairo_region_destroy (region); + + if (view_capture_rect.width == 0 || view_capture_rect.height == 0) + continue; + + offset = bpp * (view_capture_rect.y * rect->width + view_capture_rect.x); + capture_view_into (stage, paint, view, &view_capture_rect, + data + offset, rect->width * bpp); + } +}