···11// Copyright 2023, Collabora, Ltd.
22+// Copyright 2025, NVIDIA CORPORATION.
23// SPDX-License-Identifier: BSL-1.0
34/*!
45 * @file
···474475475476/*
476477 *
478478+ * Device helpers.
479479+ *
480480+ */
481481+482482+/*!
483483+ * Helper function to add a device to the space overseer. This function
484484+ * handles creating or finding a space for the device's tracking origin
485485+ * and linking the device to that space.
486486+ */
487487+static xrt_result_t
488488+add_device_helper(struct u_space_overseer *uso, struct xrt_device *xdev)
489489+{
490490+ struct xrt_tracking_origin *torig = xdev->tracking_origin;
491491+ assert(torig != NULL);
492492+493493+ struct xrt_space *root = uso->base.semantic.root;
494494+ uint64_t key = (uint64_t)(intptr_t)torig;
495495+ struct xrt_space *xs = NULL;
496496+497497+ // Need to take the write lock.
498498+ pthread_rwlock_wrlock(&uso->lock);
499499+500500+ // Does this tracking origin already have space.
501501+ void *ptr = NULL;
502502+ u_hashmap_int_find(uso->xto_map, key, &ptr);
503503+504504+ if (ptr != NULL) {
505505+ xs = (struct xrt_space *)ptr;
506506+ } else {
507507+ /*
508508+ * If we ever make u_space_overseer sub-classable maek sure
509509+ * this calls the right function, can't call interface function
510510+ * as the lock is held here.
511511+ */
512512+ xs = (struct xrt_space *)create_space(U_SPACE_TYPE_OFFSET, u_space(root));
513513+514514+ update_offset_write_locked(u_space(xs), &torig->initial_offset);
515515+516516+ u_hashmap_int_insert(uso->xto_map, key, xs);
517517+ }
518518+519519+ pthread_rwlock_unlock(&uso->lock);
520520+521521+ u_space_overseer_link_space_to_device(uso, xs, xdev);
522522+523523+ return XRT_SUCCESS;
524524+}
525525+526526+527527+/*
528528+ *
477529 * Member functions.
478530 *
479531 */
···10331085 return xret;
10341086}
1035108710881088+static xrt_result_t
10891089+add_device(struct xrt_space_overseer *xso, struct xrt_device *xdev)
10901090+{
10911091+ struct u_space_overseer *uso = u_space_overseer(xso);
10921092+10931093+ return add_device_helper(uso, xdev);
10941094+}
10951095+10361096static void
10371097destroy(struct xrt_space_overseer *xso)
10381098{
···10891149 uso->base.set_tracking_origin_offset = set_tracking_origin_offset;
10901150 uso->base.get_reference_space_offset = get_reference_space_offset;
10911151 uso->base.set_reference_space_offset = set_reference_space_offset;
11521152+ uso->base.add_device = add_device;
10921153 uso->base.destroy = destroy;
10931154 uso->broadcast = broadcast;
10941155···11171178 bool root_is_unbounded,
11181179 bool per_app_local_spaces)
11191180{
11201120- struct xrt_space *root = uso->base.semantic.root; // Convenience
11211181 uso->per_app_local_spaces = per_app_local_spaces;
1122118211831183+ // Add all devices to the space overseer.
11231184 for (uint32_t i = 0; i < xdev_count; i++) {
11241124- struct xrt_device *xdev = xdevs[i];
11251125- struct xrt_tracking_origin *torig = xdev->tracking_origin;
11261126- uint64_t key = (uint64_t)(intptr_t)torig;
11271127- struct xrt_space *xs = NULL;
11281128-11291129- void *ptr = NULL;
11301130- u_hashmap_int_find(uso->xto_map, key, &ptr);
11311131-11321132- if (ptr != NULL) {
11331133- xs = (struct xrt_space *)ptr;
11341134- } else {
11351135- u_space_overseer_create_offset_space(uso, root, &torig->initial_offset, &xs);
11361136- u_hashmap_int_insert(uso->xto_map, key, xs);
11851185+ xrt_result_t xret = add_device_helper(uso, xdevs[i]);
11861186+ if (xret != XRT_SUCCESS) {
11871187+ U_LOG_E("Failed to add device '%s' to space overseer!", xdevs[i]->str);
11371188 }
11381138-11391139- u_space_overseer_link_space_to_device(uso, xs, xdev);
11401189 }
1141119011421191 // If these are set something is probably wrong, but just in case unset them.
+47
src/xrt/include/xrt/xrt_space.h
···11// Copyright 2019-2023, Collabora, Ltd.
22+// Copyright 2025, NVIDIA CORPORATION.
23// SPDX-License-Identifier: BSL-1.0
34/*!
45 * @file
···303304 struct xrt_space **out_local_space,
304305 struct xrt_space **out_local_floor_space);
305306307307+ /*
308308+ *
309309+ * Special inter-monado component functions.
310310+ *
311311+ */
312312+313313+ /*!
314314+ * Add a new device to be tracked by the space overseer. The exact
315315+ * semantic of the space is determined by the implementation of the
316316+ * space overseer. And may be outright rejected by the implementation.
317317+ *
318318+ * After this call completes successfully, the device can be passed
319319+ * into the @ref xrt_space_overseer::locate_device function, but may
320320+ * not be locatable immediately.
321321+ *
322322+ * This function is not intended to be called by the OpenXR state
323323+ * tracker, but by other monado components that need to add devices
324324+ * but does not own the space overseer. Components like the fixer
325325+ * uppers or for push devices.
326326+ *
327327+ * @param[in] xso The space overseer.
328328+ * @param[in] xdev The device to be tracked.
329329+ * @return XRT_SUCCESS if added, otherwise an error code.
330330+ */
331331+ xrt_result_t (*add_device)(struct xrt_space_overseer *xso, struct xrt_device *xdev);
332332+333333+334334+ /*
335335+ *
336336+ * Destroy function always comes last.
337337+ *
338338+ */
339339+306340 /*!
307341 * Destroy function.
308342 *
···513547 struct xrt_space **out_local_floor_space)
514548{
515549 return xso->create_local_space(xso, out_local_space, out_local_floor_space);
550550+}
551551+552552+/*!
553553+ * @copydoc xrt_space_overseer::add_device
554554+ *
555555+ * Helper for calling through the function pointer.
556556+ *
557557+ * @public @memberof xrt_space_overseer
558558+ */
559559+static inline xrt_result_t
560560+xrt_space_overseer_add_device(struct xrt_space_overseer *xso, struct xrt_device *xdev)
561561+{
562562+ return xso->add_device(xso, xdev);
516563}
517564518565/*!