mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
screen-cast/monitor-src: Use clutter_stage_paint_to_buffer
It works correctly with scanouts, in contrast to clutter_stage_capture_into. Inspired by meta_screen_cast_area_stream_src_record_to_buffer. maybe_paint_cursor_sprite is now unused and thus removed. v2: * clutter_stage_paint_to_buffer requires switching to recording from an idle callback as well. (Jonas Ådahl) v3: * Set human readable name for idle source. (Ivan Molodetskikh) Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1940 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1914>
This commit is contained in:
parent
10d1de2bdf
commit
6c818cd8d5
@ -48,6 +48,8 @@ struct _MetaScreenCastMonitorStreamSrc
|
|||||||
|
|
||||||
gulong position_invalidated_handler_id;
|
gulong position_invalidated_handler_id;
|
||||||
gulong cursor_changed_handler_id;
|
gulong cursor_changed_handler_id;
|
||||||
|
|
||||||
|
guint maybe_record_idle_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -116,17 +118,39 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
maybe_record_frame_on_idle (gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data);
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
|
MetaScreenCastRecordFlag flags;
|
||||||
|
|
||||||
|
monitor_src->maybe_record_idle_id = 0;
|
||||||
|
|
||||||
|
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
||||||
|
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stage_painted (MetaStage *stage,
|
stage_painted (MetaStage *stage,
|
||||||
ClutterStageView *view,
|
ClutterStageView *view,
|
||||||
ClutterPaintContext *paint_context,
|
ClutterPaintContext *paint_context,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
MetaScreenCastRecordFlag flags;
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data);
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
if (monitor_src->maybe_record_idle_id)
|
||||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
return;
|
||||||
|
|
||||||
|
monitor_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle,
|
||||||
|
src);
|
||||||
|
g_source_set_name_by_id (monitor_src->maybe_record_idle_id,
|
||||||
|
"[mutter] maybe_record_frame_on_idle [monitor-src]");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -135,17 +159,20 @@ before_stage_painted (MetaStage *stage,
|
|||||||
ClutterPaintContext *paint_context,
|
ClutterPaintContext *paint_context,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
CoglScanout *scanout;
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data);
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
|
|
||||||
scanout = clutter_stage_view_peek_scanout (view);
|
if (monitor_src->maybe_record_idle_id)
|
||||||
if (scanout)
|
return;
|
||||||
{
|
|
||||||
MetaScreenCastRecordFlag flags;
|
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
if (!clutter_stage_view_peek_scanout (view))
|
||||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
return;
|
||||||
}
|
|
||||||
|
monitor_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle,
|
||||||
|
src);
|
||||||
|
g_source_set_name_by_id (monitor_src->maybe_record_idle_id,
|
||||||
|
"[mutter] maybe_record_frame_on_idle [monitor-src]");
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaBackend *
|
static MetaBackend *
|
||||||
@ -440,6 +467,8 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|||||||
g_clear_signal_handler (&monitor_src->cursor_changed_handler_id,
|
g_clear_signal_handler (&monitor_src->cursor_changed_handler_id,
|
||||||
cursor_tracker);
|
cursor_tracker);
|
||||||
|
|
||||||
|
g_clear_handle_id (&monitor_src->maybe_record_idle_id, g_source_remove);
|
||||||
|
|
||||||
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
||||||
{
|
{
|
||||||
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
||||||
@ -451,70 +480,6 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_paint_cursor_sprite (MetaScreenCastMonitorStreamSrc *monitor_src,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int stride,
|
|
||||||
uint8_t *data)
|
|
||||||
{
|
|
||||||
MetaBackend *backend = get_backend (monitor_src);
|
|
||||||
MetaCursorRenderer *cursor_renderer =
|
|
||||||
meta_backend_get_cursor_renderer (backend);
|
|
||||||
MetaCursorSprite *cursor_sprite;
|
|
||||||
CoglTexture *sprite_texture;
|
|
||||||
int sprite_width, sprite_height, sprite_stride;
|
|
||||||
float sprite_scale;
|
|
||||||
uint8_t *sprite_data;
|
|
||||||
cairo_surface_t *sprite_surface;
|
|
||||||
graphene_rect_t sprite_rect;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
if (!is_cursor_in_stream (monitor_src))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
|
||||||
if (!cursor_sprite)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (meta_cursor_renderer_is_overlay_visible (cursor_renderer))
|
|
||||||
return;
|
|
||||||
|
|
||||||
sprite_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
|
|
||||||
cursor_sprite);
|
|
||||||
sprite_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
|
||||||
sprite_width = cogl_texture_get_width (sprite_texture);
|
|
||||||
sprite_height = cogl_texture_get_height (sprite_texture);
|
|
||||||
sprite_stride = sprite_width * 4;
|
|
||||||
sprite_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
|
|
||||||
sprite_data = g_new0 (uint8_t, sprite_stride * sprite_height);
|
|
||||||
cogl_texture_get_data (sprite_texture,
|
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
|
||||||
sprite_stride,
|
|
||||||
sprite_data);
|
|
||||||
sprite_surface = cairo_image_surface_create_for_data (sprite_data,
|
|
||||||
CAIRO_FORMAT_ARGB32,
|
|
||||||
sprite_width,
|
|
||||||
sprite_height,
|
|
||||||
sprite_stride);
|
|
||||||
cairo_surface_set_device_scale (sprite_surface, sprite_scale, sprite_scale);
|
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data (data,
|
|
||||||
CAIRO_FORMAT_ARGB32,
|
|
||||||
width, height, stride);
|
|
||||||
|
|
||||||
cr = cairo_create (surface);
|
|
||||||
cairo_set_source_surface (cr, sprite_surface,
|
|
||||||
sprite_rect.origin.x,
|
|
||||||
sprite_rect.origin.y);
|
|
||||||
cairo_paint (cr);
|
|
||||||
cairo_destroy (cr);
|
|
||||||
cairo_surface_destroy (sprite_surface);
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
g_free (sprite_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||||
int width,
|
int width,
|
||||||
@ -530,6 +495,7 @@ meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *
|
|||||||
MetaMonitor *monitor;
|
MetaMonitor *monitor;
|
||||||
MetaLogicalMonitor *logical_monitor;
|
MetaLogicalMonitor *logical_monitor;
|
||||||
float scale;
|
float scale;
|
||||||
|
ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_CLEAR;
|
||||||
|
|
||||||
monitor = get_monitor (monitor_src);
|
monitor = get_monitor (monitor_src);
|
||||||
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||||
@ -540,18 +506,25 @@ meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *
|
|||||||
else
|
else
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
clutter_stage_capture_into (stage, &logical_monitor->rect, scale, data, stride);
|
|
||||||
|
|
||||||
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
||||||
{
|
{
|
||||||
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
|
||||||
maybe_paint_cursor_sprite (monitor_src, width, height, stride, data);
|
|
||||||
break;
|
|
||||||
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
||||||
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
||||||
|
paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS;
|
||||||
|
break;
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
||||||
|
paint_flags |= CLUTTER_PAINT_FLAG_FORCE_CURSORS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!clutter_stage_paint_to_buffer (stage, &logical_monitor->rect, scale,
|
||||||
|
data,
|
||||||
|
stride,
|
||||||
|
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||||
|
paint_flags,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,6 +609,8 @@ meta_screen_cast_monitor_stream_record_follow_up (MetaScreenCastStreamSrc *src)
|
|||||||
MetaRectangle logical_monitor_layout;
|
MetaRectangle logical_monitor_layout;
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
|
g_clear_handle_id (&monitor_src->maybe_record_idle_id, g_source_remove);
|
||||||
|
|
||||||
monitor = get_monitor (monitor_src);
|
monitor = get_monitor (monitor_src);
|
||||||
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||||
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
|
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
|
||||||
|
Loading…
Reference in New Issue
Block a user