mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-29 18:08:29 +00:00
Enable eye tracking on demand
Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2223>
This commit is contained in:
parent
357cf0e93b
commit
ed1ea5af73
|
@ -44,6 +44,16 @@ get_index_for_device(const struct xrt_system_devices *xsysd, const struct xrt_de
|
|||
return -1;
|
||||
}
|
||||
|
||||
static const char *
|
||||
type_to_small_string(enum xrt_device_feature_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT: return "hand_tracking_left";
|
||||
case XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT: return "hand_tracking_right";
|
||||
case XRT_DEVICE_FEATURE_EYE_TRACKING: return "eye_tracking";
|
||||
default: return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -71,6 +81,72 @@ get_roles(struct xrt_system_devices *xsysd, struct xrt_system_roles *out_roles)
|
|||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
feature_inc(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
|
||||
{
|
||||
struct u_system_devices_static *usysds = u_system_devices_static(xsysd);
|
||||
|
||||
if (type >= XRT_DEVICE_FEATURE_MAX_ENUM) {
|
||||
return XRT_ERROR_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// If it wasn't zero nothing to do.
|
||||
if (!xrt_reference_inc_and_was_zero(&usysds->feature_use[type])) {
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xrt_result_t xret;
|
||||
if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT) {
|
||||
xret = xrt_device_begin_feature(xsysd->static_roles.hand_tracking.left, type);
|
||||
} else if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT) {
|
||||
xret = xrt_device_begin_feature(xsysd->static_roles.hand_tracking.right, type);
|
||||
} else if (type == XRT_DEVICE_FEATURE_EYE_TRACKING) {
|
||||
xret = xrt_device_begin_feature(xsysd->static_roles.eyes, type);
|
||||
} else {
|
||||
xret = XRT_ERROR_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
if (xret != XRT_SUCCESS) {
|
||||
return xret;
|
||||
}
|
||||
|
||||
U_LOG_D("Device-feature %s in use", type_to_small_string(type));
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
feature_dec(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
|
||||
{
|
||||
struct u_system_devices_static *usysds = u_system_devices_static(xsysd);
|
||||
|
||||
if (type >= XRT_DEVICE_FEATURE_MAX_ENUM) {
|
||||
return XRT_ERROR_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// If it is not zero we are done.
|
||||
if (!xrt_reference_dec_and_is_zero(&usysds->feature_use[type])) {
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xrt_result_t xret;
|
||||
if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT) {
|
||||
xret = xrt_device_end_feature(xsysd->static_roles.hand_tracking.left, type);
|
||||
} else if (type == XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT) {
|
||||
xret = xrt_device_end_feature(xsysd->static_roles.hand_tracking.right, type);
|
||||
} else if (type == XRT_DEVICE_FEATURE_EYE_TRACKING) {
|
||||
xret = xrt_device_end_feature(xsysd->static_roles.eyes, type);
|
||||
} else {
|
||||
xret = XRT_ERROR_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
if (xret != XRT_SUCCESS) {
|
||||
return xret;
|
||||
}
|
||||
|
||||
U_LOG_D("Device-feature %s no longer in use", type_to_small_string(type));
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -107,6 +183,8 @@ u_system_devices_static_allocate(void)
|
|||
struct u_system_devices_static *usysds = U_TYPED_CALLOC(struct u_system_devices_static);
|
||||
usysds->base.base.destroy = destroy;
|
||||
usysds->base.base.get_roles = get_roles;
|
||||
usysds->base.base.feature_inc = feature_inc;
|
||||
usysds->base.base.feature_dec = feature_dec;
|
||||
|
||||
return usysds;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,9 @@ struct u_system_devices_static
|
|||
|
||||
//! Is automatically returned.
|
||||
struct xrt_system_roles cached;
|
||||
|
||||
//! Tracks usage of device features.
|
||||
struct xrt_reference feature_use[XRT_DEVICE_FEATURE_MAX_ENUM];
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
|
@ -219,6 +219,17 @@ struct xrt_binding_profile
|
|||
size_t output_count;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Higher level features for devices.
|
||||
*/
|
||||
enum xrt_device_feature_type
|
||||
{
|
||||
XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT = 0,
|
||||
XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT,
|
||||
XRT_DEVICE_FEATURE_EYE_TRACKING,
|
||||
XRT_DEVICE_FEATURE_MAX_ENUM,
|
||||
};
|
||||
|
||||
/*!
|
||||
* @interface xrt_device
|
||||
*
|
||||
|
@ -519,6 +530,22 @@ struct xrt_device
|
|||
bool *out_charging,
|
||||
float *out_charge);
|
||||
|
||||
/*!
|
||||
* Enable the feature for this device.
|
||||
*
|
||||
* @param[in] xdev The device.
|
||||
* @param[in] type The type of device feature.
|
||||
*/
|
||||
xrt_result_t (*begin_feature)(struct xrt_device *xdev, enum xrt_device_feature_type type);
|
||||
|
||||
/*!
|
||||
* Disable the feature for this device.
|
||||
*
|
||||
* @param[in] xdev The device.
|
||||
* @param[in] type The type of device feature.
|
||||
*/
|
||||
xrt_result_t (*end_feature)(struct xrt_device *xdev, enum xrt_device_feature_type type);
|
||||
|
||||
/*!
|
||||
* Destroy device.
|
||||
*/
|
||||
|
@ -736,6 +763,38 @@ xrt_device_get_battery_status(struct xrt_device *xdev, bool *out_present, bool *
|
|||
return xdev->get_battery_status(xdev, out_present, out_charging, out_charge);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Helper function for @ref xrt_device::begin_feature.
|
||||
*
|
||||
* @copydoc xrt_device::begin_feature
|
||||
*
|
||||
* @public @memberof xrt_device
|
||||
*/
|
||||
static inline xrt_result_t
|
||||
xrt_device_begin_feature(struct xrt_device *xdev, enum xrt_device_feature_type type)
|
||||
{
|
||||
if (xdev->begin_feature == NULL) {
|
||||
return XRT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return xdev->begin_feature(xdev, type);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Helper function for @ref xrt_device::end_feature.
|
||||
*
|
||||
* @copydoc xrt_device::end_feature
|
||||
*
|
||||
* @public @memberof xrt_device
|
||||
*/
|
||||
static inline xrt_result_t
|
||||
xrt_device_end_feature(struct xrt_device *xdev, enum xrt_device_feature_type type)
|
||||
{
|
||||
if (xdev->end_feature == NULL) {
|
||||
return XRT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return xdev->end_feature(xdev, type);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Helper function for @ref xrt_device::destroy.
|
||||
*
|
||||
|
|
|
@ -193,4 +193,9 @@ typedef enum xrt_result
|
|||
* Some other Android error, typically a logic error that should be impossible to reach.
|
||||
*/
|
||||
XRT_ERROR_ANDROID = -31,
|
||||
|
||||
/*!
|
||||
* Returned when a feature is not supported by the device.
|
||||
*/
|
||||
XRT_ERROR_FEATURE_NOT_SUPPORTED = -32,
|
||||
} xrt_result_t;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "xrt/xrt_compiler.h"
|
||||
#include "xrt/xrt_defines.h"
|
||||
#include "xrt/xrt_device.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -301,6 +302,24 @@ struct xrt_system_devices
|
|||
*/
|
||||
xrt_result_t (*get_roles)(struct xrt_system_devices *xsysd, struct xrt_system_roles *out_roles);
|
||||
|
||||
/*!
|
||||
* Increment the usage count of a feature.
|
||||
* When the feature is used for the first time, then the feature will be begun.
|
||||
*
|
||||
* @param xsysd Pointer to self
|
||||
* @param feature Which feature is being counted.
|
||||
*/
|
||||
xrt_result_t (*feature_inc)(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type);
|
||||
|
||||
/*!
|
||||
* Decrement the usage count of a feature.
|
||||
* When the feature is not used by the current application any more, then the feature will be ended.
|
||||
*
|
||||
* @param xsysd Pointer to self
|
||||
* @param feature Which feature is being counted.
|
||||
*/
|
||||
xrt_result_t (*feature_dec)(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type);
|
||||
|
||||
/*!
|
||||
* Destroy all the devices that are owned by this system devices.
|
||||
*
|
||||
|
@ -324,6 +343,32 @@ xrt_system_devices_get_roles(struct xrt_system_devices *xsysd, struct xrt_system
|
|||
return xsysd->get_roles(xsysd, out_roles);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @copydoc xrt_system_devices::feature_inc
|
||||
*
|
||||
* Helper for calling through the function pointer.
|
||||
*
|
||||
* @public @memberof xrt_system_devices
|
||||
*/
|
||||
static inline xrt_result_t
|
||||
xrt_system_devices_feature_inc(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
|
||||
{
|
||||
return xsysd->feature_inc(xsysd, type);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @copydoc xrt_system_devices::feature_dec
|
||||
*
|
||||
* Helper for calling through the function pointer.
|
||||
*
|
||||
* @public @memberof xrt_system_devices
|
||||
*/
|
||||
static inline xrt_result_t
|
||||
xrt_system_devices_feature_dec(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
|
||||
{
|
||||
return xsysd->feature_dec(xsysd, type);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destroy an xrt_system_devices and owned devices - helper function.
|
||||
*
|
||||
|
|
|
@ -21,6 +21,8 @@ struct ipc_client_system_devices
|
|||
|
||||
//! Connection to service.
|
||||
struct ipc_connection *ipc_c;
|
||||
|
||||
struct xrt_reference feature_use[XRT_DEVICE_FEATURE_MAX_ENUM];
|
||||
};
|
||||
|
||||
|
||||
|
@ -51,6 +53,41 @@ ipc_client_system_devices_get_roles(struct xrt_system_devices *xsysd, struct xrt
|
|||
return ipc_call_system_devices_get_roles(usysd->ipc_c, out_roles);
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
ipc_client_system_devices_feature_inc(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
|
||||
{
|
||||
struct ipc_client_system_devices *usysd = ipc_system_devices(xsysd);
|
||||
xrt_result_t xret;
|
||||
|
||||
assert(type < XRT_DEVICE_FEATURE_MAX_ENUM);
|
||||
|
||||
// If it wasn't zero nothing to do.
|
||||
if (!xrt_reference_inc_and_was_zero(&usysd->feature_use[type])) {
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xret = ipc_call_system_devices_begin_feature(usysd->ipc_c, type);
|
||||
IPC_CHK_ALWAYS_RET(usysd->ipc_c, xret, "ipc_call_system_devices_begin_feature");
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
ipc_client_system_devices_feature_dec(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
|
||||
{
|
||||
struct ipc_client_system_devices *usysd = ipc_system_devices(xsysd);
|
||||
xrt_result_t xret;
|
||||
|
||||
assert(type < XRT_DEVICE_FEATURE_MAX_ENUM);
|
||||
|
||||
// If it is not zero we are done.
|
||||
if (!xrt_reference_dec_and_is_zero(&usysd->feature_use[type])) {
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xret = ipc_call_system_devices_end_feature(usysd->ipc_c, type);
|
||||
IPC_CHK_ALWAYS_RET(usysd->ipc_c, xret, "ipc_call_system_devices_end_feature");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ipc_client_system_devices_destroy(struct xrt_system_devices *xsysd)
|
||||
{
|
||||
|
@ -74,6 +111,8 @@ ipc_client_system_devices_create(struct ipc_connection *ipc_c)
|
|||
struct ipc_client_system_devices *icsd = U_TYPED_CALLOC(struct ipc_client_system_devices);
|
||||
icsd->base.base.get_roles = ipc_client_system_devices_get_roles;
|
||||
icsd->base.base.destroy = ipc_client_system_devices_destroy;
|
||||
icsd->base.base.feature_inc = ipc_client_system_devices_feature_inc;
|
||||
icsd->base.base.feature_dec = ipc_client_system_devices_feature_dec;
|
||||
icsd->ipc_c = ipc_c;
|
||||
|
||||
return &icsd->base.base;
|
||||
|
|
|
@ -131,6 +131,9 @@ struct ipc_client_state
|
|||
//! Which of the references spaces is the client using.
|
||||
bool ref_space_used[XRT_SPACE_REFERENCE_TYPE_COUNT];
|
||||
|
||||
//! Which of the device features is the client using.
|
||||
bool device_feature_used[XRT_DEVICE_FEATURE_MAX_ENUM];
|
||||
|
||||
//! Socket fd used for client comms
|
||||
struct ipc_message_channel imc;
|
||||
|
||||
|
|
|
@ -113,6 +113,18 @@ validate_reference_space_type(volatile struct ipc_client_state *ics, enum xrt_re
|
|||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
validate_device_feature_type(volatile struct ipc_client_state *ics, enum xrt_device_feature_type type)
|
||||
{
|
||||
if ((uint32_t)type >= XRT_DEVICE_FEATURE_MAX_ENUM) {
|
||||
IPC_ERROR(ics->server, "Invalid device feature type %u", type);
|
||||
return XRT_ERROR_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static xrt_result_t
|
||||
validate_space_id(volatile struct ipc_client_state *ics, int64_t space_id, struct xrt_space **out_xspc)
|
||||
{
|
||||
|
@ -2150,6 +2162,63 @@ ipc_handle_system_devices_get_roles(volatile struct ipc_client_state *ics, struc
|
|||
return xrt_system_devices_get_roles(ics->server->xsysd, out_roles);
|
||||
}
|
||||
|
||||
xrt_result_t
|
||||
ipc_handle_system_devices_begin_feature(volatile struct ipc_client_state *ics, enum xrt_device_feature_type type)
|
||||
{
|
||||
struct xrt_system_devices *xsysd = ics->server->xsysd;
|
||||
xrt_result_t xret;
|
||||
|
||||
xret = validate_device_feature_type(ics, type);
|
||||
if (xret != XRT_SUCCESS) {
|
||||
return XRT_ERROR_IPC_FAILURE;
|
||||
}
|
||||
|
||||
// Is this feature already used?
|
||||
if (ics->device_feature_used[type]) {
|
||||
IPC_ERROR(ics->server, "feature '%u' already used!", type);
|
||||
return XRT_ERROR_IPC_FAILURE;
|
||||
}
|
||||
|
||||
xret = xrt_system_devices_feature_inc(xsysd, type);
|
||||
if (xret != XRT_SUCCESS) {
|
||||
IPC_ERROR(ics->server, "xrt_system_devices_feature_inc failed");
|
||||
return xret;
|
||||
}
|
||||
|
||||
// Can now mark it as used.
|
||||
ics->device_feature_used[type] = true;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xrt_result_t
|
||||
ipc_handle_system_devices_end_feature(volatile struct ipc_client_state *ics, enum xrt_device_feature_type type)
|
||||
{
|
||||
struct xrt_system_devices *xsysd = ics->server->xsysd;
|
||||
xrt_result_t xret;
|
||||
|
||||
xret = validate_device_feature_type(ics, type);
|
||||
if (xret != XRT_SUCCESS) {
|
||||
return XRT_ERROR_IPC_FAILURE;
|
||||
}
|
||||
|
||||
if (!ics->device_feature_used[type]) {
|
||||
IPC_ERROR(ics->server, "feature '%u' not used!", type);
|
||||
return XRT_ERROR_IPC_FAILURE;
|
||||
}
|
||||
|
||||
xret = xrt_system_devices_feature_dec(xsysd, type);
|
||||
if (xret != XRT_SUCCESS) {
|
||||
IPC_ERROR(ics->server, "xrt_system_devices_feature_dec failed");
|
||||
return xret;
|
||||
}
|
||||
|
||||
// Now we can mark it as not used.
|
||||
ics->device_feature_used[type] = false;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
xrt_result_t
|
||||
ipc_handle_device_get_face_tracking(volatile struct ipc_client_state *ics,
|
||||
uint32_t id,
|
||||
|
|
|
@ -90,6 +90,17 @@ common_shutdown(volatile struct ipc_client_state *ics)
|
|||
ics->ref_space_used[i] = false;
|
||||
}
|
||||
|
||||
// Make a still in use device features as no longer used.
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(ics->device_feature_used); i++) {
|
||||
bool used = ics->device_feature_used[i];
|
||||
if (!used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
xrt_system_devices_feature_dec(ics->server->xsysd, (enum xrt_device_feature_type)i);
|
||||
ics->device_feature_used[i] = false;
|
||||
}
|
||||
|
||||
// Should we stop the server when a client disconnects?
|
||||
if (ics->server->exit_on_disconnect) {
|
||||
ics->server->running = false;
|
||||
|
|
|
@ -62,6 +62,18 @@
|
|||
]
|
||||
},
|
||||
|
||||
"system_devices_begin_feature": {
|
||||
"in": [
|
||||
{"name": "type", "type": "enum xrt_device_feature_type"}
|
||||
]
|
||||
},
|
||||
|
||||
"system_devices_end_feature": {
|
||||
"in": [
|
||||
{"name": "type", "type": "enum xrt_device_feature_type"}
|
||||
]
|
||||
},
|
||||
|
||||
"system_compositor_get_info": {
|
||||
"out": [
|
||||
{"name": "info", "type": "struct xrt_system_compositor_info"}
|
||||
|
|
|
@ -72,6 +72,12 @@ get_xrt_space_action(struct oxr_logger *log, struct oxr_space *spc, struct xrt_s
|
|||
if (xret != XRT_SUCCESS) {
|
||||
oxr_warn(log, "Failed to create pose space");
|
||||
} else {
|
||||
struct xrt_system_devices *xsysd = spc->sess->sys->xsysd;
|
||||
if (xdev == xsysd->static_roles.eyes) {
|
||||
// eye tracking is being used
|
||||
xrt_system_devices_feature_inc(xsysd, XRT_DEVICE_FEATURE_EYE_TRACKING);
|
||||
}
|
||||
|
||||
spc->action.xdev = xdev;
|
||||
spc->action.name = name;
|
||||
}
|
||||
|
@ -128,6 +134,12 @@ oxr_space_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
|
|||
xrt_space_overseer_ref_space_dec(spc->sess->sys->xso, xtype);
|
||||
}
|
||||
|
||||
struct xrt_system_devices *xsysd = spc->sess->sys->xsysd;
|
||||
if (spc->action.xdev && spc->action.xdev == xsysd->static_roles.eyes) {
|
||||
// eye tracking isn't being used anymore
|
||||
xrt_system_devices_feature_dec(xsysd, XRT_DEVICE_FEATURE_EYE_TRACKING);
|
||||
}
|
||||
|
||||
xrt_space_reference(&spc->xdev_pose.xs, NULL);
|
||||
xrt_space_reference(&spc->action.xs, NULL);
|
||||
spc->action.xdev = NULL;
|
||||
|
|
Loading…
Reference in a new issue