st/oxr: Add oxr_session_action_context

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2761>
This commit is contained in:
Jakob Bornecrantz authored and Marge Bot committed 2026-03-11 13:54:52 +00:00
1 parent 8ff0ba352d
commit 6d503d082f
10 files changed
+395 -177

No files matched your search

@@ -33,6 +33,8 @@ add_library(
actions/oxr_instance_path_cache.h
actions/oxr_interaction_profile_array.c
actions/oxr_interaction_profile_array.h
actions/oxr_session_action_context.c
actions/oxr_session_action_context.h
actions/oxr_set_haptic.c
actions/oxr_set_haptic.h
common/oxr_defines.h
@@ -21,6 +21,7 @@
#include "oxr_input.h"
#include "oxr_binding.h"
#include "oxr_haptic.h"
#include "oxr_session_action_context.h"
#include "../oxr_api_verify.h"
#include "../oxr_objects.h"
@@ -178,7 +179,7 @@ oxr_xrAttachSessionActionSets(XrSession session, const XrSessionActionSetsAttach
OXR_VERIFY_SESSION_NOT_LOST(&log, sess);
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, bindInfo, XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO);
if (sess->act_set_attachments != NULL) {
if (oxr_session_action_context_has_attached_act_sets(&sess->action_context)) {
return oxr_error(&log, XR_ERROR_ACTIONSETS_ALREADY_ATTACHED,
"(session) has already had action sets "
"attached, can only attach action sets once.");
@@ -423,10 +424,12 @@ oxr_xrGetCurrentInteractionProfile(XrSession session,
str);
}
OXR_SESSION_CHECK_ATTACHED_AND_RET(sess, &log);
XrResult ret = oxr_action_get_current_interaction_profile( //
&log, //
&inst->path_cache, //
sess, //
&sess->action_context, //
topLevelUserPath, //
interactionProfile); //
if (ret == XR_SUCCESS) {
@@ -454,10 +457,7 @@ oxr_xrGetInputSourceLocalizedName(XrSession session,
// Short hand.
inst = sess->sys->inst;
if (sess->act_set_attachments == NULL) {
return oxr_error(&log, XR_ERROR_ACTIONSET_NOT_ATTACHED,
"ActionSet(s) have not been attached to this session");
}
OXR_SESSION_CHECK_ATTACHED_AND_RET(sess, &log);
if (getInfo->sourcePath == XR_NULL_PATH) {
return oxr_error(&log, XR_ERROR_PATH_INVALID,
@@ -487,7 +487,7 @@ oxr_xrGetInputSourceLocalizedName(XrSession session,
XrResult ret = oxr_action_get_input_source_localized_name( //
&log, //
&inst->path_store, //
sess, //
&sess->action_context, //
getInfo, //
bufferCapacityInput, //
bufferCountOutput, //
@@ -805,11 +805,7 @@ oxr_xrEnumerateBoundSourcesForAction(XrSession session,
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, enumerateInfo, XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO);
OXR_VERIFY_ACTION_NOT_NULL(&log, enumerateInfo->action, act);
if (sess->act_set_attachments == NULL) {
return oxr_error(&log, XR_ERROR_ACTIONSET_NOT_ATTACHED,
"(session) xrAttachSessionActionSets has not "
"been called on this session.");
}
OXR_SESSION_CHECK_ATTACHED_AND_RET(sess, &log);
return oxr_action_enumerate_bound_sources(&log, sess, act->act_key, sourceCapacityInput, sourceCountOutput,
sources);
@@ -15,13 +15,13 @@
#include "oxr_subaction.h"
#include "oxr_generated_bindings.h"
#include "oxr_dpad_state.h"
#include "oxr_session_action_context.h"
#include "oxr_interaction_profile_array.h"
#include "../oxr_objects.h"
#include "../oxr_logger.h"
#include "../oxr_two_call.h"
#include <stdio.h>
@@ -354,11 +354,12 @@ get_subaction_path_str(enum oxr_subaction_path subaction_path)
}
static XrPath
get_interaction_bound_to_sub_path(struct oxr_session *sess, enum oxr_subaction_path subaction_path)
get_interaction_bound_to_sub_path(const struct oxr_session_action_context *action_context,
enum oxr_subaction_path subaction_path)
{
switch (subaction_path) {
#define OXR_PATH_MEMBER(lower, CAP, _) \
case OXR_SUB_ACTION_PATH_##CAP: return sess->lower;
case OXR_SUB_ACTION_PATH_##CAP: return action_context->lower;
OXR_FOR_EACH_VALID_SUBACTION_PATH_DETAILED(OXR_PATH_MEMBER)
#undef OXR_PATH_MEMBER
@@ -610,18 +611,15 @@ out:
XrResult
oxr_action_get_current_interaction_profile(struct oxr_logger *log,
const struct oxr_instance_path_cache *cache,
struct oxr_session *sess,
const struct oxr_session_action_context *action_context,
XrPath topLevelUserPath,
XrInteractionProfileState *interactionProfile)
{
if (sess->act_set_attachments == NULL) {
return oxr_error(log, XR_ERROR_ACTIONSET_NOT_ATTACHED,
"xrAttachSessionActionSets has not been "
"called on this session.");
}
// Action sets attachment is checked in the API function.
#define IDENTIFY_TOP_LEVEL_PATH(X) \
if (topLevelUserPath == cache->X) { \
interactionProfile->interactionProfile = sess->X; \
interactionProfile->interactionProfile = action_context->X; \
} else
OXR_FOR_EACH_VALID_SUBACTION_PATH(IDENTIFY_TOP_LEVEL_PATH)
@@ -636,7 +634,7 @@ oxr_action_get_current_interaction_profile(struct oxr_logger *log,
XrResult
oxr_action_get_input_source_localized_name(struct oxr_logger *log,
const struct oxr_path_store *store,
struct oxr_session *sess,
const struct oxr_session_action_context *action_context,
const XrInputSourceLocalizedNameGetInfo *getInfo,
uint32_t bufferCapacityInput,
uint32_t *bufferCountOutput,
@@ -653,7 +651,7 @@ oxr_action_get_input_source_localized_name(struct oxr_logger *log,
}
// Get the interaction profile bound to this subaction_path.
XrPath path = get_interaction_bound_to_sub_path(sess, subaction_path);
XrPath path = get_interaction_bound_to_sub_path(action_context, subaction_path);
if (path == XR_NULL_PATH) {
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
"(getInfo->sourcePath) no interaction profile "
@@ -663,7 +661,7 @@ oxr_action_get_input_source_localized_name(struct oxr_logger *log,
// Find the interaction profile.
struct oxr_interaction_profile *oip = NULL;
//! @todo: If we ever rebind a profile that has not been suggested by the client, it will not be found.
oxr_interaction_profile_array_find_by_path(&sess->profiles_on_attachment, path, &oip);
oxr_interaction_profile_array_find_by_path(&action_context->profiles_on_attachment, path, &oip);
if (oip == NULL) {
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "no interaction profile found");
}
@@ -90,11 +90,12 @@ oxr_action_suggest_interaction_profile_bindings(struct oxr_logger *log,
/*!
* Get the currently active interaction profile for a top-level user path
* on the session (e.g. /user/hand/left). Requires action sets to be attached.
* on the session action context (e.g. /user/hand/left). Requires action sets to
* be attached.
*
* @param log Logger
* @param cache Instance path cache
* @param sess Session
* @param action_context Action context
* @param topLevelUserPath Top-level user path (e.g. left hand)
* @param interactionProfile Output interaction profile state
* @return XR_SUCCESS on success
@@ -103,7 +104,7 @@ oxr_action_suggest_interaction_profile_bindings(struct oxr_logger *log,
XrResult
oxr_action_get_current_interaction_profile(struct oxr_logger *log,
const struct oxr_instance_path_cache *cache,
struct oxr_session *sess,
const struct oxr_session_action_context *action_context,
XrPath topLevelUserPath,
XrInteractionProfileState *interactionProfile);
@@ -112,7 +113,7 @@ oxr_action_get_current_interaction_profile(struct oxr_logger *log,
*
* @param log Logger
* @param path_store Needed to look up path strings.
* @param sess Session.
* @param action_context Action context
* @param getInfo Input source localized name get info
* @param bufferCapacityInput Buffer capacity
* @param bufferCountOutput Buffer count output
@@ -123,7 +124,7 @@ oxr_action_get_current_interaction_profile(struct oxr_logger *log,
XrResult
oxr_action_get_input_source_localized_name(struct oxr_logger *log,
const struct oxr_path_store *store,
struct oxr_session *sess,
const struct oxr_session_action_context *action_context,
const XrInputSourceLocalizedNameGetInfo *getInfo,
uint32_t bufferCapacityInput,
uint32_t *bufferCountOutput,
+72 -67
View File
@@ -93,6 +93,26 @@ print_profiles(struct oxr_logger *log,
oxr_log_slog(log, &slog);
}
/*!
* Given an Action Set handle, return the @ref oxr_action_set and the
* associated @ref oxr_action_set_attachment in the given Session.
*/
static void
get_action_set_attachment(struct oxr_session_action_context *sess_context,
XrActionSet actionSet,
struct oxr_action_set_attachment **out_act_set_attached,
struct oxr_action_set **out_act_set)
{
struct oxr_action_set *act_set = XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_action_set *, actionSet);
// Make sure all are set.
*out_act_set = act_set;
*out_act_set_attached = NULL;
// Safe to call even if nothing has been attached.
oxr_session_action_context_find_set(sess_context, act_set->act_set_key, out_act_set_attached);
}
/*
*
@@ -100,12 +120,6 @@ print_profiles(struct oxr_logger *log,
*
*/
static void
oxr_session_get_action_set_attachment(struct oxr_session *sess,
XrActionSet actionSet,
struct oxr_action_set_attachment **act_set_attached,
struct oxr_action_set **act_set);
static void
oxr_action_cache_update(struct oxr_logger *log,
struct oxr_session *sess,
@@ -218,7 +232,7 @@ static void
oxr_action_attachment_teardown(struct oxr_action_attachment *act_attached)
{
struct oxr_session *sess = act_attached->sess;
u_hashmap_int_erase(sess->act_attachments_by_key, act_attached->act_key);
u_hashmap_int_erase(sess->action_context.act_attachments_by_key, act_attached->act_key);
#define CACHE_TEARDOWN(X) oxr_action_cache_teardown(&(act_attached->X));
OXR_FOR_EACH_SUBACTION_PATH(CACHE_TEARDOWN)
@@ -242,7 +256,7 @@ oxr_action_attachment_init(struct oxr_logger *log,
struct oxr_session *sess = act_set_attached->sess;
act_attached->sess = sess;
act_attached->act_set_attached = act_set_attached;
u_hashmap_int_insert(sess->act_attachments_by_key, act->act_key, act_attached);
u_hashmap_int_insert(sess->action_context.act_attachments_by_key, act->act_key, act_attached);
// Reference this action's refcounted data
act_attached->act_ref = act->data;
@@ -275,7 +289,7 @@ oxr_action_set_attachment_init(struct oxr_logger *log,
act_set_attached->act_set_ref = act_set->data;
oxr_refcounted_ref(&act_set_attached->act_set_ref->base);
u_hashmap_int_insert(sess->act_sets_attachments_by_key, act_set->act_set_key, act_set_attached);
u_hashmap_int_insert(sess->action_context.act_sets_attachments_by_key, act_set->act_set_key, act_set_attached);
// Copy this for efficiency.
act_set_attached->act_set_key = act_set->act_set_key;
@@ -294,7 +308,7 @@ oxr_action_set_attachment_teardown(struct oxr_action_set_attachment *act_set_att
act_set_attached->action_attachment_count = 0;
struct oxr_session *sess = act_set_attached->sess;
u_hashmap_int_erase(sess->act_sets_attachments_by_key, act_set_attached->act_set_key);
u_hashmap_int_erase(sess->action_context.act_sets_attachments_by_key, act_set_attached->act_set_key);
// Unref this action set's refcounted data
oxr_refcounted_unref(&act_set_attached->act_set_ref->base);
@@ -1088,7 +1102,7 @@ oxr_input_supressed(struct oxr_session *sess,
struct oxr_action_set *other_act_set = NULL;
struct oxr_action_set_attachment *other_act_set_attached = NULL;
oxr_session_get_action_set_attachment(sess, set, &other_act_set_attached, &other_act_set);
get_action_set_attachment(&sess->action_context, set, &other_act_set_attached, &other_act_set);
if (other_act_set_attached == NULL) {
continue;
@@ -1814,34 +1828,6 @@ oxr_action_bind_io(struct oxr_logger *log,
*
*/
/*!
* Given an Action Set handle, return the @ref oxr_action_set and the
* associated
* @ref oxr_action_set_attachment in the given Session.
*
* @private @memberof oxr_session
*/
static void
oxr_session_get_action_set_attachment(struct oxr_session *sess,
XrActionSet actionSet,
struct oxr_action_set_attachment **act_set_attached,
struct oxr_action_set **act_set)
{
void *ptr = NULL;
*act_set = XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_action_set *, actionSet);
*act_set_attached = NULL;
// In case no action_sets have been attached.
if (sess->act_sets_attachments_by_key == NULL) {
return;
}
int ret = u_hashmap_int_find(sess->act_sets_attachments_by_key, (*act_set)->act_set_key, &ptr);
if (ret == 0) {
*act_set_attached = (struct oxr_action_set_attachment *)ptr;
}
}
void
oxr_session_get_action_attachment(struct oxr_session *sess,
uint32_t act_key,
@@ -1849,7 +1835,7 @@ oxr_session_get_action_attachment(struct oxr_session *sess,
{
void *ptr = NULL;
int ret = u_hashmap_int_find(sess->act_attachments_by_key, act_key, &ptr);
int ret = u_hashmap_int_find(sess->action_context.act_attachments_by_key, act_key, &ptr);
if (ret == 0) {
*out_act_attached = (struct oxr_action_attachment *)ptr;
}
@@ -1875,22 +1861,23 @@ oxr_session_attach_action_sets(struct oxr_logger *log,
struct oxr_instance *inst = sess->sys->inst;
const struct oxr_instance_action_context *inst_context = inst->action_context;
struct oxr_session_action_context *sess_context = &sess->action_context;
oxr_interaction_profile_array_clone(&inst_context->suggested_profiles, &sess->profiles_on_attachment);
oxr_interaction_profile_array_clone(&inst_context->suggested_profiles, &sess_context->profiles_on_attachment);
// Allocate room for list. No need to check if anything has been
// attached the API function does that.
sess->action_set_attachment_count = bindInfo->countActionSets;
sess->act_set_attachments =
U_TYPED_ARRAY_CALLOC(struct oxr_action_set_attachment, sess->action_set_attachment_count);
sess->action_context.action_set_attachment_count = bindInfo->countActionSets;
sess->action_context.act_set_attachments =
U_TYPED_ARRAY_CALLOC(struct oxr_action_set_attachment, sess->action_context.action_set_attachment_count);
// Set up the per-session data for these action sets.
for (uint32_t i = 0; i < sess->action_set_attachment_count; i++) {
for (uint32_t i = 0; i < sess->action_context.action_set_attachment_count; i++) {
struct oxr_action_set *act_set =
XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_action_set *, bindInfo->actionSets[i]);
struct oxr_action_set_ref *act_set_ref = act_set->data;
act_set_ref->ever_attached = true;
struct oxr_action_set_attachment *act_set_attached = &sess->act_set_attachments[i];
struct oxr_action_set_attachment *act_set_attached = &sess->action_context.act_set_attachments[i];
oxr_action_set_attachment_init(log, sess, act_set, act_set_attached);
// Allocate the action attachments for this set.
@@ -1924,13 +1911,14 @@ oxr_session_attach_action_sets(struct oxr_logger *log,
static XrResult
session_update_action_bindings(struct oxr_logger *log,
struct oxr_instance *inst,
struct oxr_session *sess,
const struct oxr_roles *roles)
struct oxr_session_action_context *action_context,
const struct oxr_roles *roles,
bool *out_interaction_profile_changed)
{
// Convenience.
const struct oxr_path_store *store = &inst->path_store;
const struct oxr_instance_path_cache *cache = &inst->path_cache;
const struct oxr_interaction_profile_array *array = &sess->profiles_on_attachment;
const struct oxr_interaction_profile_array *array = &action_context->profiles_on_attachment;
struct oxr_profiles_per_subaction profiles = {0};
find_profiles_from_roles(cache, array, roles, &profiles);
@@ -1940,14 +1928,16 @@ session_update_action_bindings(struct oxr_logger *log,
print_profiles(log, store, &profiles);
}
for (size_t i = 0; i < sess->action_set_attachment_count; i++) {
struct oxr_action_set_attachment *act_set_attached = &sess->act_set_attachments[i];
for (size_t i = 0; i < action_context->action_set_attachment_count; i++) {
struct oxr_action_set_attachment *act_set_attached = &action_context->act_set_attachments[i];
for (size_t k = 0; k < act_set_attached->action_attachment_count; k++) {
struct oxr_action_attachment *act_attached = &act_set_attached->act_attachments[k];
oxr_action_attachment_bind(log, inst, act_attached, roles, &profiles);
}
}
bool interaction_profile_changed = false;
/*
* This code will only send events (and update the bindings) if there
* is a profile mapped to the subaction path. Meaning it won't update
@@ -1960,15 +1950,17 @@ session_update_action_bindings(struct oxr_logger *log,
if (path == XR_NULL_PATH) { \
break; /* Only update on "active" interaction profiles per sub-action path. */ \
} \
if (sess->X != path) { \
sess->X = path; \
oxr_event_push_XrEventDataInteractionProfileChanged(log, sess); \
if (action_context->X != path) { \
action_context->X = path; \
interaction_profile_changed = true; \
} \
} while (false);
OXR_FOR_EACH_VALID_SUBACTION_PATH(POPULATE_PROFILE)
#undef POPULATE_PROFILE
return oxr_session_success_result(sess);
*out_interaction_profile_changed = interaction_profile_changed;
return XR_SUCCESS;
}
XrResult
@@ -1978,6 +1970,9 @@ oxr_action_sync_data(struct oxr_logger *log,
const XrActiveActionSet *actionSets,
const XrActiveActionSetPrioritiesEXT *activePriorities)
{
struct oxr_session_action_context *sess_context = &sess->action_context;
struct oxr_instance *inst = sess->sys->inst;
struct oxr_action_set *act_set = NULL;
struct oxr_action_set_attachment *act_set_attached = NULL;
@@ -1988,7 +1983,7 @@ oxr_action_sync_data(struct oxr_logger *log,
// Check that all action sets has been attached.
for (uint32_t i = 0; i < countActionSets; i++) {
oxr_session_get_action_set_attachment(sess, actionSets[i].actionSet, &act_set_attached, &act_set);
get_action_set_attachment(sess_context, actionSets[i].actionSet, &act_set_attached, &act_set);
if (act_set_attached == NULL) {
return oxr_error(log, XR_ERROR_ACTIONSET_NOT_ATTACHED,
"(actionSets[%i].actionSet) action set '%s' has "
@@ -2019,12 +2014,23 @@ oxr_action_sync_data(struct oxr_logger *log,
// Should we redo the bindings?
{
os_mutex_lock(&sess->sync_actions_mutex);
if (sess->dynamic_roles_generation_id < roles.roles.generation_id) {
sess->dynamic_roles_generation_id = roles.roles.generation_id;
session_update_action_bindings(log, sess->sys->inst, sess, &roles);
bool interaction_profile_changed = false;
os_mutex_lock(&sess_context->sync_actions_mutex);
if (sess_context->dynamic_roles_generation_id < roles.roles.generation_id) {
sess_context->dynamic_roles_generation_id = roles.roles.generation_id;
session_update_action_bindings( //
log, //
inst, //
sess_context, //
&roles, //
&interaction_profile_changed); //
}
os_mutex_unlock(&sess_context->sync_actions_mutex);
if (interaction_profile_changed) {
oxr_event_push_XrEventDataInteractionProfileChanged(log, sess);
}
os_mutex_unlock(&sess->sync_actions_mutex);
}
if (countActionSets == 0) {
@@ -2044,8 +2050,8 @@ oxr_action_sync_data(struct oxr_logger *log,
}
// Reset all action set attachments.
for (size_t i = 0; i < sess->action_set_attachment_count; ++i) {
act_set_attached = &sess->act_set_attachments[i];
for (size_t i = 0; i < sess_context->action_set_attachment_count; ++i) {
act_set_attached = &sess_context->act_set_attachments[i];
U_ZERO(&act_set_attached->requested_subaction_paths);
}
@@ -2054,7 +2060,7 @@ oxr_action_sync_data(struct oxr_logger *log,
//! @todo can be listed more than once with different paths!
for (uint32_t i = 0; i < countActionSets; i++) {
struct oxr_subaction_paths subaction_paths;
oxr_session_get_action_set_attachment(sess, actionSets[i].actionSet, &act_set_attached, &act_set);
get_action_set_attachment(sess_context, actionSets[i].actionSet, &act_set_attached, &act_set);
assert(act_set_attached != NULL);
if (!oxr_classify_subaction_paths(log, sess->sys->inst, 1, &actionSets[i].subactionPath,
@@ -2090,11 +2096,10 @@ oxr_action_sync_data(struct oxr_logger *log,
}
// Now, update all action attachments
for (size_t i = 0; i < sess->action_set_attachment_count; ++i) {
act_set_attached = &sess->act_set_attachments[i];
for (size_t i = 0; i < sess_context->action_set_attachment_count; ++i) {
act_set_attached = &sess_context->act_set_attachments[i];
struct oxr_subaction_paths subaction_paths = act_set_attached->requested_subaction_paths;
for (uint32_t k = 0; k < act_set_attached->action_attachment_count; k++) {
struct oxr_action_attachment *act_attached = &act_set_attached->act_attachments[k];
@@ -0,0 +1,99 @@
// Copyright 2018-2024, Collabora, Ltd.
// Copyright 2023-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Holds per session action context.
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
* @ingroup oxr_main
*/
#include "util/u_debug.h"
#include "util/u_hashmap.h"
#include "oxr_session_action_context.h"
#include "../oxr_logger.h"
#include "../oxr_objects.h"
#include "oxr_input.h"
XrResult
oxr_session_action_context_init(struct oxr_session_action_context *action_context)
{
// Initialize dynamic roles generation_id and mutex
action_context->dynamic_roles_generation_id = 0;
os_mutex_init(&action_context->sync_actions_mutex);
// Action system hashmaps.
int h_ret = u_hashmap_int_create(&action_context->act_sets_attachments_by_key);
if (h_ret != 0) {
return XR_ERROR_RUNTIME_FAILURE;
}
// @todo Remove or check results.
u_hashmap_int_create(&action_context->act_attachments_by_key);
// Initialize action set attachments
action_context->act_set_attachments = NULL;
action_context->action_set_attachment_count = 0;
// Initialize subaction paths
#define INIT_PATH(X) action_context->X = XR_NULL_PATH;
OXR_FOR_EACH_VALID_SUBACTION_PATH(INIT_PATH)
#undef INIT_PATH
return XR_SUCCESS;
}
void
oxr_session_action_context_fini(struct oxr_session_action_context *action_context)
{
oxr_interaction_profile_array_clear(&action_context->profiles_on_attachment);
// Teardown action set attachments
for (size_t i = 0; i < action_context->action_set_attachment_count; ++i) {
oxr_action_set_attachment_teardown(&action_context->act_set_attachments[i]);
}
free(action_context->act_set_attachments);
action_context->act_set_attachments = NULL;
action_context->action_set_attachment_count = 0;
// If we tore everything down correctly, these are empty now.
assert(action_context->act_sets_attachments_by_key == NULL ||
u_hashmap_int_empty(action_context->act_sets_attachments_by_key));
assert(action_context->act_attachments_by_key == NULL ||
u_hashmap_int_empty(action_context->act_attachments_by_key));
u_hashmap_int_destroy(&action_context->act_sets_attachments_by_key);
u_hashmap_int_destroy(&action_context->act_attachments_by_key);
// Destroy mutex
os_mutex_destroy(&action_context->sync_actions_mutex);
}
bool
oxr_session_action_context_has_attached_act_sets(const struct oxr_session_action_context *action_context)
{
return action_context->act_set_attachments != NULL;
}
XRT_NONNULL_ALL bool
oxr_session_action_context_find_set(struct oxr_session_action_context *action_context,
uint32_t act_set_key,
struct oxr_action_set_attachment **out_act_set_attached)
{
void *ptr = NULL;
// In case no action_sets have been attached.
if (!oxr_session_action_context_has_attached_act_sets(action_context)) {
return false;
}
int ret = u_hashmap_int_find(action_context->act_sets_attachments_by_key, act_set_key, &ptr);
if (ret == 0) {
*out_act_set_attached = (struct oxr_action_set_attachment *)ptr;
return true;
}
return false;
}
@@ -0,0 +1,184 @@
// Copyright 2018-2024, Collabora, Ltd.
// Copyright 2023-2026, NVIDIA CORPORATION.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Holds per session action context.
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
* @ingroup oxr_main
*/
#pragma once
#include "os/os_threading.h"
#include "oxr_forward_declarations.h"
#include "oxr_extension_support.h"
#include "oxr_subaction.h"
#include "oxr_interaction_profile_array.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
*
* Helper macros
*
*/
/*!
* Helper macro to check if action sets are attached to a session.
*
* Returns XR_ERROR_ACTIONSET_NOT_ATTACHED if action sets have not been attached.
*
* @param SESS Session pointer
* @param LOG Logger pointer
* @ingroup oxr_main
*/
#define OXR_SESSION_CHECK_ATTACHED_AND_RET(SESS, LOG) \
do { \
if (!oxr_session_action_context_has_attached_act_sets(&(SESS)->action_context)) { \
return oxr_error(LOG, XR_ERROR_ACTIONSET_NOT_ATTACHED, \
"ActionSet(s) have not been attached to this session"); \
} \
} while (false)
/*
*
* Structs
*
*/
/*!
* This holds all of the action state that belongs on the session level.
*
* Future extensions might enable multiple action contexts per session.
*/
struct oxr_session_action_context
{
/*
* Action Set fields
*/
/*!
* A map of action set key to action set attachments.
*
* If non-null, this means action sets have been attached to this
* session, since this map points to elements of
* oxr_session_action_context::act_set_attachments
*/
struct u_hashmap_int *act_sets_attachments_by_key;
/*!
* An array of action set attachments that this session owns.
*
* If non-null, this means action sets have been attached to this
* session.
*/
struct oxr_action_set_attachment *act_set_attachments;
/*!
* Length of @ref oxr_session_action_context::act_set_attachments.
*/
size_t action_set_attachment_count;
/*
* Action fields
*/
/*!
* A map of action key to action attachment.
*
* The action attachments are actually owned by the action set
* attachments, but we own the action set attachments, so this is OK.
*
* If non-null, this means an action context (default or otherwise)
* action sets have been attached to the owning session, since this map
* points to @p oxr_action_attachment members of
* @ref oxr_session_action_context::act_set_attachments elements.
*/
struct u_hashmap_int *act_attachments_by_key;
/*
* Interaction Profiles fields
*/
/*!
* Clone of all suggested binding profiles at the point of action set/session attachment.
* @ref oxr_session_attach_action_sets
*/
struct oxr_interaction_profile_array profiles_on_attachment;
//! Cache of the last known system roles generation_id
uint64_t dynamic_roles_generation_id;
//! Protects access to dynamic_roles_generation_id during sync actions
struct os_mutex sync_actions_mutex;
/*!
* Currently bound interaction profile.
* @{
*/
#define OXR_PATH_MEMBER(X) XrPath X;
OXR_FOR_EACH_VALID_SUBACTION_PATH(OXR_PATH_MEMBER)
#undef OXR_PATH_MEMBER
/*!
* @}
*/
};
/*
*
* Functions
*
*/
/*!
* Initialize the action context for a session.
*
* @public @memberof oxr_session_action_context
*/
XRT_NONNULL_ALL XRT_CHECK_RESULT XrResult
oxr_session_action_context_init(struct oxr_session_action_context *action_context);
/*!
* Finalize and cleanup the action context for a session.
*
* @public @memberof oxr_session_action_context
*/
XRT_NONNULL_ALL void
oxr_session_action_context_fini(struct oxr_session_action_context *action_context);
/*!
* Check if action sets have been attached to the action context.
*
* @return true if action sets are attached, false otherwise
* @public @memberof oxr_session_action_context
*/
XRT_NONNULL_ALL bool
oxr_session_action_context_has_attached_act_sets(const struct oxr_session_action_context *action_context);
/*!
* Helper to find action set attachment.
*
* @return true if the action set was found, false otherwise
* @public @memberof oxr_session_action_context
*/
XRT_NONNULL_ALL bool
oxr_session_action_context_find_set(struct oxr_session_action_context *action_context,
uint32_t act_set_key,
struct oxr_action_set_attachment **out_act_set_attached);
#ifdef __cplusplus
}
#endif
@@ -55,6 +55,7 @@ struct oxr_action_attachment;
struct oxr_action_set_attachment;
struct oxr_action_input;
struct oxr_action_output;
struct oxr_session_action_context;
struct oxr_dpad_state;
struct oxr_binding;
struct oxr_interaction_profile;
+3 -56
View File
@@ -40,6 +40,7 @@
#include "actions/oxr_subaction.h"
#include "actions/oxr_dpad_state.h"
#include "actions/oxr_session_action_context.h"
#include "actions/oxr_interaction_profile_array.h"
#include "actions/oxr_instance_path_cache.h"
#include "actions/oxr_instance_action_context.h"
@@ -1410,63 +1411,9 @@ struct oxr_session
struct os_precise_sleeper sleeper;
/*!
* An array of action set attachments that this session owns.
*
* If non-null, this means action sets have been attached to this
* session.
*/
struct oxr_action_set_attachment *act_set_attachments;
/*!
* Length of @ref oxr_session::act_set_attachments.
*/
size_t action_set_attachment_count;
/*!
* A map of action set key to action set attachments.
*
* If non-null, this means action sets have been attached to this
* session, since this map points to elements of
* oxr_session::act_set_attachments
*/
struct u_hashmap_int *act_sets_attachments_by_key;
/*!
* A map of action key to action attachment.
*
* The action attachments are actually owned by the action set
* attachments, but we own the action set attachments, so this is OK.
*
* If non-null, this means action sets have been attached to this
* session, since this map points to @p oxr_action_attachment members of
* @ref oxr_session::act_set_attachments elements.
*/
struct u_hashmap_int *act_attachments_by_key;
/*!
* Clone of all suggested binding profiles at the point of action set/session attachment.
* @ref oxr_session_attach_action_sets
*/
struct oxr_interaction_profile_array profiles_on_attachment;
//! Cache of the last known system roles generation_id
uint64_t dynamic_roles_generation_id;
//! Protects access to dynamic_roles_generation_id during sync actions
struct os_mutex sync_actions_mutex;
/*!
* Currently bound interaction profile.
* @{
*/
#define OXR_PATH_MEMBER(X) XrPath X;
OXR_FOR_EACH_VALID_SUBACTION_PATH(OXR_PATH_MEMBER)
#undef OXR_PATH_MEMBER
/*!
* @}
* Holds all the action state that belongs on the session level.
*/
struct oxr_session_action_context action_context;
/*!
* IPD, to be expanded to a proper 3D relation.
+9 -24
View File
@@ -49,6 +49,7 @@
#include "oxr_xret.h"
#include "oxr_roles.h"
#include "actions/oxr_input.h"
#include "actions/oxr_session_action_context.h"
#include "actions/oxr_binding.h"
#include <stdio.h>
@@ -1062,21 +1063,7 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
XrResult ret = oxr_event_remove_session_events(log, sess);
oxr_interaction_profile_array_clear(&sess->profiles_on_attachment);
for (size_t i = 0; i < sess->action_set_attachment_count; ++i) {
oxr_action_set_attachment_teardown(&sess->act_set_attachments[i]);
}
free(sess->act_set_attachments);
sess->act_set_attachments = NULL;
sess->action_set_attachment_count = 0;
// If we tore everything down correctly, these are empty now.
assert(sess->act_sets_attachments_by_key == NULL || u_hashmap_int_empty(sess->act_sets_attachments_by_key));
assert(sess->act_attachments_by_key == NULL || u_hashmap_int_empty(sess->act_attachments_by_key));
u_hashmap_int_destroy(&sess->act_sets_attachments_by_key);
u_hashmap_int_destroy(&sess->act_attachments_by_key);
oxr_session_action_context_fini(&sess->action_context);
xrt_comp_destroy(&sess->compositor);
xrt_comp_native_destroy(&sess->xcn);
@@ -1085,7 +1072,6 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
os_precise_sleeper_deinit(&sess->sleeper);
oxr_frame_sync_fini(&sess->frame_sync);
os_mutex_destroy(&sess->active_wait_frames_lock);
os_mutex_destroy(&sess->sync_actions_mutex);
free(sess);
@@ -1099,8 +1085,15 @@ oxr_session_allocate_and_init(struct oxr_logger *log,
struct oxr_session **out_session)
{
struct oxr_session *sess = NULL;
XrResult ret;
OXR_ALLOCATE_HANDLE_OR_RETURN(log, sess, OXR_XR_DEBUG_SESSION, oxr_session_destroy, &sys->inst->handle);
// Needs to happen early due to mutex.
ret = oxr_session_action_context_init(&sess->action_context);
if (ret != XR_SUCCESS) {
return oxr_error(log, ret, "Failed to initialize action context");
}
// What graphics API type was this created with.
sess->gfx_ext = gfx_ext;
@@ -1116,19 +1109,11 @@ oxr_session_allocate_and_init(struct oxr_logger *log,
sess->active_wait_frames = 0;
os_mutex_init(&sess->active_wait_frames_lock);
// Initialize dynamic roles generation_id and mutex
sess->dynamic_roles_generation_id = 0;
os_mutex_init(&sess->sync_actions_mutex);
// Debug and user options.
sess->ipd_meters = debug_get_num_option_ipd() / 1000.0f;
sess->frame_timing_spew = debug_get_bool_option_frame_timing_spew();
sess->frame_timing_wait_sleep_ms = debug_get_num_option_wait_frame_sleep();
// Action system hashmaps.
u_hashmap_int_create(&sess->act_sets_attachments_by_key);
u_hashmap_int_create(&sess->act_attachments_by_key);
// This is set to something valid in begin session, used in xrEndFrame.
sess->current_view_config_type = XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM;