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::ref_space_usage
76 bool reference_space{false};
77
78 //! @ref xrt_device::get_battery_status
79 bool battery{false};
80
81 /*!
82 * @ref xrt_device::get_brightness
83 * @ref xrt_device::set_brightness
84 */
85 bool brightness{false};
86
87 //! @ref xrt_device::get_compositor_info
88 bool compositor_info{false};
89
90 /*!
91 * @ref xrt_device::begin_feature
92 * @ref xrt_device::end_feature
93 */
94 bool features{false};
95
96 /*!
97 * @ref xrt_device::notify_chirality
98 */
99 bool notify_chirality{false};
100};
101
102/*!
103 * CRTP glue wrapper for @ref xrt_device. Relies on standard layout to recover
104 * the derived object from the C struct, and has some requirements and
105 * limitations because of that. See @ref cpp-glue-wrappers for the guide and
106 * conventions for these wrappers.
107 *
108 * Unlike the other wrappers it wires function pointers selectively: the
109 * `functions` @ref DeviceFunctions bitmask decides which C function pointers
110 * are installed, so `T` only has to implement C++ methods for the features it
111 * turns on.
112 */
113template <class T, DeviceFunctions functions> class DeviceBase
114{
115public: // Members
116 /*!
117 * Fully resets and sets function pointers on @ref xrt_device.
118 */
119 DeviceBase() noexcept
120 {
121 static_assert(std::is_standard_layout_v<DeviceBase>,
122 "glue base must be standard layout for pointer recovery");
123 static_assert(is_non_virtual_base_v<DeviceBase, T>,
124 "glue base must be a non-virtual base of T for pointer recovery");
125
126 // Setup function for the device.
127 auto &xdev = *getXDev();
128
129 u_device_id_assign(&xdev);
130
131 // Inits all functions, some are replaced below.
132 u_device_populate_function_pointers(&xdev, getTrackedPoseWrap, destroyDeviceWrap);
133
134 if constexpr (functions.hmd) {
135 xdev.get_view_poses = getViewPosesWrap;
136 xdev.is_form_factor_available = isFormFactorAvailableWrap;
137 }
138
139 if constexpr (functions.distortion) {
140 xdev.compute_distortion = computeDistortionWrap;
141 }
142
143 if constexpr (functions.visibility_mask) {
144 xdev.get_visibility_mask = getVisibilityMaskWrap;
145 }
146
147 if constexpr (functions.update_inputs) {
148 xdev.update_inputs = updateInputsWrap;
149 }
150
151 if constexpr (functions.output) {
152 xdev.set_output = setOutputWrap;
153 }
154
155 if constexpr (functions.output_limits) {
156 xdev.get_output_limits = getOutputLimitsWrap;
157 }
158
159 if constexpr (functions.hand_tracking) {
160 xdev.get_hand_tracking = getHandTrackingWrap;
161 }
162
163 if constexpr (functions.face_tracking) {
164 xdev.get_face_tracking = getFaceTrackingWrap;
165 }
166
167 if constexpr (functions.face_calibration_android) {
168 xdev.get_face_calibration_state_android = getFaceCalibrationStateAndroidWrap;
169 }
170
171 if constexpr (functions.body_tracking) {
172 xdev.get_body_skeleton = getBodySkeletonWrap;
173 xdev.get_body_joints = getBodyJointsWrap;
174 xdev.reset_body_tracking_calibration_meta = resetBodyTrackingCalibrationMetaWrap;
175 xdev.set_body_tracking_calibration_override_meta = setBodyTrackingCalibrationOverrideMetaWrap;
176 }
177
178 if constexpr (functions.plane_detection) {
179 xdev.begin_plane_detection_ext = beginPlaneDetectionExtWrap;
180 xdev.destroy_plane_detection_ext = destroyPlaneDetectionExtWrap;
181 xdev.get_plane_detection_state_ext = getPlaneDetectionStateExtWrap;
182 xdev.get_plane_detections_ext = getPlaneDetectionsExtWrap;
183 }
184
185 if constexpr (functions.reference_space) {
186 xdev.ref_space_usage = refSpaceUsageWrap;
187 }
188
189 if constexpr (functions.battery) {
190 xdev.get_battery_status = getBatteryStatusWrap;
191 }
192
193 if constexpr (functions.brightness) {
194 xdev.get_brightness = getBrightnessWrap;
195 xdev.set_brightness = setBrightnessWrap;
196 }
197
198 if constexpr (functions.compositor_info) {
199 xdev.get_compositor_info = getCompositorInfoWrap;
200 }
201
202 if constexpr (functions.features) {
203 xdev.begin_feature = beginFeatureWrap;
204 xdev.end_feature = endFeatureWrap;
205 }
206
207 if constexpr (functions.notify_chirality) {
208 xdev.notify_chirality = notifyChiralityWrap;
209 }
210 }
211
212 /*!
213 * Destructor
214 */
215 ~DeviceBase() noexcept = default;
216
217 const T &
218 derived() const noexcept
219 {
220 return static_cast<const T &>(*this);
221 }
222
223 T &
224 derived() noexcept
225 {
226 return static_cast<T &>(*this);
227 }
228
229 //! Gets the pointer to the derived class from a @ref xrt_device.
230 static const T *
231 fromXDev(const xrt_device *xdev) noexcept
232 {
233 return &(reinterpret_cast<const DeviceBase *>(xdev)->derived());
234 }
235
236 //! Gets the pointer to the derived class from a @ref xrt_device.
237 static T *
238 fromXDev(xrt_device *xdev) noexcept
239 {
240 return &(reinterpret_cast<DeviceBase *>(xdev)->derived());
241 }
242
243 //! Gets the underlying xrt_device pointer.
244 const xrt_device *
245 getXDev() const noexcept
246 {
247 return &mDevice;
248 }
249
250 //! Gets the underlying xrt_device pointer.
251 xrt_device *
252 getXDev() noexcept
253 {
254 return &mDevice;
255 }
256
257
258private: // Fields
259 /*!
260 * Wrapped @ref xrt_device. Must be the first data member: a pointer to it is
261 * then interconvertible with a pointer to this standard-layout base, which
262 * lets the glue cast a C pointer back to the derived C++ class. See
263 * @ref cpp-glue-wrappers.
264 */
265 xrt_device mDevice = {};
266
267
268private: // Functions
269#define GET(xdev) (fromXDev(xdev)->derived())
270
271 static xrt_result_t
272 updateInputsWrap(struct xrt_device *xdev) noexcept
273 try {
274 return GET(xdev).updateInputs();
275 }
276 G_CATCH_GUARDS
277
278 static xrt_result_t
279 getTrackedPoseWrap(struct xrt_device *xdev,
280 enum xrt_input_name name,
281 int64_t at_timestamp_ns,
282 struct xrt_space_relation *out_relation) noexcept
283 try {
284 return GET(xdev).getTrackedPose(name, at_timestamp_ns, out_relation);
285 }
286 G_CATCH_GUARDS
287
288 static xrt_result_t
289 getHandTrackingWrap(struct xrt_device *xdev,
290 enum xrt_input_name name,
291 int64_t desired_timestamp_ns,
292 struct xrt_hand_joint_set *out_value,
293 int64_t *out_timestamp_ns) noexcept
294 try {
295 return GET(xdev).getHandTracking(name, desired_timestamp_ns, out_value, out_timestamp_ns);
296 }
297 G_CATCH_GUARDS
298
299 static xrt_result_t
300 getFaceTrackingWrap(struct xrt_device *xdev,
301 enum xrt_input_name facial_expression_type,
302 int64_t at_timestamp_ns,
303 struct xrt_facial_expression_set *out_value) noexcept
304 try {
305 return GET(xdev).getFaceTracking(facial_expression_type, at_timestamp_ns, out_value);
306 }
307 G_CATCH_GUARDS
308
309 static xrt_result_t
310 getFaceCalibrationStateAndroidWrap(struct xrt_device *xdev, bool *out_face_is_calibrated) noexcept
311 try {
312 return GET(xdev).getFaceCalibrationStateAndroid(out_face_is_calibrated);
313 }
314 G_CATCH_GUARDS
315
316 static xrt_result_t
317 getBodySkeletonWrap(struct xrt_device *xdev,
318 enum xrt_input_name body_tracking_type,
319 struct xrt_body_skeleton *out_value) noexcept
320 try {
321 return GET(xdev).getBodySkeleton(body_tracking_type, out_value);
322 }
323 G_CATCH_GUARDS
324
325 static xrt_result_t
326 getBodyJointsWrap(struct xrt_device *xdev,
327 enum xrt_input_name body_tracking_type,
328 int64_t desired_timestamp_ns,
329 struct xrt_body_joint_set *out_value) noexcept
330 try {
331 return GET(xdev).getBodyJoints(body_tracking_type, desired_timestamp_ns, out_value);
332 }
333 G_CATCH_GUARDS
334
335 static xrt_result_t
336 resetBodyTrackingCalibrationMetaWrap(struct xrt_device *xdev) noexcept
337 try {
338 return GET(xdev).resetBodyTrackingCalibrationMeta();
339 }
340 G_CATCH_GUARDS
341
342 static xrt_result_t
343 setBodyTrackingCalibrationOverrideMetaWrap(struct xrt_device *xdev, float new_body_height) noexcept
344 try {
345 return GET(xdev).setBodyTrackingCalibrationOverrideMeta(new_body_height);
346 }
347 G_CATCH_GUARDS
348
349 static xrt_result_t
350 setOutputWrap(struct xrt_device *xdev, enum xrt_output_name name, const struct xrt_output_value *value) noexcept
351 try {
352 return GET(xdev).setOutput(name, value);
353 }
354 G_CATCH_GUARDS
355
356 static xrt_result_t
357 getOutputLimitsWrap(struct xrt_device *xdev, struct xrt_output_limits *limits) noexcept
358 try {
359 return GET(xdev).getOutputLimits(limits);
360 }
361 G_CATCH_GUARDS
362
363 static xrt_result_t
364 beginPlaneDetectionExtWrap(struct xrt_device *xdev,
365 const struct xrt_plane_detector_begin_info_ext *begin_info,
366 uint64_t plane_detection_id,
367 uint64_t *out_plane_detection_id) noexcept
368 try {
369 return GET(xdev).beginPlaneDetectionExt(begin_info, plane_detection_id, out_plane_detection_id);
370 }
371 G_CATCH_GUARDS
372
373 static xrt_result_t
374 destroyPlaneDetectionExtWrap(struct xrt_device *xdev, uint64_t plane_detection_id) noexcept
375 try {
376 return GET(xdev).destroyPlaneDetectionExt(plane_detection_id);
377 }
378 G_CATCH_GUARDS
379
380 static xrt_result_t
381 getPlaneDetectionStateExtWrap(struct xrt_device *xdev,
382 uint64_t plane_detection_id,
383 enum xrt_plane_detector_state_ext *out_state) noexcept
384 try {
385 return GET(xdev).getPlaneDetectionStateExt(plane_detection_id, out_state);
386 }
387 G_CATCH_GUARDS
388
389 static xrt_result_t
390 getPlaneDetectionsExtWrap(struct xrt_device *xdev,
391 uint64_t plane_detection_id,
392 struct xrt_plane_detections_ext *out_detections) noexcept
393 try {
394 return GET(xdev).getPlaneDetectionsExt(plane_detection_id, out_detections);
395 }
396 G_CATCH_GUARDS
397
398 static xrt_result_t
399 getViewPosesWrap(struct xrt_device *xdev,
400 const struct xrt_vec3 *default_eye_relation,
401 int64_t at_timestamp_ns,
402 enum xrt_view_type view_type,
403 uint32_t view_count,
404 struct xrt_space_relation *out_head_relation,
405 struct xrt_fov *out_fovs,
406 struct xrt_pose *out_poses) noexcept
407 try {
408 return GET(xdev).getViewPoses(default_eye_relation, at_timestamp_ns, view_type, view_count,
409 out_head_relation, out_fovs, out_poses);
410 }
411 G_CATCH_GUARDS
412
413 static xrt_result_t
414 computeDistortionWrap(
415 struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) noexcept
416 try {
417 return GET(xdev).computeDistortion(view, u, v, out_result);
418 }
419 G_CATCH_GUARDS
420
421 static xrt_result_t
422 getVisibilityMaskWrap(struct xrt_device *xdev,
423 enum xrt_visibility_mask_type type,
424 uint32_t view_index,
425 struct xrt_visibility_mask **out_mask) noexcept
426 try {
427 return GET(xdev).getVisibilityMask(type, view_index, out_mask);
428 }
429 G_CATCH_GUARDS
430
431 static xrt_result_t
432 refSpaceUsageWrap(struct xrt_device *xdev,
433 enum xrt_reference_space_type type,
434 enum xrt_input_name name,
435 bool used) noexcept
436 try {
437 return GET(xdev).refSpaceUsage(type, name, used);
438 }
439 G_CATCH_GUARDS
440
441 static xrt_result_t
442 isFormFactorAvailableWrap(struct xrt_device *xdev,
443 enum xrt_form_factor form_factor,
444 bool *out_available) noexcept
445 try {
446 return GET(xdev).isFormFactorAvailable(form_factor, out_available);
447 }
448 G_CATCH_GUARDS
449
450 static xrt_result_t
451 getBatteryStatusWrap(struct xrt_device *xdev, bool *out_present, bool *out_charging, float *out_charge) noexcept
452 try {
453 return GET(xdev).getBatteryStatus(out_present, out_charging, out_charge);
454 }
455 G_CATCH_GUARDS
456
457 static xrt_result_t
458 getBrightnessWrap(struct xrt_device *xdev, float *out_brightness) noexcept
459 try {
460 return GET(xdev).getBrightness(out_brightness);
461 }
462 G_CATCH_GUARDS
463
464 static xrt_result_t
465 setBrightnessWrap(struct xrt_device *xdev, float brightness, bool relative) noexcept
466 try {
467 return GET(xdev).setBrightness(brightness, relative);
468 }
469 G_CATCH_GUARDS
470
471 static xrt_result_t
472 getCompositorInfoWrap(struct xrt_device *xdev,
473 const struct xrt_device_compositor_mode *mode,
474 struct xrt_device_compositor_info *out_info) noexcept
475 try {
476 return GET(xdev).getCompositorInfo(mode, out_info);
477 }
478 G_CATCH_GUARDS
479
480 static xrt_result_t
481 beginFeatureWrap(struct xrt_device *xdev, enum xrt_device_feature_type type) noexcept
482 try {
483 return GET(xdev).beginFeature(type);
484 }
485 G_CATCH_GUARDS
486
487 static xrt_result_t
488 endFeatureWrap(struct xrt_device *xdev, enum xrt_device_feature_type type) noexcept
489 try {
490 return GET(xdev).endFeature(type);
491 }
492 G_CATCH_GUARDS
493
494 static xrt_result_t
495 notifyChiralityWrap(struct xrt_device *xdev, bool has_chirality, enum xrt_hand chirality) noexcept
496 try {
497 return GET(xdev).notifyChirality(has_chirality, chirality);
498 }
499 G_CATCH_GUARDS
500
501 static void
502 destroyDeviceWrap(struct xrt_device *xdev) noexcept
503 try {
504 T::destroyDevice(xdev);
505 }
506 G_CATCH_GUARDS_VOID
507
508
509#undef GET
510};
511
512} // namespace xrt::util
CRTP glue wrapper for xrt_device.
Definition g_device.hpp:114
DeviceBase() noexcept
Fully resets and sets function pointers on xrt_device.
Definition g_device.hpp:119
xrt_device * getXDev() noexcept
Gets the underlying xrt_device pointer.
Definition g_device.hpp:252
static T * fromXDev(xrt_device *xdev) noexcept
Gets the pointer to the derived class from a xrt_device.
Definition g_device.hpp:238
static const T * fromXDev(const xrt_device *xdev) noexcept
Gets the pointer to the derived class from a xrt_device.
Definition g_device.hpp:231
~DeviceBase() noexcept=default
Destructor.
const xrt_device * getXDev() const noexcept
Gets the underlying xrt_device pointer.
Definition g_device.hpp:245
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_hand
Enumeration for left and right hand.
Definition xrt_defines.h:1478
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:76
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:88
bool notify_chirality
xrt_device::notify_chirality
Definition g_device.hpp:99
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:79
bool brightness
xrt_device::get_brightness xrt_device::set_brightness
Definition g_device.hpp:85
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:94
bool face_calibration_android
xrt_device::get_face_calibration_state_android
Definition g_device.hpp:57
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:341
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