[Bf-blender-cvs] [796994d2221] soc-2019-openxr: Refactor graphics context binding to avoid memory leaks

Julian Eisel noreply at git.blender.org
Wed Jun 12 21:27:27 CEST 2019


Commit: 796994d222123f83fc3d0f6fc47f5ae12cdbdab6
Author: Julian Eisel
Date:   Wed Jun 12 21:17:18 2019 +0200
Branches: soc-2019-openxr
https://developer.blender.org/rB796994d222123f83fc3d0f6fc47f5ae12cdbdab6

Refactor graphics context binding to avoid memory leaks

* Retrieve graphics context to bind through callbacks so the XR code can
  manage their lifetime.
* Use static union to store system & chosen graphics lib specific
  graphics binding data.

Makes some things a bit cleaner, too.

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

M	source/blender/makesdna/DNA_windowmanager_types.h
M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/xr/intern/wm_xr.c
M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c
M	source/blender/windowmanager/xr/wm_xr.h

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

diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 65226d8b931..e94670249b9 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -181,7 +181,6 @@ typedef struct wmWindowManager {
 
   //#ifdef WITH_OPENXR
   struct wmXRContext *xr_context;
-  void *xr_gpu_context;
   //#endif
 } wmWindowManager;
 
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index bbea21b7c7b..68d5d2cd4df 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3525,8 +3525,7 @@ static void WM_OT_stereo3d_set(wmOperatorType *ot)
 }
 
 #ifdef WITH_OPENXR
-static GHOST_ContextHandle xr_session_gpu_binding_context_create(
-    eWM_xrGraphicsBinding graphics_lib)
+static void *xr_session_gpu_binding_context_create(eWM_xrGraphicsBinding graphics_lib)
 {
 #  ifndef WIN32
   BLI_assert(graphics_lib == WM_XR_GRAPHICS_OPENGL);
@@ -3541,8 +3540,10 @@ static GHOST_ContextHandle xr_session_gpu_binding_context_create(
 }
 
 static void xr_session_gpu_binding_context_destroy(eWM_xrGraphicsBinding graphics_lib,
-                                                   GHOST_ContextHandle ghost_context)
+                                                   void *context)
 {
+  GHOST_ContextHandle ghost_context = context;
+
   switch (graphics_lib) {
     case WM_XR_GRAPHICS_OPENGL:
       WM_opengl_context_dispose(ghost_context);
@@ -3555,20 +3556,14 @@ static int xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 {
   wmWindowManager *wm = CTX_wm_manager(C);
   struct wmXRContext *xr_context = wm->xr_context;
-  const eWM_xrGraphicsBinding gpu_binding = wm_xr_session_active_graphics_binding_type_get(
-      xr_context);
 
   if (wm_xr_session_is_running(xr_context)) {
-    BLI_assert(wm->xr_gpu_context != NULL);
-
     wm_xr_session_end(xr_context);
-    xr_session_gpu_binding_context_destroy(gpu_binding, wm->xr_gpu_context);
   }
   else {
-    BLI_assert(wm->xr_gpu_context == NULL);
-
-    wm->xr_gpu_context = xr_session_gpu_binding_context_create(gpu_binding);
-    wm_xr_session_start(xr_context, wm->xr_gpu_context);
+    wm_xr_graphics_context_bind_funcs(
+        xr_context, xr_session_gpu_binding_context_create, xr_session_gpu_binding_context_destroy);
+    wm_xr_session_start(xr_context);
   }
   return OPERATOR_FINISHED;
 }
diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c
index d3b9969d056..8b9b9acd064 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr.c
@@ -269,6 +269,9 @@ void wm_xr_context_destroy(wmXRContext *xr_context)
 {
   OpenXRData *oxr = &xr_context->oxr;
 
+  /* Unbinding may involve destruction, so call here too */
+  wm_xr_graphics_context_unbind(xr_context);
+
   if (oxr->session != XR_NULL_HANDLE) {
     xrDestroySession(oxr->session);
   }
@@ -283,3 +286,34 @@ void wm_xr_context_destroy(wmXRContext *xr_context)
 
   MEM_SAFE_FREE(xr_context);
 }
+
+/**
+ * Set context for binding and unbinding a graphics context for a session. The binding callback may
+ * create a new context thereby. In fact that's the sole reason for this callback approach to
+ * binding. Just make sure to have an unbind function set that properly destructs.
+ *
+ * \param bind_fn Function to retrieve (possibly create) a graphics context.
+ * \param unbind_fn Function to release (possibly free) a graphics context.
+ */
+void wm_xr_graphics_context_bind_funcs(wmXRContext *xr_context,
+                                       wmXRGraphicsContextBindFn bind_fn,
+                                       wmXRGraphicsContextUnbindFn unbind_fn)
+{
+  wm_xr_graphics_context_unbind(xr_context);
+  xr_context->gpu_ctx_bind_fn = bind_fn;
+  xr_context->gpu_ctx_unbind_fn = unbind_fn;
+}
+
+void wm_xr_graphics_context_bind(wmXRContext *xr_context)
+{
+  BLI_assert(xr_context->gpu_ctx_bind_fn);
+  xr_context->gpu_ctx = xr_context->gpu_ctx_bind_fn(xr_context->gpu_binding);
+}
+
+void wm_xr_graphics_context_unbind(wmXRContext *xr_context)
+{
+  if (xr_context->gpu_ctx_unbind_fn) {
+    xr_context->gpu_ctx_unbind_fn(xr_context->gpu_binding, xr_context->gpu_ctx);
+  }
+  xr_context->gpu_ctx = NULL;
+}
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index 0701840d090..daa1e896618 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -40,11 +40,20 @@ typedef struct wmXRContext {
 
   /** Active graphics binding type. */
   eWM_xrGraphicsBinding gpu_binding;
+  /** Function to retrieve (possibly create) a graphics context */
+  wmXRGraphicsContextBindFn gpu_ctx_bind_fn;
+  /** Function to release (possibly free) a graphics context */
+  wmXRGraphicsContextUnbindFn gpu_ctx_unbind_fn;
+  /** Active Ghost graphic context. */
+  void *gpu_ctx;
 
   /** Names of enabled extensions */
   const char **enabled_extensions;
 } wmXRContext;
 
+void wm_xr_graphics_context_bind(wmXRContext *xr_context) ATTR_NONNULL();
+void wm_xr_graphics_context_unbind(wmXRContext *xr_context) ATTR_NONNULL();
+
 void wm_xr_session_state_change(OpenXRData *oxr, const XrEventDataSessionStateChanged *lifecycle)
     ATTR_NONNULL();
 
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 4e4b47fd499..5aa9aea25ad 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -65,38 +65,33 @@ static void wm_xr_system_init(OpenXRData *oxr)
   xrGetSystem(oxr->instance, &system_info, &oxr->system_id);
 }
 
-eWM_xrGraphicsBinding wm_xr_session_active_graphics_binding_type_get(const wmXRContext *xr_context)
-{
-  return xr_context->gpu_binding;
-}
-
 static void *openxr_graphics_binding_create(const wmXRContext *xr_context,
                                             GHOST_ContextHandle UNUSED(ghost_context))
 {
-  void *binding_ptr = NULL;
+  static union {
+#if defined(WITH_X11)
+    XrGraphicsBindingOpenGLXlibKHR glx;
+#elif defined(WIN32)
+    XrGraphicsBindingOpenGLWin32KHR wgl;
+    XrGraphicsBindingD3D11KHR d3d11;
+#endif
+  } binding;
+
+  memset(&binding, 0, sizeof(binding));
 
   switch (xr_context->gpu_binding) {
     case WM_XR_GRAPHICS_OPENGL: {
 #if defined(WITH_X11)
-      XrGraphicsBindingOpenGLXlibKHR binding = {.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR};
-
+      binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
 #elif defined(WIN32)
-      XrGraphicsBindingOpenGLWin32KHR binding = {
-          .type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR};
-
+      binding.wgl = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
 #endif
 
-      binding_ptr = MEM_mallocN(sizeof(binding), __func__);
-      memcpy(binding_ptr, &binding, sizeof(binding));
-
       break;
     }
 #ifdef WIN32
     case WM_XR_GRAPHICS_D3D11: {
-      XrGraphicsBindingD3D11KHR binding = {.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR};
-
-      binding_ptr = MEM_mallocN(sizeof(binding), __func__);
-      memcpy(binding_ptr, &binding, sizeof(binding));
+      binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
 
       break;
     }
@@ -105,21 +100,37 @@ static void *openxr_graphics_binding_create(const wmXRContext *xr_context,
       BLI_assert(false);
   }
 
-  return binding_ptr;
+  return &binding;
 }
 
-void wm_xr_session_start(wmXRContext *xr_context, void *ghost_context)
+void wm_xr_session_start(wmXRContext *xr_context)
 {
   OpenXRData *oxr = &xr_context->oxr;
 
   BLI_assert(oxr->instance != XR_NULL_HANDLE);
   BLI_assert(oxr->session == XR_NULL_HANDLE);
+  if (xr_context->gpu_ctx_bind_fn == NULL) {
+    fprintf(stderr,
+            "Invalid API usage: No way to bind graphics context to the XR session. Call "
+            "wm_xr_graphics_context_bind_funcs() with valid parameters before starting the "
+            "session (through wm_xr_session_start()).");
+    return;
+  }
 
   wm_xr_system_init(oxr);
 
+  wm_xr_graphics_context_bind(xr_context);
+  if (xr_context->gpu_ctx == NULL) {
+    fprintf(stderr,
+            "Invalid API usage: No graphics context returned through the callback set with "
+            "wm_xr_graphics_context_bind_funcs(). This is required for session starting (through "
+            "wm_xr_session_start()).\n");
+    return;
+  }
+
   XrSessionCreateInfo create_info = {.type = XR_TYPE_SESSION_CREATE_INFO};
   create_info.systemId = oxr->system_id;
-  create_info.next = openxr_graphics_binding_create(xr_context, ghost_context);
+  create_info.next = openxr_graphics_binding_create(xr_context, xr_context->gpu_ctx);
 
   xrCreateSession(oxr->instance, &create_info, &oxr->session);
 }
@@ -127,6 +138,7 @@ void wm_xr_session_start(wmXRContext *xr_context, void *ghost_context)
 void wm_xr_session_end(wmXRContext *xr_context)
 {
   xrEndSession(xr_context->oxr.session);
+  wm_xr_graphics_context_unbind(xr_context);
 }
 
 void wm_xr_session_state_change(OpenXRData *oxr, const XrEventDataSessionStateChanged *lifecycle)
diff --git a/source/blender/windowmanager/xr/wm_xr.h b/source/blender/windowmanager/xr/wm_xr.h
index b2e2a6a0449..ae3eca83595 100644
--- a/source/blender/windowmanager/xr/wm_xr.h
+++ b/source/blender/windowmanager/xr/wm_xr.h
@@ -56,11 +56,17 @@ struct wmXRContext *wm_xr_context_create(const wmXRContextCreateInfo *create_inf
     ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 void wm_xr_context_destroy(struct wmXRContext *xr_context);
 
+typedef void *(*wmXRGraphicsContextBindFn)(eWM_xrGraphicsBinding graphics_lib);
+typedef void (*wmXRGraphicsContextUnbindFn)(eWM_xrGraphicsBinding graphics_lib,
+                                            void *graphics_context);
+
+void wm_xr_graphics_context_bind_funcs(struct wmXRContext *xr_context,
+                                       wmXRGraphicsContextBindFn bind_fn,
+                                       wmXRGraphicsContextUnbindFn unbind_fn) ATTR_NONNULL(1, 2);
+
 /* sessions */
 bool wm_xr_session_is_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list