[gnome-shell] Use clutter_stage_capture instead of cogl's read_pixels



commit f5c058a036b21da747921d0ed9eefa64331e4f17
Author: Jonas Ådahl <jadahl gmail com>
Date:   Mon Jun 27 15:57:28 2016 +0800

    Use clutter_stage_capture instead of cogl's read_pixels
    
    There is no longer any guarantee that there'll be one single
    framebuffer to read pixels from. In order to still read pixels from the
    stage, use the new clutter_stage_capture API.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=768979

 src/shell-recorder.c   |   48 +++++++++++++++++++++++++------------
 src/shell-screenshot.c |   60 ++++++++++++++++++++++++------------------------
 2 files changed, 62 insertions(+), 46 deletions(-)
---
diff --git a/src/shell-recorder.c b/src/shell-recorder.c
index e7562ef..981b7d1 100644
--- a/src/shell-recorder.c
+++ b/src/shell-recorder.c
@@ -389,11 +389,17 @@ recorder_draw_cursor (ShellRecorder *recorder,
 /* Retrieve a frame and feed it into the pipeline
  */
 static void
-recorder_record_frame (ShellRecorder *recorder)
+recorder_record_frame (ShellRecorder *recorder,
+                       gboolean       paint)
 {
   GstBuffer *buffer;
-  guint8 *data;
+  ClutterCapture *captures;
+  int n_captures;
+  cairo_surface_t *image;
   guint size;
+  uint8_t *data;
+  GstMemory *memory;
+  int i;
   GstClock *clock;
   GstClockTime now, base_time;
 
@@ -425,21 +431,31 @@ recorder_record_frame (ShellRecorder *recorder)
     return;
   recorder->last_frame_time = now;
 
-  size = recorder->area.width * recorder->area.height * 4;
+  clutter_stage_capture (recorder->stage, paint, &recorder->area,
+                         &captures, &n_captures);
+
+  if (n_captures == 0)
+    return;
+
+  /*
+   * TODO: Deal with each capture region separately, instead of dropping
+   * anything except the first one.
+   */
+
+  image = captures[0].image;
+  data = cairo_image_surface_get_data (image);
+  size = captures[0].rect.width * captures[0].rect.height * 4;
 
-  data = g_malloc (size);
-  cogl_framebuffer_read_pixels (cogl_get_draw_framebuffer (),
-                                recorder->area.x,
-                                recorder->area.y,
-                                recorder->area.width,
-                                recorder->area.height,
-                                CLUTTER_CAIRO_FORMAT_ARGB32,
-                                data);
+  /* TODO: Capture more than the first framebuffer. */
+  for (i = 1; i < n_captures; i++)
+    cairo_surface_destroy (captures[i].image);
+  g_free (captures);
 
   buffer = gst_buffer_new();
-  gst_buffer_insert_memory (buffer, -1,
-                            gst_memory_new_wrapped (0, data, size, 0,
-                                                    size, data, g_free));
+  memory = gst_memory_new_wrapped (0, data, size, 0, size,
+                                   image,
+                                   (GDestroyNotify) cairo_surface_destroy);
+  gst_buffer_insert_memory (buffer, -1, memory);
 
   GST_BUFFER_PTS(buffer) = now;
 
@@ -463,7 +479,7 @@ recorder_on_stage_paint (ClutterActor  *actor,
                          ShellRecorder *recorder)
 {
   if (recorder->state == RECORDER_STATE_RECORDING)
-    recorder_record_frame (recorder);
+    recorder_record_frame (recorder, FALSE);
 }
 
 static void
@@ -1561,7 +1577,7 @@ shell_recorder_close (ShellRecorder *recorder)
   /* We want to record one more frame since some time may have
    * elapsed since the last frame
    */
-  clutter_actor_paint (CLUTTER_ACTOR (recorder->stage));
+  recorder_record_frame (recorder, TRUE);
 
   recorder_remove_update_pointer_timeout (recorder);
   recorder_close_pipeline (recorder);
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index 9480bad..d7c8088 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -210,41 +210,40 @@ write_screenshot_thread (GTask        *result,
 
 static void
 do_grab_screenshot (ShellScreenshot *screenshot,
+                    ClutterStage    *stage,
                     int               x,
                     int               y,
                     int               width,
                     int               height)
 {
-  CoglBitmap *bitmap;
-  ClutterBackend *backend;
-  CoglContext *context;
-  int stride;
-  guchar *data;
   ShellScreenshotPrivate *priv = screenshot->priv;
+  ClutterCapture *captures;
+  int n_captures;
+  int i;
+
+  clutter_stage_capture (stage, FALSE,
+                         &(cairo_rectangle_int_t) {
+                           .x = x,
+                           .y = y,
+                           .width = width,
+                           .height = height
+                         },
+                         &captures,
+                         &n_captures);
+
+  if (n_captures == 0)
+    return;
 
-  backend = clutter_get_default_backend ();
-  context = clutter_backend_get_cogl_context (backend);
-
-  priv->image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-                                            width, height);
-
-
-  data = cairo_image_surface_get_data (priv->image);
-  stride = cairo_image_surface_get_stride (priv->image);
+  /*
+   * TODO: Deal with each capture region separately, instead of dropping
+   * anything except the first one.
+   */
+  priv->image = captures[0].image;
 
-  bitmap = cogl_bitmap_new_for_data (context,
-                                     width,
-                                     height,
-                                     CLUTTER_CAIRO_FORMAT_ARGB32,
-                                     stride,
-                                     data);
-  cogl_framebuffer_read_pixels_into_bitmap (cogl_get_draw_framebuffer (),
-                                            x, y,
-                                            COGL_READ_PIXELS_COLOR_BUFFER,
-                                            bitmap);
+  for (i = 1; i < n_captures; i++)
+    cairo_surface_destroy (captures[i].image);
 
-  cairo_surface_mark_dirty (priv->image);
-  cogl_object_unref (bitmap);
+  g_free (captures);
 }
 
 static void
@@ -312,7 +311,7 @@ grab_screenshot (ClutterActor *stage,
   screen = shell_global_get_screen (priv->global);
   meta_screen_get_size (screen, &width, &height);
 
-  do_grab_screenshot (screenshot, 0, 0, width, height);
+  do_grab_screenshot (screenshot, CLUTTER_STAGE (stage), 0, 0, width, height);
 
   if (meta_screen_get_n_monitors (screen) > 1)
     {
@@ -381,6 +380,7 @@ grab_area_screenshot (ClutterActor *stage,
   ShellScreenshotPrivate *priv = screenshot->priv;
 
   do_grab_screenshot (screenshot,
+                      CLUTTER_STAGE (stage),
                       priv->screenshot_area.x,
                       priv->screenshot_area.y,
                       priv->screenshot_area.width,


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