[Bf-blender-cvs] [3a2e459f588] soc-2019-openxr: Show useful error reports in case of errors.

Julian Eisel noreply at git.blender.org
Fri Jul 12 19:51:51 CEST 2019


Commit: 3a2e459f588851ca8c9553c803735d49bc3902de
Author: Julian Eisel
Date:   Fri Jul 12 19:44:46 2019 +0200
Branches: soc-2019-openxr
https://developer.blender.org/rB3a2e459f588851ca8c9553c803735d49bc3902de

Show useful error reports in case of errors.

E.g. with an active OpenXR runtime installed, but no HMD plugged in,
Blender will now show: "Failed to get device information. Is a device
plugged in?".
In case of such errors, the VR-session will be cleanly exited, with
no side effects to the rest of Blender (at least if there are no bugs).

The GHOST_Xr API now allows setting a custom error handling callback
which may cleanly destroy all GHOST_Xr data.

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

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_Xr.cpp
M	intern/ghost/intern/GHOST_XrContext.cpp
M	intern/ghost/intern/GHOST_XrContext.h
M	intern/ghost/intern/GHOST_XrSession.cpp
M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/intern/wm_xr.c
M	source/blender/windowmanager/wm.h

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

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index c86902de3b1..84bad87e654 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -981,6 +981,13 @@ extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
 #ifdef WITH_OPENXR
 
 /* xr-context */
+
+/**
+ * Set a custom callback to be executed whenever an error occurs. Should be set before calling
+ * #GHOST_XrContextCreate().
+ */
+void GHOST_XrErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
+
 GHOST_XrContextHandle GHOST_XrContextCreate(const GHOST_XrContextCreateInfo *create_info);
 void GHOST_XrContextDestroy(GHOST_XrContextHandle xr_context);
 
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 06bd5ca8180..78bb3deeb1a 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -616,6 +616,17 @@ typedef struct {
   } fov;
 } GHOST_XrDrawViewInfo;
 
+typedef struct {
+  const char *user_message;
+
+  /** File path and line number the error was found at. */
+  const char *source_location;
+
+  void *customdata;
+} GHOST_XrError;
+
+typedef void (*GHOST_XrErrorHandlerFn)(const GHOST_XrError *);
+
 typedef void *(*GHOST_XrGraphicsContextBindFn)(GHOST_TXrGraphicsBinding graphics_lib);
 typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_TXrGraphicsBinding graphics_lib,
                                                 void *graphics_context);
diff --git a/intern/ghost/intern/GHOST_Xr.cpp b/intern/ghost/intern/GHOST_Xr.cpp
index f23b156248f..0028a2c65ec 100644
--- a/intern/ghost/intern/GHOST_Xr.cpp
+++ b/intern/ghost/intern/GHOST_Xr.cpp
@@ -54,3 +54,8 @@ void GHOST_XrContextDestroy(GHOST_XrContextHandle xr_contexthandle)
 {
   delete (GHOST_XrContext *)xr_contexthandle;
 }
+
+void GHOST_XrErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata)
+{
+  GHOST_XrContext::setErrorHandler(handler_fn, customdata);
+}
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index c94b911fc8b..2e49c6ec85a 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -21,6 +21,7 @@
  */
 
 #include <cassert>
+#include <sstream>
 #include <string>
 
 #include "GHOST_Types.h"
@@ -47,6 +48,9 @@ PFN_xrCreateDebugUtilsMessengerEXT OpenXRInstanceData::s_xrCreateDebugUtilsMesse
 PFN_xrDestroyDebugUtilsMessengerEXT OpenXRInstanceData::s_xrDestroyDebugUtilsMessengerEXT_fn =
     nullptr;
 
+GHOST_XrErrorHandlerFn GHOST_XrContext::s_error_handler = nullptr;
+void *GHOST_XrContext::s_error_handler_customdata = nullptr;
+
 /* -------------------------------------------------------------------- */
 /** \name Create, Initialize and Destruct
  *
@@ -66,6 +70,7 @@ GHOST_XrContext::~GHOST_XrContext()
   }
   if (m_oxr->instance != XR_NULL_HANDLE) {
     xrDestroyInstance(m_oxr->instance);
+    m_oxr->instance = XR_NULL_HANDLE;
   }
 }
 
@@ -196,17 +201,44 @@ void GHOST_XrContext::initDebugMessenger()
   }
 }
 
+/** \} */ /* Debug Printing */
+
+/* -------------------------------------------------------------------- */
+/** \name Error handling
+ *
+ * \{ */
+
 void GHOST_XrContext::dispatchErrorMessage(const GHOST_XrException *exception) const
 {
-  // TODO dummy
-  printf("Error: %s %i (%s:%i)\n",
-         exception->m_msg,
-         exception->m_res,
-         exception->m_file,
-         exception->m_line);
+  std::ostringstream stream_err_location;
+  std::string str_err_location;
+  GHOST_XrError error;
+
+  stream_err_location << exception->m_file << ":" << exception->m_line;
+  str_err_location = stream_err_location.str();
+
+  error.user_message = exception->m_msg;
+  error.source_location = str_err_location.c_str();
+  error.customdata = s_error_handler_customdata;
+
+  XR_DEBUG_ONLY_CALL(this,
+                     fprintf(stderr,
+                             "Error: \t%s\n\tOpenXR error value: %i\n\tSource: (%s)\n",
+                             error.user_message,
+                             exception->m_res,
+                             error.source_location));
+
+  /* Potentially destroys GHOST_XrContext */
+  s_error_handler(&error);
 }
 
-/** \} */ /* Debug Printing */
+void GHOST_XrContext::setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata)
+{
+  s_error_handler = handler_fn;
+  s_error_handler_customdata = customdata;
+}
+
+/** \} */ /* Error handling */
 
 /* -------------------------------------------------------------------- */
 /** \name OpenXR API-Layers and Extensions
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
index b4df6689463..3e878bfa1d6 100644
--- a/intern/ghost/intern/GHOST_XrContext.h
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -46,13 +46,14 @@ class GHOST_XrContext : public GHOST_IXrContext {
  public:
   GHOST_XrContext(const GHOST_XrContextCreateInfo *create_info);
   ~GHOST_XrContext();
-
   void initialize(const GHOST_XrContextCreateInfo *create_info);
+
   void startSession(const GHOST_XrSessionBeginInfo *begin_info) override;
   void endSession() override;
   bool isSessionRunning() const override;
   void drawSessionViews(void *draw_customdata) override;
 
+  static void setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
   void dispatchErrorMessage(const class GHOST_XrException *exception) const override;
 
   void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
@@ -80,6 +81,8 @@ class GHOST_XrContext : public GHOST_IXrContext {
   /** Names of enabled API-layers */
   std::vector<const char *> m_enabled_layers;
 
+  static GHOST_XrErrorHandlerFn s_error_handler;
+  static void *s_error_handler_customdata;
   GHOST_XrCustomFuncs m_custom_funcs;
 
   /** Enable debug message prints and OpenXR API validation layers */
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index 634a92987e0..8ff812be1ce 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -62,8 +62,6 @@ GHOST_XrSession::GHOST_XrSession(GHOST_XrContext *xr_context)
 
 GHOST_XrSession::~GHOST_XrSession()
 {
-  assert(m_oxr->session != XR_NULL_HANDLE);
-
   // TODO OpenXR calls here can fail, but we should not throw an exception in the destructor.
 
   for (XrSwapchain &swapchain : m_oxr->swapchains) {
@@ -73,7 +71,9 @@ GHOST_XrSession::~GHOST_XrSession()
   if (m_oxr->reference_space != XR_NULL_HANDLE) {
     xrDestroySpace(m_oxr->reference_space);
   }
-  xrDestroySession(m_oxr->session);
+  if (m_oxr->session != XR_NULL_HANDLE) {
+    xrDestroySession(m_oxr->session);
+  }
 
   m_oxr->session = XR_NULL_HANDLE;
   m_oxr->session_state = XR_SESSION_STATE_UNKNOWN;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 89567765760..4ff58f2a867 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3516,7 +3516,7 @@ static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
   wmWindowManager *wm = CTX_wm_manager(C);
 
   /* Lazy-create xr context - tries to dynlink to the runtime, reading active_runtime.json. */
-  if (wm_xr_context_ensure(wm) == false) {
+  if (wm_xr_context_ensure(C, wm) == false) {
     return OPERATOR_CANCELLED;
   }
 
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
index 1a783df9376..237040a3db3 100644
--- a/source/blender/windowmanager/intern/wm_xr.c
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -21,6 +21,7 @@
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_report.h"
 #include "BKE_screen.h"
 
 #include "BLI_math_geom.h"
@@ -43,6 +44,8 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "UI_interface.h"
+
 #include "WM_types.h"
 #include "WM_api.h"
 
@@ -60,27 +63,57 @@ typedef struct {
   GHOST_TXrGraphicsBinding gpu_binding_type;
 } XrSurfaceData;
 
-bool wm_xr_context_ensure(wmWindowManager *wm)
+typedef struct {
+  wmWindowManager *wm;
+  bContext *evil_C;
+} wmXrErrorHandlerData;
+
+static void wm_xr_error_handler(const GHOST_XrError *error)
+{
+  wmXrErrorHandlerData *handler_data = error->customdata;
+  wmWindowManager *wm = handler_data->wm;
+
+  BKE_reports_clear(&wm->reports);
+  WM_report(RPT_ERROR, error->user_message);
+  WM_report_banner_show();
+  UI_popup_menu_reports(handler_data->evil_C, &wm->reports);
+
+  if (wm->xr_context) {
+    /* Just play safe and destroy the entire context. */
+    GHOST_XrContextDestroy(wm->xr_context);
+    wm->xr_context = NULL;
+  }
+}
+
+bool wm_xr_context_ensure(bContext *C, wmWindowManager *wm)
 {
   if (wm->xr_context) {
     return true;
   }
+  static wmXrErrorHandlerData error_customdata;
+
+  /* Set up error handling */
+  error_customdata.wm = wm;
+  error_customdata.evil_C = C;
+  GHOST_XrErrorHandler(wm_xr_error_handler, &error_customdata);
 
-  const GHOST_TXrGraphicsBinding gpu_bindings_candidates[] = {
-      GHOST_kXrGraphicsOpenGL,
+  {
+    const GHOST_TXrGraphicsBinding gpu_bindings_candidates[] = {
+        GHOST_kXrGraphicsOpenGL,
 #ifdef WIN32
-      GHOST_kXrGraphicsD3D11,
+        GHOST_kXrGraphicsD3D11,
 #endif
-  };
-  GHOST_XrContextCreateInfo create_info = {
-      .gpu_binding_candidates = gpu_bindings_candidates,
-      .gpu_binding_candidates_count = ARRAY_SIZE(gpu_bindings_candidates)};
+    };
+    GHOST_XrContextCreateInfo create_info = {
+        .gpu_binding_candidates = gpu_bindings_candidates,
+        .gpu_binding_candidates_count = ARRAY_SIZE(gpu_bindings_candidates)};
 
-  if (G.debug & G_DEBUG_XR) {
-    create_info.context_flag |= GHOST_kXrContextDebug;
-  }
+    if (G.debug & G_DEBUG_XR) {
+      create_info.context_flag |= GHOST_kXrContextDebug;
+    }
 
-  wm->xr_context = GHOST_XrContextCreate(&create_info);
+    wm->xr_context = GHOST_XrContextCreate(&create_info);
+  }
 
   return wm->xr_context != NULL;
 }
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index e1d2d186af3..f28552916f2 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -102,7 +102,7 @@ void wm_draw_upside_down(int sizex, int sizey);
 


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list