[Bf-blender-cvs] [df40e9d0aad] master: Fix memory leak with off-screen buffers under Wayland

Campbell Barton noreply at git.blender.org
Thu Jun 30 15:49:16 CEST 2022


Commit: df40e9d0aad0c2a5b649d99c25e991a3664501c5
Author: Campbell Barton
Date:   Thu Jun 30 22:53:09 2022 +1000
Branches: master
https://developer.blender.org/rBdf40e9d0aad0c2a5b649d99c25e991a3664501c5

Fix memory leak with off-screen buffers under Wayland

Each off-screen buffer created a surface and EGL window which was
only freed when Blender exited.

Resolve by freeing the associated data when disposing the off-screen
context.

===================================================================

M	intern/ghost/intern/GHOST_Context.h
M	intern/ghost/intern/GHOST_SystemWayland.cpp

===================================================================

diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index d9c2cdce258..e707f1c3475 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -92,6 +92,22 @@ class GHOST_Context : public GHOST_IContext {
     return GHOST_kFailure;
   }
 
+  /**
+   * Get user data.
+   */
+  void *getUserData()
+  {
+    return m_user_data;
+  }
+
+  /**
+   * Set user data (intended for the caller to use as needed).
+   */
+  void setUserData(void *user_data)
+  {
+    m_user_data = user_data;
+  }
+
   /**
    * Stereo visual created. Only necessary for 'real' stereo support,
    * ie quad buffered stereo. This is not always possible, depends on
@@ -124,6 +140,9 @@ class GHOST_Context : public GHOST_IContext {
 
   bool m_stereoVisual;
 
+  /** Caller specified, not for internal use. */
+  void *m_user_data = nullptr;
+
   static void initClearGL();
 
 #ifdef WITH_CXX_GUARDEDALLOC
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 36c9421f596..af629e83b19 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -334,9 +334,6 @@ struct display_t {
   struct zwp_tablet_manager_v2 *tablet_manager = nullptr;
   struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
   struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
-
-  std::vector<struct wl_surface *> os_surfaces;
-  std::vector<struct wl_egl_window *> os_egl_windows;
 };
 
 /** \} */
@@ -472,14 +469,6 @@ static void display_destroy(display_t *d)
     zwp_pointer_constraints_v1_destroy(d->pointer_constraints);
   }
 
-  for (wl_egl_window *os_egl_window : d->os_egl_windows) {
-    wl_egl_window_destroy(os_egl_window);
-  }
-
-  for (wl_surface *os_surface : d->os_surfaces) {
-    wl_surface_destroy(os_surface);
-  }
-
   if (d->compositor) {
     wl_compositor_destroy(d->compositor);
   }
@@ -2745,22 +2734,17 @@ void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &hei
   height = xy_max[1] - xy_min[1];
 }
 
-GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
+static GHOST_Context *createOffscreenContext_impl(GHOST_SystemWayland *system,
+                                                  struct wl_display *wl_display,
+                                                  wl_egl_window *egl_window)
 {
-  /* Create new off-screen window. */
-  wl_surface *os_surface = wl_compositor_create_surface(compositor());
-  wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1));
-
-  d->os_surfaces.push_back(os_surface);
-  d->os_egl_windows.push_back(os_egl_window);
-
   GHOST_Context *context;
 
   for (int minor = 6; minor >= 0; --minor) {
-    context = new GHOST_ContextEGL(this,
+    context = new GHOST_ContextEGL(system,
                                    false,
-                                   EGLNativeWindowType(os_egl_window),
-                                   EGLNativeDisplayType(d->display),
+                                   EGLNativeWindowType(egl_window),
+                                   EGLNativeDisplayType(wl_display),
                                    EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
                                    4,
                                    minor,
@@ -2774,10 +2758,10 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*g
     delete context;
   }
 
-  context = new GHOST_ContextEGL(this,
+  context = new GHOST_ContextEGL(system,
                                  false,
-                                 EGLNativeWindowType(os_egl_window),
-                                 EGLNativeDisplayType(d->display),
+                                 EGLNativeWindowType(egl_window),
+                                 EGLNativeDisplayType(wl_display),
                                  EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
                                  3,
                                  3,
@@ -2789,15 +2773,39 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*g
     return context;
   }
   delete context;
+  return nullptr;
+}
 
-  GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
+GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
+{
+  /* Create new off-screen window. */
+  wl_surface *wl_surface = wl_compositor_create_surface(compositor());
+  wl_egl_window *egl_window = wl_egl_window_create(wl_surface, int(1), int(1));
 
-  return nullptr;
+  GHOST_Context *context = createOffscreenContext_impl(this, d->display, egl_window);
+
+  if (!context) {
+    GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
+    wl_surface_destroy(wl_surface);
+    wl_egl_window_destroy(egl_window);
+    return nullptr;
+  }
+
+  wl_surface_set_user_data(wl_surface, egl_window);
+  context->setUserData(wl_surface);
+
+  return context;
 }
 
 GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context)
 {
+  struct wl_surface *wl_surface = (struct wl_surface *)((GHOST_Context *)context)->getUserData();
+  wl_egl_window *egl_window = (wl_egl_window *)wl_surface_get_user_data(wl_surface);
+  wl_egl_window_destroy(egl_window);
+  wl_surface_destroy(wl_surface);
+
   delete context;
+
   return GHOST_kSuccess;
 }



More information about the Bf-blender-cvs mailing list