st/oxr: Clone profiles to session on action sets attachment.

Co-authored-by: Jakob Bornecrantz <jakob@collabora.com>
This commit is contained in:
Korcan Hussein 2023-10-17 12:03:57 +01:00 committed by korejan
parent d033955678
commit f60ffe5af7
4 changed files with 191 additions and 25 deletions

View file

@ -45,13 +45,16 @@ setup_paths(struct oxr_logger *log,
}
static bool
interaction_profile_find(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath path,
struct oxr_interaction_profile **out_p)
interaction_profile_find_in_array(struct oxr_logger *log,
const size_t profile_count,
struct oxr_interaction_profile **profiles,
XrPath path,
struct oxr_interaction_profile **out_p)
{
for (size_t x = 0; x < inst->profile_count; x++) {
struct oxr_interaction_profile *p = inst->profiles[x];
if (profiles == NULL)
return false;
for (size_t x = 0; x < profile_count; x++) {
struct oxr_interaction_profile *p = profiles[x];
if (p->path != path) {
continue;
}
@ -63,6 +66,34 @@ interaction_profile_find(struct oxr_logger *log,
return false;
}
static inline bool
interaction_profile_find_in_instance(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath path,
struct oxr_interaction_profile **out_p)
{
return interaction_profile_find_in_array( //
log, //
inst->profile_count, //
inst->profiles, //
path, //
out_p); //
}
static inline bool
internaction_profile_find_in_session(struct oxr_logger *log,
struct oxr_session *sess,
XrPath path,
struct oxr_interaction_profile **out_p)
{
return interaction_profile_find_in_array( //
log, //
sess->profiles_on_attachment_size, //
sess->profiles_on_attachment, //
path, //
out_p); //
}
static bool
get_subaction_path_from_path(struct oxr_logger *log,
struct oxr_instance *inst,
@ -70,12 +101,12 @@ get_subaction_path_from_path(struct oxr_logger *log,
enum oxr_subaction_path *out_subaction_path);
static bool
interaction_profile_find_or_create(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath path,
struct oxr_interaction_profile **out_p)
interaction_profile_find_or_create_in_instance(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath path,
struct oxr_interaction_profile **out_p)
{
if (interaction_profile_find(log, inst, path, out_p)) {
if (interaction_profile_find_in_instance(log, inst, path, out_p)) {
return true;
}
@ -313,15 +344,16 @@ get_identifier_str_in_profile(struct oxr_logger *log,
static void
get_profile_for_device_name(struct oxr_logger *log,
struct oxr_instance *inst,
struct oxr_session *sess,
enum xrt_device_name name,
struct oxr_interaction_profile **out_p)
{
struct oxr_instance *inst = sess->sys->inst;
/*
* Map xrt_device_name to an interaction profile XrPath.
* Set *out_p to an oxr_interaction_profile if bindings for that interaction profile XrPath have been suggested.
*/
#define FIND_PROFILE(PATH) interaction_profile_find(log, inst, inst->path_cache.PATH, out_p)
#define FIND_PROFILE(PATH) internaction_profile_find_in_session(log, sess, inst->path_cache.PATH, out_p)
switch (name) {
case XRT_DEVICE_PSMV: FIND_PROFILE(mndx_ball_on_a_stick_controller); return;
@ -366,7 +398,7 @@ get_profile_for_device_name(struct oxr_logger *log,
void
oxr_find_profile_for_device(struct oxr_logger *log,
struct oxr_instance *inst,
struct oxr_session *sess,
struct xrt_device *xdev,
struct oxr_interaction_profile **out_p)
{
@ -375,7 +407,7 @@ oxr_find_profile_for_device(struct oxr_logger *log,
}
// Have bindings for this device's interaction profile been suggested?
get_profile_for_device_name(log, inst, xdev->name, out_p);
get_profile_for_device_name(log, sess, xdev->name, out_p);
if (*out_p != NULL) {
return;
}
@ -383,7 +415,7 @@ oxr_find_profile_for_device(struct oxr_logger *log,
// Check if bindings for any of this device's alternative interaction profiles have been suggested.
for (size_t i = 0; i < xdev->binding_profile_count; i++) {
struct xrt_binding_profile *xbp = &xdev->binding_profiles[i];
get_profile_for_device_name(log, inst, xbp->name, out_p);
get_profile_for_device_name(log, sess, xbp->name, out_p);
if (*out_p != NULL) {
return;
}
@ -425,11 +457,91 @@ oxr_binding_find_bindings_from_key(struct oxr_logger *log,
*binding_count = num;
}
void
oxr_binding_destroy_all(struct oxr_logger *log, struct oxr_instance *inst)
struct oxr_interaction_profile *
oxr_clone_profile(const struct oxr_interaction_profile *src_profile)
{
for (size_t x = 0; x < inst->profile_count; x++) {
struct oxr_interaction_profile *p = inst->profiles[x];
if (src_profile == NULL)
return NULL;
struct oxr_interaction_profile *dst_profile = U_TYPED_CALLOC(struct oxr_interaction_profile);
*dst_profile = *src_profile;
dst_profile->binding_count = 0;
dst_profile->bindings = NULL;
if (src_profile->bindings && src_profile->binding_count > 0) {
dst_profile->binding_count = src_profile->binding_count;
dst_profile->bindings = U_TYPED_ARRAY_CALLOC(struct oxr_binding, src_profile->binding_count);
for (size_t binding_idx = 0; binding_idx < src_profile->binding_count; ++binding_idx) {
struct oxr_binding *dst_binding = dst_profile->bindings + binding_idx;
const struct oxr_binding *src_binding = src_profile->bindings + binding_idx;
*dst_binding = *src_binding;
dst_binding->path_count = 0;
dst_binding->paths = NULL;
if (src_binding->paths && src_binding->path_count > 0) {
dst_binding->path_count = src_binding->path_count;
dst_binding->paths = U_TYPED_ARRAY_CALLOC(XrPath, src_binding->path_count);
memcpy(dst_binding->paths, src_binding->paths,
sizeof(XrPath) * src_binding->path_count);
}
dst_binding->key_count = 0;
dst_binding->keys = NULL;
dst_binding->preferred_binding_path_index = NULL;
if (src_binding->keys && src_binding->key_count > 0) {
dst_binding->key_count = src_binding->key_count;
dst_binding->keys = U_TYPED_ARRAY_CALLOC(uint32_t, src_binding->key_count);
memcpy(dst_binding->keys, src_binding->keys, sizeof(uint32_t) * src_binding->key_count);
}
if (src_binding->preferred_binding_path_index && src_binding->key_count > 0) {
assert(dst_binding->key_count == src_binding->key_count);
dst_binding->preferred_binding_path_index =
U_TYPED_ARRAY_CALLOC(uint32_t, src_binding->key_count);
memcpy(dst_binding->preferred_binding_path_index,
src_binding->preferred_binding_path_index,
sizeof(uint32_t) * src_binding->key_count);
}
}
}
dst_profile->dpad_count = 0;
dst_profile->dpads = NULL;
if (src_profile->dpads && src_profile->dpad_count > 0) {
dst_profile->dpad_count = src_profile->dpad_count;
dst_profile->dpads = U_TYPED_ARRAY_CALLOC(struct oxr_dpad_emulation, src_profile->dpad_count);
for (size_t dpad_index = 0; dpad_index < src_profile->dpad_count; ++dpad_index) {
struct oxr_dpad_emulation *dst_dpad = dst_profile->dpads + dpad_index;
const struct oxr_dpad_emulation *src_dpad = src_profile->dpads + dpad_index;
*dst_dpad = *src_dpad;
dst_dpad->path_count = 0;
dst_dpad->paths = NULL;
if (src_dpad->paths && src_dpad->path_count > 0) {
dst_dpad->path_count = src_dpad->path_count;
dst_dpad->paths = U_TYPED_ARRAY_CALLOC(XrPath, src_dpad->path_count);
memcpy(dst_dpad->paths, src_dpad->paths, sizeof(XrPath) * src_dpad->path_count);
}
}
}
return dst_profile;
}
static void
oxr_destroy_profiles(struct oxr_interaction_profile **profiles, const size_t profile_count)
{
if (profiles == NULL)
return;
for (size_t x = 0; x < profile_count; x++) {
struct oxr_interaction_profile *p = profiles[x];
for (size_t y = 0; y < p->binding_count; y++) {
struct oxr_binding *b = &p->bindings[y];
@ -451,11 +563,24 @@ oxr_binding_destroy_all(struct oxr_logger *log, struct oxr_instance *inst)
free(p);
}
free(inst->profiles);
free(profiles);
}
void
oxr_binding_destroy_all(struct oxr_logger *log, struct oxr_instance *inst)
{
oxr_destroy_profiles(inst->profiles, inst->profile_count);
inst->profiles = NULL;
inst->profile_count = 0;
}
void
oxr_session_binding_destroy_all(struct oxr_logger *log, struct oxr_session *sess)
{
oxr_destroy_profiles(sess->profiles_on_attachment, sess->profiles_on_attachment_size);
sess->profiles_on_attachment = NULL;
sess->profiles_on_attachment_size = 0;
}
/*
*
@ -473,7 +598,7 @@ oxr_action_suggest_interaction_profile_bindings(struct oxr_logger *log,
// Path already validated.
XrPath path = suggestedBindings->interactionProfile;
interaction_profile_find_or_create(log, inst, path, &p);
interaction_profile_find_or_create_in_instance(log, inst, path, &p);
// Valid path, but not used.
if (p == NULL) {
@ -559,7 +684,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.
interaction_profile_find(log, sess->sys->inst, path, &oip);
internaction_profile_find_in_session(log, sess, path, &oip);
if (oip == NULL) {
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "no interaction profile found");
}

View file

@ -1522,14 +1522,36 @@ oxr_handle_base_get_num_children(struct oxr_handle_base *hb)
return ret;
}
static void
oxr_clone_profiles_to_session(struct oxr_logger *log, struct oxr_instance *inst, struct oxr_session *sess)
{
if (inst == NULL || sess == NULL)
return;
oxr_session_binding_destroy_all(log, sess);
if (inst->profiles == NULL || inst->profile_count == 0)
return;
sess->profiles_on_attachment_size = inst->profile_count;
sess->profiles_on_attachment = U_TYPED_ARRAY_CALLOC(struct oxr_interaction_profile *, inst->profile_count);
for (size_t profile_idx = 0; profile_idx < inst->profile_count; ++profile_idx) {
sess->profiles_on_attachment[profile_idx] = oxr_clone_profile(inst->profiles[profile_idx]);
}
}
XrResult
oxr_session_attach_action_sets(struct oxr_logger *log,
struct oxr_session *sess,
const XrSessionActionSetsAttachInfo *bindInfo)
{
struct oxr_instance *inst = sess->sys->inst;
oxr_clone_profiles_to_session(log, inst, sess);
struct oxr_profiles_per_subaction profiles = {0};
#define FIND_PROFILE(X) oxr_find_profile_for_device(log, inst, GET_XDEV_BY_ROLE(sess->sys, X), &profiles.X);
#define FIND_PROFILE(X) oxr_find_profile_for_device(log, sess, GET_XDEV_BY_ROLE(sess->sys, X), &profiles.X);
OXR_FOR_EACH_VALID_SUBACTION_PATH(FIND_PROFILE)
#undef FIND_PROFILE

View file

@ -555,10 +555,13 @@ oxr_hand_tracker_create(struct oxr_logger *log,
*/
void
oxr_find_profile_for_device(struct oxr_logger *log,
struct oxr_instance *inst,
struct oxr_session *sess,
struct xrt_device *xdev,
struct oxr_interaction_profile **out_p);
struct oxr_interaction_profile *
oxr_clone_profile(const struct oxr_interaction_profile *src_profile);
/*!
* Free all memory allocated by the binding system.
*
@ -567,6 +570,14 @@ oxr_find_profile_for_device(struct oxr_logger *log,
void
oxr_binding_destroy_all(struct oxr_logger *log, struct oxr_instance *inst);
/*!
* Free all memory allocated by the binding system.
*
* @public @memberof oxr_instance
*/
void
oxr_session_binding_destroy_all(struct oxr_logger *log, struct oxr_session *sess);
/*!
* Find all bindings that is the given action key is bound to.
* @public @memberof oxr_interaction_profile
@ -1521,6 +1532,12 @@ struct oxr_session
*/
struct u_hashmap_int *act_attachments_by_key;
/*!
* Clone of all suggested binding profiles at the point of action set/session attachment.
* ref to @oxr_session_attach_action_sets
*/
size_t profiles_on_attachment_size;
struct oxr_interaction_profile **profiles_on_attachment;
/*!
* Currently bound interaction profile.

View file

@ -651,6 +651,8 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
XrResult ret = oxr_event_remove_session_events(log, sess);
oxr_session_binding_destroy_all(log, sess);
for (size_t i = 0; i < sess->action_set_attachment_count; ++i) {
oxr_action_set_attachment_teardown(&sess->act_set_attachments[i]);
}