ipc: Get tracking origins ready to be hot-addable

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2628>
This commit is contained in:
Jakob Bornecrantz authored and Marge Bot committed 2026-01-30 12:15:49 +00:00
1 parent 16f43e9734
commit 4a65e88e68
17 files changed
+582 -145

No files matched your search

+5 -1
View File
@@ -1,5 +1,5 @@
# Copyright 2020-2021, Collabora, Ltd.
# Copyright 2025, NVIDIA CORPORATION.
# Copyright 2025-2026, NVIDIA CORPORATION.
# SPDX-License-Identifier: BSL-1.0
###
@@ -100,6 +100,8 @@ add_library(
client/ipc_client_space_overseer.c
client/ipc_client_system.c
client/ipc_client_system_devices.c
client/ipc_client_tracking_origin.c
client/ipc_client_tracking_origin.h
client/ipc_client_xdev.c
client/ipc_client_xdev.h
)
@@ -133,6 +135,8 @@ add_library(
server/ipc_server_handler.c
server/ipc_server_per_client_thread.c
server/ipc_server_process.c
server/ipc_server_objects.c
server/ipc_server_objects.h
)
target_include_directories(
ipc_server
+5 -4
View File
@@ -1,5 +1,5 @@
// Copyright 2020-2023, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -23,6 +23,8 @@
#include "shared/ipc_protocol.h"
#include "shared/ipc_message_channel.h"
#include "ipc_client_tracking_origin.h"
#include <stdio.h>
@@ -82,9 +84,8 @@ struct ipc_client_system_devices
//! Connection to service.
struct ipc_connection *ipc_c;
struct xrt_tracking_origin *xtracks[XRT_SYSTEM_MAX_DEVICES];
size_t xtrack_count;
//! Tracking origin manager for on-demand fetching
struct ipc_client_tracking_origin_manager tracking_origin_manager;
struct xrt_reference feature_use[XRT_DEVICE_FEATURE_MAX_ENUM];
};
+19 -23
View File
@@ -1,5 +1,5 @@
// Copyright 2020-2024, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -31,6 +31,7 @@
#include "client/ipc_client.h"
#include "client/ipc_client_interface.h"
#include "client/ipc_client_connection.h"
#include "client/ipc_client_tracking_origin.h"
#include "ipc_client_generated.h"
@@ -163,32 +164,27 @@ ipc_client_instance_create_system(struct xrt_instance *xinst,
struct xrt_system_devices *xsysd = &icsd->base.base;
uint32_t count = 0;
struct xrt_tracking_origin *xtrack = NULL;
struct ipc_shared_memory *ism = ii->ipc_c.ism;
// Query the server for how many tracking origins it has.
count = 0;
for (uint32_t i = 0; i < ism->itrack_count; i++) {
xtrack = U_TYPED_CALLOC(struct xrt_tracking_origin);
memcpy(xtrack->name, ism->itracks[i].name, sizeof(xtrack->name));
xtrack->type = ism->itracks[i].type;
xtrack->initial_offset = ism->itracks[i].offset;
icsd->xtracks[count++] = xtrack;
u_var_add_root(xtrack, "Tracking origin", true);
u_var_add_ro_text(xtrack, xtrack->name, "name");
u_var_add_pose(xtrack, &xtrack->initial_offset, "offset");
}
icsd->xtrack_count = count;
// Query the server for how many devices it has.
count = 0;
// Query the server for how many devices it has and create them.
uint32_t count = 0;
for (uint32_t i = 0; i < ism->isdev_count; i++) {
struct ipc_shared_device *isdev = &ism->isdevs[i];
xtrack = icsd->xtracks[isdev->tracking_origin_index];
// Get tracking origin from manager (fetches on-demand)
struct xrt_tracking_origin *xtrack = NULL;
xret = ipc_client_tracking_origin_manager_get(&icsd->tracking_origin_manager, isdev->tracking_origin_id,
&xtrack);
if (xret != XRT_SUCCESS) {
IPC_ERROR(&ii->ipc_c, "Failed to get tracking origin for device %u (id %u)", i,
isdev->tracking_origin_id);
continue;
}
if (xtrack == NULL) {
IPC_ERROR(&ii->ipc_c, "Tracking origin for device %u (id %u) is NULL", i,
isdev->tracking_origin_id);
continue;
}
if (isdev->device_type == XRT_DEVICE_TYPE_HMD) {
xsysd->xdevs[count++] = ipc_client_hmd_create(&ii->ipc_c, xtrack, i);
+13 -7
View File
@@ -1,5 +1,5 @@
// Copyright 2023, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -10,6 +10,7 @@
*/
#include "ipc_client.h"
#include "ipc_client_tracking_origin.h"
#include "ipc_client_generated.h"
#include "util/u_system_helpers.h"
@@ -83,12 +84,8 @@ ipc_client_system_devices_destroy(struct xrt_system_devices *xsysd)
{
struct ipc_client_system_devices *usysd = ipc_system_devices(xsysd);
for (size_t i = 0; i < usysd->xtrack_count; i++) {
u_var_remove_root(usysd->xtracks[i]);
free(usysd->xtracks[i]);
usysd->xtracks[i] = NULL;
}
usysd->xtrack_count = 0;
// Finalize the tracking origin manager (which cleans up all cached tracking origins)
ipc_client_tracking_origin_manager_fini(&usysd->tracking_origin_manager);
u_system_devices_close(&usysd->base.base);
@@ -112,7 +109,16 @@ ipc_client_system_devices_create(struct ipc_connection *ipc_c, struct ipc_client
icsd->base.base.feature_dec = ipc_client_system_devices_feature_dec;
icsd->ipc_c = ipc_c;
// Initialize tracking origin manager
xrt_result_t xret = ipc_client_tracking_origin_manager_init(&icsd->tracking_origin_manager, ipc_c);
IPC_CHK_WITH_GOTO(ipc_c, xret, "ipc_client_tracking_origin_manager_init", err_free);
*out_icsd = icsd;
return XRT_SUCCESS;
err_free:
free(icsd);
return xret;
}
@@ -0,0 +1,127 @@
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief IPC Client tracking origin management.
* @author Jakob Bornecrantz <tbornecrantz@nvidia.com>
* @ingroup ipc_client
*/
#include "xrt/xrt_defines.h"
#include "xrt/xrt_tracking.h"
#include "util/u_misc.h"
#include "util/u_var.h"
#include "util/u_hashmap.h"
#include <assert.h>
#include "shared/ipc_message_channel.h"
#include "shared/ipc_protocol.h"
#include "client/ipc_client.h"
#include "client/ipc_client_connection.h"
#include "client/ipc_client_tracking_origin.h"
#include "ipc_client_generated.h"
/*
*
* Helper functions
*
*/
static void
tracking_origin_cleanup_callback(void *item, void *priv)
{
struct xrt_tracking_origin *xtrack = (struct xrt_tracking_origin *)item;
// Remove from variable tracking
u_var_remove_root(xtrack);
// Free the tracking origin
free(xtrack);
}
/*
*
* Exported functions
*
*/
xrt_result_t
ipc_client_tracking_origin_manager_init(struct ipc_client_tracking_origin_manager *manager,
struct ipc_connection *ipc_c)
{
assert(manager != NULL);
assert(ipc_c != NULL);
manager->ipc_c = ipc_c;
manager->tracking_origin_map = NULL;
int ret = u_hashmap_int_create(&manager->tracking_origin_map);
if (ret != 0) {
IPC_ERROR(ipc_c, "Failed to create tracking origin hashmap");
return XRT_ERROR_ALLOCATION;
}
return XRT_SUCCESS;
}
xrt_result_t
ipc_client_tracking_origin_manager_get(struct ipc_client_tracking_origin_manager *manager,
uint32_t tracking_origin_id,
struct xrt_tracking_origin **out_xtrack)
{
// Check if we already have this tracking origin cached
void *cached_xtrack = NULL;
int ret = u_hashmap_int_find(manager->tracking_origin_map, tracking_origin_id, &cached_xtrack);
if (ret == 0) {
// Found in cache
*out_xtrack = (struct xrt_tracking_origin *)cached_xtrack;
return XRT_SUCCESS;
}
// Not in cache, fetch from server
struct ipc_tracking_origin_info info;
xrt_result_t xret = ipc_call_tracking_origin_get_info(manager->ipc_c, tracking_origin_id, &info);
IPC_CHK_AND_RET(manager->ipc_c, xret, "ipc_call_tracking_origin_get_info");
// Create a new tracking origin
struct xrt_tracking_origin *xtrack = U_TYPED_CALLOC(struct xrt_tracking_origin);
memcpy(xtrack->name, info.name, sizeof(xtrack->name));
xtrack->type = info.type;
xtrack->initial_offset = info.offset;
// Add to variable tracking
u_var_add_root(xtrack, "Tracking origin", true);
u_var_add_ro_text(xtrack, xtrack->name, "name");
u_var_add_pose(xtrack, &xtrack->initial_offset, "offset");
// Store in cache
u_hashmap_int_insert(manager->tracking_origin_map, tracking_origin_id, xtrack);
*out_xtrack = xtrack;
return XRT_SUCCESS;
}
void
ipc_client_tracking_origin_manager_fini(struct ipc_client_tracking_origin_manager *manager)
{
assert(manager != NULL);
assert(manager->ipc_c != NULL);
// Clean up all cached tracking origins
if (manager->tracking_origin_map != NULL) {
u_hashmap_int_clear_and_call_for_each(manager->tracking_origin_map, tracking_origin_cleanup_callback,
NULL);
u_hashmap_int_destroy(&manager->tracking_origin_map);
manager->tracking_origin_map = NULL;
}
manager->ipc_c = NULL;
}
@@ -0,0 +1,70 @@
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief IPC Client tracking origin management.
* @author Jakob Bornecrantz <tbornecrantz@nvidia.com>
* @ingroup ipc_client
*/
#pragma once
#include "xrt/xrt_tracking.h"
#include "util/u_hashmap.h"
#ifdef __cplusplus
extern "C" {
#endif
struct ipc_connection;
/*!
* Tracking origin manager for IPC client.
*
* Maintains a hashmap of tracking origin IDs to xrt_tracking_origin objects.
* Fetches tracking origin info from the server on-demand.
*
* @ingroup ipc_client
*/
struct ipc_client_tracking_origin_manager
{
//! Connection to the IPC server
struct ipc_connection *ipc_c;
//! Hashmap from tracking_origin_id to xrt_tracking_origin*
struct u_hashmap_int *tracking_origin_map;
};
/*!
* Initialize a tracking origin manager.
*
* @ingroup ipc_client
*/
xrt_result_t
ipc_client_tracking_origin_manager_init(struct ipc_client_tracking_origin_manager *manager,
struct ipc_connection *ipc_c);
/*!
* Get a tracking origin by ID. If not already cached, fetches it from the server.
*
* @ingroup ipc_client
*/
xrt_result_t
ipc_client_tracking_origin_manager_get(struct ipc_client_tracking_origin_manager *manager,
uint32_t tracking_origin_id,
struct xrt_tracking_origin **out_xtrack);
/*!
* Finalize the tracking origin manager and all cached tracking origins.
*
* @ingroup ipc_client
*/
void
ipc_client_tracking_origin_manager_fini(struct ipc_client_tracking_origin_manager *manager);
#ifdef __cplusplus
}
#endif
+14 -2
View File
@@ -1,5 +1,5 @@
// Copyright 2020-2023, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -20,6 +20,7 @@
#include "os/os_threading.h"
#include "util/u_logging.h"
#include "util/u_hashmap.h"
#include "shared/ipc_protocol.h"
#include "shared/ipc_message_channel.h"
@@ -96,6 +97,18 @@ struct ipc_client_state
//! Has the system part of the shm initialized.
bool has_init_shm_system;
struct
{
/*!
* Array of tracking origins.
*
* We don't control the lifetime of the tracking origins,
* and we only access it from the per client thread,
* so we don't need to lock it.
*/
struct xrt_tracking_origin *xtracks[XRT_SYSTEM_MAX_DEVICES];
} objects;
//! Session for this client.
struct xrt_session *xs;
@@ -370,7 +383,6 @@ struct ipc_server
struct xrt_system_compositor *xsysc;
struct ipc_device idevs[XRT_SYSTEM_MAX_DEVICES];
struct xrt_tracking_origin *xtracks[XRT_SYSTEM_MAX_DEVICES];
struct ipc_shared_memory *isms[IPC_MAX_CLIENTS];
+56 -31
View File
@@ -1,5 +1,5 @@
// Copyright 2020-2024, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -17,6 +17,7 @@
#include "util/u_trace_marker.h"
#include "server/ipc_server.h"
#include "server/ipc_server_objects.h"
#include "ipc_server_generated.h"
#include "xrt/xrt_device.h"
#include "xrt/xrt_results.h"
@@ -32,6 +33,12 @@
*
*/
#define GET_XTRACK_OR_RETURN(ICS, ID, XTRACK) \
do { \
xrt_result_t xret = ipc_server_objects_get_xtrack_and_validate((ICS), ID, &(XTRACK)); \
IPC_CHK_AND_RET((ICS)->server, xret, "ipc_server_objects_get_xtrack_and_validate"); \
} while (0)
static xrt_result_t
validate_device_id(volatile struct ipc_client_state *ics, int64_t device_id, struct xrt_device **out_device)
{
@@ -59,26 +66,6 @@ validate_device_id(volatile struct ipc_client_state *ics, int64_t device_id, str
} \
} while (0)
static xrt_result_t
validate_origin_id(volatile struct ipc_client_state *ics, int64_t origin_id, struct xrt_tracking_origin **out_xtrack)
{
if (origin_id >= XRT_SYSTEM_MAX_DEVICES) {
IPC_ERROR(ics->server, "Invalid origin ID (origin_id >= XRT_SYSTEM_MAX_DEVICES)!");
return XRT_ERROR_IPC_FAILURE;
}
struct xrt_tracking_origin *xtrack = ics->server->xtracks[origin_id];
if (xtrack == NULL) {
IPC_ERROR(ics->server, "Invalid origin ID (xtrack is NULL)!");
return XRT_ERROR_IPC_FAILURE;
}
*out_xtrack = xtrack;
return XRT_SUCCESS;
}
static xrt_result_t
validate_swapchain_state(volatile struct ipc_client_state *ics, uint32_t *out_index)
{
@@ -946,11 +933,9 @@ ipc_handle_space_get_tracking_origin_offset(volatile struct ipc_client_state *ic
struct xrt_pose *out_offset)
{
struct xrt_space_overseer *xso = ics->server->xso;
struct xrt_tracking_origin *xto;
xrt_result_t xret = validate_origin_id(ics, origin_id, &xto);
if (xret != XRT_SUCCESS) {
return xret;
}
struct xrt_tracking_origin *xto = NULL;
GET_XTRACK_OR_RETURN(ics, origin_id, xto);
return xrt_space_overseer_get_tracking_origin_offset(xso, xto, out_offset);
}
@@ -960,11 +945,9 @@ ipc_handle_space_set_tracking_origin_offset(volatile struct ipc_client_state *ic
const struct xrt_pose *offset)
{
struct xrt_space_overseer *xso = ics->server->xso;
struct xrt_tracking_origin *xto;
xrt_result_t xret = validate_origin_id(ics, origin_id, &xto);
if (xret != XRT_SUCCESS) {
return xret;
}
struct xrt_tracking_origin *xto = NULL;
GET_XTRACK_OR_RETURN(ics, origin_id, xto);
return xrt_space_overseer_set_tracking_origin_offset(xso, xto, offset);
}
@@ -1922,6 +1905,48 @@ ipc_handle_compositor_semaphore_destroy(volatile struct ipc_client_state *ics, u
}
/*
*
* Tracking origin functions.
*
*/
xrt_result_t
ipc_handle_tracking_origin_get_list(volatile struct ipc_client_state *ics, struct ipc_tracking_origin_list *out_list)
{
// Count and collect origin IDs.
uint32_t count = 0;
for (uint32_t i = 0; i < XRT_SYSTEM_MAX_DEVICES; i++) {
struct xrt_tracking_origin *xtrack = ics->objects.xtracks[i];
if (xtrack != NULL) {
out_list->origins[count].id = i;
count++;
}
}
out_list->origin_count = count;
return XRT_SUCCESS;
}
xrt_result_t
ipc_handle_tracking_origin_get_info(volatile struct ipc_client_state *ics,
uint32_t tracking_origin_id,
struct ipc_tracking_origin_info *out_info)
{
// Validate the tracking origin ID and get the tracking origin
struct xrt_tracking_origin *xtrack = NULL;
GET_XTRACK_OR_RETURN(ics, tracking_origin_id, xtrack);
// Copy tracking origin info to output
memcpy(out_info->name, xtrack->name, sizeof(out_info->name));
out_info->type = xtrack->type;
out_info->offset = xtrack->initial_offset;
return XRT_SUCCESS;
}
/*
*
* Device functions.
+67
View File
@@ -0,0 +1,67 @@
// 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_tracking.h"
#include "ipc_server.h"
#include "ipc_server_objects.h"
/*
*
* Tracking origin functions.
*
*/
xrt_result_t
ipc_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_t
ipc_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);
// Find the next available slot in xtracks array and assign an ID, or if we find the xtrack return it.
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;
}
if (ics->objects.xtracks[index] == xtrack) {
*out_id = index;
return XRT_SUCCESS;
}
}
// No available slot or xtrack found
IPC_ERROR(ics->server, "Failed to find available slot for tracking origin: '%s'", xtrack->name);
return XRT_ERROR_IPC_FAILURE;
}
+48
View File
@@ -0,0 +1,48 @@
// 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
*/
#pragma once
#include "xrt/xrt_results.h"
struct ipc_client_state;
/*!
* Get a tracking origin by ID, must only be called from the per client
* thread as this function accesses the client state's memory.
*
* @param ics The client state instance.
* @param id The tracking origin ID.
* @param out_xtrack Will be filled with the tracking origin object on success.
* @return XRT_SUCCESS on success, some other result on failure.
*
* @ingroup ipc_server
*/
xrt_result_t
ipc_server_objects_get_xtrack_and_validate(volatile struct ipc_client_state *ics,
uint32_t id,
struct xrt_tracking_origin **out_xtrack);
/*!
* Get a tracking origin ID for a given tracking origin object, must only be
* called from the per client thread as this function accesses the client
* state's memory.
*
* @param ics The client state instance.
* @param xtrack The tracking origin object.
* @param out_id Will be filled with the tracking origin ID on success.
* @return XRT_SUCCESS on success, some other result on failure.
*
* @ingroup ipc_server
*/
xrt_result_t
ipc_server_objects_get_xtrack_id_or_add(volatile struct ipc_client_state *ics,
struct xrt_tracking_origin *xtrack,
uint32_t *out_id);
@@ -1,5 +1,5 @@
// Copyright 2020-2023, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -133,6 +133,15 @@ common_shutdown(volatile struct ipc_client_state *ics)
ics->device_feature_used[i] = false;
}
// Clear the tracking origins array.
for (uint32_t i = 0; i < XRT_SYSTEM_MAX_DEVICES; i++) {
/*
* We don't control the lifetime of the tracking origins,
* so we just set the pointer to NULL.
*/
ics->objects.xtracks[i] = NULL;
}
// Make sure undestroyed plane detections are cleaned up
for (uint32_t i = 0; i < ics->plane_detection_count; i++) {
xrt_device_destroy_plane_detection_ext(ics->plane_detection_xdev[i], ics->plane_detection_ids[i]);
+20 -42
View File
@@ -1,5 +1,5 @@
// Copyright 2020-2024, Collabora, Ltd.
// Copyright 2024-2025, NVIDIA CORPORATION.
// Copyright 2024-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -33,6 +33,7 @@
#include "shared/ipc_protocol.h"
#include "shared/ipc_shmem.h"
#include "server/ipc_server.h"
#include "server/ipc_server_objects.h"
#include "server/ipc_server_interface.h"
#include <stdlib.h>
@@ -218,8 +219,10 @@ teardown_all(struct ipc_server *s)
}
static void
init_tracking_origins(struct ipc_server *s)
init_tracking_origins(volatile struct ipc_client_state *ics)
{
struct ipc_server *s = ics->server;
for (size_t i = 0; i < XRT_SYSTEM_MAX_DEVICES; i++) {
struct xrt_device *xdev = s->idevs[i].xdev;
if (xdev == NULL) {
@@ -228,16 +231,13 @@ init_tracking_origins(struct ipc_server *s)
struct xrt_tracking_origin *xtrack = xdev->tracking_origin;
assert(xtrack != NULL);
size_t index = 0;
for (; index < XRT_SYSTEM_MAX_DEVICES; index++) {
if (s->xtracks[index] == NULL) {
s->xtracks[index] = xtrack;
break;
}
if (s->xtracks[index] == xtrack) {
break;
}
// Get or add tracking origin ID
uint32_t tracking_origin_id = 0;
xrt_result_t xret = ipc_server_objects_get_xtrack_id_or_add(ics, xtrack, &tracking_origin_id);
if (xret != XRT_SUCCESS) {
IPC_ERROR(s, "Failed to get/add tracking origin ID for: '%s'", xtrack->name);
continue;
}
}
}
@@ -318,25 +318,8 @@ init_system_shm_state(struct ipc_server *s, volatile struct ipc_client_state *cs
uint32_t count = 0;
struct ipc_shared_memory *ism = s->isms[cs->server_thread_index];
// Setup the tracking origins.
count = 0;
for (size_t i = 0; i < XRT_SYSTEM_MAX_DEVICES; i++) {
struct xrt_tracking_origin *xtrack = s->xtracks[i];
if (xtrack == NULL) {
continue;
}
// The position of the tracking origin matches that in the
// server's memory.
assert(i < XRT_SYSTEM_MAX_DEVICES);
struct ipc_shared_tracking_origin *itrack = &ism->itracks[count++];
memcpy(itrack->name, xtrack->name, sizeof(itrack->name));
itrack->type = xtrack->type;
itrack->offset = xtrack->initial_offset;
}
ism->itrack_count = count;
// Tracking origins are no longer copied to shared memory.
// They are fetched on-demand via IPC calls.
count = 0;
uint32_t input_index = 0;
@@ -361,18 +344,13 @@ init_system_shm_state(struct ipc_server *s, volatile struct ipc_client_state *cs
isdev->device_type = xdev->device_type;
isdev->supported = xdev->supported;
// Setup the tracking origin.
isdev->tracking_origin_index = (uint32_t)-1;
for (uint32_t k = 0; k < XRT_SYSTEM_MAX_DEVICES; k++) {
if (xdev->tracking_origin != s->xtracks[k]) {
continue;
}
// Setup the tracking origin ID.
uint32_t tracking_origin_id = UINT32_MAX;
xrt_result_t xret =
ipc_server_objects_get_xtrack_id_or_add(cs, xdev->tracking_origin, &tracking_origin_id);
assert(xret == XRT_SUCCESS);
isdev->tracking_origin_index = k;
break;
}
assert(isdev->tracking_origin_index != (uint32_t)-1);
isdev->tracking_origin_id = tracking_origin_id;
// Initial update.
xrt_device_update_inputs(xdev);
@@ -843,11 +821,11 @@ ipc_server_init_system_if_available_locked(struct ipc_server *s,
// Always succeeds.
init_idevs(s);
init_tracking_origins(s);
}
}
if (available && ics != NULL && !ics->has_init_shm_system) {
init_tracking_origins(ics);
init_system_shm_state(s, ics);
ics->has_init_shm_system = true;
}
+28 -15
View File
@@ -1,5 +1,5 @@
// Copyright 2020-2024 Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -59,12 +59,37 @@ typedef int pid_t;
*
*/
/*!
* Information about a device in the device list.
*
* @ingroup ipc
*/
struct ipc_tracking_origin_list_entry
{
//! Tracking origin ID
uint32_t id;
};
/*!
* A list of the current tracking origins.
*
* @ingroup ipc
*/
struct ipc_tracking_origin_list
{
//! Number of tracking origins.
uint32_t origin_count;
//! Compact list of tracking origins.
struct ipc_tracking_origin_list_entry origins[XRT_SYSTEM_MAX_DEVICES];
};
/*!
* A tracking in the shared memory area.
*
* @ingroup ipc
*/
struct ipc_shared_tracking_origin
struct ipc_tracking_origin_info
{
//! For debugging.
char name[XRT_TRACKING_NAME_LEN];
@@ -108,7 +133,7 @@ struct ipc_shared_device
enum xrt_device_type device_type;
//! Which tracking system origin is this device attached to.
uint32_t tracking_origin_index;
uint32_t tracking_origin_id;
//! A string describing the device.
char str[XRT_DEVICE_NAME_LEN];
@@ -195,18 +220,6 @@ struct ipc_shared_memory
*/
char u_git_tag[IPC_VERSION_NAME_LEN];
/*!
* Number of elements in @ref itracks that are populated/valid.
*/
uint32_t itrack_count;
/*!
* @brief Array of shared tracking origin data.
*
* Only @ref itrack_count elements are populated/valid.
*/
struct ipc_shared_tracking_origin itracks[XRT_SYSTEM_MAX_DEVICES];
/*!
* Number of elements in @ref isdevs that are populated/valid.
*/
+18
View File
@@ -0,0 +1,18 @@
{
"$schema": "../proto.schema.json",
"tracking_origin_get_list": {
"out": [
{"name": "list", "type": "struct ipc_tracking_origin_list"}
]
},
"tracking_origin_get_info": {
"in": [
{"name": "tracking_origin_id", "type": "uint32_t"}
],
"out": [
{"name": "info", "type": "struct ipc_tracking_origin_info"}
]
}
}
@@ -0,0 +1,3 @@
Copyright 2025-2026, NVIDIA CORPORATION.
SPDX-License-Identifier: BSL-1.0
+72 -13
View File
@@ -1,5 +1,5 @@
// Copyright 2019-2024, Collabora, Ltd.
// Copyright 2025, NVIDIA CORPORATION.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -36,6 +36,12 @@ struct mnd_root
//! List of clients.
struct ipc_client_list clients;
//! The retrieved list of tracking origins.
struct ipc_tracking_origin_list tracking_origin_list;
//! Cached infos about tracking origins.
struct ipc_tracking_origin_info origin_infos[XRT_SYSTEM_MAX_DEVICES];
/// State of most recent app asked about
struct ipc_app_state app_state;
};
@@ -87,6 +93,14 @@ enum role_enum
} \
} while (false)
#define CHECK_ORIGIN_INDEX(INDEX) \
do { \
if (INDEX >= root->tracking_origin_list.origin_count) { \
PE("Invalid itrack index (%u)\n", INDEX); \
return MND_ERROR_INVALID_VALUE; \
} \
} while (false)
#define CHECK_DEVICE_INDEX(INDEX) \
do { \
if (INDEX >= root->ipc_c.ism->isdev_count) { \
@@ -95,6 +109,7 @@ enum role_enum
} \
} while (false)
static int
get_client_info(mnd_root_t *root, uint32_t client_id)
{
@@ -109,6 +124,28 @@ get_client_info(mnd_root_t *root, uint32_t client_id)
return MND_SUCCESS;
}
static mnd_result_t
update_tracking_origin_list_and_infos(mnd_root_t *root)
{
xrt_result_t xret = ipc_call_tracking_origin_get_list(&root->ipc_c, &root->tracking_origin_list);
if (xret != XRT_SUCCESS) {
PE("Failed ipc_call_tracking_origin_get_list '%i'", xret);
return MND_ERROR_OPERATION_FAILED;
}
for (uint32_t i = 0; i < root->tracking_origin_list.origin_count; i++) {
uint32_t id = root->tracking_origin_list.origins[i].id;
xret = ipc_call_tracking_origin_get_info(&root->ipc_c, id, &root->origin_infos[i]);
if (xret != XRT_SUCCESS) {
PE("Failed ipc_call_tracking_origin_get_list '%i'", xret);
return MND_ERROR_OPERATION_FAILED;
}
}
return MND_SUCCESS;
}
/*
*
@@ -158,6 +195,12 @@ mnd_root_create(mnd_root_t **out_root)
PE("System isn't available, devices won't be available!");
}
mnd_result_t mret = update_tracking_origin_list_and_infos(r);
if (mret != MND_SUCCESS) {
mnd_root_destroy(&r);
return mret;
}
*out_root = r;
return MND_SUCCESS;
@@ -369,7 +412,15 @@ mnd_root_get_device_info_u32(mnd_root_t *root, uint32_t device_index, mnd_proper
const struct ipc_shared_device *shared_device = &root->ipc_c.ism->isdevs[device_index];
switch (prop) {
case MND_PROPERTY_TRACKING_ORIGIN_U32: *out_u32 = shared_device->tracking_origin_index; break;
case MND_PROPERTY_TRACKING_ORIGIN_U32:
for (uint32_t i = 0; i < root->tracking_origin_list.origin_count; i++) {
if (shared_device->tracking_origin_id == root->tracking_origin_list.origins[i].id) {
*out_u32 = i;
return MND_SUCCESS;
}
}
PE("Could not find tracking origin id in origins list '%u'!\n", shared_device->tracking_origin_id);
return MND_ERROR_INVALID_VALUE;
default: PE("Is not a valid u32 property (%u)", prop); return MND_ERROR_INVALID_PROPERTY;
}
@@ -538,8 +589,14 @@ mnd_root_set_reference_space_offset(mnd_root_t *root, mnd_reference_space_type_t
}
mnd_result_t
mnd_root_get_tracking_origin_offset(mnd_root_t *root, uint32_t origin_id, mnd_pose_t *out_offset)
mnd_root_get_tracking_origin_offset(mnd_root_t *root, uint32_t origin_index, mnd_pose_t *out_offset)
{
CHECK_NOT_NULL(root);
CHECK_NOT_NULL(out_offset);
CHECK_ORIGIN_INDEX(origin_index);
uint32_t origin_id = root->tracking_origin_list.origins[origin_index].id;
xrt_result_t xret =
ipc_call_space_get_tracking_origin_offset(&root->ipc_c, origin_id, (struct xrt_pose *)out_offset);
switch (xret) {
@@ -551,8 +608,14 @@ mnd_root_get_tracking_origin_offset(mnd_root_t *root, uint32_t origin_id, mnd_po
}
mnd_result_t
mnd_root_set_tracking_origin_offset(mnd_root_t *root, uint32_t origin_id, const mnd_pose_t *offset)
mnd_root_set_tracking_origin_offset(mnd_root_t *root, uint32_t origin_index, const mnd_pose_t *offset)
{
CHECK_NOT_NULL(root);
CHECK_NOT_NULL(offset);
CHECK_ORIGIN_INDEX(origin_index);
uint32_t origin_id = root->tracking_origin_list.origins[origin_index].id;
xrt_result_t xret =
ipc_call_space_set_tracking_origin_offset(&root->ipc_c, origin_id, (struct xrt_pose *)offset);
switch (xret) {
@@ -569,25 +632,21 @@ mnd_root_get_tracking_origin_count(mnd_root_t *root, uint32_t *out_track_count)
CHECK_NOT_NULL(root);
CHECK_NOT_NULL(out_track_count);
*out_track_count = root->ipc_c.ism->itrack_count;
*out_track_count = root->tracking_origin_list.origin_count;
return MND_SUCCESS;
}
mnd_result_t
mnd_root_get_tracking_origin_name(mnd_root_t *root, uint32_t origin_id, const char **out_string)
mnd_root_get_tracking_origin_name(mnd_root_t *root, uint32_t origin_index, const char **out_string)
{
CHECK_NOT_NULL(root);
CHECK_NOT_NULL(out_string);
CHECK_ORIGIN_INDEX(origin_index);
if (origin_id >= root->ipc_c.ism->itrack_count) {
PE("Invalid itrack index (%u)", origin_id);
return MND_ERROR_INVALID_VALUE;
}
const struct ipc_tracking_origin_info *itoi = &root->origin_infos[origin_index];
const struct ipc_shared_tracking_origin *ipcsto = &root->ipc_c.ism->itracks[origin_id];
*out_string = ipcsto->name;
*out_string = itoi->name;
return MND_SUCCESS;
}
+7 -6
View File
@@ -1,4 +1,5 @@
// Copyright 2019-2023, Collabora, Ltd.
// Copyright 2025-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@@ -433,13 +434,13 @@ mnd_root_set_reference_space_offset(mnd_root_t *root, mnd_reference_space_type_t
* Supported in version 1.3 and above.
*
* @param root The libmonado state.
* @param origin_id The ID of the tracking origin.
* @param origin_index The index of the tracking origin into the internal list.
* @param[out] out_offset A pointer to where the offset should be written.
*
* @return MND_SUCCESS on success
*/
mnd_result_t
mnd_root_get_tracking_origin_offset(mnd_root_t *root, uint32_t origin_id, mnd_pose_t *out_offset);
mnd_root_get_tracking_origin_offset(mnd_root_t *root, uint32_t origin_index, mnd_pose_t *out_offset);
/*!
* Apply an offset to the specified tracking origin.
@@ -447,13 +448,13 @@ mnd_root_get_tracking_origin_offset(mnd_root_t *root, uint32_t origin_id, mnd_po
* Supported in version 1.3 and above.
*
* @param root The libmonado state.
* @param origin_id The ID of the tracking origin.
* @param origin_index The index of the tracking origin into the internal list.
* @param offset A pointer to valid xrt_pose.
*
* @return MND_SUCCESS on success
*/
mnd_result_t
mnd_root_set_tracking_origin_offset(mnd_root_t *root, uint32_t origin_id, const mnd_pose_t *offset);
mnd_root_set_tracking_origin_offset(mnd_root_t *root, uint32_t origin_index, const mnd_pose_t *offset);
/*!
* Retrieve the number of tracking origins available.
@@ -474,13 +475,13 @@ mnd_root_get_tracking_origin_count(mnd_root_t *root, uint32_t *out_track_count);
* Supported in version 1.3 and above.
*
* @param root The libmonado state.
* @param origin_id The ID of a tracking origin.
* @param origin_index The index of the tracking origin into the internal list.
* @param out_string The pointer to write the name's pointer to.
*
* @return MND_SUCCESS on success
*/
mnd_result_t
mnd_root_get_tracking_origin_name(mnd_root_t *root, uint32_t origin_id, const char **out_string);
mnd_root_get_tracking_origin_name(mnd_root_t *root, uint32_t origin_index, const char **out_string);
/*!
* Get battery status of a device.