[gnome-remote-desktop] rdp: Run do_render() as GSourceFunc in custom GMainContext



commit acd990aff25a327e6f0fb2797d4998824b0fbdc0
Author: Pascal Nowack <Pascal Nowack gmx de>
Date:   Mon Aug 23 19:18:10 2021 +0200

    rdp: Run do_render() as GSourceFunc in custom GMainContext
    
    In order to be able to run all graphics operations in a different
    thread, add a new GSource, which runs do_render() as callback function.
    This GSource will then be attached to a custom GMainContext.
    In a future commit, this custom GMainContext will be the GMainContext
    of the graphics thread.

 src/grd-rdp-pipewire-stream.c | 122 +++++++++++++++++++++++++-----------------
 src/grd-rdp-pipewire-stream.h |   1 +
 src/grd-session-rdp.c         |   1 +
 3 files changed, 76 insertions(+), 48 deletions(-)
---
diff --git a/src/grd-rdp-pipewire-stream.c b/src/grd-rdp-pipewire-stream.c
index 1d4a5a2..ba8050a 100644
--- a/src/grd-rdp-pipewire-stream.c
+++ b/src/grd-rdp-pipewire-stream.c
@@ -67,6 +67,7 @@ struct _GrdRdpPipeWireStream
 
   struct spa_hook pipewire_core_listener;
 
+  GSource *render_source;
   GMutex frame_mutex;
   GrdRdpFrame *pending_frame;
 
@@ -81,6 +82,69 @@ struct _GrdRdpPipeWireStream
 G_DEFINE_TYPE (GrdRdpPipeWireStream, grd_rdp_pipewire_stream,
                G_TYPE_OBJECT)
 
+static gboolean
+do_render (gpointer user_data)
+{
+  GrdRdpPipeWireStream *stream = GRD_RDP_PIPEWIRE_STREAM (user_data);
+  GrdRdpFrame *frame;
+
+  g_mutex_lock (&stream->frame_mutex);
+  frame = g_steal_pointer (&stream->pending_frame);
+  g_mutex_unlock (&stream->frame_mutex);
+
+  if (!frame)
+    return G_SOURCE_CONTINUE;
+
+  if (frame->data)
+    {
+      grd_session_rdp_take_buffer (stream->session_rdp, frame->data,
+                                   frame->width, frame->height);
+    }
+
+  if (frame->pointer_bitmap)
+    {
+      grd_session_rdp_update_pointer (stream->session_rdp,
+                                      frame->pointer_hotspot_x,
+                                      frame->pointer_hotspot_y,
+                                      frame->pointer_width,
+                                      frame->pointer_height,
+                                      frame->pointer_bitmap);
+    }
+  else if (frame->pointer_is_hidden)
+    {
+      grd_session_rdp_hide_pointer (stream->session_rdp);
+    }
+
+  g_free (frame);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+render_source_dispatch (GSource     *source,
+                        GSourceFunc  callback,
+                        gpointer     user_data)
+{
+  g_source_set_ready_time (source, -1);
+
+  return callback (user_data);
+}
+
+static GSourceFuncs render_source_funcs =
+{
+  .dispatch = render_source_dispatch,
+};
+
+static void
+create_render_source (GrdRdpPipeWireStream *stream,
+                      GMainContext         *render_context)
+{
+  stream->render_source = g_source_new (&render_source_funcs, sizeof (GSource));
+  g_source_set_callback (stream->render_source, do_render, stream, NULL);
+  g_source_set_ready_time (stream->render_source, -1);
+  g_source_attach (stream->render_source, render_context);
+}
+
 static gboolean
 pipewire_loop_source_prepare (GSource *base,
                               int     *timeout)
@@ -212,49 +276,6 @@ on_stream_param_changed (void                 *user_data,
                            params, G_N_ELEMENTS (params));
 }
 
-static int
-do_render (struct spa_loop *loop,
-           bool             async,
-           uint32_t         seq,
-           const void      *data,
-           size_t           size,
-           void            *user_data)
-{
-  GrdRdpPipeWireStream *stream = GRD_RDP_PIPEWIRE_STREAM (user_data);
-  GrdRdpFrame *frame;
-
-  g_mutex_lock (&stream->frame_mutex);
-  frame = g_steal_pointer (&stream->pending_frame);
-  g_mutex_unlock (&stream->frame_mutex);
-
-  if (!frame)
-    return 0;
-
-  if (frame->data)
-    {
-      grd_session_rdp_take_buffer (stream->session_rdp, frame->data,
-                                   frame->width, frame->height);
-    }
-
-  if (frame->pointer_bitmap)
-    {
-      grd_session_rdp_update_pointer (stream->session_rdp,
-                                      frame->pointer_hotspot_x,
-                                      frame->pointer_hotspot_y,
-                                      frame->pointer_width,
-                                      frame->pointer_height,
-                                      frame->pointer_bitmap);
-    }
-  else if (frame->pointer_is_hidden)
-    {
-      grd_session_rdp_hide_pointer (stream->session_rdp);
-    }
-
-  g_free (frame);
-
-  return 0;
-}
-
 static GrdRdpFrame *
 process_buffer (GrdRdpPipeWireStream *stream,
                 struct spa_buffer    *buffer)
@@ -386,8 +407,6 @@ static void
 on_stream_process (void *user_data)
 {
   GrdRdpPipeWireStream *stream = GRD_RDP_PIPEWIRE_STREAM (user_data);
-  GrdPipeWireSource *pipewire_source =
-    (GrdPipeWireSource *) stream->pipewire_source;
   struct pw_buffer *next_buffer;
   struct pw_buffer *buffer = NULL;
   GrdRdpFrame *frame;
@@ -419,9 +438,7 @@ on_stream_process (void *user_data)
 
   pw_stream_queue_buffer (stream->pipewire_stream, buffer);
 
-  pw_loop_invoke (pipewire_source->pipewire_loop, do_render,
-                  SPA_ID_INVALID, NULL, 0,
-                  false, stream);
+  g_source_set_ready_time (stream->render_source, 0);
 }
 
 static const struct pw_stream_events stream_events = {
@@ -516,6 +533,7 @@ static const struct pw_core_events core_events = {
 
 GrdRdpPipeWireStream *
 grd_rdp_pipewire_stream_new (GrdSessionRdp  *session_rdp,
+                             GMainContext   *render_context,
                              uint32_t        src_node_id,
                              uint32_t        refresh_rate,
                              GError        **error)
@@ -529,6 +547,8 @@ grd_rdp_pipewire_stream_new (GrdSessionRdp  *session_rdp,
   stream->session_rdp = session_rdp;
   stream->src_node_id = src_node_id;
 
+  create_render_source (stream, render_context);
+
   pipewire_source = create_pipewire_source ();
   if (!pipewire_source)
     {
@@ -586,6 +606,12 @@ grd_rdp_pipewire_stream_finalize (GObject *object)
       g_clear_pointer (&stream->pipewire_source, g_source_unref);
     }
 
+  if (stream->render_source)
+    {
+      g_source_destroy (stream->render_source);
+      g_clear_pointer (&stream->render_source, g_source_unref);
+    }
+
   G_OBJECT_CLASS (grd_rdp_pipewire_stream_parent_class)->finalize (object);
 }
 
diff --git a/src/grd-rdp-pipewire-stream.h b/src/grd-rdp-pipewire-stream.h
index 69b7592..dcedf84 100644
--- a/src/grd-rdp-pipewire-stream.h
+++ b/src/grd-rdp-pipewire-stream.h
@@ -31,6 +31,7 @@ G_DECLARE_FINAL_TYPE (GrdRdpPipeWireStream, grd_rdp_pipewire_stream,
                       GObject)
 
 GrdRdpPipeWireStream *grd_rdp_pipewire_stream_new (GrdSessionRdp  *session_rdp,
+                                                   GMainContext   *render_context,
                                                    uint32_t        src_node_id,
                                                    uint32_t        refresh_rate,
                                                    GError        **error);
diff --git a/src/grd-session-rdp.c b/src/grd-session-rdp.c
index 17a37f9..f85e3e7 100644
--- a/src/grd-session-rdp.c
+++ b/src/grd-session-rdp.c
@@ -2095,6 +2095,7 @@ grd_session_rdp_stream_ready (GrdSession *session,
   pipewire_node_id = grd_stream_get_pipewire_node_id (stream);
   refresh_rate = session_rdp->rdp_surface->refresh_rate;
   session_rdp->pipewire_stream = grd_rdp_pipewire_stream_new (session_rdp,
+                                                              NULL,
                                                               pipewire_node_id,
                                                               refresh_rate,
                                                               &error);


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