Overte C++ Documentation
OpenXrContext.h
1 //
2 // Overte OpenXR Plugin
3 //
4 // Copyright 2024 Lubosz Sarnecki
5 // Copyright 2024 Overte e.V.
6 //
7 // SPDX-License-Identifier: Apache-2.0
8 //
9 
10 #pragma once
11 
12 #include <optional>
13 
14 #include <openxr/openxr.h>
16 
17 #include "gpu/gl/GLBackend.h"
18 
19 #if defined(HAVE_VULKAN)
20  #warning "OpenXR plugin doesn't support Vulkan yet and will always fail on startup"
21  #define XR_USE_GRAPHICS_API_VULKAN
22 #else
23  #if defined(Q_OS_ANDROID)
24  #define XR_USE_GRAPHICS_API_OPENGL_ES
25  #define XR_USE_PLATFORM_ANDROID
26  #define XR_USE_PLATFORM_EGL
27  #elif defined(Q_OS_LINUX)
28  #define XR_USE_GRAPHICS_API_OPENGL
29  // Wayland uses XR_USE_PLATFORM_EGL, XR_USE_PLATFORM_WAYLAND
30  // is deprecated and never worked anyway
31  #define XR_USE_PLATFORM_EGL
32  #define XR_USE_PLATFORM_XLIB
33  #include <GL/glx.h>
34  // Unsorted from glx.h conflicts with qdir.h
35  #undef Unsorted
36  // MappingPointer from X11 conflicts with one from controllers/Forward.h
37  #undef MappingPointer
38  // CursorShape conflicts with QCursor
39  #undef CursorShape
40  #elif defined(Q_OS_WIN)
41  // TODO: We can't support EGL on Windows yet, because we create
42  // the OpenGL contexts ourselves using WGL on Windows.
43  #define XR_USE_GRAPHICS_API_OPENGL
44  #define XR_USE_PLATFORM_WIN32
45  #include <Unknwn.h>
46  #include <Windows.h>
47  #else
48  #error "Unsupported platform"
49  #endif
50 
51  #if defined(XR_USE_PLATFORM_EGL)
52  #include <EGL/egl.h>
53  #endif
54 #endif
55 
56 
57 #include <openxr/openxr_platform.h>
58 
59 #include <glm/glm.hpp>
60 #include <glm/gtx/quaternion.hpp>
61 
62 #include "controllers/Pose.h"
63 
64 #define HAND_COUNT 2
65 
66 constexpr XrPosef XR_INDENTITY_POSE = {
67  .orientation = { .x = 0, .y = 0, .z = 0, .w = 1.0 },
68  .position = { .x = 0, .y = 0, .z = 0 },
69 };
70 
71 constexpr XrViewConfigurationType XR_VIEW_CONFIG_TYPE = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
72 
73 class OpenXrContext {
74 public:
75  XrInstance _instance = XR_NULL_HANDLE;
76  XrSession _session = XR_NULL_HANDLE;
77  XrSystemId _systemId = XR_NULL_SYSTEM_ID;
78 
79  XrSpace _stageSpace = XR_NULL_HANDLE;
80  XrSpace _viewSpace = XR_NULL_HANDLE;
81  XrPath _handPaths[HAND_COUNT];
82 
83  controller::Pose _lastHeadPose;
84  std::optional<XrTime> _lastPredictedDisplayTime;
85 
86  bool _isValid = true; // set to false when the context is lost
87  bool _shouldQuit = false;
88  bool _shouldRunFrameCycle = false;
89  bool _isDisplayActive = false;
90 
91  bool _isSupported = false;
92 
93  QString _systemName;
94  bool _isSessionRunning = false;
95 
96  std::array<bool, HAND_COUNT> _vivePoseHack = { false, false };
97 
98  // only supported by a few runtimes, but lets us
99  // emulate OpenVR's headset proximity sensor system
100  bool _userPresenceAvailable = false;
101 
102  // whether the headset is on, using XR_EXT_user_presence
103  bool _hmdMounted = true;
104 
105  bool _handTrackingSupported = false;
106  PFN_xrCreateHandTrackerEXT xrCreateHandTrackerEXT = nullptr;
107  PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT = nullptr;
108  PFN_xrDestroyHandTrackerEXT xrDestroyHandTrackerEXT = nullptr;
109 
110  bool _palmPoseSupported = false;
111 
112  bool _MNDX_xdevSpaceSupported = false;
113  PFN_xrCreateXDevListMNDX xrCreateXDevListMNDX = nullptr;
114  PFN_xrGetXDevListGenerationNumberMNDX xrGetXDevListGenerationNumberMNDX = nullptr;
115  PFN_xrEnumerateXDevsMNDX xrEnumerateXDevsMNDX = nullptr;
116  PFN_xrGetXDevPropertiesMNDX xrGetXDevPropertiesMNDX = nullptr;
117  PFN_xrDestroyXDevListMNDX xrDestroyXDevListMNDX = nullptr;
118  PFN_xrCreateXDevSpaceMNDX xrCreateXDevSpaceMNDX = nullptr;
119 
120  bool _HTCX_viveTrackerInteractionSupported = false;
121  PFN_xrEnumerateViveTrackerPathsHTCX xrEnumerateViveTrackerPathsHTCX = nullptr;
122 
123  bool _MNDX_eglEnableSupported = false;
124 
125  bool _EXT_debugUtilsSupported = false;
126  XrDebugUtilsMessengerEXT _debugMessenger = {};
127  PFN_xrCreateDebugUtilsMessengerEXT xrCreateDebugUtilsMessengerEXT = nullptr;
128 
129 private:
130  XrSessionState _lastSessionState = XR_SESSION_STATE_UNKNOWN;
131 
132  XrPath _viveControllerPath = XR_NULL_PATH;
133 
134 public:
135  OpenXrContext();
136  ~OpenXrContext();
137 
138  bool initPostGraphics();
139  bool beginFrame();
140  bool pollEvents();
141  bool requestExitSession();
142  void reset();
143 
144 private:
145  bool initPreGraphics();
146  bool initInstance();
147  bool initSystem();
148  bool initGraphics();
149  bool initSession();
150  bool initSpaces();
151 
152  bool updateSessionState(XrSessionState newState);
153 };
154 
155 inline static glm::vec3 xrVecToGlm(const XrVector3f& v) {
156  return glm::vec3(v.x, v.y, v.z);
157 }
158 
159 inline static glm::quat xrQuatToGlm(const XrQuaternionf& q) {
160  return glm::quat(q.w, q.x, q.y, q.z);
161 }
162 
163 bool xrCheck(XrInstance instance, XrResult result, const char* message);
Preview header for XR_MNDX_xdev_space extension.