Blame SOURCES/cursor-move-only-screen-cast-fixes.patch

180070
From 30caca0cb389dcbbab3d7ba72b92fce8e243b30b Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 16:42:45 +0200
180070
Subject: [PATCH 1/9] screen-cast-src: Make the two record vfuncs more
180070
 similarly named
180070
180070
Both do more or less the same but with different methods - one puts
180070
pixels into a buffer using the CPU, the other puts pixels into a buffer
180070
using the GPU.
180070
180070
However, they are behaving slightly different, which they shouldn't.
180070
Lets first address the misleading disconnect in naming, and later we'll
180070
make them behave more similarly.
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit d07335cd4ca094d790eac75e75cff01a28fda827)
180070
---
180070
 .../meta-screen-cast-monitor-stream-src.c       | 15 ++++++++-------
180070
 src/backends/meta-screen-cast-stream-src.c      | 17 +++++++++--------
180070
 src/backends/meta-screen-cast-stream-src.h      |  8 ++++----
180070
 .../meta-screen-cast-window-stream-src.c        | 15 ++++++++-------
180070
 4 files changed, 29 insertions(+), 26 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
index 655b682610..a1a98eb05b 100644
180070
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
@@ -347,8 +347,8 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
180070
-                                                  uint8_t                 *data)
180070
+meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
180070
+                                                      uint8_t                 *data)
180070
 {
180070
   MetaScreenCastMonitorStreamSrc *monitor_src =
180070
     META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
180070
@@ -368,8 +368,8 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
-                                                         CoglFramebuffer         *framebuffer)
180070
+meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
+                                                           CoglFramebuffer         *framebuffer)
180070
 {
180070
   MetaScreenCastMonitorStreamSrc *monitor_src =
180070
     META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
180070
@@ -551,9 +551,10 @@ meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcCl
180070
   src_class->get_specs = meta_screen_cast_monitor_stream_src_get_specs;
180070
   src_class->enable = meta_screen_cast_monitor_stream_src_enable;
180070
   src_class->disable = meta_screen_cast_monitor_stream_src_disable;
180070
-  src_class->record_frame = meta_screen_cast_monitor_stream_src_record_frame;
180070
-  src_class->blit_to_framebuffer =
180070
-    meta_screen_cast_monitor_stream_src_blit_to_framebuffer;
180070
+  src_class->record_to_buffer =
180070
+    meta_screen_cast_monitor_stream_src_record_to_buffer;
180070
+  src_class->record_to_framebuffer =
180070
+    meta_screen_cast_monitor_stream_src_record_to_framebuffer;
180070
   src_class->set_cursor_metadata =
180070
     meta_screen_cast_monitor_stream_src_set_cursor_metadata;
180070
 }
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index b77186415f..bafb82388d 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -133,23 +133,23 @@ meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
180070
-                                          uint8_t                 *data)
180070
+meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
180070
+                                              uint8_t                 *data)
180070
 {
180070
   MetaScreenCastStreamSrcClass *klass =
180070
     META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
180070
 
180070
-  return klass->record_frame (src, data);
180070
+  return klass->record_to_buffer (src, data);
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
-                                                 CoglFramebuffer         *framebuffer)
180070
+meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
+                                                   CoglFramebuffer         *framebuffer)
180070
 {
180070
   MetaScreenCastStreamSrcClass *klass =
180070
     META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
180070
 
180070
-  return klass->blit_to_framebuffer (src, framebuffer);
180070
+  return klass->record_to_framebuffer (src, framebuffer);
180070
 }
180070
 
180070
 static void
180070
@@ -417,7 +417,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
180070
   if (spa_buffer->datas[0].data ||
180070
       spa_buffer->datas[0].type == SPA_DATA_MemFd)
180070
     {
180070
-      return meta_screen_cast_stream_src_record_frame (src, data);
180070
+      return meta_screen_cast_stream_src_record_to_buffer (src, data);
180070
     }
180070
   else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
180070
     {
180070
@@ -427,7 +427,8 @@ do_record_frame (MetaScreenCastStreamSrc *src,
180070
       CoglFramebuffer *dmabuf_fbo =
180070
         cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
180070
 
180070
-      return meta_screen_cast_stream_src_blit_to_framebuffer (src, dmabuf_fbo);
180070
+      return meta_screen_cast_stream_src_record_to_framebuffer (src,
180070
+                                                                dmabuf_fbo);
180070
     }
180070
 
180070
   return FALSE;
180070
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
180070
index 3f6a1af2bb..0eda02f717 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.h
180070
+++ b/src/backends/meta-screen-cast-stream-src.h
180070
@@ -53,10 +53,10 @@ struct _MetaScreenCastStreamSrcClass
180070
                       float                   *frame_rate);
180070
   void (* enable) (MetaScreenCastStreamSrc *src);
180070
   void (* disable) (MetaScreenCastStreamSrc *src);
180070
-  gboolean (* record_frame) (MetaScreenCastStreamSrc *src,
180070
-                             uint8_t                 *data);
180070
-  gboolean (* blit_to_framebuffer) (MetaScreenCastStreamSrc *src,
180070
-                                    CoglFramebuffer         *framebuffer);
180070
+  gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src,
180070
+                                 uint8_t                 *data);
180070
+  gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src,
180070
+                                      CoglFramebuffer         *framebuffer);
180070
   gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
180070
                               MetaRectangle           *crop_rect);
180070
   void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
180070
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
180070
index c252b4356b..281df5e7b2 100644
180070
--- a/src/backends/meta-screen-cast-window-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-window-stream-src.c
180070
@@ -462,8 +462,8 @@ meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src)
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
180070
-                                                 uint8_t                 *data)
180070
+meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
180070
+                                                     uint8_t                 *data)
180070
 {
180070
   MetaScreenCastWindowStreamSrc *window_src =
180070
     META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
180070
@@ -474,8 +474,8 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
-                                                        CoglFramebuffer         *framebuffer)
180070
+meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
+                                                          CoglFramebuffer         *framebuffer)
180070
 {
180070
   MetaScreenCastWindowStreamSrc *window_src =
180070
     META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
180070
@@ -591,9 +591,10 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas
180070
   src_class->get_specs = meta_screen_cast_window_stream_src_get_specs;
180070
   src_class->enable = meta_screen_cast_window_stream_src_enable;
180070
   src_class->disable = meta_screen_cast_window_stream_src_disable;
180070
-  src_class->record_frame = meta_screen_cast_window_stream_src_record_frame;
180070
-  src_class->blit_to_framebuffer =
180070
-    meta_screen_cast_window_stream_src_blit_to_framebuffer;
180070
+  src_class->record_to_buffer =
180070
+    meta_screen_cast_window_stream_src_record_to_buffer;
180070
+  src_class->record_to_framebuffer =
180070
+    meta_screen_cast_window_stream_src_record_to_framebuffer;
180070
   src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop;
180070
   src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata;
180070
 }
180070
-- 
180070
2.26.2
180070
180070
180070
From ddc2094222fb55143922364cd4887cb18f856628 Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 16:46:44 +0200
180070
Subject: [PATCH 2/9] screen-cast/window-stream-src: Fix indentation
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit b1d45820efc5c9136f12d8a3b97a573a2eede9e7)
180070
---
180070
 src/backends/meta-screen-cast-window-stream-src.c | 4 ++--
180070
 1 file changed, 2 insertions(+), 2 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
180070
index 281df5e7b2..abdc791575 100644
180070
--- a/src/backends/meta-screen-cast-window-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-window-stream-src.c
180070
@@ -488,8 +488,8 @@ meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSr
180070
   stream_rect.height = get_stream_height (window_src);
180070
 
180070
   if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
180070
-                                                     &stream_rect,
180070
-                                                     framebuffer))
180070
+                                                    &stream_rect,
180070
+                                                    framebuffer))
180070
     return FALSE;
180070
 
180070
   stream = meta_screen_cast_stream_src_get_stream (src);
180070
-- 
180070
2.26.2
180070
180070
180070
From 59382848840aeb5c6491412742f474a3fb61639e Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 16:48:52 +0200
180070
Subject: [PATCH 3/9] screen-cast/src: Add flag to maybe_record()
180070
180070
Will later be used to make recording avoid recording actual pixel
180070
content if e.g. only the cursor moved.
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit 92db8902d9c3229a13d104bba71dd74f14d6dfac)
180070
---
180070
 src/backends/meta-screen-cast-monitor-stream-src.c |  8 ++++++--
180070
 src/backends/meta-screen-cast-stream-src.c         |  3 ++-
180070
 src/backends/meta-screen-cast-stream-src.h         |  8 +++++++-
180070
 src/backends/meta-screen-cast-window-stream-src.c  | 12 +++++++++---
180070
 4 files changed, 24 insertions(+), 7 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
index a1a98eb05b..8d57fafc0f 100644
180070
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
@@ -120,8 +120,10 @@ stage_painted (MetaStage        *stage,
180070
                gpointer          user_data)
180070
 {
180070
   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
180070
+  MetaScreenCastRecordFlag flags;
180070
 
180070
-  meta_screen_cast_stream_src_maybe_record_frame (src);
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
 static MetaBackend *
180070
@@ -180,6 +182,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
180070
 {
180070
   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
180070
   ClutterStage *stage = get_stage (monitor_src);
180070
+  MetaScreenCastRecordFlag flags;
180070
 
180070
   if (!is_cursor_in_stream (monitor_src))
180070
     return;
180070
@@ -187,7 +190,8 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
180070
   if (clutter_stage_is_redraw_queued (stage))
180070
     return;
180070
 
180070
-  meta_screen_cast_stream_src_maybe_record_frame (src);
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
 static void
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index bafb82388d..303c030be7 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -435,7 +435,8 @@ do_record_frame (MetaScreenCastStreamSrc *src,
180070
 }
180070
 
180070
 void
180070
-meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
180070
+meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
+                                                MetaScreenCastRecordFlag  flags)
180070
 {
180070
   MetaScreenCastStreamSrcPrivate *priv =
180070
     meta_screen_cast_stream_src_get_instance_private (src);
180070
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
180070
index 0eda02f717..6c73d05c1d 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.h
180070
+++ b/src/backends/meta-screen-cast-stream-src.h
180070
@@ -37,6 +37,11 @@
180070
 
180070
 typedef struct _MetaScreenCastStream MetaScreenCastStream;
180070
 
180070
+typedef enum _MetaScreenCastRecordFlag
180070
+{
180070
+  META_SCREEN_CAST_RECORD_FLAG_NONE = 0,
180070
+} MetaScreenCastRecordFlag;
180070
+
180070
 #define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ())
180070
 G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc,
180070
                           meta_screen_cast_stream_src,
180070
@@ -63,7 +68,8 @@ struct _MetaScreenCastStreamSrcClass
180070
                                 struct spa_meta_cursor  *spa_meta_cursor);
180070
 };
180070
 
180070
-void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src);
180070
+void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
+                                                     MetaScreenCastRecordFlag  flags);
180070
 
180070
 MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
180070
 
180070
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
180070
index abdc791575..f64d00860a 100644
180070
--- a/src/backends/meta-screen-cast-window-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-window-stream-src.c
180070
@@ -338,8 +338,10 @@ screen_cast_window_damaged (MetaWindowActor               *actor,
180070
                             MetaScreenCastWindowStreamSrc *window_src)
180070
 {
180070
   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
180070
+  MetaScreenCastRecordFlag flags;
180070
 
180070
-  meta_screen_cast_stream_src_maybe_record_frame (src);
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
 static void
180070
@@ -376,6 +378,7 @@ static void
180070
 sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
180070
 {
180070
   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
180070
+  MetaScreenCastRecordFlag flags;
180070
 
180070
   if (!is_cursor_in_stream (window_src))
180070
     return;
180070
@@ -383,7 +386,8 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
180070
   if (meta_screen_cast_window_has_damage (window_src->screen_cast_window))
180070
     return;
180070
 
180070
-  meta_screen_cast_stream_src_maybe_record_frame (src);
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
 static void
180070
@@ -412,6 +416,7 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
180070
   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
180070
   MetaWindowActor *window_actor;
180070
   MetaScreenCastStream *stream;
180070
+  MetaScreenCastRecordFlag flags;
180070
 
180070
   window_actor = meta_window_actor_from_window (get_window (window_src));
180070
   if (!window_actor)
180070
@@ -449,7 +454,8 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
180070
       break;
180070
     }
180070
 
180070
-  meta_screen_cast_stream_src_maybe_record_frame (src);
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
 static void
180070
-- 
180070
2.26.2
180070
180070
180070
From b8d76f2ded6a0c8b88403d97d4ea2c84993c0263 Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 16:52:43 +0200
180070
Subject: [PATCH 4/9] screen-cast: Let the reason for recording determine what
180070
 to record
180070
180070
E.g. we'll have pointer movement that, if no painting is already
180070
scheduled, should only send new cursor metadata without any new pixel
180070
buffer. When this happens, tell next step to not record the pixels if
180070
this was the case, instead of having it rediscover this itself.
180070
180070
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1323
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit cf88d648822eb6b7d412c08d4038c657d415bfff)
180070
---
180070
 .../meta-screen-cast-monitor-stream-src.c     |  5 +-
180070
 src/backends/meta-screen-cast-stream-src.c    | 51 +++++++++++--------
180070
 src/backends/meta-screen-cast-stream-src.h    |  1 +
180070
 .../meta-screen-cast-window-stream-src.c      |  4 +-
180070
 4 files changed, 33 insertions(+), 28 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
index 8d57fafc0f..2352c3b3d8 100644
180070
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
@@ -190,7 +190,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
180070
   if (clutter_stage_is_redraw_queued (stage))
180070
     return;
180070
 
180070
-  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
180070
   meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
@@ -361,9 +361,6 @@ meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *s
180070
   MetaLogicalMonitor *logical_monitor;
180070
 
180070
   stage = get_stage (monitor_src);
180070
-  if (!clutter_stage_is_redraw_queued (stage))
180070
-    return FALSE;
180070
-
180070
   monitor = get_monitor (monitor_src);
180070
   logical_monitor = meta_monitor_get_logical_monitor (monitor);
180070
   clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index 303c030be7..aa4b03b180 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -470,34 +470,41 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
       return;
180070
     }
180070
 
180070
-  if (do_record_frame (src, spa_buffer, data))
180070
+  if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY))
180070
     {
180070
-      struct spa_meta_region *spa_meta_video_crop;
180070
+      if (do_record_frame (src, spa_buffer, data))
180070
+        {
180070
+          struct spa_meta_region *spa_meta_video_crop;
180070
 
180070
-      spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
180070
-      spa_buffer->datas[0].chunk->stride = priv->video_stride;
180070
+          spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
180070
+          spa_buffer->datas[0].chunk->stride = priv->video_stride;
180070
 
180070
-      /* Update VideoCrop if needed */
180070
-      spa_meta_video_crop =
180070
-        spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
180070
-                                   sizeof (*spa_meta_video_crop));
180070
-      if (spa_meta_video_crop)
180070
-        {
180070
-          if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
180070
-            {
180070
-              spa_meta_video_crop->region.position.x = crop_rect.x;
180070
-              spa_meta_video_crop->region.position.y = crop_rect.y;
180070
-              spa_meta_video_crop->region.size.width = crop_rect.width;
180070
-              spa_meta_video_crop->region.size.height = crop_rect.height;
180070
-            }
180070
-          else
180070
+          /* Update VideoCrop if needed */
180070
+          spa_meta_video_crop =
180070
+            spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
180070
+                                       sizeof (*spa_meta_video_crop));
180070
+          if (spa_meta_video_crop)
180070
             {
180070
-              spa_meta_video_crop->region.position.x = 0;
180070
-              spa_meta_video_crop->region.position.y = 0;
180070
-              spa_meta_video_crop->region.size.width = priv->stream_width;
180070
-              spa_meta_video_crop->region.size.height = priv->stream_height;
180070
+              if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
180070
+                {
180070
+                  spa_meta_video_crop->region.position.x = crop_rect.x;
180070
+                  spa_meta_video_crop->region.position.y = crop_rect.y;
180070
+                  spa_meta_video_crop->region.size.width = crop_rect.width;
180070
+                  spa_meta_video_crop->region.size.height = crop_rect.height;
180070
+                }
180070
+              else
180070
+                {
180070
+                  spa_meta_video_crop->region.position.x = 0;
180070
+                  spa_meta_video_crop->region.position.y = 0;
180070
+                  spa_meta_video_crop->region.size.width = priv->stream_width;
180070
+                  spa_meta_video_crop->region.size.height = priv->stream_height;
180070
+                }
180070
             }
180070
         }
180070
+      else
180070
+        {
180070
+          spa_buffer->datas[0].chunk->size = 0;
180070
+        }
180070
     }
180070
   else
180070
     {
180070
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
180070
index 6c73d05c1d..87054eedf5 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.h
180070
+++ b/src/backends/meta-screen-cast-stream-src.h
180070
@@ -40,6 +40,7 @@ typedef struct _MetaScreenCastStream MetaScreenCastStream;
180070
 typedef enum _MetaScreenCastRecordFlag
180070
 {
180070
   META_SCREEN_CAST_RECORD_FLAG_NONE = 0,
180070
+  META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY = 1 << 0,
180070
 } MetaScreenCastRecordFlag;
180070
 
180070
 #define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ())
180070
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
180070
index f64d00860a..63c3429df0 100644
180070
--- a/src/backends/meta-screen-cast-window-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-window-stream-src.c
180070
@@ -340,7 +340,7 @@ screen_cast_window_damaged (MetaWindowActor               *actor,
180070
   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
180070
   MetaScreenCastRecordFlag flags;
180070
 
180070
-  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
180070
   meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
@@ -386,7 +386,7 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
180070
   if (meta_screen_cast_window_has_damage (window_src->screen_cast_window))
180070
     return;
180070
 
180070
-  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
180070
   meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
 
180070
-- 
180070
2.26.2
180070
180070
180070
From 5c925cf4de91c9fdd44cb1c13748b2f4d6187dd9 Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 16:57:01 +0200
180070
Subject: [PATCH 5/9] screen-cast/src: Make record functions return an error
180070
 when failing
180070
180070
Now that we don't use the record function to early out depending on
180070
implicit state (don't record pixels if only cursor moved for example),
180070
let it simply report an error when it fails, as we should no longer ever
180070
return without pixels if nothing failed.
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit 2d899596e21d43ab241d0ba37c0a9f90c2e610be)
180070
---
180070
 .../meta-screen-cast-monitor-stream-src.c     | 19 +++++------
180070
 src/backends/meta-screen-cast-stream-src.c    | 32 ++++++++++++-------
180070
 src/backends/meta-screen-cast-stream-src.h    | 10 +++---
180070
 .../meta-screen-cast-window-stream-src.c      | 16 +++++++---
180070
 4 files changed, 45 insertions(+), 32 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
index 2352c3b3d8..27b3ea37d8 100644
180070
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
@@ -351,8 +351,9 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
180070
-                                                      uint8_t                 *data)
180070
+meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc  *src,
180070
+                                                      uint8_t                  *data,
180070
+                                                      GError                  **error)
180070
 {
180070
   MetaScreenCastMonitorStreamSrc *monitor_src =
180070
     META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
180070
@@ -369,8 +370,9 @@ meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *s
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
-                                                           CoglFramebuffer         *framebuffer)
180070
+meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc  *src,
180070
+                                                           CoglFramebuffer          *framebuffer,
180070
+                                                           GError                  **error)
180070
 {
180070
   MetaScreenCastMonitorStreamSrc *monitor_src =
180070
     META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
180070
@@ -394,7 +396,6 @@ meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamS
180070
   for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
180070
     {
180070
       ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
180070
-      g_autoptr (GError) error = NULL;
180070
       CoglFramebuffer *view_framebuffer;
180070
       MetaRectangle view_layout;
180070
       int x, y;
180070
@@ -415,12 +416,8 @@ meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamS
180070
                                   x, y,
180070
                                   cogl_framebuffer_get_width (view_framebuffer),
180070
                                   cogl_framebuffer_get_height (view_framebuffer),
180070
-                                  &error))
180070
-        {
180070
-          g_warning ("Error blitting view into DMABuf framebuffer: %s",
180070
-                     error->message);
180070
-          return FALSE;
180070
-        }
180070
+                                  error))
180070
+        return FALSE;
180070
     }
180070
 
180070
   cogl_framebuffer_finish (framebuffer);
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index aa4b03b180..b930d5e7c0 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -133,23 +133,25 @@ meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
180070
-                                              uint8_t                 *data)
180070
+meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc  *src,
180070
+                                              uint8_t                  *data,
180070
+                                              GError                  **error)
180070
 {
180070
   MetaScreenCastStreamSrcClass *klass =
180070
     META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
180070
 
180070
-  return klass->record_to_buffer (src, data);
180070
+  return klass->record_to_buffer (src, data, error);
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
-                                                   CoglFramebuffer         *framebuffer)
180070
+meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc  *src,
180070
+                                                   CoglFramebuffer          *framebuffer,
180070
+                                                   GError                  **error)
180070
 {
180070
   MetaScreenCastStreamSrcClass *klass =
180070
     META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
180070
 
180070
-  return klass->record_to_framebuffer (src, framebuffer);
180070
+  return klass->record_to_framebuffer (src, framebuffer, error);
180070
 }
180070
 
180070
 static void
180070
@@ -407,9 +409,10 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
180070
 }
180070
 
180070
 static gboolean
180070
-do_record_frame (MetaScreenCastStreamSrc *src,
180070
-                 struct spa_buffer       *spa_buffer,
180070
-                 uint8_t                 *data)
180070
+do_record_frame (MetaScreenCastStreamSrc  *src,
180070
+                 struct spa_buffer        *spa_buffer,
180070
+                 uint8_t                  *data,
180070
+                 GError                  **error)
180070
 {
180070
   MetaScreenCastStreamSrcPrivate *priv =
180070
     meta_screen_cast_stream_src_get_instance_private (src);
180070
@@ -417,7 +420,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
180070
   if (spa_buffer->datas[0].data ||
180070
       spa_buffer->datas[0].type == SPA_DATA_MemFd)
180070
     {
180070
-      return meta_screen_cast_stream_src_record_to_buffer (src, data);
180070
+      return meta_screen_cast_stream_src_record_to_buffer (src, data, error);
180070
     }
180070
   else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
180070
     {
180070
@@ -428,9 +431,12 @@ do_record_frame (MetaScreenCastStreamSrc *src,
180070
         cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
180070
 
180070
       return meta_screen_cast_stream_src_record_to_framebuffer (src,
180070
-                                                                dmabuf_fbo);
180070
+                                                                dmabuf_fbo,
180070
+                                                                error);
180070
     }
180070
 
180070
+  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
180070
+               "Unknown SPA buffer type %u", spa_buffer->datas[0].type);
180070
   return FALSE;
180070
 }
180070
 
180070
@@ -445,6 +451,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
   struct spa_buffer *spa_buffer;
180070
   uint8_t *data = NULL;
180070
   uint64_t now_us;
180070
+  g_autoptr (GError) error = NULL;
180070
 
180070
   now_us = g_get_monotonic_time ();
180070
   if (priv->video_format.max_framerate.num > 0 &&
180070
@@ -472,7 +479,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
 
180070
   if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY))
180070
     {
180070
-      if (do_record_frame (src, spa_buffer, data))
180070
+      if (do_record_frame (src, spa_buffer, data, &error))
180070
         {
180070
           struct spa_meta_region *spa_meta_video_crop;
180070
 
180070
@@ -503,6 +510,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
         }
180070
       else
180070
         {
180070
+          g_warning ("Failed to record screen cast frame: %s", error->message);
180070
           spa_buffer->datas[0].chunk->size = 0;
180070
         }
180070
     }
180070
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
180070
index 87054eedf5..152790ecfb 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.h
180070
+++ b/src/backends/meta-screen-cast-stream-src.h
180070
@@ -59,10 +59,12 @@ struct _MetaScreenCastStreamSrcClass
180070
                       float                   *frame_rate);
180070
   void (* enable) (MetaScreenCastStreamSrc *src);
180070
   void (* disable) (MetaScreenCastStreamSrc *src);
180070
-  gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src,
180070
-                                 uint8_t                 *data);
180070
-  gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src,
180070
-                                      CoglFramebuffer         *framebuffer);
180070
+  gboolean (* record_to_buffer) (MetaScreenCastStreamSrc  *src,
180070
+                                 uint8_t                  *data,
180070
+                                 GError                  **error);
180070
+  gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc  *src,
180070
+                                      CoglFramebuffer          *framebuffer,
180070
+                                      GError                  **error);
180070
   gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
180070
                               MetaRectangle           *crop_rect);
180070
   void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
180070
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
180070
index 63c3429df0..70e868997e 100644
180070
--- a/src/backends/meta-screen-cast-window-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-window-stream-src.c
180070
@@ -468,8 +468,9 @@ meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src)
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
180070
-                                                     uint8_t                 *data)
180070
+meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc  *src,
180070
+                                                     uint8_t                  *data,
180070
+                                                     GError                  **error)
180070
 {
180070
   MetaScreenCastWindowStreamSrc *window_src =
180070
     META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
180070
@@ -480,8 +481,9 @@ meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *sr
180070
 }
180070
 
180070
 static gboolean
180070
-meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
180070
-                                                          CoglFramebuffer         *framebuffer)
180070
+meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc  *src,
180070
+                                                          CoglFramebuffer          *framebuffer,
180070
+                                                          GError                  **error)
180070
 {
180070
   MetaScreenCastWindowStreamSrc *window_src =
180070
     META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
180070
@@ -496,7 +498,11 @@ meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSr
180070
   if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
180070
                                                     &stream_rect,
180070
                                                     framebuffer))
180070
-    return FALSE;
180070
+    {
180070
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
180070
+                   "Failed to blit window content to framebuffer");
180070
+      return FALSE;
180070
+    }
180070
 
180070
   stream = meta_screen_cast_stream_src_get_stream (src);
180070
   switch (meta_screen_cast_stream_get_cursor_mode (stream))
180070
-- 
180070
2.26.2
180070
180070
180070
From 47b03793413aad449f021f64e66c68ca95be9a0f Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 23:50:28 +0200
180070
Subject: [PATCH 6/9] screen-cast/src: Fix signedness of timestamp field
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit 449fa7bf81fe0bee63f497d896cbeffe84dca82d)
180070
---
180070
 src/backends/meta-screen-cast-stream-src.c | 2 +-
180070
 1 file changed, 1 insertion(+), 1 deletion(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index b930d5e7c0..f6f66daaa3 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -89,7 +89,7 @@ typedef struct _MetaScreenCastStreamSrcPrivate
180070
   struct spa_video_info_raw video_format;
180070
   int video_stride;
180070
 
180070
-  uint64_t last_frame_timestamp_us;
180070
+  int64_t last_frame_timestamp_us;
180070
 
180070
   GHashTable *dmabuf_handles;
180070
 
180070
-- 
180070
2.26.2
180070
180070
180070
From d8c8ea23e700f85a55a5cc0b79151fbed75ab191 Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 3 Jul 2020 23:57:31 +0200
180070
Subject: [PATCH 7/9] screen-cast/src: Record follow up frame after timeout
180070
180070
During animation or other things that cause multiple frames in a row
180070
being painted, we might skip recording frames if the max framerate is
180070
reached.
180070
180070
Doing so means we might end up skipping the last frame in a series,
180070
ending with the last frame we sent was not the last one, making things
180070
appear to get stuck sometimes.
180070
180070
Handle this by creating a timeout if we ever throttle, and at the time
180070
the timeout callback is triggered, make sure we eventually send an up to
180070
date frame.
180070
180070
This is handle differently depending on the source type. A monitor
180070
source type reports 1x1 pixel damage on each view its monitor overlaps,
180070
while a window source type simply records a frame from the surface
180070
directly, except without recording a timestamp, so that timestamps
180070
always refer to when damage actually happened.
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit e8052f169b957a502bf86ca65071582692039b9c)
180070
---
180070
 .../meta-screen-cast-monitor-stream-src.c     | 43 +++++++++++
180070
 src/backends/meta-screen-cast-stream-src.c    | 77 +++++++++++++++++--
180070
 src/backends/meta-screen-cast-stream-src.h    |  4 +
180070
 .../meta-screen-cast-window-stream-src.c      | 11 +++
180070
 4 files changed, 130 insertions(+), 5 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
index 27b3ea37d8..3079578d8d 100644
180070
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
180070
@@ -190,6 +190,9 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
180070
   if (clutter_stage_is_redraw_queued (stage))
180070
     return;
180070
 
180070
+  if (meta_screen_cast_stream_src_pending_follow_up_frame (src))
180070
+    return;
180070
+
180070
   flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
180070
   meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
 }
180070
@@ -425,6 +428,44 @@ meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamS
180070
   return TRUE;
180070
 }
180070
 
180070
+static void
180070
+meta_screen_cast_monitor_stream_record_follow_up (MetaScreenCastStreamSrc *src)
180070
+{
180070
+  MetaScreenCastMonitorStreamSrc *monitor_src =
180070
+    META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
180070
+  MetaBackend *backend = get_backend (monitor_src);
180070
+  MetaRenderer *renderer = meta_backend_get_renderer (backend);
180070
+  ClutterStage *stage = get_stage (monitor_src);
180070
+  MetaMonitor *monitor;
180070
+  MetaLogicalMonitor *logical_monitor;
180070
+  MetaRectangle logical_monitor_layout;
180070
+  GList *l;
180070
+
180070
+  monitor = get_monitor (monitor_src);
180070
+  logical_monitor = meta_monitor_get_logical_monitor (monitor);
180070
+  logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
180070
+
180070
+  for (l = meta_renderer_get_views (renderer); l; l = l->next)
180070
+    {
180070
+      MetaRendererView *view = l->data;
180070
+      MetaRectangle view_layout;
180070
+      MetaRectangle damage;
180070
+
180070
+      clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
180070
+
180070
+      if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
180070
+        continue;
180070
+
180070
+      damage = (cairo_rectangle_int_t) {
180070
+        .x = view_layout.x,
180070
+        .y = view_layout.y,
180070
+        .width = 1,
180070
+        .height = 1,
180070
+      };
180070
+      clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &damage);
180070
+    }
180070
+}
180070
+
180070
 static void
180070
 meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
180070
                                                          struct spa_meta_cursor  *spa_meta_cursor)
180070
@@ -553,6 +594,8 @@ meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcCl
180070
     meta_screen_cast_monitor_stream_src_record_to_buffer;
180070
   src_class->record_to_framebuffer =
180070
     meta_screen_cast_monitor_stream_src_record_to_framebuffer;
180070
+  src_class->record_follow_up =
180070
+    meta_screen_cast_monitor_stream_record_follow_up;
180070
   src_class->set_cursor_metadata =
180070
     meta_screen_cast_monitor_stream_src_set_cursor_metadata;
180070
 }
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index f6f66daaa3..55af56f8b9 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -90,6 +90,7 @@ typedef struct _MetaScreenCastStreamSrcPrivate
180070
   int video_stride;
180070
 
180070
   int64_t last_frame_timestamp_us;
180070
+  guint follow_up_frame_source_id;
180070
 
180070
   GHashTable *dmabuf_handles;
180070
 
180070
@@ -107,6 +108,12 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc,
180070
                                                 meta_screen_cast_stream_src_init_initable_iface)
180070
                          G_ADD_PRIVATE (MetaScreenCastStreamSrc))
180070
 
180070
+static inline uint32_t
180070
+us2ms (uint64_t us)
180070
+{
180070
+  return (uint32_t) (us / 1000);
180070
+}
180070
+
180070
 static void
180070
 meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
180070
                                        int                     *width,
180070
@@ -154,6 +161,15 @@ meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc  *src
180070
   return klass->record_to_framebuffer (src, framebuffer, error);
180070
 }
180070
 
180070
+static void
180070
+meta_screen_cast_stream_src_record_follow_up (MetaScreenCastStreamSrc *src)
180070
+{
180070
+  MetaScreenCastStreamSrcClass *klass =
180070
+    META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
180070
+
180070
+  klass->record_follow_up (src);
180070
+}
180070
+
180070
 static void
180070
 meta_screen_cast_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
180070
                                                  struct spa_meta_cursor  *spa_meta_cursor)
180070
@@ -440,6 +456,43 @@ do_record_frame (MetaScreenCastStreamSrc  *src,
180070
   return FALSE;
180070
 }
180070
 
180070
+gboolean
180070
+meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src)
180070
+{
180070
+  MetaScreenCastStreamSrcPrivate *priv =
180070
+    meta_screen_cast_stream_src_get_instance_private (src);
180070
+
180070
+  return priv->follow_up_frame_source_id != 0;
180070
+}
180070
+
180070
+static gboolean
180070
+follow_up_frame_cb (gpointer user_data)
180070
+{
180070
+  MetaScreenCastStreamSrc *src = user_data;
180070
+  MetaScreenCastStreamSrcPrivate *priv =
180070
+    meta_screen_cast_stream_src_get_instance_private (src);
180070
+
180070
+  priv->follow_up_frame_source_id = 0;
180070
+  meta_screen_cast_stream_src_record_follow_up (src);
180070
+
180070
+  return G_SOURCE_REMOVE;
180070
+}
180070
+
180070
+static void
180070
+maybe_schedule_follow_up_frame (MetaScreenCastStreamSrc *src,
180070
+                                int64_t                  timeout_us)
180070
+{
180070
+  MetaScreenCastStreamSrcPrivate *priv =
180070
+    meta_screen_cast_stream_src_get_instance_private (src);
180070
+
180070
+  if (priv->follow_up_frame_source_id)
180070
+    return;
180070
+
180070
+  priv->follow_up_frame_source_id = g_timeout_add (us2ms (timeout_us),
180070
+                                                   follow_up_frame_cb,
180070
+                                                   src);
180070
+}
180070
+
180070
 void
180070
 meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
                                                 MetaScreenCastRecordFlag  flags)
180070
@@ -455,11 +508,24 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
 
180070
   now_us = g_get_monotonic_time ();
180070
   if (priv->video_format.max_framerate.num > 0 &&
180070
-      priv->last_frame_timestamp_us != 0 &&
180070
-      (now_us - priv->last_frame_timestamp_us <
180070
-       ((1000000 * priv->video_format.max_framerate.denom) /
180070
-        priv->video_format.max_framerate.num)))
180070
-    return;
180070
+      priv->last_frame_timestamp_us != 0)
180070
+    {
180070
+      int64_t min_interval_us;
180070
+      int64_t time_since_last_frame_us;
180070
+
180070
+      min_interval_us = ((1000000 * priv->video_format.max_framerate.denom) /
180070
+                         priv->video_format.max_framerate.num);
180070
+
180070
+      time_since_last_frame_us = now_us - priv->last_frame_timestamp_us;
180070
+      if (time_since_last_frame_us < min_interval_us)
180070
+        {
180070
+          int64_t timeout_us;
180070
+
180070
+          timeout_us = min_interval_us - time_since_last_frame_us;
180070
+          maybe_schedule_follow_up_frame (src, timeout_us);
180070
+          return;
180070
+        }
180070
+    }
180070
 
180070
   if (!priv->pipewire_stream)
180070
     return;
180070
@@ -479,6 +545,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
 
180070
   if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY))
180070
     {
180070
+      g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
180070
       if (do_record_frame (src, spa_buffer, data, &error))
180070
         {
180070
           struct spa_meta_region *spa_meta_video_crop;
180070
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
180070
index 152790ecfb..81ea20b173 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.h
180070
+++ b/src/backends/meta-screen-cast-stream-src.h
180070
@@ -65,6 +65,8 @@ struct _MetaScreenCastStreamSrcClass
180070
   gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc  *src,
180070
                                       CoglFramebuffer          *framebuffer,
180070
                                       GError                  **error);
180070
+  void (* record_follow_up) (MetaScreenCastStreamSrc *src);
180070
+
180070
   gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
180070
                               MetaRectangle           *crop_rect);
180070
   void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
180070
@@ -74,6 +76,8 @@ struct _MetaScreenCastStreamSrcClass
180070
 void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
                                                      MetaScreenCastRecordFlag  flags);
180070
 
180070
+gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src);
180070
+
180070
 MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
180070
 
180070
 gboolean meta_screen_cast_stream_src_draw_cursor_into (MetaScreenCastStreamSrc  *src,
180070
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
180070
index 70e868997e..7026ec3b4f 100644
180070
--- a/src/backends/meta-screen-cast-window-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-window-stream-src.c
180070
@@ -520,6 +520,15 @@ meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSr
180070
   return TRUE;
180070
 }
180070
 
180070
+static void
180070
+meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src)
180070
+{
180070
+  MetaScreenCastRecordFlag flags;
180070
+
180070
+  flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
180070
+  meta_screen_cast_stream_src_maybe_record_frame (src, flags);
180070
+}
180070
+
180070
 static void
180070
 meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
180070
                                                         struct spa_meta_cursor  *spa_meta_cursor)
180070
@@ -607,6 +616,8 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas
180070
     meta_screen_cast_window_stream_src_record_to_buffer;
180070
   src_class->record_to_framebuffer =
180070
     meta_screen_cast_window_stream_src_record_to_framebuffer;
180070
+  src_class->record_follow_up =
180070
+    meta_screen_cast_window_stream_record_follow_up;
180070
   src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop;
180070
   src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata;
180070
 }
180070
-- 
180070
2.26.2
180070
180070
180070
From f2babf5129df9e948f471e3d464162888a99201d Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Wed, 8 Jul 2020 15:08:23 +0200
180070
Subject: [PATCH 8/9] screen-cast/src: Use G_USEC_PER_SEC instead of 1000000
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1351
180070
(cherry picked from commit 0c6ac287e6da91ba76bf3958befef4bec6ed28f6)
180070
---
180070
 src/backends/meta-screen-cast-stream-src.c | 5 +++--
180070
 1 file changed, 3 insertions(+), 2 deletions(-)
180070
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index 55af56f8b9..1d6c2b9d08 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -513,8 +513,9 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc  *src,
180070
       int64_t min_interval_us;
180070
       int64_t time_since_last_frame_us;
180070
 
180070
-      min_interval_us = ((1000000 * priv->video_format.max_framerate.denom) /
180070
-                         priv->video_format.max_framerate.num);
180070
+      min_interval_us =
180070
+        ((G_USEC_PER_SEC * priv->video_format.max_framerate.denom) /
180070
+         priv->video_format.max_framerate.num);
180070
 
180070
       time_since_last_frame_us = now_us - priv->last_frame_timestamp_us;
180070
       if (time_since_last_frame_us < min_interval_us)
180070
-- 
180070
2.26.2
180070
180070
180070
From 950b3ea51391ffcb434f8f5380459174ba4c4853 Mon Sep 17 00:00:00 2001
180070
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
180070
Date: Fri, 10 Jul 2020 07:06:33 +0000
180070
Subject: [PATCH 9/9] screen-cast/src: Remove follow up timeout source on
180070
 disable
180070
180070
We failed to remove the timeout source when disabling, meaning that if a
180070
follow up was scheduled, and shortly after we disabled the source, the
180070
timeout would be invoked after the source was freed causing
180070
use-after-free bugs.
180070
180070
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1337
180070
180070
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1365
180070
180070
(cherry picked from commit d67ba3ea65717ceab3e0c91267191c6ed2aac2c2)
180070
(cherry picked from commit 1fd53c480f9bb58bd4ac0efc2bbce17dfda8645b)
180070
---
180070
 src/backends/meta-screen-cast-stream-src.c | 2 ++
180070
 1 file changed, 2 insertions(+)
180070
180070
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
180070
index 1d6c2b9d08..f39d348baa 100644
180070
--- a/src/backends/meta-screen-cast-stream-src.c
180070
+++ b/src/backends/meta-screen-cast-stream-src.c
180070
@@ -622,6 +622,8 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
180070
 
180070
   META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src);
180070
 
180070
+  g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
180070
+
180070
   priv->is_enabled = FALSE;
180070
 }
180070
 
180070
-- 
180070
2.26.2
180070