[Bf-blender-cvs] [c333f576033] soc-2019-openxr: Ghost: Ghost-XR API to abstract away and access OpenXR functionality

Julian Eisel noreply at git.blender.org
Tue Mar 17 20:20:26 CET 2020


Commit: c333f5760335cd11aa1c3319df39fa3d4b010aa5
Author: Julian Eisel
Date:   Tue Mar 17 20:10:57 2020 +0100
Branches: soc-2019-openxr
https://developer.blender.org/rBc333f5760335cd11aa1c3319df39fa3d4b010aa5

Ghost: Ghost-XR API to abstract away and access OpenXR functionality

Extends Ghost to include an abstraction for OpenXR, which I refer to as
Ghost-XR. Such an API is the base for the following commit, which introduces VR
support to Blender.

Main features:
* Simple and high-level interface for Blender specific code to call.
* Extensible for muliple graphics backends, currently OpenGL and a DirectX
  compatibility layer are supported.
* Carefully designed error handling strategy allowing Blender to handle errors
  gracefully and with useful error messages.
* OpenXR extension and API-layer management.
* OpenXR session management.
* Basic OpenXR event management.
* Debug utilities for Ghost-XR and OpenXR

For more information on this API, check
https://wiki.blender.org/wiki/Source/Interface/XR.

Reviewed by: Brecht Van Lommel

Differential Revision: https://developer.blender.org/D6188

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

M	intern/ghost/CMakeLists.txt
M	intern/ghost/GHOST_C-api.h
A	intern/ghost/GHOST_IXrContext.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_ContextD3D.h
M	intern/ghost/intern/GHOST_ContextGLX.cpp
M	intern/ghost/intern/GHOST_ContextGLX.h
M	intern/ghost/intern/GHOST_ContextWGL.h
A	intern/ghost/intern/GHOST_IXrGraphicsBinding.h
A	intern/ghost/intern/GHOST_Xr.cpp
A	intern/ghost/intern/GHOST_XrContext.cpp
A	intern/ghost/intern/GHOST_XrContext.h
A	intern/ghost/intern/GHOST_XrEvent.cpp
A	intern/ghost/intern/GHOST_XrException.h
A	intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
A	intern/ghost/intern/GHOST_XrSession.cpp
A	intern/ghost/intern/GHOST_XrSession.h
A	intern/ghost/intern/GHOST_XrSwapchain.cpp
A	intern/ghost/intern/GHOST_XrSwapchain.h
A	intern/ghost/intern/GHOST_Xr_intern.h
A	intern/ghost/intern/GHOST_Xr_openxr_includes.h

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

diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index c4f1efe1580..07d98475c00 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -357,6 +357,50 @@ elseif(WIN32)
 
 endif()
 
+if(WITH_XR_OPENXR)
+  list(APPEND SRC
+    intern/GHOST_Xr.cpp
+    intern/GHOST_XrContext.cpp
+    intern/GHOST_XrEvent.cpp
+    intern/GHOST_XrGraphicsBinding.cpp
+    intern/GHOST_XrSession.cpp
+    intern/GHOST_XrSwapchain.cpp
+
+    GHOST_IXrContext.h
+    intern/GHOST_IXrGraphicsBinding.h
+    intern/GHOST_Xr_intern.h
+    intern/GHOST_Xr_openxr_includes.h
+    intern/GHOST_XrContext.h
+    intern/GHOST_XrSession.h
+    intern/GHOST_XrSwapchain.h
+  )
+  list(APPEND INC_SYS
+    ${XR_OPENXR_SDK_INCLUDE_DIR}
+  )
+
+  set(XR_PLATFORM_DEFINES -DXR_USE_GRAPHICS_API_OPENGL)
+
+  # Add compiler defines as required by the OpenXR specification.
+  if(WIN32)
+    list(APPEND XR_PLATFORM_DEFINES
+      -DXR_USE_PLATFORM_WIN32
+      -DXR_USE_GRAPHICS_API_D3D11
+    )
+    list(APPEND LIB
+      shlwapi
+    )
+  elseif(UNIX AND NOT APPLE)
+    list(APPEND XR_PLATFORM_DEFINES
+      -DXR_OS_LINUX
+      -DXR_USE_PLATFORM_XLIB
+    )
+  endif()
+
+  add_definitions(-DWITH_XR_OPENXR ${XR_PLATFORM_DEFINES})
+
+  unset(XR_PLATFORM_DEFINES)
+endif()
+
 add_definitions(${GL_DEFINITIONS})
 
 blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index a3cc9aa1df5..aafe374a93b 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -30,21 +30,6 @@
 extern "C" {
 #endif
 
-/**
- * Creates a "handle" for a C++ GHOST object.
- * A handle is just an opaque pointer to an empty struct.
- * In the API the pointer is cast to the actual C++ class.
- * The 'name' argument to the macro is the name of the handle to create.
- */
-
-GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
-GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
-GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
-GHOST_DECLARE_HANDLE(GHOST_EventHandle);
-GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
-GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
-GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
-
 /**
  * Definition of a callback routine that receives events.
  * \param event The event received.
@@ -1006,6 +991,91 @@ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
  */
 extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
 
+#ifdef WITH_XR_OPENXR
+
+/* XR-context */
+
+/**
+ * Set a custom callback to be executed whenever an error occurs. Should be set before calling
+ * #GHOST_XrContextCreate() to get error handling during context creation too.
+ *
+ * \param customdata: Handle to some data that will get passed to \a handler_fn should an error be
+ *                    thrown.
+ */
+void GHOST_XrErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
+
+/**
+ * \brief Initialize the Ghost XR-context.
+ *
+ * Includes setting up the OpenXR runtime link, querying available extensions and API layers,
+ * enabling extensions and API layers.
+ *
+ * \param create_info: Options for creating the XR-context, e.g. debug-flags and ordered array of
+ *                     graphics bindings to try enabling.
+ */
+GHOST_XrContextHandle GHOST_XrContextCreate(const GHOST_XrContextCreateInfo *create_info);
+/**
+ * Free a XR-context involving OpenXR runtime link destruction and freeing of all internal data.
+ */
+void GHOST_XrContextDestroy(GHOST_XrContextHandle xr_context);
+
+/**
+ * Set callbacks for binding and unbinding a graphics context for a session. The binding callback
+ * may create a new graphics 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 GHOST_XrGraphicsContextBindFuncs(GHOST_XrContextHandle xr_context,
+                                      GHOST_XrGraphicsContextBindFn bind_fn,
+                                      GHOST_XrGraphicsContextUnbindFn unbind_fn);
+
+/**
+ * Set the drawing callback for views. A view would typically be either the left or the right eye,
+ * although other configurations are possible. When #GHOST_XrSessionDrawViews() is called to draw
+ * an XR frame, \a draw_view_fn is executed for each view.
+ *
+ * \param draw_view_fn: The callback to draw a single view for an XR frame.
+ */
+void GHOST_XrDrawViewFunc(GHOST_XrContextHandle xr_context, GHOST_XrDrawViewFn draw_view_fn);
+
+/* sessions */
+/**
+ * Create internal session data for \a xr_context and ask the OpenXR runtime to invoke a session.
+ *
+ * \param begin_info: Options for the session creation.
+ */
+void GHOST_XrSessionStart(GHOST_XrContextHandle xr_context,
+                          const GHOST_XrSessionBeginInfo *begin_info);
+/**
+ * Destruct internal session data for \a xr_context and ask the OpenXR runtime to stop a session.
+ */
+void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_context);
+/**
+ * Draw a single frame by calling the view drawing callback defined by #GHOST_XrDrawViewFunc() for
+ * each view and submit it to the OpenXR runtime.
+ *
+ * \param customdata: Handle to some data that will get passed to the view drawing callback.
+ */
+void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_context, void *customdata);
+/**
+ * Check if a \a xr_context has a session that, according to the OpenXR definition would be
+ * considered to be 'running'
+ * (https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#session_running).
+ */
+int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
+
+/* events */
+/**
+ * Invoke handling of all OpenXR events for \a xr_context. Should be called on every main-loop
+ * iteration and will early-exit if \a xr_context is NULL (so caller doesn't have to check).
+ *
+ * \returns GHOST_kSuccess if any event was handled, otherwise GHOST_kFailure.
+ */
+GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h
new file mode 100644
index 00000000000..362bc923ee8
--- /dev/null
+++ b/intern/ghost/GHOST_IXrContext.h
@@ -0,0 +1,42 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_IXRCONTEXT_H__
+#define __GHOST_IXRCONTEXT_H__
+
+#include "GHOST_Types.h"
+
+class GHOST_IXrContext {
+ public:
+  virtual ~GHOST_IXrContext() = default;
+
+  virtual void startSession(const GHOST_XrSessionBeginInfo *begin_info) = 0;
+  virtual void endSession() = 0;
+  virtual bool isSessionRunning() const = 0;
+  virtual void drawSessionViews(void *draw_customdata) = 0;
+
+  virtual void dispatchErrorMessage(const class GHOST_XrException *) const = 0;
+
+  virtual void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
+                                           GHOST_XrGraphicsContextUnbindFn unbind_fn) = 0;
+  virtual void setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn) = 0;
+};
+
+#endif  // __GHOST_IXRCONTEXT_H__
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 8bc75d01b96..adda782b96d 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -41,6 +41,22 @@
     } * name
 #endif
 
+/**
+ * Creates a "handle" for a C++ GHOST object.
+ * A handle is just an opaque pointer to an empty struct.
+ * In the API the pointer is cast to the actual C++ class.
+ * The 'name' argument to the macro is the name of the handle to create.
+ */
+
+GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
+GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
+GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
+GHOST_DECLARE_HANDLE(GHOST_EventHandle);
+GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
+GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
+GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
+GHOST_DECLARE_HANDLE(GHOST_XrContextHandle);
+
 typedef char GHOST_TInt8;
 typedef unsigned char GHOST_TUns8;
 typedef short GHOST_TInt16;
@@ -580,4 +596,78 @@ struct GHOST_TimerTaskHandle__;
 typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_TUns64 time);
 #endif
 
+#ifdef WITH_XR_OPENXR
+
+/**
+ * The XR view (i.e. the OpenXR runtime) may require a different graphics library than OpenGL. An
+ * offscreen texture of the viewport will then be drawn into using OpenGL, but the final texture
+ * draw call will happen through another lib (say DirectX).
+ *
+ * This enum defines the possible graphics bindings to attempt to enable.
+ */
+typedef enum {
+  GHOST_kXrGraphicsUnknown = 0,
+  GHOST_kXrGraphicsOpenGL,
+#  ifdef WIN32
+  GHOST_kXrGraphicsD3D11,
+#  endif
+  /* For later */
+  //  GHOST_kXrGraphicsVulkan,
+} GHOST_TXrGraphicsBinding;
+/* An array of GHOST_TXrGraphicsBinding items defining the candidate bindings to use. The first
+ * available candidate will be chosen, so order defines priority. */
+typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
+
+typedef struct {
+  float position[3];
+  /* Blender convention (w, x, y, z) */
+  float orientation_quat[4];
+} GHOST_XrPose;
+
+enum {
+  GHOST_kXrContextDebug = (1 << 0),
+  GHOST_kXrContextDebugTime = (1 << 1),
+};
+
+typedef struct {
+  const GHOST_XrGraphicsBindingCandidates gpu_binding_candidates;
+  unsigned int gpu_binding_candidates_count;
+
+  unsigned int context_flag;
+} GHOST_XrContextCre

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list