[mutter] screen-cast/monitor-src: Use clutter_stage_paint_to_buffer



commit 6c818cd8d5d29a21288d64fcbb13eae6a69d65df
Author: Michel Dänzer <mdaenzer redhat com>
Date:   Fri Jun 25 18:33:28 2021 +0200

    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>

 src/backends/meta-screen-cast-monitor-stream-src.c | 139 +++++++++------------
 1 file changed, 57 insertions(+), 82 deletions(-)
---
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c 
b/src/backends/meta-screen-cast-monitor-stream-src.c
index ac6be6730f..82d3862c9a 100644
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
@@ -48,6 +48,8 @@ struct _MetaScreenCastMonitorStreamSrc
 
   gulong position_invalidated_handler_id;
   gulong cursor_changed_handler_id;
+
+  guint maybe_record_idle_id;
 };
 
 static void
@@ -116,17 +118,39 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
   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
 stage_painted (MetaStage           *stage,
                ClutterStageView    *view,
                ClutterPaintContext *paint_context,
                gpointer             user_data)
 {
-  MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
-  MetaScreenCastRecordFlag flags;
+  MetaScreenCastMonitorStreamSrc *monitor_src =
+    META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data);
+  MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
 
-  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
-  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+  if (monitor_src->maybe_record_idle_id)
+    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
@@ -135,17 +159,20 @@ before_stage_painted (MetaStage           *stage,
                       ClutterPaintContext *paint_context,
                       gpointer             user_data)
 {
-  MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
-  CoglScanout *scanout;
+  MetaScreenCastMonitorStreamSrc *monitor_src =
+    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 (scanout)
-    {
-      MetaScreenCastRecordFlag flags;
+  if (monitor_src->maybe_record_idle_id)
+    return;
 
-      flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
-      meta_screen_cast_stream_src_maybe_record_frame (src, flags);
-    }
+  if (!clutter_stage_view_peek_scanout (view))
+    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 *
@@ -440,6 +467,8 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
   g_clear_signal_handler (&monitor_src->cursor_changed_handler_id,
                           cursor_tracker);
 
+  g_clear_handle_id (&monitor_src->maybe_record_idle_id, g_source_remove);
+
   switch (meta_screen_cast_stream_get_cursor_mode (stream))
     {
     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
 meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc  *src,
                                                       int                       width,
@@ -530,6 +495,7 @@ meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc  *
   MetaMonitor *monitor;
   MetaLogicalMonitor *logical_monitor;
   float scale;
+  ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_CLEAR;
 
   monitor = get_monitor (monitor_src);
   logical_monitor = meta_monitor_get_logical_monitor (monitor);
@@ -540,18 +506,25 @@ meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc  *
   else
     scale = 1.0;
 
-  clutter_stage_capture_into (stage, &logical_monitor->rect, scale, data, stride);
-
   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_HIDDEN:
+      paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS;
+      break;
+    case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
+      paint_flags |= CLUTTER_PAINT_FLAG_FORCE_CURSORS;
       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;
 }
 
@@ -636,6 +609,8 @@ meta_screen_cast_monitor_stream_record_follow_up (MetaScreenCastStreamSrc *src)
   MetaRectangle logical_monitor_layout;
   GList *l;
 
+  g_clear_handle_id (&monitor_src->maybe_record_idle_id, g_source_remove);
+
   monitor = get_monitor (monitor_src);
   logical_monitor = meta_monitor_get_logical_monitor (monitor);
   logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);


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