[mutter] clutter: Add capture API for reading stage pixels



commit ff6186f1ecd0f483754455b3096e774d4b28ad7e
Author: Jonas Ådahl <jadahl gmail com>
Date:   Sat Jun 25 08:10:27 2016 +0800

    clutter: Add capture API for reading stage pixels
    
    clutter_stage_capture should be used instead of directly utilizing
    cogl's read_pixels API's.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=768978

 clutter/clutter/clutter-stage.c |   97 +++++++++++++++++++++++++++++++++++++++
 clutter/clutter/clutter-stage.h |   13 +++++
 2 files changed, 110 insertions(+), 0 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 8041262..edbc9b4 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -4661,3 +4661,100 @@ _clutter_stage_presented (ClutterStage     *stage,
   g_signal_emit (stage, stage_signals[PRESENTED], 0,
                  (int) frame_event, frame_info);
 }
+
+static void
+capture_view (ClutterStage          *stage,
+              gboolean               paint,
+              ClutterStageView      *view,
+              cairo_rectangle_int_t *rect,
+              ClutterCapture        *capture)
+{
+  CoglFramebuffer *framebuffer;
+  ClutterBackend *backend;
+  CoglContext *context;
+  cairo_surface_t *image;
+  uint8_t *data;
+  int stride;
+  CoglBitmap *bitmap;
+
+  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);
+    }
+
+  image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                      rect->width, rect->height);
+
+  data = cairo_image_surface_get_data (image);
+  stride = cairo_image_surface_get_stride (image);
+
+  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);
+
+  cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
+                                            rect->x, rect->y,
+                                            COGL_READ_PIXELS_COLOR_BUFFER,
+                                            bitmap);
+
+  if (paint)
+    cogl_pop_framebuffer ();
+
+  capture->rect = *rect;
+  capture->image = image;
+
+  cairo_surface_mark_dirty (capture->image);
+  cogl_object_unref (bitmap);
+}
+
+gboolean
+clutter_stage_capture (ClutterStage          *stage,
+                       gboolean               paint,
+                       cairo_rectangle_int_t *rect,
+                       ClutterCapture       **out_captures,
+                       int                   *out_n_captures)
+{
+  ClutterStagePrivate *priv = stage->priv;
+  GList *views = _clutter_stage_window_get_views (priv->impl);
+  GList *l;
+  ClutterCapture *captures;
+  int n_captures;
+
+  captures = g_new0 (ClutterCapture, g_list_length (views));
+  n_captures = 0;
+
+  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;
+
+      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;
+
+      capture_view (stage, paint, view, &view_capture_rect,
+                    &captures[n_captures]);
+
+      n_captures++;
+    }
+
+  *out_captures = captures;
+  *out_n_captures = n_captures;
+
+  return TRUE;
+}
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h
index e0911bc..e8fbda8 100644
--- a/clutter/clutter/clutter-stage.h
+++ b/clutter/clutter/clutter-stage.h
@@ -145,6 +145,12 @@ struct _ClutterFrameInfo
   float refresh_rate;
 };
 
+typedef struct _ClutterCapture
+{
+  cairo_surface_t *image;
+  cairo_rectangle_int_t rect;
+} ClutterCapture;
+
 CLUTTER_AVAILABLE_IN_ALL
 GType clutter_perspective_get_type (void) G_GNUC_CONST;
 CLUTTER_DEPRECATED_IN_1_10
@@ -252,6 +258,13 @@ CLUTTER_AVAILABLE_IN_1_14
 void            clutter_stage_skip_sync_delay                   (ClutterStage          *stage);
 #endif
 
+CLUTTER_AVAILABLE_IN_MUTTER
+gboolean clutter_stage_capture (ClutterStage          *stage,
+                                gboolean               paint,
+                                cairo_rectangle_int_t *rect,
+                                ClutterCapture       **captures,
+                                int                   *n_captures);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_STAGE_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]