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
This commit is contained in:
parent
0dac0ad516
commit
f5c058a036
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user