[gnome-remote-desktop] rdp: Adapt to RDP buffer pool
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] rdp: Adapt to RDP buffer pool
- Date: Tue, 22 Feb 2022 23:10:23 +0000 (UTC)
commit 61b9740d9e417871174c879a446f63595dea97d2
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Mon Jan 3 13:41:58 2022 +0100
rdp: Adapt to RDP buffer pool
Instead of allocating new buffers over and over again, adapt to the
previously implemented RDP buffer pool.
src/grd-rdp-buffer-pool.c | 2 +-
src/grd-rdp-buffer.c | 11 +++-
src/grd-rdp-buffer.h | 6 +-
src/grd-rdp-pipewire-stream.c | 128 ++++++++++++++++++++++++++----------------
src/grd-rdp-surface.c | 20 ++++++-
src/grd-rdp-surface.h | 4 ++
src/grd-session-rdp.c | 45 +++++++++++----
src/grd-session-rdp.h | 5 +-
8 files changed, 154 insertions(+), 67 deletions(-)
---
diff --git a/src/grd-rdp-buffer-pool.c b/src/grd-rdp-buffer-pool.c
index d59de088..379e91c6 100644
--- a/src/grd-rdp-buffer-pool.c
+++ b/src/grd-rdp-buffer-pool.c
@@ -53,7 +53,7 @@ add_buffer_to_pool (GrdRdpBufferPool *buffer_pool)
GrdRdpBuffer *buffer;
BufferInfo *buffer_info;
- buffer = grd_rdp_buffer_new ();
+ buffer = grd_rdp_buffer_new (buffer_pool);
buffer_info = g_new0 (BufferInfo, 1);
if (buffer_pool->has_buffer_size)
diff --git a/src/grd-rdp-buffer.c b/src/grd-rdp-buffer.c
index 9d1ffca5..eb33a310 100644
--- a/src/grd-rdp-buffer.c
+++ b/src/grd-rdp-buffer.c
@@ -23,12 +23,15 @@
#include <gio/gio.h>
+#include "grd-rdp-buffer-pool.h"
+
GrdRdpBuffer *
-grd_rdp_buffer_new (void)
+grd_rdp_buffer_new (GrdRdpBufferPool *buffer_pool)
{
GrdRdpBuffer *buffer;
buffer = g_new0 (GrdRdpBuffer, 1);
+ buffer->buffer_pool = buffer_pool;
return buffer;
}
@@ -46,6 +49,12 @@ grd_rdp_buffer_free (GrdRdpBuffer *buffer)
g_free (buffer);
}
+void
+grd_rdp_buffer_release (GrdRdpBuffer *buffer)
+{
+ grd_rdp_buffer_pool_release_buffer (buffer->buffer_pool, buffer);
+}
+
void
grd_rdp_buffer_resize (GrdRdpBuffer *buffer,
uint32_t width,
diff --git a/src/grd-rdp-buffer.h b/src/grd-rdp-buffer.h
index c0e3dee4..aeefa25d 100644
--- a/src/grd-rdp-buffer.h
+++ b/src/grd-rdp-buffer.h
@@ -26,16 +26,20 @@
struct _GrdRdpBuffer
{
+ GrdRdpBufferPool *buffer_pool;
+
uint32_t width;
uint32_t height;
uint8_t *local_data;
};
-GrdRdpBuffer *grd_rdp_buffer_new (void);
+GrdRdpBuffer *grd_rdp_buffer_new (GrdRdpBufferPool *buffer_pool);
void grd_rdp_buffer_free (GrdRdpBuffer *buffer);
+void grd_rdp_buffer_release (GrdRdpBuffer *buffer);
+
void grd_rdp_buffer_resize (GrdRdpBuffer *buffer,
uint32_t width,
uint32_t height,
diff --git a/src/grd-rdp-pipewire-stream.c b/src/grd-rdp-pipewire-stream.c
index da8991a2..92810230 100644
--- a/src/grd-rdp-pipewire-stream.c
+++ b/src/grd-rdp-pipewire-stream.c
@@ -34,7 +34,11 @@
#include "grd-egl-thread.h"
#include "grd-pipewire-utils.h"
#include "grd-rdp-buffer.h"
+#include "grd-rdp-buffer-pool.h"
#include "grd-rdp-surface.h"
+#include "grd-utils.h"
+
+#define DEFAULT_BUFFER_POOL_SIZE 5
enum
{
@@ -84,6 +88,8 @@ struct _GrdRdpPipeWireStream
struct spa_hook pipewire_core_listener;
+ GrdRdpBufferPool *buffer_pool;
+
GSource *render_source;
GMutex frame_mutex;
GrdRdpFrame *pending_frame;
@@ -134,7 +140,7 @@ grd_rdp_frame_unref (GrdRdpFrame *frame)
{
if (g_atomic_ref_count_dec (&frame->refcount))
{
- g_clear_pointer (&frame->buffer, grd_rdp_buffer_free);
+ g_clear_pointer (&frame->buffer, grd_rdp_buffer_release);
g_free (frame->pointer_bitmap);
g_free (frame);
}
@@ -148,16 +154,22 @@ do_render (gpointer user_data)
g_mutex_lock (&stream->frame_mutex);
frame = g_steal_pointer (&stream->pending_frame);
+
+ if (frame && frame->buffer)
+ {
+ g_mutex_lock (&stream->rdp_surface->surface_mutex);
+ g_assert (!stream->rdp_surface->new_framebuffer);
+
+ stream->rdp_surface->new_framebuffer = g_steal_pointer (&frame->buffer);
+ g_mutex_unlock (&stream->rdp_surface->surface_mutex);
+ }
g_mutex_unlock (&stream->frame_mutex);
if (!frame)
return G_SOURCE_CONTINUE;
- if (frame->buffer)
- {
- grd_session_rdp_take_buffer (stream->session_rdp, stream->rdp_surface,
- g_steal_pointer (&frame->buffer));
- }
+ grd_session_rdp_maybe_encode_new_frame (stream->session_rdp,
+ stream->rdp_surface);
if (frame->pointer_bitmap)
{
@@ -291,6 +303,45 @@ on_stream_state_changed (void *user_data,
}
}
+static void
+on_sync_complete (gboolean success,
+ gpointer user_data)
+{
+ GrdSyncPoint *sync_point = user_data;
+
+ grd_sync_point_complete (sync_point, success);
+}
+
+static void
+sync_egl_thread (GrdEglThread *egl_thread)
+{
+ GrdSyncPoint sync_point = {};
+
+ grd_sync_point_init (&sync_point);
+ grd_egl_thread_sync (egl_thread, on_sync_complete, &sync_point, NULL);
+
+ grd_sync_point_wait_for_completion (&sync_point);
+ grd_sync_point_clear (&sync_point);
+}
+
+static void
+release_all_buffers (GrdRdpPipeWireStream *stream)
+{
+ g_mutex_lock (&stream->frame_mutex);
+ if (stream->pending_frame)
+ g_clear_pointer (&stream->pending_frame->buffer, grd_rdp_buffer_release);
+ g_mutex_unlock (&stream->frame_mutex);
+
+ g_mutex_lock (&stream->rdp_surface->surface_mutex);
+ g_clear_pointer (&stream->rdp_surface->new_framebuffer,
+ grd_rdp_buffer_release);
+ g_clear_pointer (&stream->rdp_surface->last_framebuffer,
+ grd_rdp_buffer_release);
+ g_clear_pointer (&stream->rdp_surface->pending_framebuffer,
+ grd_rdp_buffer_release);
+ g_mutex_unlock (&stream->rdp_surface->surface_mutex);
+}
+
static void
on_stream_param_changed (void *user_data,
uint32_t id,
@@ -299,6 +350,10 @@ on_stream_param_changed (void *user_data,
GrdRdpPipeWireStream *stream = GRD_RDP_PIPEWIRE_STREAM (user_data);
GrdSession *session = GRD_SESSION (stream->session_rdp);
GrdContext *context = grd_session_get_context (session);
+ GrdEglThread *egl_thread = grd_context_get_egl_thread (context);
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
uint8_t params_buffer[1024];
struct spa_pod_builder pod_builder;
enum spa_data_type allowed_buffer_types;
@@ -308,11 +363,20 @@ on_stream_param_changed (void *user_data,
return;
spa_format_video_raw_parse (format, &stream->spa_format);
+ height = stream->spa_format.size.height;
+ width = stream->spa_format.size.width;
+ stride = grd_session_rdp_get_stride_for_width (stream->session_rdp, width);
+
+ if (egl_thread)
+ sync_egl_thread (egl_thread);
+ release_all_buffers (stream);
+
+ grd_rdp_buffer_pool_resize_buffers (stream->buffer_pool, width, height, stride);
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
allowed_buffer_types = 1 << SPA_DATA_MemFd;
- if (grd_context_get_egl_thread (context))
+ if (egl_thread)
allowed_buffer_types |= 1 << SPA_DATA_DmaBuf;
params[0] = spa_pod_builder_add_object (
@@ -458,8 +522,7 @@ process_buffer (GrdRdpPipeWireStream *stream,
}
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
- frame->buffer = grd_rdp_buffer_new ();
- grd_rdp_buffer_resize (frame->buffer, width, height, dst_stride);
+ frame->buffer = grd_rdp_buffer_pool_acquire (stream->buffer_pool);
copy_frame_data (frame,
src_data,
@@ -486,8 +549,7 @@ process_buffer (GrdRdpPipeWireStream *stream,
unsigned int i;
uint8_t *dst_data;
- frame->buffer = grd_rdp_buffer_new ();
- grd_rdp_buffer_resize (frame->buffer, width, height, dst_stride);
+ frame->buffer = grd_rdp_buffer_pool_acquire (stream->buffer_pool);
row_width = dst_stride / bpp;
@@ -526,8 +588,7 @@ process_buffer (GrdRdpPipeWireStream *stream,
src_data = buffer->datas[0].data;
- frame->buffer = grd_rdp_buffer_new ();
- grd_rdp_buffer_resize (frame->buffer, width, height, dst_stride);
+ frame->buffer = grd_rdp_buffer_pool_acquire (stream->buffer_pool);
copy_frame_data (frame,
src_data,
@@ -836,26 +897,9 @@ grd_rdp_pipewire_stream_new (GrdSessionRdp *session_rdp,
if (!connect_to_stream (stream, rdp_surface->refresh_rate, error))
return NULL;
- return g_steal_pointer (&stream);
-}
-
-typedef struct
-{
- GMutex mutex;
- GCond cond;
- gboolean done;
-} SyncData;
+ stream->buffer_pool = grd_rdp_buffer_pool_new (DEFAULT_BUFFER_POOL_SIZE);
-static void
-on_sync_done (gboolean success,
- gpointer user_data)
-{
- SyncData *sync_data = user_data;
-
- g_mutex_lock (&sync_data->mutex);
- sync_data->done = TRUE;
- g_cond_signal (&sync_data->cond);
- g_mutex_unlock (&sync_data->mutex);
+ return g_steal_pointer (&stream);
}
static void
@@ -873,22 +917,7 @@ grd_rdp_pipewire_stream_finalize (GObject *object)
egl_thread = grd_context_get_egl_thread (context);
if (egl_thread && stream->pipewire_stream)
- {
- SyncData sync_data = {};
-
- g_mutex_init (&sync_data.mutex);
- g_cond_init (&sync_data.cond);
-
- grd_egl_thread_sync (egl_thread, on_sync_done, &sync_data, NULL);
-
- g_mutex_lock (&sync_data.mutex);
- while (!sync_data.done)
- g_cond_wait (&sync_data.cond, &sync_data.mutex);
- g_mutex_unlock (&sync_data.mutex);
-
- g_cond_clear (&sync_data.cond);
- g_mutex_clear (&sync_data.mutex);
- }
+ sync_egl_thread (egl_thread);
/*
* We can't clear stream->pipewire_stream before destroying it, as the data
@@ -913,6 +942,9 @@ grd_rdp_pipewire_stream_finalize (GObject *object)
g_clear_pointer (&stream->pending_frame, grd_rdp_frame_unref);
+ release_all_buffers (stream);
+ g_clear_object (&stream->buffer_pool);
+
g_mutex_clear (&stream->frame_mutex);
G_OBJECT_CLASS (grd_rdp_pipewire_stream_parent_class)->finalize (object);
diff --git a/src/grd-rdp-surface.c b/src/grd-rdp-surface.c
index b9f59c7b..ba78c26a 100644
--- a/src/grd-rdp-surface.c
+++ b/src/grd-rdp-surface.c
@@ -23,12 +23,28 @@
#include "grd-rdp-buffer.h"
+GrdRdpSurface *
+grd_rdp_surface_new (void)
+{
+ GrdRdpSurface *rdp_surface;
+
+ rdp_surface = g_malloc0 (sizeof (GrdRdpSurface));
+
+ g_mutex_init (&rdp_surface->surface_mutex);
+
+ return rdp_surface;
+}
+
void
grd_rdp_surface_free (GrdRdpSurface *rdp_surface)
{
g_assert (!rdp_surface->gfx_surface);
- g_clear_pointer (&rdp_surface->last_framebuffer, grd_rdp_buffer_free);
- g_clear_pointer (&rdp_surface->pending_framebuffer, grd_rdp_buffer_free);
+
+ g_assert (!rdp_surface->new_framebuffer);
+ g_assert (!rdp_surface->last_framebuffer);
+ g_assert (!rdp_surface->pending_framebuffer);
+
+ g_mutex_clear (&rdp_surface->surface_mutex);
g_free (rdp_surface);
}
diff --git a/src/grd-rdp-surface.h b/src/grd-rdp-surface.h
index 3d1d18b6..9f20a641 100644
--- a/src/grd-rdp-surface.h
+++ b/src/grd-rdp-surface.h
@@ -32,6 +32,8 @@ struct _GrdRdpSurface
uint16_t width;
uint16_t height;
+ GMutex surface_mutex;
+ GrdRdpBuffer *new_framebuffer;
GrdRdpBuffer *last_framebuffer;
GrdRdpBuffer *pending_framebuffer;
@@ -42,6 +44,8 @@ struct _GrdRdpSurface
gboolean encoding_suspended;
};
+GrdRdpSurface *grd_rdp_surface_new (void);
+
void grd_rdp_surface_free (GrdRdpSurface *rdp_surface);
#endif /* GRD_RDP_SURFACE_H */
diff --git a/src/grd-session-rdp.c b/src/grd-session-rdp.c
index f3016cf5..027b43f7 100644
--- a/src/grd-session-rdp.c
+++ b/src/grd-session-rdp.c
@@ -246,17 +246,17 @@ maybe_resize_graphics_output_buffer (GrdSessionRdp *session_rdp,
set_rdp_peer_flag (session_rdp, RDP_PEER_ALL_SURFACES_INVALID);
}
-void
-grd_session_rdp_take_buffer (GrdSessionRdp *session_rdp,
- GrdRdpSurface *rdp_surface,
- GrdRdpBuffer *buffer)
+static void
+take_or_encode_frame (GrdSessionRdp *session_rdp,
+ GrdRdpSurface *rdp_surface,
+ GrdRdpBuffer *buffer)
{
uint16_t width = buffer->width;
uint16_t height = buffer->height;
uint32_t stride;
cairo_region_t *region;
- g_clear_pointer (&rdp_surface->pending_framebuffer, grd_rdp_buffer_free);
+ g_clear_pointer (&rdp_surface->pending_framebuffer, grd_rdp_buffer_release);
maybe_resize_graphics_output_buffer (session_rdp, width, height);
if (is_rdp_peer_flag_set (session_rdp, RDP_PEER_ALL_SURFACES_INVALID))
@@ -276,7 +276,7 @@ grd_session_rdp_take_buffer (GrdSessionRdp *session_rdp,
}
if (!rdp_surface->valid)
- g_clear_pointer (&rdp_surface->last_framebuffer, grd_rdp_buffer_free);
+ g_clear_pointer (&rdp_surface->last_framebuffer, grd_rdp_buffer_release);
if (is_rdp_peer_flag_set (session_rdp, RDP_PEER_ACTIVATED) &&
is_rdp_peer_flag_set (session_rdp, RDP_PEER_OUTPUT_ENABLED) &&
@@ -299,7 +299,7 @@ grd_session_rdp_take_buffer (GrdSessionRdp *session_rdp,
if (!cairo_region_is_empty (region))
rdp_peer_refresh_region (session_rdp, rdp_surface, region, buffer);
- g_clear_pointer (&rdp_surface->last_framebuffer, grd_rdp_buffer_free);
+ g_clear_pointer (&rdp_surface->last_framebuffer, grd_rdp_buffer_release);
rdp_surface->last_framebuffer = buffer;
cairo_region_destroy (region);
@@ -310,6 +310,22 @@ grd_session_rdp_take_buffer (GrdSessionRdp *session_rdp,
}
}
+void
+grd_session_rdp_maybe_encode_new_frame (GrdSessionRdp *session_rdp,
+ GrdRdpSurface *rdp_surface)
+{
+ g_mutex_lock (&rdp_surface->surface_mutex);
+ if (!rdp_surface->new_framebuffer)
+ {
+ g_mutex_unlock (&rdp_surface->surface_mutex);
+ return;
+ }
+
+ take_or_encode_frame (session_rdp, rdp_surface,
+ g_steal_pointer (&rdp_surface->new_framebuffer));
+ g_mutex_unlock (&rdp_surface->surface_mutex);
+}
+
void
grd_session_rdp_maybe_encode_pending_frame (GrdSessionRdp *session_rdp,
GrdRdpSurface *rdp_surface)
@@ -321,11 +337,18 @@ grd_session_rdp_maybe_encode_pending_frame (GrdSessionRdp *session_rdp,
is_rdp_peer_flag_set (session_rdp, RDP_PEER_PENDING_GFX_INIT))
return;
+ g_mutex_lock (&rdp_surface->surface_mutex);
+ g_assert (!rdp_surface->new_framebuffer);
+
if (!rdp_surface->pending_framebuffer)
- return;
+ {
+ g_mutex_unlock (&rdp_surface->surface_mutex);
+ return;
+ }
- grd_session_rdp_take_buffer (session_rdp, rdp_surface,
- g_steal_pointer (&rdp_surface->pending_framebuffer));
+ take_or_encode_frame (session_rdp, rdp_surface,
+ g_steal_pointer (&rdp_surface->pending_framebuffer));
+ g_mutex_unlock (&rdp_surface->surface_mutex);
}
static gboolean
@@ -1631,7 +1654,7 @@ rdp_peer_post_connect (freerdp_peer *peer)
rdp_settings->PointerCacheSize = MIN (rdp_settings->PointerCacheSize, 100);
- session_rdp->rdp_surface = g_malloc0 (sizeof (GrdRdpSurface));
+ session_rdp->rdp_surface = grd_rdp_surface_new ();
session_rdp->rdp_surface->refresh_rate = rdp_settings->SupportGraphicsPipeline ? 60
: 30;
diff --git a/src/grd-session-rdp.h b/src/grd-session-rdp.h
index 2572d329..48deceb6 100644
--- a/src/grd-session-rdp.h
+++ b/src/grd-session-rdp.h
@@ -49,9 +49,8 @@ void grd_session_rdp_notify_graphics_pipeline_ready (GrdSessionRdp *session_rdp)
int grd_session_rdp_get_stride_for_width (GrdSessionRdp *session_rdp,
int width);
-void grd_session_rdp_take_buffer (GrdSessionRdp *session_rdp,
- GrdRdpSurface *rdp_surface,
- GrdRdpBuffer *buffer);
+void grd_session_rdp_maybe_encode_new_frame (GrdSessionRdp *session_rdp,
+ GrdRdpSurface *rdp_surface);
void grd_session_rdp_maybe_encode_pending_frame (GrdSessionRdp *session_rdp,
GrdRdpSurface *rdp_surface);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]