Something went wrong. Try again.
The open source OpenXR runtime
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272// Copyright 2023, Collabora, Ltd.// Copyright 2024-2026, NVIDIA CORPORATION.// SPDX-License-Identifier: BSL-1.0/*! * @file * @brief Helper to implement @ref xrt_system. * @author Jakob Bornecrantz <jakob@collabora.com> * @ingroup aux_util */
#include "xrt/xrt_compositor.h"
#include "os/os_threading.h"
#include "util/u_misc.h"#include "util/u_logging.h"
#include "b_system.h"#include "b_session.h"
#include <stdio.h>
/* * * Helpers. * */
static inline struct b_system *b_system(struct xrt_system *xsys){ return (struct b_system *)xsys;}
/* * * Member functions. * */
static xrt_result_tpush_event(struct xrt_session_event_sink *xses, const union xrt_session_event *xse){ struct b_system *bsys = container_of(xses, struct b_system, broadcast);
b_system_broadcast_event(bsys, xse);
return XRT_SUCCESS;}
static xrt_result_tcreate_session(struct xrt_system *xsys, const struct xrt_session_info *xsi, struct xrt_session **out_xs, struct xrt_compositor_native **out_xcn){ struct b_system *bsys = b_system(xsys); xrt_result_t xret = XRT_SUCCESS;
if (out_xcn != NULL && bsys->xsysc == NULL) { U_LOG_E("No system compositor in system, can't create native compositor."); return XRT_ERROR_COMPOSITOR_NOT_SUPPORTED; }
struct b_session *bs = b_session_create(bsys);
// Skip making a native compositor if not asked for. if (out_xcn == NULL) { goto out_session; }
xret = xrt_syscomp_create_native_compositor( // bsys->xsysc, // xsi, // &bs->sink, // out_xcn); // if (xret != XRT_SUCCESS) { goto err; }
out_session: *out_xs = &bs->base;
return XRT_SUCCESS;
err: bs->base.destroy(&bs->base); return xret;}
static voiddestroy(struct xrt_system *xsys){ struct b_system *bsys = b_system(xsys);
// Use shared fini function. b_system_fini(bsys);
free(bsys);}
/* * * 'Exported' functions. * */
struct b_system *b_system_create(void){ struct b_system *bsys = U_TYPED_CALLOC(struct b_system);
// Use init function, then add the common destroy function. if (!b_system_init(bsys, destroy)) { free(bsys); return NULL; }
return bsys;}
boolb_system_init(struct b_system *bsys, void (*destroy_fn)(struct xrt_system *)){ // xrt_system fields. bsys->base.create_session = create_session; bsys->base.destroy = destroy_fn;
// xrt_session_event_sink fields. bsys->broadcast.push_event = push_event;
bsys->sessions.capacity = 2; bsys->sessions.pairs = U_TYPED_ARRAY_CALLOC(struct b_system_session_pair, bsys->sessions.capacity); if (bsys->sessions.pairs == NULL) { U_LOG_E("Failed to allocate session array"); return false; }
// b_system fields. XRT_MAYBE_UNUSED int ret = os_mutex_init(&bsys->sessions.mutex); assert(ret == 0);
return true;}
voidb_system_fini(struct b_system *bsys){ // Just in case, should never happen. if (bsys->sessions.count > 0) { U_LOG_E("Number of sessions not zero, things will crash!"); }
free(bsys->sessions.pairs); bsys->sessions.count = 0;
// Mutex needs to be destroyed. os_mutex_destroy(&bsys->sessions.mutex);}
voidb_system_add_session(struct b_system *bsys, struct xrt_session *xs, struct xrt_session_event_sink *xses){ assert(xs != NULL); assert(xses != NULL);
os_mutex_lock(&bsys->sessions.mutex);
const uint32_t new_count = bsys->sessions.count + 1;
if (new_count > bsys->sessions.capacity) { const uint32_t new_capacity = bsys->sessions.capacity * 2; const size_t size = new_capacity * sizeof(*bsys->sessions.pairs); struct b_system_session_pair *tmp = realloc(bsys->sessions.pairs, size); if (tmp == NULL) { U_LOG_E("Failed to reallocate session array"); goto add_unlock; } bsys->sessions.pairs = tmp; bsys->sessions.capacity = new_capacity; }
bsys->sessions.pairs[bsys->sessions.count++] = (struct b_system_session_pair){xs, xses};
add_unlock: os_mutex_unlock(&bsys->sessions.mutex);}
voidb_system_remove_session(struct b_system *bsys, struct xrt_session *xs, struct xrt_session_event_sink *xses){ os_mutex_lock(&bsys->sessions.mutex);
uint32_t count = bsys->sessions.count; uint32_t dst = 0;
// Find where the session we are removing is. while (dst < count) { if (bsys->sessions.pairs[dst].xs == xs) { break; } else { dst++; } }
// Guards against empty array as well as not finding the session. if (dst >= count) { U_LOG_E("Could not find session to remove!"); goto remove_unlock; }
// Should not be true with above check. assert(count > 0);
/* * Do copies if we are not removing the last session, * this also guards against uint32_t::max. */ if (dst < count - 1) { // Copy from every follow down one. for (uint32_t src = dst + 1; src < count; src++, dst++) { bsys->sessions.pairs[dst] = bsys->sessions.pairs[src]; } }
count--; // This ensures that the memory returned in add is always zero initialized. U_ZERO(&bsys->sessions.pairs[count]);
bsys->sessions.count = count;
remove_unlock: os_mutex_unlock(&bsys->sessions.mutex);}
voidb_system_broadcast_event(struct b_system *bsys, const union xrt_session_event *xse){ xrt_result_t xret;
os_mutex_lock(&bsys->sessions.mutex);
for (uint32_t i = 0; i < bsys->sessions.count; i++) { xret = xrt_session_event_sink_push(bsys->sessions.pairs[i].xses, xse); if (xret != XRT_SUCCESS) { U_LOG_W("Failed to push event to session, dropping."); } }
os_mutex_unlock(&bsys->sessions.mutex);}
voidb_system_set_system_compositor(struct b_system *bsys, struct xrt_system_compositor *xsysc){ assert(bsys->xsysc == NULL);
bsys->xsysc = xsysc;}
voidb_system_fill_properties(struct b_system *bsys, const char *name){ bsys->base.properties.vendor_id = 42; // The magical 247 number, is to silence warnings. snprintf(bsys->base.properties.name, XRT_MAX_SYSTEM_NAME_SIZE, "Monado: %.*s", 247, name); bsys->base.properties.form_factor = XRT_FORM_FACTOR_HMD;}