From f5c058a036b21da747921d0ed9eefa64331e4f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jun 2016 15:57:28 +0800 Subject: [PATCH] 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 | 50 +++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/src/shell-recorder.c b/src/shell-recorder.c index e7562ef01..981b7d1f0 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); - 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); + 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; + + /* 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 9480bad98..d7c80881d 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; - backend = clutter_get_default_backend (); - context = clutter_backend_get_cogl_context (backend); + clutter_stage_capture (stage, FALSE, + &(cairo_rectangle_int_t) { + .x = x, + .y = y, + .width = width, + .height = height + }, + &captures, + &n_captures); - priv->image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - width, height); + if (n_captures == 0) + return; + /* + * TODO: Deal with each capture region separately, instead of dropping + * anything except the first one. + */ + priv->image = captures[0].image; - data = cairo_image_surface_get_data (priv->image); - stride = cairo_image_surface_get_stride (priv->image); + for (i = 1; i < n_captures; i++) + cairo_surface_destroy (captures[i].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); - - 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,