summaryrefslogtreecommitdiff
path: root/clutter
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2017-05-16 23:09:27 +0800
committerJonas Ådahl <jadahl@gmail.com>2017-08-29 11:49:01 +0800
commit12710dc6448f9a5bb2b3bcba406f4ce74ef204e8 (patch)
treead7bf817bd73a22aba1c11801b9508e0df559497 /clutter
parenta10ad577a751a3ecc266b0e48af7d7e94b4d2b75 (diff)
downloadmutter-12710dc6448f9a5bb2b3bcba406f4ce74ef204e8.tar.gz
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
Diffstat (limited to 'clutter')
-rw-r--r--clutter/clutter/clutter-mutter.h6
-rw-r--r--clutter/clutter/clutter-stage.c79
2 files changed, 85 insertions, 0 deletions
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);
+ }
+}