Something went wrong. Try again.
The open source OpenXR runtime
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479// Copyright 2025-2026, NVIDIA CORPORATION.// SPDX-License-Identifier: BSL-1.0/*! * @file * @brief Tracking objects to IDs. * @author Jakob Bornecrantz <tbornecrantz@nvidia.com> * @ingroup ipc_server */
#include "xrt/xrt_device.h"#include "xrt/xrt_tracking.h"#include "xrt/xrt_space.h"#include "xrt/xrt_body_tracker.h"#include "xrt/xrt_hand_tracker.h"
#include "shared/ipc_protocol.h"#include "server/ipc_server.h"#include "server/ipc_server_objects.h"
#include <assert.h>#include <string.h>
/* * * Device functions. * */
xrt_result_tipc_server_objects_get_xdev_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_device **out_xdev){ if (id >= XRT_SYSTEM_MAX_DEVICES) { IPC_ERROR(ics->server, "Invalid device ID %u (>= XRT_SYSTEM_MAX_DEVICES)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_device *xdev = ics->objects.xdevs[id]; if (xdev == NULL) { IPC_ERROR(ics->server, "Device ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xdev = xdev;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xdev_id_or_add(volatile struct ipc_client_state *ics, struct xrt_device *xdev, uint32_t *out_id){ assert(out_id != NULL); assert(xdev != NULL);
// Check if device is already tracked and return its ID. for (uint32_t index = 0; index < XRT_SYSTEM_MAX_DEVICES; index++) { if (ics->objects.xdevs[index] == xdev) { *out_id = index; return XRT_SUCCESS; } }
// If not, find a free slot for it, filled below. uint32_t index = 0; for (; index < XRT_SYSTEM_MAX_DEVICES; index++) { // Found a free slot. if (ics->objects.xdevs[index] == NULL) { break; } }
if (index >= XRT_SYSTEM_MAX_DEVICES) { IPC_ERROR(ics->server, "Failed to find available slot for device: '%s'", xdev->str); return XRT_ERROR_IPC_FAILURE; }
// Check that we can also get the tracking origin allocated. uint32_t tracking_origin_id = UINT32_MAX; xrt_result_t xret = ipc_server_objects_get_xtrack_id_or_add(ics, xdev->tracking_origin, &tracking_origin_id); IPC_CHK_AND_RET(ics->server, xret, "ipc_server_objects_get_xtrack_id_or_add");
ics->objects.xdevs[index] = xdev;
*out_id = index;
return XRT_SUCCESS;}
/* * * Tracking origin functions. * */
xrt_result_tipc_server_objects_get_xtrack_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_tracking_origin **out_xtrack){ if (id >= XRT_SYSTEM_MAX_DEVICES) { IPC_ERROR(ics->server, "Invalid tracking origin ID %u (>= XRT_SYSTEM_MAX_DEVICES)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_tracking_origin *xtrack = ics->objects.xtracks[id]; if (xtrack == NULL) { IPC_ERROR(ics->server, "Tracking origin ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xtrack = xtrack;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xtrack_id_or_add(volatile struct ipc_client_state *ics, struct xrt_tracking_origin *xtrack, uint32_t *out_id){ assert(out_id != NULL);
// Check if tracking origin is already tracked and return its ID. for (uint32_t index = 0; index < XRT_SYSTEM_MAX_DEVICES; index++) { if (ics->objects.xtracks[index] == xtrack) { *out_id = index; return XRT_SUCCESS; } }
// If not, find a free slot for it, filled below. for (uint32_t index = 0; index < XRT_SYSTEM_MAX_DEVICES; index++) { if (ics->objects.xtracks[index] == NULL) { ics->objects.xtracks[index] = xtrack; *out_id = index; return XRT_SUCCESS; } }
IPC_ERROR(ics->server, "Failed to find available slot for tracking origin: '%s'", xtrack->name);
return XRT_ERROR_IPC_FAILURE;}
/* * * Space functions. * */
xrt_result_tipc_server_objects_get_xspc_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_space **out_xspc){ if (id >= IPC_MAX_CLIENT_SPACES) { IPC_ERROR(ics->server, "Invalid space ID %u (>= IPC_MAX_CLIENT_SPACES)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_space *xspc = ics->xspcs[id]; if (xspc == NULL) { IPC_ERROR(ics->server, "Space ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xspc = xspc;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xspc_id_or_add(volatile struct ipc_client_state *ics, struct xrt_space *xspc, uint32_t *out_id){ assert(out_id != NULL); assert(xspc != NULL);
// Check if space is already tracked and return its ID. for (uint32_t index = 0; index < IPC_MAX_CLIENT_SPACES; index++) { if (ics->xspcs[index] == xspc) { *out_id = index; return XRT_SUCCESS; } }
// If not, find a free slot for it, filled below. for (uint32_t index = 0; index < IPC_MAX_CLIENT_SPACES; index++) { if (ics->xspcs[index] == NULL) { struct xrt_space **xspc_ptr = (struct xrt_space **)&ics->xspcs[index]; xrt_space_reference(xspc_ptr, xspc); *out_id = index; return XRT_SUCCESS; } }
IPC_ERROR(ics->server, "Failed to find available slot for space"); return XRT_ERROR_IPC_FAILURE;}
xrt_result_tipc_server_objects_destroy_xspc(volatile struct ipc_client_state *ics, uint32_t id){ if (id >= IPC_MAX_CLIENT_SPACES) { IPC_ERROR(ics->server, "Invalid space ID %u (>= IPC_MAX_CLIENT_SPACES)", id); return XRT_ERROR_IPC_FAILURE; }
if (ics->xspcs[id] == NULL) { IPC_ERROR(ics->server, "Client tried to destroy non-existent space!"); return XRT_ERROR_IPC_FAILURE; }
struct xrt_space **xspc_ptr = (struct xrt_space **)&ics->xspcs[id]; xrt_space_reference(xspc_ptr, NULL);
return XRT_SUCCESS;}
/* * * Body tracker functions. * */
xrt_result_tipc_server_objects_get_xbt_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_body_tracker **out_xbt){ if (id >= IPC_MAX_CLIENT_BODY_TRACKERS) { IPC_ERROR(ics->server, "Invalid body tracker ID %u (>= IPC_MAX_CLIENT_BODY_TRACKERS)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_body_tracker *xbt = ics->objects.xbts[id]; if (xbt == NULL) { IPC_ERROR(ics->server, "Body tracker ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xbt = xbt;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xbt_id_or_add(volatile struct ipc_client_state *ics, struct xrt_body_tracker *xbt, uint32_t *out_id){ assert(out_id != NULL); assert(xbt != NULL);
for (uint32_t index = 0; index < IPC_MAX_CLIENT_BODY_TRACKERS; index++) { if (ics->objects.xbts[index] == NULL) { ics->objects.xbts[index] = xbt; *out_id = index; return XRT_SUCCESS; } }
IPC_ERROR(ics->server, "Failed to find available slot for body tracker"); return XRT_ERROR_IPC_FAILURE;}
xrt_result_tipc_server_objects_destroy_xbt(volatile struct ipc_client_state *ics, uint32_t id){ if (id >= IPC_MAX_CLIENT_BODY_TRACKERS) { IPC_ERROR(ics->server, "Invalid body tracker ID %u (>= IPC_MAX_CLIENT_BODY_TRACKERS)", id); return XRT_ERROR_IPC_FAILURE; }
if (ics->objects.xbts[id] == NULL) { IPC_ERROR(ics->server, "Client tried to destroy non-existent body tracker!"); return XRT_ERROR_IPC_FAILURE; }
xrt_body_tracker_destroy((struct xrt_body_tracker **)&ics->objects.xbts[id]);
return XRT_SUCCESS;}
/* * * Hand tracker functions. * */
xrt_result_tipc_server_objects_get_xht_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_hand_tracker **out_xht){ if (id >= IPC_MAX_CLIENT_HAND_TRACKERS) { IPC_ERROR(ics->server, "Invalid hand tracker ID %u (>= IPC_MAX_CLIENT_HAND_TRACKERS)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_hand_tracker *xht = ics->objects.xhts[id]; if (xht == NULL) { IPC_ERROR(ics->server, "Hand tracker ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xht = xht;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xht_id_or_add(volatile struct ipc_client_state *ics, struct xrt_hand_tracker *xht, uint32_t *out_id){ assert(out_id != NULL); assert(xht != NULL);
for (uint32_t index = 0; index < IPC_MAX_CLIENT_HAND_TRACKERS; index++) { if (ics->objects.xhts[index] == NULL) { ics->objects.xhts[index] = xht; *out_id = index; return XRT_SUCCESS; } }
IPC_ERROR(ics->server, "Failed to find available slot for hand tracker"); return XRT_ERROR_IPC_FAILURE;}
xrt_result_tipc_server_objects_destroy_xht(volatile struct ipc_client_state *ics, uint32_t id){ if (id >= IPC_MAX_CLIENT_HAND_TRACKERS) { IPC_ERROR(ics->server, "Invalid hand tracker ID %u (>= IPC_MAX_CLIENT_HAND_TRACKERS)", id); return XRT_ERROR_IPC_FAILURE; }
if (ics->objects.xhts[id] == NULL) { IPC_ERROR(ics->server, "Client tried to destroy non-existent hand tracker!"); return XRT_ERROR_IPC_FAILURE; }
xrt_hand_tracker_destroy((struct xrt_hand_tracker **)&ics->objects.xhts[id]);
return XRT_SUCCESS;}
/* * * App policy functions. * */
xrt_result_tipc_server_objects_get_xainst_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_app_instance **out_xainst){ if (id >= IPC_MAX_CLIENT_APP_INSTANCES) { IPC_ERROR(ics->server, "Invalid app instance ID %u (>= IPC_MAX_CLIENT_APP_INSTANCES)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_app_instance *xainst = ics->objects.xainsts[id]; if (xainst == NULL) { IPC_ERROR(ics->server, "App instance ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xainst = xainst;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xainst_id_or_add(volatile struct ipc_client_state *ics, struct xrt_app_instance *xainst, uint32_t *out_id){ assert(out_id != NULL); assert(xainst != NULL);
for (uint32_t index = 0; index < IPC_MAX_CLIENT_APP_INSTANCES; index++) { if (ics->objects.xainsts[index] == NULL) { ics->objects.xainsts[index] = xainst; *out_id = index; return XRT_SUCCESS; } }
IPC_ERROR(ics->server, "Failed to find available slot for app instance"); return XRT_ERROR_IPC_FAILURE;}
xrt_result_tipc_server_objects_destroy_xainst(volatile struct ipc_client_state *ics, uint32_t id){ if (id >= IPC_MAX_CLIENT_APP_INSTANCES) { IPC_ERROR(ics->server, "Invalid app instance ID %u (>= IPC_MAX_CLIENT_APP_INSTANCES)", id); return XRT_ERROR_IPC_FAILURE; }
if (ics->objects.xainsts[id] == NULL) { IPC_ERROR(ics->server, "Client tried to destroy non-existent app instance!"); return XRT_ERROR_IPC_FAILURE; }
xrt_app_instance_destroy((struct xrt_app_instance **)&ics->objects.xainsts[id]);
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xasys_and_validate(volatile struct ipc_client_state *ics, uint32_t id, struct xrt_app_system **out_xasys){ if (id >= IPC_MAX_CLIENT_APP_SYSTEMS) { IPC_ERROR(ics->server, "Invalid app system ID %u (>= IPC_MAX_CLIENT_APP_SYSTEMS)", id); return XRT_ERROR_IPC_FAILURE; }
struct xrt_app_system *xasys = ics->objects.xasys[id]; if (xasys == NULL) { IPC_ERROR(ics->server, "App system ID %u not found (NULL)", id); return XRT_ERROR_IPC_FAILURE; }
*out_xasys = xasys;
return XRT_SUCCESS;}
xrt_result_tipc_server_objects_get_xasys_id_or_add(volatile struct ipc_client_state *ics, struct xrt_app_system *xasys, uint32_t *out_id){ assert(out_id != NULL); assert(xasys != NULL);
for (uint32_t index = 0; index < IPC_MAX_CLIENT_APP_SYSTEMS; index++) { if (ics->objects.xasys[index] == NULL) { ics->objects.xasys[index] = xasys; *out_id = index; return XRT_SUCCESS; } }
IPC_ERROR(ics->server, "Failed to find available slot for app system"); return XRT_ERROR_IPC_FAILURE;}
xrt_result_tipc_server_objects_destroy_xasys(volatile struct ipc_client_state *ics, uint32_t id){ if (id >= IPC_MAX_CLIENT_APP_SYSTEMS) { IPC_ERROR(ics->server, "Invalid app system ID %u (>= IPC_MAX_CLIENT_APP_SYSTEMS)", id); return XRT_ERROR_IPC_FAILURE; }
if (ics->objects.xasys[id] == NULL) { IPC_ERROR(ics->server, "Client tried to destroy non-existent app system!"); return XRT_ERROR_IPC_FAILURE; }
xrt_app_system_destroy((struct xrt_app_system **)&ics->objects.xasys[id]);
return XRT_SUCCESS;}