Monado OpenXR Runtime
Loading...
Searching...
No Matches
g_device.hpp
Go to the documentation of this file.
1// Copyright 2024-2026, NVIDIA CORPORATION.
2// Copyright 2026, Collabora, Ltd.
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Header for glue classes to wrap XRT device interfaces.
7 * @author Jakob Bornecrantz <tbornecrantz@nvidia.com>
8 * @ingroup aux_util
9 */
10
11#pragma once
12
13#include "xrt/xrt_device.h"
14#include "util/u_device.h"
15#include "util/u_device_id.h"
16#include "g_catch_guard.hpp"
17#include "g_traits.hpp"
18
19#include <type_traits>
20
21
22namespace xrt::util {
23
24/*!
25 * Selects which functions that the @ref DeviceBase wrapper should set.
26 */
28{
29 /*!
30 * @ref xrt_device::get_view_poses
31 * @ref xrt_device::is_form_factor_available
32 */
33 bool hmd{false};
34
35 //! @ref xrt_device::compute_distortion
36 bool distortion{false};
37
38 //! @ref xrt_device::get_visibility_mask
39 bool visibility_mask{false};
40
41 //! @ref xrt_device::update_inputs
42 bool update_inputs{false};
43
44 //! @ref xrt_device::set_output
45 bool output{false};
46
47 //! @ref xrt_device::get_output_limits
48 bool output_limits{false};
49
50 //! @ref xrt_device::get_hand_tracking
51 bool hand_tracking{false};
52
53 //! @ref xrt_device::get_face_tracking
54 bool face_tracking{false};
55
56 //! @ref xrt_device::get_face_calibration_state_android
58
59 /*!
60 * @ref xrt_device::get_body_skeleton
61 * @ref xrt_device::get_body_joints
62 * @ref xrt_device::reset_body_tracking_calibration_meta
63 * @ref xrt_device::set_body_tracking_calibration_override_meta
64 */
65 bool body_tracking{false};
66
67 /*!
68 * @ref xrt_device::begin_plane_detection_ext
69 * @ref xrt_device::destroy_plane_detection_ext
70 * @ref xrt_device::get_plane_detection_state_ext
71 * @ref xrt_device::get_plane_detections_ext
72 */
73 bool plane_detection{false};
74
75 //! @ref xrt_device::get_presence
76 bool presence{false};
77
78 //! @ref xrt_device::ref_space_usage
79 bool reference_space{false};
80
81 //! @ref xrt_device::get_battery_status
82 bool battery{false};
83
84 /*!
85 * @ref xrt_device::get_brightness
86 * @ref xrt_device::set_brightness
87 */
88 bool brightness{false};
89
90 //! @ref xrt_device::get_compositor_info
91 bool compositor_info{false};
92
93 /*!
94 * @ref xrt_device::begin_feature
95 * @ref xrt_device::end_feature
96 */
97 bool features{false};
98};
99
100/*!
101 * CRTP glue wrapper for @ref xrt_device. Relies on standard layout to recover
102 * the derived object from the C struct, and has some requirements and
103 * limitations because of that. See @ref cpp-glue-wrappers for the guide and
104 * conventions for these wrappers.
105 *
106 * Unlike the other wrappers it wires function pointers selectively: the
107 * `functions` @ref DeviceFunctions bitmask decides which C function pointers
108 * are installed, so `T` only has to implement C++ methods for the features it
109 * turns on.
110 */
111template <class T, DeviceFunctions functions> class DeviceBase
112{
113public: // Members
114 /*!
115 * Fully resets and sets function pointers on @ref xrt_device.
116 */
117 DeviceBase() noexcept
118 {
119 static_assert(std::is_standard_layout_v<DeviceBase>,
120 "glue base must be standard layout for pointer recovery");
121 static_assert(is_non_virtual_base_v<DeviceBase, T>,
122 "glue base must be a non-virtual base of T for pointer recovery");
123
124 // Setup function for the device.
125 auto &xdev = *getXDev();
126
127 u_device_id_assign(&xdev);
128
129 // Inits all functions, some are replaced below.
130 u_device_populate_function_pointers(&xdev, getTrackedPoseWrap, destroyDeviceWrap);
131
132 if constexpr (functions.hmd) {
133 xdev.get_view_poses = getViewPosesWrap;
134 xdev.is_form_factor_available = isFormFactorAvailableWrap;
135 }
136
137 if constexpr (functions.distortion) {
138 xdev.compute_distortion = computeDistortionWrap;
139 }
140
141 if constexpr (functions.visibility_mask) {
142 xdev.get_visibility_mask = getVisibilityMaskWrap;
143 }
144
145 if constexpr (functions.update_inputs) {
146 xdev.update_inputs = updateInputsWrap;
147 }
148
149 if constexpr (functions.output) {
150 xdev.set_output = setOutputWrap;
151 }
152
153 if constexpr (functions.output_limits) {
154 xdev.get_output_limits = getOutputLimitsWrap;
155 }
156
157 if constexpr (functions.hand_tracking) {
158 xdev.get_hand_tracking = getHandTrackingWrap;
159 }
160
161 if constexpr (functions.face_tracking) {
162 xdev.get_face_tracking = getFaceTrackingWrap;
163 }
164
165 if constexpr (functions.face_calibration_android) {
166 xdev.get_face_calibration_state_android = getFaceCalibrationStateAndroidWrap;
167 }
168
169 if constexpr (functions.body_tracking) {
170 xdev.get_body_skeleton = getBodySkeletonWrap;
171 xdev.get_body_joints = getBodyJointsWrap;
172 xdev.reset_body_tracking_calibration_meta = resetBodyTrackingCalibrationMetaWrap;
173 xdev.set_body_tracking_calibration_override_meta = setBodyTrackingCalibrationOverrideMetaWrap;
174 }
175
176 if constexpr (functions.plane_detection) {
177 xdev.begin_plane_detection_ext = beginPlaneDetectionExtWrap;
178 xdev.destroy_plane_detection_ext = destroyPlaneDetectionExtWrap;
179 xdev.get_plane_detection_state_ext = getPlaneDetectionStateExtWrap;
180 xdev.get_plane_detections_ext = getPlaneDetectionsExtWrap;
181 }
182
183 if constexpr (functions.presence) {
184 xdev.get_presence = getPresenceWrap;
185 }
186
187 if constexpr (functions.reference_space) {
188 xdev.ref_space_usage = refSpaceUsageWrap;
189 }
190
191 if constexpr (functions.battery) {
192 xdev.get_battery_status = getBatteryStatusWrap;
193 }
194
195 if constexpr (functions.brightness) {
196 xdev.get_brightness = getBrightnessWrap;
197 xdev.set_brightness = setBrightnessWrap;
198 }
199
200 if constexpr (functions.compositor_info) {
201 xdev.get_compositor_info = getCompositorInfoWrap;
202 }
203
204 if constexpr (functions.features) {
205 xdev.begin_feature = beginFeatureWrap;
206 xdev.end_feature = endFeatureWrap;
207 }
208 }
209
210 /*!
211 * Destructor
212 */
213 ~DeviceBase() noexcept = default;
214
215 const T &
216 derived() const noexcept
217 {
218 return static_cast<const T &>(*this);
219 }
220
221 T &
222 derived() noexcept
223 {
224 return static_cast<T &>(*this);
225 }
226
227 //! Gets the pointer to the derived class from a @ref xrt_device.
228 static const T *
229 fromXDev(const xrt_device *xdev) noexcept
230 {
231 return &(reinterpret_cast<const DeviceBase *>(xdev)->derived());
232 }
233
234 //! Gets the pointer to the derived class from a @ref xrt_device.
235 static T *
236 fromXDev(xrt_device *xdev) noexcept
237 {
238 return &(reinterpret_cast<DeviceBase *>(xdev)->derived());
239 }
240
241 //! Gets the underlying xrt_device pointer.
242 const xrt_device *
243 getXDev() const noexcept
244 {
245 return &mDevice;
246 }
247
248 //! Gets the underlying xrt_device pointer.
249 xrt_device *
250 getXDev() noexcept
251 {
252 return &mDevice;
253 }
254
255
256private: // Fields
257 /*!
258 * Wrapped @ref xrt_device. Must be the first data member: a pointer to it is
259 * then interconvertible with a pointer to this standard-layout base, which
260 * lets the glue cast a C pointer back to the derived C++ class. See
261 * @ref cpp-glue-wrappers.
262 */
263 xrt_device mDevice = {};
264
265
266private: // Functions
267#define GET(xdev) (fromXDev(xdev)->derived())
268
269 static xrt_result_t
270 updateInputsWrap(struct xrt_device *xdev) noexcept
271 try {
272 return GET(xdev).updateInputs();
273 }
274 G_CATCH_GUARDS
275
276 static xrt_result_t
277 getTrackedPoseWrap(struct xrt_device *xdev,
278 enum xrt_input_name name,
279 int64_t at_timestamp_ns,
280 struct xrt_space_relation *out_relation) noexcept
281 try {
282 return GET(xdev).getTrackedPose(name, at_timestamp_ns, out_relation);
283 }
284 G_CATCH_GUARDS
285
286 static xrt_result_t
287 getHandTrackingWrap(struct xrt_device *xdev,
288 enum xrt_input_name name,
289 int64_t desired_timestamp_ns,
290 struct xrt_hand_joint_set *out_value,
291 int64_t *out_timestamp_ns) noexcept
292 try {
293 return GET(xdev).getHandTracking(name, desired_timestamp_ns, out_value, out_timestamp_ns);
294 }
295 G_CATCH_GUARDS
296
297 static xrt_result_t
298 getFaceTrackingWrap(struct xrt_device *xdev,
299 enum xrt_input_name facial_expression_type,
300 int64_t at_timestamp_ns,
301 struct xrt_facial_expression_set *out_value) noexcept
302 try {
303 return GET(xdev).getFaceTracking(facial_expression_type, at_timestamp_ns, out_value);
304 }
305 G_CATCH_GUARDS
306
307 static xrt_result_t
308 getFaceCalibrationStateAndroidWrap(struct xrt_device *xdev, bool *out_face_is_calibrated) noexcept
309 try {
310 return GET(xdev).getFaceCalibrationStateAndroid(out_face_is_calibrated);
311 }
312 G_CATCH_GUARDS
313
314 static xrt_result_t
315 getBodySkeletonWrap(struct xrt_device *xdev,
316 enum xrt_input_name body_tracking_type,
317 struct xrt_body_skeleton *out_value) noexcept
318 try {
319 return GET(xdev).getBodySkeleton(body_tracking_type, out_value);
320 }
321 G_CATCH_GUARDS
322
323 static xrt_result_t
324 getBodyJointsWrap(struct xrt_device *xdev,
325 enum xrt_input_name body_tracking_type,
326 int64_t desired_timestamp_ns,
327 struct xrt_body_joint_set *out_value) noexcept
328 try {
329 return GET(xdev).getBodyJoints(body_tracking_type, desired_timestamp_ns, out_value);
330 }
331 G_CATCH_GUARDS
332
333 static xrt_result_t
334 resetBodyTrackingCalibrationMetaWrap(struct xrt_device *xdev) noexcept
335 try {
336 return GET(xdev).resetBodyTrackingCalibrationMeta();
337 }
338 G_CATCH_GUARDS
339
340 static xrt_result_t
341 setBodyTrackingCalibrationOverrideMetaWrap(struct xrt_device *xdev, float new_body_height) noexcept
342 try {
343 return GET(xdev).setBodyTrackingCalibrationOverrideMeta(new_body_height);
344 }
345 G_CATCH_GUARDS
346
347 static xrt_result_t
348 setOutputWrap(struct xrt_device *xdev, enum xrt_output_name name, const struct xrt_output_value *value) noexcept
349 try {
350 return GET(xdev).setOutput(name, value);
351 }
352 G_CATCH_GUARDS
353
354 static xrt_result_t
355 getOutputLimitsWrap(struct xrt_device *xdev, struct xrt_output_limits *limits) noexcept
356 try {
357 return GET(xdev).getOutputLimits(limits);
358 }
359 G_CATCH_GUARDS
360
361 static xrt_result_t
362 getPresenceWrap(struct xrt_device *xdev, bool *presence) noexcept
363 try {
364 return GET(xdev).getPresence(presence);
365 }
366 G_CATCH_GUARDS
367
368 static xrt_result_t
369 beginPlaneDetectionExtWrap(struct xrt_device *xdev,
370 const struct xrt_plane_detector_begin_info_ext *begin_info,
371 uint64_t plane_detection_id,
372 uint64_t *out_plane_detection_id) noexcept
373 try {
374 return GET(xdev).beginPlaneDetectionExt(begin_info, plane_detection_id, out_plane_detection_id);
375 }
376 G_CATCH_GUARDS
377
378 static xrt_result_t
379 destroyPlaneDetectionExtWrap(struct xrt_device *xdev, uint64_t plane_detection_id) noexcept
380 try {
381 return GET(xdev).destroyPlaneDetectionExt(plane_detection_id);
382 }
383 G_CATCH_GUARDS
384
385 static xrt_result_t
386 getPlaneDetectionStateExtWrap(struct xrt_device *xdev,
387 uint64_t plane_detection_id,
388 enum xrt_plane_detector_state_ext *out_state) noexcept
389 try {
390 return GET(xdev).getPlaneDetectionStateExt(plane_detection_id, out_state);
391 }
392 G_CATCH_GUARDS
393
394 static xrt_result_t
395 getPlaneDetectionsExtWrap(struct xrt_device *xdev,
396 uint64_t plane_detection_id,
397 struct xrt_plane_detections_ext *out_detections) noexcept
398 try {
399 return GET(xdev).getPlaneDetectionsExt(plane_detection_id, out_detections);
400 }
401 G_CATCH_GUARDS
402
403 static xrt_result_t
404 getViewPosesWrap(struct xrt_device *xdev,
405 const struct xrt_vec3 *default_eye_relation,
406 int64_t at_timestamp_ns,
407 enum xrt_view_type view_type,
408 uint32_t view_count,
409 struct xrt_space_relation *out_head_relation,
410 struct xrt_fov *out_fovs,
411 struct xrt_pose *out_poses) noexcept
412 try {
413 return GET(xdev).getViewPoses(default_eye_relation, at_timestamp_ns, view_type, view_count,
414 out_head_relation, out_fovs, out_poses);
415 }
416 G_CATCH_GUARDS
417
418 static xrt_result_t
419 computeDistortionWrap(
420 struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) noexcept
421 try {
422 return GET(xdev).computeDistortion(view, u, v, out_result);
423 }
424 G_CATCH_GUARDS
425
426 static xrt_result_t
427 getVisibilityMaskWrap(struct xrt_device *xdev,
428 enum xrt_visibility_mask_type type,
429 uint32_t view_index,
430 struct xrt_visibility_mask **out_mask) noexcept
431 try {
432 return GET(xdev).getVisibilityMask(type, view_index, out_mask);
433 }
434 G_CATCH_GUARDS
435
436 static xrt_result_t
437 refSpaceUsageWrap(struct xrt_device *xdev,
438 enum xrt_reference_space_type type,
439 enum xrt_input_name name,
440 bool used) noexcept
441 try {
442 return GET(xdev).refSpaceUsage(type, name, used);
443 }
444 G_CATCH_GUARDS
445
446 static xrt_result_t
447 isFormFactorAvailableWrap(struct xrt_device *xdev,
448 enum xrt_form_factor form_factor,
449 bool *out_available) noexcept
450 try {
451 return GET(xdev).isFormFactorAvailable(form_factor, out_available);
452 }
453 G_CATCH_GUARDS
454
455 static xrt_result_t
456 getBatteryStatusWrap(struct xrt_device *xdev, bool *out_present, bool *out_charging, float *out_charge) noexcept
457 try {
458 return GET(xdev).getBatteryStatus(out_present, out_charging, out_charge);
459 }
460 G_CATCH_GUARDS
461
462 static xrt_result_t
463 getBrightnessWrap(struct xrt_device *xdev, float *out_brightness) noexcept
464 try {
465 return GET(xdev).getBrightness(out_brightness);
466 }
467 G_CATCH_GUARDS
468
469 static xrt_result_t
470 setBrightnessWrap(struct xrt_device *xdev, float brightness, bool relative) noexcept
471 try {
472 return GET(xdev).setBrightness(brightness, relative);
473 }
474 G_CATCH_GUARDS
475
476 static xrt_result_t
477 getCompositorInfoWrap(struct xrt_device *xdev,
478 const struct xrt_device_compositor_mode *mode,
479 struct xrt_device_compositor_info *out_info) noexcept
480 try {
481 return GET(xdev).getCompositorInfo(mode, out_info);
482 }
483 G_CATCH_GUARDS
484
485 static xrt_result_t
486 beginFeatureWrap(struct xrt_device *xdev, enum xrt_device_feature_type type) noexcept
487 try {
488 return GET(xdev).beginFeature(type);
489 }
490 G_CATCH_GUARDS
491
492 static xrt_result_t
493 endFeatureWrap(struct xrt_device *xdev, enum xrt_device_feature_type type) noexcept
494 try {
495 return GET(xdev).endFeature(type);
496 }
497 G_CATCH_GUARDS
498
499 static void
500 destroyDeviceWrap(struct xrt_device *xdev) noexcept
501 try {
502 T::destroyDevice(xdev);
503 }
504 G_CATCH_GUARDS_VOID
505
506
507#undef GET
508};
509
510} // namespace xrt::util
CRTP glue wrapper for xrt_device.
Definition g_device.hpp:112
DeviceBase() noexcept
Fully resets and sets function pointers on xrt_device.
Definition g_device.hpp:117
xrt_device * getXDev() noexcept
Gets the underlying xrt_device pointer.
Definition g_device.hpp:250
static T * fromXDev(xrt_device *xdev) noexcept
Gets the pointer to the derived class from a xrt_device.
Definition g_device.hpp:236
static const T * fromXDev(const xrt_device *xdev) noexcept
Gets the pointer to the derived class from a xrt_device.
Definition g_device.hpp:229
~DeviceBase() noexcept=default
Destructor.
const xrt_device * getXDev() const noexcept
Gets the underlying xrt_device pointer.
Definition g_device.hpp:243
Catch guards for glue classes.
Shared type traits for glue classes.
void u_device_populate_function_pointers(struct xrt_device *xdev, u_device_get_tracked_pose_function_t get_tracked_pose_fn, u_device_destroy_function_t destroy_fn)
Populate the device's function pointers with default implementations.
Definition u_device.c:599
void u_device_id_assign(struct xrt_device *xdev)
Assign a newly generated ID to the given device.
Definition u_device_id.c:31
xrt_visibility_mask_type
Visibility mask, mirror of XrVisibilityMaskKHR.
Definition xrt_defines.h:2468
xrt_form_factor
What form factor is this device, mostly maps onto OpenXR's XrFormFactor.
Definition xrt_defines.h:2408
xrt_input_name
Every internal input source known to monado with a baked in type.
Definition xrt_defines.h:930
enum xrt_result xrt_result_t
Result type used across Monado.
xrt_reference_space_type
Type of a OpenXR mapped reference space, maps to the semantic spaces on the xrt_space_overseer struct...
Definition xrt_defines.h:625
xrt_output_name
Name of a output with a baked in type.
Definition xrt_defines.h:1612
xrt_plane_detector_state_ext
State of a plane detector, see xrt_device.
Definition xrt_plane_detector.h:83
Selects which functions that the DeviceBase wrapper should set.
Definition g_device.hpp:28
bool body_tracking
xrt_device::get_body_skeleton xrt_device::get_body_joints xrt_device::reset_body_tracking_calibration...
Definition g_device.hpp:65
bool reference_space
xrt_device::ref_space_usage
Definition g_device.hpp:79
bool plane_detection
xrt_device::begin_plane_detection_ext xrt_device::destroy_plane_detection_ext xrt_device::get_plane_d...
Definition g_device.hpp:73
bool output_limits
xrt_device::get_output_limits
Definition g_device.hpp:48
bool visibility_mask
xrt_device::get_visibility_mask
Definition g_device.hpp:39
bool update_inputs
xrt_device::update_inputs
Definition g_device.hpp:42
bool compositor_info
xrt_device::get_compositor_info
Definition g_device.hpp:91
bool hmd
xrt_device::get_view_poses xrt_device::is_form_factor_available
Definition g_device.hpp:33
bool output
xrt_device::set_output
Definition g_device.hpp:45
bool battery
xrt_device::get_battery_status
Definition g_device.hpp:82
bool brightness
xrt_device::get_brightness xrt_device::set_brightness
Definition g_device.hpp:88
bool hand_tracking
xrt_device::get_hand_tracking
Definition g_device.hpp:51
bool face_tracking
xrt_device::get_face_tracking
Definition g_device.hpp:54
bool distortion
xrt_device::compute_distortion
Definition g_device.hpp:36
bool features
xrt_device::begin_feature xrt_device::end_feature
Definition g_device.hpp:97
bool face_calibration_android
xrt_device::get_face_calibration_state_android
Definition g_device.hpp:57
bool presence
xrt_device::get_presence
Definition g_device.hpp:76
Definition xrt_defines.h:2301
Definition xrt_defines.h:2198
Compositor information for a device.
Definition xrt_device.h:110
Compositor mode information for a device.
Definition xrt_device.h:126
A single HMD or input device.
Definition xrt_device.h:340
Definition xrt_defines.h:1967
Describes a projection matrix fov.
Definition xrt_defines.h:512
Joint set type used for hand tracking.
Definition xrt_defines.h:1521
Output limits of a particular device.
Definition xrt_device.h:288
A union of all output types.
Definition xrt_defines.h:2386
Each plane has n polygons; ultimately plane metadata from xrt_plane_detections_ext::locations and xrt...
Definition xrt_plane_detector.h:172
A query for a plane.
Definition xrt_plane_detector.h:97
A pose composed of a position and orientation.
Definition xrt_defines.h:492
A relation with two spaces, includes velocity and acceleration.
Definition xrt_defines.h:683
Represents a uv triplet for distortion, basically just three xrt_vec2.
Definition xrt_defines.h:279
A 3 element vector with single floats.
Definition xrt_defines.h:289
Visibility mask helper, the indices and vertices are tightly packed after this struct.
Definition xrt_visibility_mask.h:26
Misc helpers for device drivers.
Generator for per-process unique xrt_device_id values.
xrt_view_type
View type to be rendered to by the compositor.
Definition xrt_defines.h:2417
Header defining an xrt display or controller device.
xrt_device_feature_type
Higher level features for devices.
Definition xrt_device.h:276