Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-06-30 15:53:09 +0300
committerCampbell Barton <campbell@blender.org>2022-06-30 16:46:57 +0300
commitdf40e9d0aad0c2a5b649d99c25e991a3664501c5 (patch)
tree45700639814125074435828df1785c21600cd68e /intern/ghost
parente190b70946b776cb105f8987c4cf1ec5157e75d0 (diff)
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.
Diffstat (limited to 'intern/ghost')
-rw-r--r--intern/ghost/intern/GHOST_Context.h19
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp62
2 files changed, 54 insertions, 27 deletions
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
@@ -93,6 +93,22 @@ class GHOST_Context : public GHOST_IContext {
}
/**
+ * 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
* the graphics h/w
@@ -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;
}