[gnome-remote-desktop] rdp-graphics-pipeline: Create separate render surface when needed
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] rdp-graphics-pipeline: Create separate render surface when needed
- Date: Fri, 4 Mar 2022 18:25:36 +0000 (UTC)
commit 2be38c330f2ccf46277cddf6149ac04ffedbb433
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Fri Feb 11 14:00:09 2022 +0100
rdp-graphics-pipeline: Create separate render surface when needed
The documentation of the graphics pipeline says:
[...] "the width and height of the MPEG-4 AVC/H.264 codec bitstream
MUST be aligned to a multiple of 16 and MUST be cropped by the region
mask specified in the regionRects field that is embedded in the
avc420MetaData field." ([MS-RDPEGFX] 2.2.4.4 RFX_AVC420_BITMAP_STREAM)
For the NVENC session, the height of each frame needs to be aligned to
a multiple of 64.
64 is a multiple of 16, but mstsc actually requires the bitstream to be
aligned to 16x16 tiles, as long as these tiles cover the surface.
This last part is not mentioned in the documentation, but this applies
to a lot of things of the RDP protocol.
In case of an error in the documentation, the behaviour of mstsc and
the RDS in MS Windows determine the behaviour of the RDP protocol.
So, adjust the implementation in gnome-remote-desktop accordingly.
Whenever the aligned height of the NVENC session, which is a multiple
of 64, does not match the aligned height of the mapped surface, create
a separate render surface.
This render surface will then have the aligned size of the NVENC
session and will be used to render the data to on the client side.
With the work in the previous commits, the client is instructed to blit
from the render surface to the mapped surface, when the render surface
needs to be used.
Without these changes, mstsc would abort the remote desktop connection
upon receiving a RDPGFX_WIRE_TO_SURFACE_PDU_1 message with a protocol
error.
src/grd-rdp-graphics-pipeline.c | 97 +++++++++++++++++++++++++++--------------
1 file changed, 65 insertions(+), 32 deletions(-)
---
diff --git a/src/grd-rdp-graphics-pipeline.c b/src/grd-rdp-graphics-pipeline.c
index ba36fa33..88535d28 100644
--- a/src/grd-rdp-graphics-pipeline.c
+++ b/src/grd-rdp-graphics-pipeline.c
@@ -33,6 +33,7 @@
#include "grd-rdp-network-autodetection.h"
#include "grd-rdp-surface.h"
#include "grd-session-rdp.h"
+#include "grd-utils.h"
#define ENC_TIMES_CHECK_INTERVAL_MS 1000
#define MAX_TRACKED_ENC_FRAMES 1000
@@ -117,6 +118,38 @@ grd_rdp_graphics_pipeline_set_hwaccel_nvidia (GrdRdpGraphicsPipeline *graphics_p
graphics_pipeline->hwaccel_nvidia = hwaccel_nvidia;
}
+static uint16_t
+get_next_free_surface_id (GrdRdpGraphicsPipeline *graphics_pipeline)
+{
+ uint16_t surface_id = graphics_pipeline->next_surface_id;
+
+ g_mutex_lock (&graphics_pipeline->gfx_mutex);
+ while (g_hash_table_contains (graphics_pipeline->surface_table,
+ GUINT_TO_POINTER (surface_id)))
+ ++surface_id;
+ g_mutex_unlock (&graphics_pipeline->gfx_mutex);
+
+ graphics_pipeline->next_surface_id = surface_id + 1;
+
+ return surface_id;
+}
+
+static uint32_t
+get_next_free_serial (GrdRdpGraphicsPipeline *graphics_pipeline)
+{
+ uint32_t serial = graphics_pipeline->next_serial;
+
+ g_mutex_lock (&graphics_pipeline->gfx_mutex);
+ while (g_hash_table_contains (graphics_pipeline->serial_surface_table,
+ GUINT_TO_POINTER (serial)))
+ ++serial;
+ g_mutex_unlock (&graphics_pipeline->gfx_mutex);
+
+ graphics_pipeline->next_serial = serial + 1;
+
+ return serial;
+}
+
void
grd_rdp_graphics_pipeline_create_surface (GrdRdpGraphicsPipeline *graphics_pipeline,
GrdRdpGfxSurface *gfx_surface)
@@ -129,6 +162,7 @@ grd_rdp_graphics_pipeline_create_surface (GrdRdpGraphicsPipeline *graphics_pipel
uint16_t surface_width = grd_rdp_gfx_surface_get_width (gfx_surface);
uint16_t surface_height = grd_rdp_gfx_surface_get_height (gfx_surface);
GfxSurfaceContext *surface_context;
+ gboolean needs_separate_render_surface = FALSE;
HWAccelContext *hwaccel_context;
uint32_t encode_session_id;
uint16_t aligned_width;
@@ -155,8 +189,16 @@ grd_rdp_graphics_pipeline_create_surface (GrdRdpGraphicsPipeline *graphics_pipel
&aligned_width, &aligned_height,
rdp_surface->refresh_rate))
{
+ uint16_t aligned_width_16;
+ uint16_t aligned_height_16;
+
g_debug ("[RDP.RDPGFX] Creating NVENC session for surface %u", surface_id);
+ aligned_width_16 = grd_get_aligned_size (surface_width, 16);
+ aligned_height_16 = grd_get_aligned_size (surface_height, 16);
+ if (aligned_width != aligned_width_16 || aligned_height != aligned_height_16)
+ needs_separate_render_surface = TRUE;
+
hwaccel_context = g_malloc0 (sizeof (HWAccelContext));
hwaccel_context->api = HW_ACCEL_API_NVENC;
hwaccel_context->encode_session_id = encode_session_id;
@@ -174,6 +216,29 @@ grd_rdp_graphics_pipeline_create_surface (GrdRdpGraphicsPipeline *graphics_pipel
create_surface.pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
rdpgfx_context->CreateSurface (rdpgfx_context, &create_surface);
+
+ if (needs_separate_render_surface)
+ {
+ g_autoptr (GrdRdpGfxSurface) render_surface = NULL;
+ GrdRdpGfxSurfaceDescriptor surface_descriptor = {};
+
+ g_debug ("[RDP.RDPGFX] Creating separate render surface for surface %u",
+ surface_id);
+
+ surface_descriptor.flags = GRD_RDP_GFX_SURFACE_FLAG_ALIGNED_SIZE |
+ GRD_RDP_GFX_SURFACE_FLAG_NO_HWACCEL_SESSIONS;
+ surface_descriptor.surface_id = get_next_free_surface_id (graphics_pipeline);
+ surface_descriptor.serial = get_next_free_serial (graphics_pipeline);
+ surface_descriptor.rdp_surface = rdp_surface;
+
+ surface_descriptor.aligned_width = aligned_width;
+ surface_descriptor.aligned_height = aligned_height;
+
+ render_surface = grd_rdp_gfx_surface_new (graphics_pipeline,
+ &surface_descriptor);
+ grd_rdp_gfx_surface_override_render_surface (gfx_surface,
+ g_steal_pointer (&render_surface));
+ }
}
void
@@ -855,38 +920,6 @@ refresh_gfx_surface_rfx_progressive (GrdRdpGraphicsPipeline *graphics_pipeline,
return TRUE;
}
-static uint16_t
-get_next_free_surface_id (GrdRdpGraphicsPipeline *graphics_pipeline)
-{
- uint16_t surface_id = graphics_pipeline->next_surface_id;
-
- g_mutex_lock (&graphics_pipeline->gfx_mutex);
- while (g_hash_table_contains (graphics_pipeline->surface_table,
- GUINT_TO_POINTER (surface_id)))
- ++surface_id;
- g_mutex_unlock (&graphics_pipeline->gfx_mutex);
-
- graphics_pipeline->next_surface_id = surface_id + 1;
-
- return surface_id;
-}
-
-static uint32_t
-get_next_free_serial (GrdRdpGraphicsPipeline *graphics_pipeline)
-{
- uint32_t serial = graphics_pipeline->next_serial;
-
- g_mutex_lock (&graphics_pipeline->gfx_mutex);
- while (g_hash_table_contains (graphics_pipeline->serial_surface_table,
- GUINT_TO_POINTER (serial)))
- ++serial;
- g_mutex_unlock (&graphics_pipeline->gfx_mutex);
-
- graphics_pipeline->next_serial = serial + 1;
-
- return serial;
-}
-
static void
map_surface_to_output (GrdRdpGraphicsPipeline *graphics_pipeline,
GrdRdpGfxSurface *gfx_surface)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]