[gnome-remote-desktop] rdp: Defer cairo region creation if possible
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] rdp: Defer cairo region creation if possible
- Date: Thu, 3 Mar 2022 14:23:09 +0000 (UTC)
commit 39f0e6ff014ca3715de3e65df41ccf8ef3532a04
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Thu Jan 13 15:32:12 2022 +0100
rdp: Defer cairo region creation if possible
NVENC does not make use of damage regions, but xfreerdp uses damage
regions to cut out unnecessary operations to display the decoded frame.
When NVENC encodes a frame, CUDA kernels can still run and data can
still be transferred between the Host and the GPU, without affecting
the NVENC operation.
With the split up of the NVENC encode operation done in the last
commit, run the cairo damage region creation, while NVENC encodes the
frame.
As the damage checking is already done, the damage region just needs to
be simplified and transferred to the host.
When this task is done, the graphics thread will wait for NVENC to
finish the encoding operation.
src/grd-rdp-graphics-pipeline.c | 36 ++++++++++++++++++++++++++++++------
src/grd-rdp-graphics-pipeline.h | 2 --
src/grd-session-rdp.c | 40 ++++++++++++++++++----------------------
3 files changed, 48 insertions(+), 30 deletions(-)
---
diff --git a/src/grd-rdp-graphics-pipeline.c b/src/grd-rdp-graphics-pipeline.c
index 088b92e4..fa7d6ad5 100644
--- a/src/grd-rdp-graphics-pipeline.c
+++ b/src/grd-rdp-graphics-pipeline.c
@@ -21,10 +21,12 @@
#include "grd-rdp-graphics-pipeline.h"
+#include <cairo/cairo.h>
#include <winpr/sysinfo.h>
#include "grd-hwaccel-nvidia.h"
#include "grd-rdp-buffer.h"
+#include "grd-rdp-damage-detector.h"
#include "grd-rdp-frame-info.h"
#include "grd-rdp-gfx-surface.h"
#include "grd-rdp-network-autodetection.h"
@@ -389,7 +391,6 @@ static gboolean
refresh_gfx_surface_avc420 (GrdRdpGraphicsPipeline *graphics_pipeline,
HWAccelContext *hwaccel_context,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer,
int64_t *enc_time_us)
{
@@ -406,6 +407,7 @@ refresh_gfx_surface_avc420 (GrdRdpGraphicsPipeline *graphics_pipeline,
uint16_t surface_height = rdp_surface->height;
uint16_t aligned_width;
uint16_t aligned_height;
+ cairo_region_t *region;
uint32_t surface_serial;
int64_t enc_ack_time_us;
int i;
@@ -428,11 +430,23 @@ refresh_gfx_surface_avc420 (GrdRdpGraphicsPipeline *graphics_pipeline,
return FALSE;
}
+ region = grd_rdp_damage_detector_get_damage_region (rdp_surface->detector);
+ if (!region)
+ {
+ grd_session_rdp_notify_error (graphics_pipeline->session_rdp,
+ GRD_SESSION_RDP_ERROR_GRAPHICS_SUBSYSTEM_FAILED);
+ grd_hwaccel_nvidia_avc420_retrieve_bitstream (graphics_pipeline->hwaccel_nvidia,
+ hwaccel_context->encode_session_id,
+ NULL, NULL);
+ return FALSE;
+ }
+
if (!grd_hwaccel_nvidia_avc420_retrieve_bitstream (graphics_pipeline->hwaccel_nvidia,
hwaccel_context->encode_session_id,
&avc420.data, &avc420.length))
{
g_warning ("[RDP.RDPGFX] Failed to retrieve AVC420 bitstream");
+ cairo_region_destroy (region);
return FALSE;
}
@@ -504,6 +518,7 @@ refresh_gfx_surface_avc420 (GrdRdpGraphicsPipeline *graphics_pipeline,
g_free (avc420.data);
g_free (avc420.meta.quantQualityVals);
g_free (avc420.meta.regionRects);
+ cairo_region_destroy (region);
return TRUE;
}
@@ -642,7 +657,6 @@ rfx_progressive_write_message (RFX_MESSAGE *rfx_message,
static gboolean
refresh_gfx_surface_rfx_progressive (GrdRdpGraphicsPipeline *graphics_pipeline,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer,
int64_t *enc_time_us)
{
@@ -655,6 +669,7 @@ refresh_gfx_surface_rfx_progressive (GrdRdpGraphicsPipeline *graphics_pipeline,
RDPGFX_START_FRAME_PDU cmd_start = {0};
RDPGFX_END_FRAME_PDU cmd_end = {0};
gboolean needs_progressive_header = FALSE;
+ cairo_region_t *region;
cairo_rectangle_int_t cairo_rect;
RFX_RECT *rfx_rects, *rfx_rect;
int n_rects;
@@ -665,6 +680,14 @@ refresh_gfx_surface_rfx_progressive (GrdRdpGraphicsPipeline *graphics_pipeline,
int64_t enc_ack_time_us;
int i;
+ region = grd_rdp_damage_detector_get_damage_region (rdp_surface->detector);
+ if (!region)
+ {
+ grd_session_rdp_notify_error (
+ session_rdp, GRD_SESSION_RDP_ERROR_GRAPHICS_SUBSYSTEM_FAILED);
+ return FALSE;
+ }
+
graphics_pipeline->rfx_context->mode = RLGR1;
if (!rdp_surface->valid)
{
@@ -722,6 +745,7 @@ refresh_gfx_surface_rfx_progressive (GrdRdpGraphicsPipeline *graphics_pipeline,
{
g_warning ("[RDP.RDPGFX] rfx_progressive_write_message() failed");
rfx_message_free (graphics_pipeline->rfx_context, rfx_message);
+ cairo_region_destroy (region);
return FALSE;
}
rfx_message_free (graphics_pipeline->rfx_context, rfx_message);
@@ -761,6 +785,8 @@ refresh_gfx_surface_rfx_progressive (GrdRdpGraphicsPipeline *graphics_pipeline,
*enc_time_us = enc_ack_time_us;
+ cairo_region_destroy (region);
+
return TRUE;
}
@@ -881,7 +907,6 @@ ensure_rtt_receivement (GrdRdpGraphicsPipeline *graphics_pipeline)
void
grd_rdp_graphics_pipeline_refresh_gfx (GrdRdpGraphicsPipeline *graphics_pipeline,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer)
{
RdpgfxServerContext *rdpgfx_context = graphics_pipeline->rdpgfx_context;
@@ -918,13 +943,12 @@ grd_rdp_graphics_pipeline_refresh_gfx (GrdRdpGraphicsPipeline *graphics_pipeline
{
g_assert (hwaccel_context->api == HW_ACCEL_API_NVENC);
success = refresh_gfx_surface_avc420 (graphics_pipeline, hwaccel_context,
- rdp_surface, region, buffer,
- &enc_time_us);
+ rdp_surface, buffer, &enc_time_us);
}
else
{
success = refresh_gfx_surface_rfx_progressive (graphics_pipeline, rdp_surface,
- region, buffer, &enc_time_us);
+ buffer, &enc_time_us);
}
if (success)
diff --git a/src/grd-rdp-graphics-pipeline.h b/src/grd-rdp-graphics-pipeline.h
index c67aa108..e3346cf3 100644
--- a/src/grd-rdp-graphics-pipeline.h
+++ b/src/grd-rdp-graphics-pipeline.h
@@ -20,7 +20,6 @@
#ifndef GRD_RDP_GRAPHICS_PIPELINE_H
#define GRD_RDP_GRAPHICS_PIPELINE_H
-#include <cairo/cairo.h>
#include <freerdp/server/rdpgfx.h>
#include <glib-object.h>
@@ -61,7 +60,6 @@ void grd_rdp_graphics_pipeline_notify_new_round_trip_time (GrdRdpGraphicsPipelin
void grd_rdp_graphics_pipeline_refresh_gfx (GrdRdpGraphicsPipeline *graphics_pipeline,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer);
#endif /* GRD_RDP_GRAPHICS_PIPELINE_H */
diff --git a/src/grd-session-rdp.c b/src/grd-session-rdp.c
index cde858f2..17a5cd53 100644
--- a/src/grd-session-rdp.c
+++ b/src/grd-session-rdp.c
@@ -166,7 +166,6 @@ close_session_idle (gpointer user_data);
static void
rdp_peer_refresh_region (GrdSessionRdp *session_rdp,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer);
static gboolean
@@ -249,7 +248,6 @@ take_or_encode_frame (GrdSessionRdp *session_rdp,
{
uint16_t width = buffer->width;
uint16_t height = buffer->height;
- cairo_region_t *region;
g_clear_pointer (&rdp_surface->pending_framebuffer, grd_rdp_buffer_release);
maybe_resize_graphics_output_buffer (session_rdp, width, height);
@@ -284,8 +282,6 @@ take_or_encode_frame (GrdSessionRdp *session_rdp,
!is_rdp_peer_flag_set (session_rdp, RDP_PEER_PENDING_GFX_INIT) &&
!rdp_surface->encoding_suspended)
{
- gboolean is_region_damaged;
-
if (!grd_rdp_damage_detector_submit_new_framebuffer (rdp_surface->detector,
buffer))
{
@@ -295,20 +291,8 @@ take_or_encode_frame (GrdSessionRdp *session_rdp,
return;
}
- is_region_damaged =
- grd_rdp_damage_detector_is_region_damaged (rdp_surface->detector);
-
- region = grd_rdp_damage_detector_get_damage_region (rdp_surface->detector);
- if (!region)
- {
- grd_session_rdp_notify_error (
- session_rdp, GRD_SESSION_RDP_ERROR_GRAPHICS_SUBSYSTEM_FAILED);
- return;
- }
- if (is_region_damaged)
- rdp_peer_refresh_region (session_rdp, rdp_surface, region, buffer);
-
- cairo_region_destroy (region);
+ if (grd_rdp_damage_detector_is_region_damaged (rdp_surface->detector))
+ rdp_peer_refresh_region (session_rdp, rdp_surface, buffer);
}
else
{
@@ -680,7 +664,6 @@ get_current_monitor_config (GrdSessionRdp *session_rdp,
static void
rdp_peer_refresh_gfx (GrdSessionRdp *session_rdp,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer)
{
freerdp_peer *peer = session_rdp->peer;
@@ -704,7 +687,7 @@ rdp_peer_refresh_gfx (GrdSessionRdp *session_rdp,
}
grd_rdp_graphics_pipeline_refresh_gfx (graphics_pipeline,
- rdp_surface, region, buffer);
+ rdp_surface, buffer);
}
static void
@@ -1229,15 +1212,26 @@ rdp_peer_refresh_raw (GrdSessionRdp *session_rdp,
static void
rdp_peer_refresh_region (GrdSessionRdp *session_rdp,
GrdRdpSurface *rdp_surface,
- cairo_region_t *region,
GrdRdpBuffer *buffer)
{
freerdp_peer *peer = session_rdp->peer;
RdpPeerContext *rdp_peer_context = (RdpPeerContext *) peer->context;
rdpSettings *rdp_settings = peer->settings;
+ cairo_region_t *region = NULL;
+
+ if (!rdp_settings->SupportGraphicsPipeline)
+ {
+ region = grd_rdp_damage_detector_get_damage_region (rdp_surface->detector);
+ if (!region)
+ {
+ grd_session_rdp_notify_error (
+ session_rdp, GRD_SESSION_RDP_ERROR_GRAPHICS_SUBSYSTEM_FAILED);
+ return;
+ }
+ }
if (rdp_settings->SupportGraphicsPipeline)
- rdp_peer_refresh_gfx (session_rdp, rdp_surface, region, buffer);
+ rdp_peer_refresh_gfx (session_rdp, rdp_surface, buffer);
else if (rdp_settings->RemoteFxCodec)
rdp_peer_refresh_rfx (session_rdp, rdp_surface, region, buffer);
else if (rdp_settings->NSCodec)
@@ -1245,6 +1239,8 @@ rdp_peer_refresh_region (GrdSessionRdp *session_rdp,
else
rdp_peer_refresh_raw (session_rdp, rdp_surface, region, buffer);
+ g_clear_pointer (®ion, cairo_region_destroy);
+
++rdp_peer_context->frame_id;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]