[gnome-remote-desktop] rdp/rdpgfx: Only clear main surfaces directly



commit 99b9b02b1459831c75eb8bac21b5ee4d4c78c41e
Author: Pascal Nowack <Pascal Nowack gmx de>
Date:   Thu Aug 18 09:39:46 2022 +0200

    rdp/rdpgfx: Only clear main surfaces directly
    
    When overriding the render surface of a GFX surface, the render surface
    is managed by its GFX surface.
    This includes the destruction of the GFX surface, which is performed,
    when its parental surface is destroyed.
    
    When destroying all surfaces, e.g. because the monitor configuration
    changed or due to a protocol reset of the graphics pipeline, then
    currently all auxiliary surfaces (this includes the separate render
    surfaces) are manually destroyed too.
    Since they are already managed by their parental surface, a
    segmentation fault can occur, when destroying an auxiliary surface.
    In practice, this segfault, for some reason, did not happen yet, but
    the error is there.
    So, on some systems or situations, the segfault is expected to happen.
    
    Fix this issue by marking all separate render surfaces as auxiliary
    surfaces.
    When clearing all surfaces, only clear the surfaces directly, that are
    not marked as auxiliary surface, i.e. surfaces that are main surfaces.
    Any auxiliary surface is destroyed, when its parental surface is
    destroyed.

 src/grd-rdp-gfx-surface.c       |  9 +++++++++
 src/grd-rdp-gfx-surface.h       |  2 ++
 src/grd-rdp-graphics-pipeline.c | 33 +++++++++++++++++++++++++++++----
 3 files changed, 40 insertions(+), 4 deletions(-)
---
diff --git a/src/grd-rdp-gfx-surface.c b/src/grd-rdp-gfx-surface.c
index 6a2cc56c..1275fe5b 100644
--- a/src/grd-rdp-gfx-surface.c
+++ b/src/grd-rdp-gfx-surface.c
@@ -40,6 +40,8 @@ struct _GrdRdpGfxSurface
   uint16_t width;
   uint16_t height;
 
+  gboolean is_auxiliary_surface;
+
   GrdRdpGfxSurface *render_surface;
 
   GrdRdpGfxFrameController *frame_controller;
@@ -83,6 +85,12 @@ grd_rdp_gfx_surface_get_height (GrdRdpGfxSurface *gfx_surface)
   return gfx_surface->height;
 }
 
+gboolean
+grd_rdp_gfx_surface_is_auxiliary_surface (GrdRdpGfxSurface *gfx_surface)
+{
+  return gfx_surface->is_auxiliary_surface;
+}
+
 gboolean
 grd_rdp_gfx_surface_disallows_hwaccel_sessions (GrdRdpGfxSurface *gfx_surface)
 {
@@ -105,6 +113,7 @@ grd_rdp_gfx_surface_override_render_surface (GrdRdpGfxSurface *gfx_surface,
   g_assert (!gfx_surface->render_surface);
 
   gfx_surface->render_surface = render_surface;
+  render_surface->is_auxiliary_surface = TRUE;
 }
 
 GrdRdpGfxFrameController *
diff --git a/src/grd-rdp-gfx-surface.h b/src/grd-rdp-gfx-surface.h
index 26dcdc4e..fb30ec0a 100644
--- a/src/grd-rdp-gfx-surface.h
+++ b/src/grd-rdp-gfx-surface.h
@@ -65,6 +65,8 @@ uint16_t grd_rdp_gfx_surface_get_width (GrdRdpGfxSurface *gfx_surface);
 
 uint16_t grd_rdp_gfx_surface_get_height (GrdRdpGfxSurface *gfx_surface);
 
+gboolean grd_rdp_gfx_surface_is_auxiliary_surface (GrdRdpGfxSurface *gfx_surface);
+
 gboolean grd_rdp_gfx_surface_disallows_hwaccel_sessions (GrdRdpGfxSurface *gfx_surface);
 
 GrdRdpGfxSurface *grd_rdp_gfx_surface_get_render_surface (GrdRdpGfxSurface *gfx_surface);
diff --git a/src/grd-rdp-graphics-pipeline.c b/src/grd-rdp-graphics-pipeline.c
index 283084b1..7d94347f 100644
--- a/src/grd-rdp-graphics-pipeline.c
+++ b/src/grd-rdp-graphics-pipeline.c
@@ -322,6 +322,23 @@ grd_rdp_graphics_pipeline_delete_surface (GrdRdpGraphicsPipeline *graphics_pipel
   rdpgfx_context->DeleteSurface (rdpgfx_context, &delete_surface);
 }
 
+static GList *
+get_main_surfaces_from_surface_list (GList *surfaces)
+{
+  GList *main_surfaces = NULL;
+  GList *l;
+
+  for (l = surfaces; l; l = l->next)
+    {
+      GrdRdpGfxSurface *gfx_surface = l->data;
+
+      if (!grd_rdp_gfx_surface_is_auxiliary_surface (gfx_surface))
+        main_surfaces = g_list_append (main_surfaces, gfx_surface);
+    }
+
+  return main_surfaces;
+}
+
 void
 grd_rdp_graphics_pipeline_reset_graphics (GrdRdpGraphicsPipeline *graphics_pipeline,
                                           uint32_t                width,
@@ -331,6 +348,7 @@ grd_rdp_graphics_pipeline_reset_graphics (GrdRdpGraphicsPipeline *graphics_pipel
 {
   RdpgfxServerContext *rdpgfx_context = graphics_pipeline->rdpgfx_context;
   RDPGFX_RESET_GRAPHICS_PDU reset_graphics = {0};
+  GList *main_surfaces;
   GList *surfaces;
   GList *l;
 
@@ -342,7 +360,10 @@ grd_rdp_graphics_pipeline_reset_graphics (GrdRdpGraphicsPipeline *graphics_pipel
   g_hash_table_steal_all (graphics_pipeline->surface_table);
   g_mutex_unlock (&graphics_pipeline->gfx_mutex);
 
-  for (l = surfaces; l; l = l->next)
+  main_surfaces = get_main_surfaces_from_surface_list (surfaces);
+  g_list_free (surfaces);
+
+  for (l = main_surfaces; l; l = l->next)
     {
       GrdRdpGfxSurface *gfx_surface = l->data;
       GrdRdpSurface *rdp_surface;
@@ -350,7 +371,7 @@ grd_rdp_graphics_pipeline_reset_graphics (GrdRdpGraphicsPipeline *graphics_pipel
       rdp_surface = grd_rdp_gfx_surface_get_rdp_surface (gfx_surface);
       g_clear_object (&rdp_surface->gfx_surface);
     }
-  g_list_free (surfaces);
+  g_list_free (main_surfaces);
 
   /*
    * width and height refer here to the size of the Graphics Output Buffer
@@ -1555,6 +1576,7 @@ grd_rdp_graphics_pipeline_new (GrdSessionRdp              *session_rdp,
 static void
 reset_graphics_pipeline (GrdRdpGraphicsPipeline *graphics_pipeline)
 {
+  GList *main_surfaces;
   GList *surfaces;
   GList *l;
 
@@ -1567,7 +1589,10 @@ reset_graphics_pipeline (GrdRdpGraphicsPipeline *graphics_pipeline)
                                frame_serial_free, graphics_pipeline);
   g_mutex_unlock (&graphics_pipeline->gfx_mutex);
 
-  for (l = surfaces; l; l = l->next)
+  main_surfaces = get_main_surfaces_from_surface_list (surfaces);
+  g_list_free (surfaces);
+
+  for (l = main_surfaces; l; l = l->next)
     {
       GrdRdpGfxSurface *gfx_surface = l->data;
       GrdRdpSurface *rdp_surface;
@@ -1575,7 +1600,7 @@ reset_graphics_pipeline (GrdRdpGraphicsPipeline *graphics_pipeline)
       rdp_surface = grd_rdp_gfx_surface_get_rdp_surface (gfx_surface);
       g_clear_object (&rdp_surface->gfx_surface);
     }
-  g_list_free (surfaces);
+  g_list_free (main_surfaces);
 
   g_mutex_lock (&graphics_pipeline->gfx_mutex);
   graphics_pipeline->frame_acks_suspended = FALSE;


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