Monado OpenXR Runtime
oxr_input.c File Reference

Holds input related functions. More...

#include "util/u_debug.h"
#include "util/u_time.h"
#include "util/u_misc.h"
#include "math/m_vec2.h"
#include "xrt/xrt_compiler.h"
#include "oxr_objects.h"
#include "oxr_logger.h"
#include "oxr_handle.h"
#include "oxr_two_call.h"
#include "oxr_input_transform.h"
#include "oxr_subaction.h"
#include "oxr_conversions.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
Include dependency graph for oxr_input.c:

Data Structures

struct  oxr_profiles_per_subaction
 

Macros

#define ACCUMULATE_SUBACTION_PATHS(X)   subaction_paths->X |= new_subaction_paths->X;
 
#define CACHE_TEARDOWN(X)   oxr_action_cache_teardown(&(act_attached->X));
 
#define IDENTIFY_PATH(X)
 
#define GET_POSE_INPUT(X)
 
#define PATH_CASE(NAME, NAMECAPS, PATH)
 
#define PROFILE_MEMBER(X)   struct oxr_interaction_profile *X;
 
#define FIND_PROFILE(X)
 
#define BIND_SUBACTION(NAME, NAME_CAPS, PATH)
 
#define RESET_ANY(NAME)   act_attached->any_pose_subaction_path.NAME = false;
 
#define POSE_ANY(NAME)
 
#define ACCUMULATE_PATHS(X)
 
#define ACCUMULATE_PATHS(X)    relevant_subactionpath |= (other_act_set_attached->requested_subaction_paths.X && subaction_path->X);
 
#define BOOL_CHECK(NAME)   oxr_state_update_bool(&active, &value, &timestamp, &act_attached->NAME.current);
 
#define VEC1_CHECK(NAME)   oxr_state_update_vec1(&active, &value, &timestamp, &act_attached->NAME.current);
 
#define VEC2_CHECK(NAME)   oxr_state_update_vec2(&active, &x, &y, &distance, &timestamp, &act_attached->NAME.current);
 
#define UPDATE_SELECT(X)
 
#define FIND_PROFILE(X)   oxr_find_profile_for_device(log, sess, GET_XDEV_BY_ROLE(sess->sys, X), &profiles.X);
 
#define POPULATE_PROFILE(X)
 
#define POPULATE_PROFILE(X)
 
#define ACCUMULATE_REQUESTED(X)    any_action_with_subactionpath |= subaction_paths.X && act_attached->act_ref->subaction_paths.X;
 
#define ACCUMULATE_PATHS(X)
 
#define OXR_ACTION_GET_XR_STATE_FROM_ACTION_STATE_COMMON(ACTION_STATE, DATA)
 
#define OXR_ACTION_GET_FILLER(TYPE)
 This populates the internals of action get state functions. More...
 
#define OXR_ACTION_RESET_XR_ACTION_STATE(data)
 Clear the actual data members of the XrActionState* types, to have the correct return value in case of the action being not active. More...
 
#define COMPUTE_ACTIVE(X)
 
#define SET_OUT_VIBRATION(X)
 
#define STOP_VIBRATION(X)
 

Functions

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_session_get_action_attachment (struct oxr_session *sess, uint32_t act_key, struct oxr_action_attachment **out_act_attached)
 
static void oxr_action_cache_update (struct oxr_logger *log, struct oxr_session *sess, uint32_t countActionSets, const XrActiveActionSet *actionSets, struct oxr_action_attachment *act_attached, struct oxr_action_cache *cache, int64_t time, struct oxr_subaction_paths *subaction_path, bool select)
 
static void oxr_action_attachment_update (struct oxr_logger *log, struct oxr_session *sess, uint32_t countActionSets, const XrActiveActionSet *actionSets, struct oxr_action_attachment *act_attached, int64_t time, struct oxr_subaction_paths subaction_paths)
 
static void oxr_action_bind_io (struct oxr_logger *log, struct oxr_sink_logger *slog, struct oxr_session *sess, const struct oxr_action_ref *act_ref, const uint32_t act_set_key, struct oxr_action_cache *cache, struct oxr_interaction_profile *profile, enum oxr_subaction_path subaction_path)
 
void oxr_action_set_attachment_teardown (struct oxr_action_set_attachment *act_set_attached)
 
static void oxr_action_set_ref_destroy_cb (struct oxr_refcounted *orc)
 
static XrResult oxr_action_set_destroy_cb (struct oxr_logger *log, struct oxr_handle_base *hb)
 
XrResult oxr_action_set_create (struct oxr_logger *log, struct oxr_instance *inst, const XrActionSetCreateInfo *createInfo, struct oxr_action_set **out_act_set)
 
static void oxr_action_ref_destroy_cb (struct oxr_refcounted *orc)
 
static XrResult oxr_action_destroy_cb (struct oxr_logger *log, struct oxr_handle_base *hb)
 
XrResult oxr_action_create (struct oxr_logger *log, struct oxr_action_set *act_set, const XrActionCreateInfo *createInfo, struct oxr_action **out_act)
 
bool oxr_classify_subaction_paths (struct oxr_logger *log, const struct oxr_instance *inst, uint32_t subaction_path_count, const XrPath *subaction_paths, struct oxr_subaction_paths *subaction_paths_out)
 
XrResult oxr_action_get_pose_input (struct oxr_session *sess, uint32_t act_key, const struct oxr_subaction_paths *subaction_paths_ptr, struct oxr_action_input **out_input)
 
static bool do_inputs (struct oxr_binding *binding_point, struct xrt_device *xdev, struct xrt_binding_profile *xbp, XrPath matched_path, struct oxr_action_input inputs[32], uint32_t *input_count)
 
static bool do_outputs (struct oxr_binding *binding_point, struct xrt_device *xdev, struct xrt_binding_profile *xbp, XrPath matched_path, struct oxr_action_output outputs[32], uint32_t *output_count)
 
static bool do_io_bindings (struct oxr_binding *binding_point, const struct oxr_action_ref *act_ref, struct xrt_device *xdev, struct xrt_binding_profile *xbp, XrPath matched_path, struct oxr_action_input inputs[32], uint32_t *input_count, struct oxr_action_output outputs[32], uint32_t *output_count)
 Delegate to do_outputs or do_inputs depending on whether the action is output or input. More...
 
static struct xrt_binding_profileget_matching_binding_profile (struct oxr_interaction_profile *profile, struct xrt_device *xdev)
 
static XrPath get_matched_xrpath (struct oxr_binding *b, const struct oxr_action_ref *act)
 
static void get_binding (struct oxr_logger *log, struct oxr_sink_logger *slog, struct oxr_session *sess, const struct oxr_action_ref *act_ref, struct oxr_interaction_profile *profile, enum oxr_subaction_path subaction_path, struct oxr_action_input inputs[32], uint32_t *input_count, struct oxr_action_output outputs[32], uint32_t *output_count)
 
static void oxr_find_profiles_from_roles (struct oxr_logger *log, struct oxr_session *sess, struct oxr_profiles_per_subaction *out_profiles)
 
static void oxr_action_cache_stop_output (struct oxr_logger *log, struct oxr_session *sess, struct oxr_action_cache *cache)
 
static bool oxr_input_is_input_for_cache (struct oxr_action_input *action_input, struct oxr_action_cache *cache)
 
static bool oxr_input_is_bound_in_act_set (struct oxr_action_input *action_input, struct oxr_action_set_attachment *act_set_attached)
 
static bool oxr_input_supressed (struct oxr_session *sess, uint32_t countActionSets, const XrActiveActionSet *actionSets, struct oxr_subaction_paths *subaction_path, struct oxr_action_attachment *act_attached, struct oxr_action_input *action_input)
 
static bool oxr_input_combine_input (struct oxr_session *sess, uint32_t countActionSets, const XrActiveActionSet *actionSets, struct oxr_action_attachment *act_attached, struct oxr_subaction_paths *subaction_path, struct oxr_action_cache *cache, struct oxr_input_value_tagged *out_input, int64_t *out_timestamp, bool *out_is_active)
 
static bool oxr_state_equal_bool (const struct oxr_action_state *a, const struct oxr_action_state *b)
 
static bool oxr_state_equal_vec1 (const struct oxr_action_state *a, const struct oxr_action_state *b)
 
static bool oxr_state_equal_vec2 (const struct oxr_action_state *a, const struct oxr_action_state *b)
 
static void oxr_state_update_bool (bool *active, bool *value, XrTime *timestamp, const struct oxr_action_state *new_state)
 
static void oxr_state_update_vec1 (bool *active, float *value, XrTime *timestamp, const struct oxr_action_state *new_state)
 
static void oxr_state_update_vec2 (bool *active, float *x, float *y, float *distance, XrTime *timestamp, const struct oxr_action_state *new_state)
 
static bool oxr_action_populate_input_transform (struct oxr_logger *log, struct oxr_sink_logger *slog, struct oxr_session *sess, const struct oxr_action_ref *act_ref, struct oxr_action_input *action_input)
 Try to produce a transform chain to convert the available input into the desired input type. More...
 
static bool find_matching_dpad (struct oxr_logger *log, struct oxr_instance *inst, struct oxr_dpad_entry *dpad_entry, const char *bound_path_string, struct oxr_dpad_binding_modification **out_dpad_binding)
 Find dpad settings in dpad_entry whose binding path is a prefix of bound_path_string. More...
 
static bool oxr_action_populate_input_transform_dpad (struct oxr_logger *log, struct oxr_sink_logger *slog, struct oxr_session *sess, const struct oxr_action_ref *act_ref, struct oxr_dpad_entry *dpad_entry, enum oxr_dpad_region dpad_region, struct oxr_interaction_profile *profile, struct oxr_action_input *action_inputs, uint32_t action_input_count, uint32_t selected_input)
 Try to produce a transform chain to create a dpad button from the selected input (potentially using other inputs like /force in the process). More...
 
static bool get_dpad_region_from_path (struct oxr_logger *log, struct oxr_instance *inst, XrPath path, enum oxr_dpad_region *out_dpad_region)
 
static size_t oxr_handle_base_get_num_children (struct oxr_handle_base *hb)
 
static void oxr_clone_profiles_to_session (struct oxr_logger *log, struct oxr_instance *inst, struct oxr_session *sess)
 
XrResult oxr_session_attach_action_sets (struct oxr_logger *log, struct oxr_session *sess, const XrSessionActionSetsAttachInfo *bindInfo)
 
XrResult oxr_session_update_action_bindings (struct oxr_logger *log, struct oxr_session *sess)
 
XrResult oxr_action_sync_data (struct oxr_logger *log, struct oxr_session *sess, uint32_t countActionSets, const XrActiveActionSet *actionSets)
 
static void add_path_to_set (XrPath path_set[32], XrPath new_path, uint32_t *inout_path_count)
 
XrResult oxr_action_enumerate_bound_sources (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, uint32_t sourceCapacityInput, uint32_t *sourceCountOutput, XrPath *sources)
 
static void get_xr_state_from_action_state_bool (struct oxr_instance *inst, struct oxr_action_state *state, XrActionStateBoolean *data)
 
static void get_xr_state_from_action_state_vec1 (struct oxr_instance *inst, struct oxr_action_state *state, XrActionStateFloat *data)
 
static void get_xr_state_from_action_state_vec2 (struct oxr_instance *inst, struct oxr_action_state *state, XrActionStateVector2f *data)
 
XrResult oxr_action_get_boolean (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, struct oxr_subaction_paths subaction_paths, XrActionStateBoolean *data)
 
XrResult oxr_action_get_vector1f (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, struct oxr_subaction_paths subaction_paths, XrActionStateFloat *data)
 
XrResult oxr_action_get_vector2f (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, struct oxr_subaction_paths subaction_paths, XrActionStateVector2f *data)
 
XrResult oxr_action_get_pose (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, struct oxr_subaction_paths subaction_paths, XrActionStatePose *data)
 
static void set_action_output_vibration (struct oxr_session *sess, struct oxr_action_cache *cache, int64_t stop, const XrHapticVibration *data)
 
XrResult oxr_action_apply_haptic_feedback (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, struct oxr_subaction_paths subaction_paths, const XrHapticBaseHeader *hapticEvent)
 
XrResult oxr_action_stop_haptic_feedback (struct oxr_logger *log, struct oxr_session *sess, uint32_t act_key, struct oxr_subaction_paths subaction_paths)
 

Detailed Description

Macro Definition Documentation

◆ ACCUMULATE_PATHS [1/2]

#define ACCUMULATE_PATHS (   X)
Value:
if (oxr_input_is_input_for_cache(action_input, &act_attached->X)) { \
return true; \
}

◆ ACCUMULATE_PATHS [2/2]

#define ACCUMULATE_PATHS (   X)
Value:
if (act_attached->X.input_count > 0) { \
for (uint32_t i = 0; i < act_attached->X.input_count; i++) { \
add_path_to_set(temp, act_attached->X.inputs[i].bound_path, &path_count); \
} \
} \
if (act_attached->X.output_count > 0) { \
for (uint32_t i = 0; i < act_attached->X.output_count; i++) { \
add_path_to_set(temp, act_attached->X.outputs[i].bound_path, &path_count); \
} \
}

◆ BIND_SUBACTION

#define BIND_SUBACTION (   NAME,
  NAME_CAPS,
  PATH 
)
Value:
if (act_ref->subaction_paths.NAME || act_ref->subaction_paths.any) { \
oxr_action_bind_io(log, &slog, sess, act_ref, act_set_key, &act_attached->NAME, profiles->NAME, \
OXR_SUB_ACTION_PATH_##NAME_CAPS); \
}

◆ COMPUTE_ACTIVE

#define COMPUTE_ACTIVE (   X)
Value:
if (subaction_paths.X) { \
data->isActive |= act_attached->X.current.active; \
}

◆ FIND_PROFILE

#define FIND_PROFILE (   X)
Value:
{ \
struct xrt_device *xdev = GET_XDEV_BY_ROLE(sess->sys, X); \
if (xdev != NULL) { \
oxr_find_profile_for_device(log, sess, xdev, &out_profiles->X); \
} else { \
oxr_get_profile_for_device_name(log, sess, GET_PROFILE_NAME_BY_ROLE(sess->sys, X), \
&out_profiles->X); \
} \
}
A single HMD or input device.
Definition: xrt_device.h:230

◆ GET_POSE_INPUT

#define GET_POSE_INPUT (   X)
Value:
if (act_attached->X.current.active && subaction_paths.X) { \
*out_input = act_attached->X.inputs; \
return XR_SUCCESS; \
}

◆ IDENTIFY_PATH

#define IDENTIFY_PATH (   X)
Value:
else if (path == inst->path_cache.X) \
{ \
subaction_paths_out->X = true; \
}

◆ OXR_ACTION_GET_FILLER

#define OXR_ACTION_GET_FILLER (   TYPE)
Value:
if (subaction_paths.any && act_attached->any_state.active) { \
get_xr_state_from_action_state_##TYPE(sess->sys->inst, &act_attached->any_state, data); \
} \
if (subaction_paths.user && act_attached->user.current.active) { \
get_xr_state_from_action_state_##TYPE(sess->sys->inst, &act_attached->user.current, data); \
} \
if (subaction_paths.head && act_attached->head.current.active) { \
get_xr_state_from_action_state_##TYPE(sess->sys->inst, &act_attached->head.current, data); \
} \
if (subaction_paths.left && act_attached->left.current.active) { \
get_xr_state_from_action_state_##TYPE(sess->sys->inst, &act_attached->left.current, data); \
} \
if (subaction_paths.right && act_attached->right.current.active) { \
get_xr_state_from_action_state_##TYPE(sess->sys->inst, &act_attached->right.current, data); \
} \
if (subaction_paths.gamepad && act_attached->gamepad.current.active) { \
get_xr_state_from_action_state_##TYPE(sess->sys->inst, &act_attached->gamepad.current, data); \
}

This populates the internals of action get state functions.

Note
Keep this synchronized with OXR_FOR_EACH_SUBACTION_PATH!

◆ OXR_ACTION_GET_XR_STATE_FROM_ACTION_STATE_COMMON

#define OXR_ACTION_GET_XR_STATE_FROM_ACTION_STATE_COMMON (   ACTION_STATE,
  DATA 
)
Value:
do { \
DATA->lastChangeTime = time_state_monotonic_to_ts_ns(inst->timekeeping, ACTION_STATE->timestamp); \
DATA->changedSinceLastSync = ACTION_STATE->changed; \
DATA->isActive = XR_TRUE; \
} while (0)
timepoint_ns time_state_monotonic_to_ts_ns(struct time_state const *state, uint64_t monotonic_ns)
Convert a monotonic system time (such as from Portable Timekeeping) to an adjusted integer timestamp.
Definition: u_time.cpp:107

◆ OXR_ACTION_RESET_XR_ACTION_STATE

#define OXR_ACTION_RESET_XR_ACTION_STATE (   data)
Value:
do { \
data->isActive = XR_FALSE; \
data->changedSinceLastSync = XR_FALSE; \
data->lastChangeTime = 0; \
U_ZERO(&data->currentState); \
} while (0)

Clear the actual data members of the XrActionState* types, to have the correct return value in case of the action being not active.

◆ PATH_CASE

#define PATH_CASE (   NAME,
  NAMECAPS,
  PATH 
)
Value:
case OXR_SUB_ACTION_PATH_##NAMECAPS: \
user_path_str = PATH; \
xdev = GET_XDEV_BY_ROLE(sess->sys, NAME); \
break;

◆ POPULATE_PROFILE [1/2]

#define POPULATE_PROFILE (   X)
Value:
sess->X = XR_NULL_PATH; \
if (profiles.X != NULL) { \
sess->X = profiles.X->path; \
oxr_event_push_XrEventDataInteractionProfileChanged(log, sess); \
}

◆ POPULATE_PROFILE [2/2]

#define POPULATE_PROFILE (   X)
Value:
sess->X = XR_NULL_PATH; \
if (profiles.X != NULL) { \
sess->X = profiles.X->path; \
oxr_event_push_XrEventDataInteractionProfileChanged(log, sess); \
}

◆ POSE_ANY

#define POSE_ANY (   NAME)
Value:
if ((act_ref->subaction_paths.NAME || act_ref->subaction_paths.any) && act_attached->NAME.input_count > 0) { \
act_attached->any_pose_subaction_path.NAME = true; \
oxr_slog(&slog, "\tFor: <any>\n\t\tBinding any pose to " #NAME ".\n"); \
} else

◆ SET_OUT_VIBRATION

#define SET_OUT_VIBRATION (   X)
Value:
if (is_focused && act_attached->X.current.active && (subaction_paths.X || subaction_paths.any)) { \
set_action_output_vibration(sess, &act_attached->X, stop_ns, data); \
}

◆ STOP_VIBRATION

#define STOP_VIBRATION (   X)
Value:
if (is_focused && act_attached->X.current.active && (subaction_paths.X || subaction_paths.any)) { \
oxr_action_cache_stop_output(log, sess, &act_attached->X); \
}

◆ UPDATE_SELECT

#define UPDATE_SELECT (   X)
Value:
struct oxr_subaction_paths subaction_paths_##X = {0}; \
subaction_paths_##X.X = true; \
bool select_##X = subaction_paths.X || subaction_paths.any; \
oxr_action_cache_update(log, sess, countActionSets, actionSets, act_attached, &act_attached->X, time, \
&subaction_paths_##X, select_##X);
A parsed equivalent of a list of sub-action paths.
Definition: oxr_objects.h:1935

Function Documentation

◆ do_io_bindings()

static bool do_io_bindings ( struct oxr_binding binding_point,
const struct oxr_action_ref act_ref,
struct xrt_device xdev,
struct xrt_binding_profile xbp,
XrPath  matched_path,
struct oxr_action_input  inputs[32],
uint32_t *  input_count,
struct oxr_action_output  outputs[32],
uint32_t *  output_count 
)
static

Delegate to do_outputs or do_inputs depending on whether the action is output or input.

◆ find_matching_dpad()

static bool find_matching_dpad ( struct oxr_logger log,
struct oxr_instance inst,
struct oxr_dpad_entry dpad_entry,
const char *  bound_path_string,
struct oxr_dpad_binding_modification **  out_dpad_binding 
)
static

Find dpad settings in dpad_entry whose binding path is a prefix of bound_path_string.

Returns
true if settings were found and written to out_dpad_settings

◆ get_binding()

static void get_binding ( struct oxr_logger log,
struct oxr_sink_logger slog,
struct oxr_session sess,
const struct oxr_action_ref act_ref,
struct oxr_interaction_profile profile,
enum oxr_subaction_path  subaction_path,
struct oxr_action_input  inputs[32],
uint32_t *  input_count,
struct oxr_action_output  outputs[32],
uint32_t *  output_count 
)
static
Todo:
This probably falls on its head if the application doesn't use sub action paths.

Lookup device binding that matches the interactive profile, this is used as a fallback should the device not match the interactive profile. This allows the device to provide a mapping from one device to itself.

◆ oxr_action_populate_input_transform()

static bool oxr_action_populate_input_transform ( struct oxr_logger log,
struct oxr_sink_logger slog,
struct oxr_session sess,
const struct oxr_action_ref act_ref,
struct oxr_action_input action_input 
)
static

Try to produce a transform chain to convert the available input into the desired input type.

Populates action_input->transforms and action_input->transform_count on success.

Returns
false if it could not, true if it could

◆ oxr_action_populate_input_transform_dpad()

static bool oxr_action_populate_input_transform_dpad ( struct oxr_logger log,
struct oxr_sink_logger slog,
struct oxr_session sess,
const struct oxr_action_ref act_ref,
struct oxr_dpad_entry dpad_entry,
enum oxr_dpad_region  dpad_region,
struct oxr_interaction_profile profile,
struct oxr_action_input action_inputs,
uint32_t  action_input_count,
uint32_t  selected_input 
)
static

Try to produce a transform chain to create a dpad button from the selected input (potentially using other inputs like /force in the process).

Populates action_input->transforms and action_input->transform_count on success.

Returns
false if it could not, true if it could

◆ oxr_action_sync_data()

XrResult oxr_action_sync_data ( struct oxr_logger log,
struct oxr_session sess,
uint32_t  countActionSets,
const XrActiveActionSet *  actionSets 
)