ipc: Add variable number of views get function

This commit is contained in:
Jakob Bornecrantz 2023-11-07 20:05:02 +00:00
parent 7251417569
commit cec787ba0f
4 changed files with 184 additions and 3 deletions

View file

@ -21,6 +21,7 @@
#include "util/u_distortion_mesh.h"
#include "client/ipc_client.h"
#include "client/ipc_client_connection.h"
#include "ipc_client_generated.h"
#include <math.h>
@ -48,7 +49,7 @@ typedef struct ipc_client_xdev ipc_client_hmd_t;
/*
*
* Functions
* Helpers.
*
*/
@ -58,6 +59,78 @@ ipc_client_hmd(struct xrt_device *xdev)
return (ipc_client_hmd_t *)xdev;
}
static void
call_get_view_poses_raw(ipc_client_hmd_t *ich,
const struct xrt_vec3 *default_eye_relation,
uint64_t at_timestamp_ns,
uint32_t view_count,
struct xrt_space_relation *out_head_relation,
struct xrt_fov *out_fovs,
struct xrt_pose *out_poses)
{
struct ipc_connection *ipc_c = ich->ipc_c;
xrt_result_t xret = XRT_SUCCESS;
ipc_client_connection_lock(ipc_c);
// Using the raw send helper is the only one that is required.
xret = ipc_send_device_get_view_poses_locked( //
ipc_c, //
ich->device_id, //
default_eye_relation, //
at_timestamp_ns, //
view_count); //
if (xret != XRT_SUCCESS) {
goto out;
}
// This is the data we get back in the provided reply.
uint32_t returned_view_count = 0;
struct xrt_space_relation head_relation = XRT_SPACE_RELATION_ZERO;
// Get the reply, use the raw function helper.
xret = ipc_receive_device_get_view_poses_locked( //
ipc_c, //
&head_relation, //
&returned_view_count); //
if (xret != XRT_SUCCESS) {
goto out;
}
if (view_count != returned_view_count) {
IPC_ERROR(ich->ipc_c, "Wrong view counts (sent: %u != got: %u)", view_count, returned_view_count);
assert(false);
}
// We can read directly to the output variables.
xret = ipc_receive(&ipc_c->imc, out_fovs, sizeof(struct xrt_fov) * view_count);
if (xret != XRT_SUCCESS) {
goto out;
}
// We can read directly to the output variables.
xret = ipc_receive(&ipc_c->imc, out_poses, sizeof(struct xrt_pose) * view_count);
if (xret != XRT_SUCCESS) {
goto out;
}
/*
* Finally set the head_relation that we got in the reply, mostly to
* demonstrate that you can use the reply struct in such a way.
*/
*out_head_relation = head_relation;
out:
ipc_client_connection_unlock(ipc_c);
}
/*
*
* Member functions
*
*/
static void
ipc_client_hmd_destroy(struct xrt_device *xdev)
{
@ -114,6 +187,7 @@ ipc_client_hmd_get_view_poses(struct xrt_device *xdev,
struct ipc_info_get_view_poses_2 info = {0};
if (view_count == 2) {
// Fast path.
xrt_result_t r = ipc_call_device_get_view_poses_2( //
ich->ipc_c, //
ich->device_id, //
@ -129,9 +203,22 @@ ipc_client_hmd_get_view_poses(struct xrt_device *xdev,
out_fovs[i] = info.fovs[i];
out_poses[i] = info.poses[i];
}
} else if (view_count <= IPC_MAX_RAW_VIEWS) {
// Artificial limit.
call_get_view_poses_raw( //
ich, //
default_eye_relation, //
at_timestamp_ns, //
view_count, //
out_head_relation, //
out_fovs, //
out_poses); //
} else {
IPC_ERROR(ich->ipc_c, "Cannot handle %u view_count, only 2 supported.", view_count);
assert(false && !"Can only handle view_count of 2.");
IPC_ERROR(ich->ipc_c, "Cannot handle %u view_count, %u or less supported.", view_count,
(uint32_t)IPC_MAX_RAW_VIEWS);
assert(false && !"Too large view_count!");
}
}

View file

@ -1419,6 +1419,85 @@ ipc_handle_device_get_hand_tracking(volatile struct ipc_client_state *ics,
return XRT_SUCCESS;
}
xrt_result_t
ipc_handle_device_get_view_poses(volatile struct ipc_client_state *ics,
uint32_t id,
const struct xrt_vec3 *fallback_eye_relation,
uint64_t at_timestamp_ns,
uint32_t view_count)
{
struct ipc_message_channel *imc = (struct ipc_message_channel *)&ics->imc;
struct ipc_device_get_view_poses_reply reply = XRT_STRUCT_INIT;
struct ipc_server *s = ics->server;
xrt_result_t xret;
// To make the code a bit more readable.
uint32_t device_id = id;
struct xrt_device *xdev = get_xdev(ics, device_id);
if (view_count == 0 || view_count > IPC_MAX_RAW_VIEWS) {
IPC_ERROR(s, "Client asked for zero or too many views! (%u)", view_count);
reply.result = XRT_ERROR_IPC_FAILURE;
// Send the full reply, the client expects it.
return ipc_send(imc, &reply, sizeof(reply));
}
// Data to get.
struct xrt_fov fovs[IPC_MAX_RAW_VIEWS];
struct xrt_pose poses[IPC_MAX_RAW_VIEWS];
xrt_device_get_view_poses( //
xdev, //
fallback_eye_relation, //
at_timestamp_ns, //
view_count, //
&reply.head_relation, //
fovs, //
poses); //
/*
* Operation ok, head_relation has already been put in the reply
* struct, so we don't need to send that manually.
*/
reply.result = XRT_SUCCESS;
/*
* This isn't really needed, but demonstrates the server sending the
* length back in the reply, a common pattern for other functions.
*/
reply.view_count = view_count;
/*
* Send the reply first isn't required for functions in general, but it
* will need to match what the client expects. This demonstrates the
* server sending the length back in the reply, a common pattern for
* other functions.
*/
xret = ipc_send(imc, &reply, sizeof(reply));
if (xret != XRT_SUCCESS) {
IPC_ERROR(s, "Failed to send reply!");
return xret;
}
// Send the fovs that we got.
xret = ipc_send(imc, fovs, sizeof(struct xrt_fov) * view_count);
if (xret != XRT_SUCCESS) {
IPC_ERROR(s, "Failed to send fovs!");
return xret;
}
// And finally the poses.
xret = ipc_send(imc, poses, sizeof(struct xrt_pose) * view_count);
if (xret != XRT_SUCCESS) {
IPC_ERROR(s, "Failed to send poses!");
return xret;
}
return XRT_SUCCESS;
}
xrt_result_t
ipc_handle_device_get_view_poses_2(volatile struct ipc_client_state *ics,
uint32_t id,

View file

@ -33,6 +33,7 @@
#define IPC_MAX_LAYERS 16
#define IPC_MAX_SLOTS 128
#define IPC_MAX_CLIENTS 8
#define IPC_MAX_RAW_VIEWS 32 // Max views that we can get, artificial limit.
#define IPC_EVENT_QUEUE_SIZE 32
#define IPC_SHARED_MAX_INPUTS 1024

View file

@ -307,6 +307,20 @@
]
},
"device_get_view_poses": {
"varlen": true,
"in": [
{"name": "id", "type": "uint32_t"},
{"name": "fallback_eye_relation", "type": "struct xrt_vec3"},
{"name": "at_timestamp_ns", "type": "uint64_t"},
{"name": "view_count", "type": "uint32_t"}
],
"out": [
{"name": "head_relation", "type": "struct xrt_space_relation"},
{"name": "view_count", "type": "uint32_t"}
]
},
"device_get_view_poses_2": {
"in": [
{"name": "id", "type": "uint32_t"},