[mutter] clutter/stage: Add API to paint to a custom target
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] clutter/stage: Add API to paint to a custom target
- Date: Thu, 23 Apr 2020 18:44:34 +0000 (UTC)
commit b7bf42e778b597302e64a6ab853fd828fc169010
Author: Jonas Ådahl <jadahl gmail com>
Date: Mon Apr 20 22:29:50 2020 +0200
clutter/stage: Add API to paint to a custom target
Either onto a framebuffer, or into a CPU memory buffer. The latter will
use an former API and then copy the result to CPU memory. The former
allocates an offscreen framebuffer, sets up the relevant framebuffer
matrices and paints part of the stage defined by the passed rectangle.
This will be used by a RecordArea screen cast API. The former to paint
directly onto PipeWire handled dma-buf framebuffers, and the latter for
PipeWire handled shared memory buffers.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1207
clutter/clutter/clutter-mutter.h | 17 ++++++++
clutter/clutter/clutter-stage.c | 91 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+)
---
diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h
index 5c652a4e3..7506e74da 100644
--- a/clutter/clutter/clutter-mutter.h
+++ b/clutter/clutter/clutter-mutter.h
@@ -48,6 +48,23 @@ void clutter_stage_capture_into (ClutterStage *stage,
cairo_rectangle_int_t *rect,
uint8_t *data);
+CLUTTER_EXPORT
+void clutter_stage_paint_to_framebuffer (ClutterStage *stage,
+ CoglFramebuffer *framebuffer,
+ const cairo_rectangle_int_t *rect,
+ float scale,
+ ClutterPaintFlag paint_flags);
+
+CLUTTER_EXPORT
+gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
+ const cairo_rectangle_int_t *rect,
+ float scale,
+ uint8_t *data,
+ int stride,
+ CoglPixelFormat format,
+ ClutterPaintFlag paint_flags,
+ GError **error);
+
CLUTTER_EXPORT
void clutter_stage_freeze_updates (ClutterStage *stage);
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index a7afaf802..c97d9bd9a 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -4164,6 +4164,97 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
return TRUE;
}
+void
+clutter_stage_paint_to_framebuffer (ClutterStage *stage,
+ CoglFramebuffer *framebuffer,
+ const cairo_rectangle_int_t *rect,
+ float scale,
+ ClutterPaintFlag paint_flags)
+{
+ ClutterStagePrivate *priv = stage->priv;
+ ClutterPaintContext *paint_context;
+ cairo_region_t *redraw_clip;
+
+ redraw_clip = cairo_region_create_rectangle (rect);
+ paint_context =
+ clutter_paint_context_new_for_framebuffer (framebuffer,
+ redraw_clip,
+ paint_flags);
+ cairo_region_destroy (redraw_clip);
+
+ cogl_framebuffer_push_matrix (framebuffer);
+ cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection);
+ cogl_framebuffer_set_viewport (framebuffer,
+ -(rect->x * scale),
+ -(rect->y * scale),
+ priv->viewport[2] * scale,
+ priv->viewport[3] * scale);
+ clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);
+ cogl_framebuffer_pop_matrix (framebuffer);
+
+ clutter_paint_context_destroy (paint_context);
+}
+
+gboolean
+clutter_stage_paint_to_buffer (ClutterStage *stage,
+ const cairo_rectangle_int_t *rect,
+ float scale,
+ uint8_t *data,
+ int stride,
+ CoglPixelFormat format,
+ ClutterPaintFlag paint_flags,
+ GError **error)
+{
+ ClutterBackend *clutter_backend = clutter_get_default_backend ();
+ CoglContext *cogl_context =
+ clutter_backend_get_cogl_context (clutter_backend);
+ int texture_width, texture_height;
+ CoglTexture2D *texture;
+ CoglOffscreen *offscreen;
+ CoglFramebuffer *framebuffer;
+ CoglBitmap *bitmap;
+
+ texture_width = (int) ceilf (rect->width * scale);
+ texture_height = (int) ceilf (rect->height * scale);
+ texture = cogl_texture_2d_new_with_size (cogl_context,
+ texture_width,
+ texture_height);
+ if (!texture)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to create %dx%d texture",
+ texture_width, texture_height);
+ return FALSE;
+ }
+
+ offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
+ framebuffer = COGL_FRAMEBUFFER (offscreen);
+
+ cogl_object_unref (texture);
+
+ if (!cogl_framebuffer_allocate (framebuffer, error))
+ return FALSE;
+
+ clutter_stage_paint_to_framebuffer (stage, framebuffer,
+ rect, scale, paint_flags);
+
+ bitmap = cogl_bitmap_new_for_data (cogl_context,
+ texture_width, texture_height,
+ format,
+ stride,
+ data);
+
+ cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
+ 0, 0,
+ COGL_READ_PIXELS_COLOR_BUFFER,
+ bitmap);
+
+ cogl_object_unref (bitmap);
+ cogl_object_unref (framebuffer);
+
+ return TRUE;
+}
+
static void
capture_view_into (ClutterStage *stage,
gboolean paint,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]