The open source OpenXR runtime
at main 298 lines 9.8 kB view raw
1// Copyright 2022-2023, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Helpers for @ref xrt_builder implementations. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup aux_util 8 */ 9 10#include "xrt/xrt_prober.h" 11#include "xrt/xrt_system.h" 12#include "xrt/xrt_tracking.h" 13 14#include "util/u_debug.h" 15#include "util/u_builders.h" 16#include "util/u_system_helpers.h" 17#include "util/u_space_overseer.h" 18 19 20DEBUG_GET_ONCE_FLOAT_OPTION(tracking_origin_offset_x, "XRT_TRACKING_ORIGIN_OFFSET_X", 0.0f) 21DEBUG_GET_ONCE_FLOAT_OPTION(tracking_origin_offset_y, "XRT_TRACKING_ORIGIN_OFFSET_Y", 0.0f) 22DEBUG_GET_ONCE_FLOAT_OPTION(tracking_origin_offset_z, "XRT_TRACKING_ORIGIN_OFFSET_Z", 0.0f) 23 24 25/* 26 * 27 * Helper functions. 28 * 29 */ 30 31static void 32apply_offset(struct xrt_vec3 *position, struct xrt_vec3 *offset) 33{ 34 position->x += offset->x; 35 position->y += offset->y; 36 position->z += offset->z; 37} 38 39 40/* 41 * 42 * 'Exported' function. 43 * 44 */ 45 46struct xrt_prober_device * 47u_builder_find_prober_device(struct xrt_prober_device *const *xpdevs, 48 size_t xpdev_count, 49 uint16_t vendor_id, 50 uint16_t product_id, 51 enum xrt_bus_type bus_type) 52{ 53 for (size_t i = 0; i < xpdev_count; i++) { 54 struct xrt_prober_device *xpdev = xpdevs[i]; 55 if (xpdev->product_id != product_id || // 56 xpdev->vendor_id != vendor_id || // 57 xpdev->bus != bus_type) { 58 continue; 59 } 60 61 return xpdev; 62 } 63 64 return NULL; 65} 66 67void 68u_builder_search(struct xrt_prober *xp, 69 struct xrt_prober_device *const *xpdevs, 70 size_t xpdev_count, 71 const struct u_builder_search_filter *filters, 72 size_t filter_count, 73 struct u_builder_search_results *results) 74{ 75 for (size_t i = 0; i < xpdev_count; i++) { 76 struct xrt_prober_device *xpdev = xpdevs[i]; 77 bool match = false; 78 79 for (size_t k = 0; k < filter_count; k++) { 80 struct u_builder_search_filter f = filters[k]; 81 82 if (xpdev->product_id != f.product_id || // 83 xpdev->vendor_id != f.vendor_id || // 84 xpdev->bus != f.bus_type) { // 85 continue; 86 } 87 88 match = true; 89 break; 90 } 91 92 if (!match) { 93 continue; 94 } 95 96 results->xpdevs[results->xpdev_count++] = xpdev; 97 98 // Exit if full. 99 if (results->xpdev_count >= ARRAY_SIZE(results->xpdevs)) { 100 return; 101 } 102 } 103} 104 105void 106u_builder_setup_tracking_origins(struct xrt_device *head, 107 struct xrt_device *left, 108 struct xrt_device *right, 109 struct xrt_device *gamepad, 110 struct xrt_vec3 *global_tracking_origin_offset) 111{ 112 struct xrt_tracking_origin *head_origin = head ? head->tracking_origin : NULL; 113 struct xrt_tracking_origin *left_origin = left ? left->tracking_origin : NULL; 114 struct xrt_tracking_origin *right_origin = right ? right->tracking_origin : NULL; 115 struct xrt_tracking_origin *gamepad_origin = gamepad ? gamepad->tracking_origin : NULL; 116 117 if (left_origin != NULL && left_origin->type == XRT_TRACKING_TYPE_NONE) { 118 left_origin->initial_offset.position.x = -0.2f; 119 left_origin->initial_offset.position.y = 1.3f; 120 left_origin->initial_offset.position.z = -0.5f; 121 } 122 123 if (right_origin != NULL && right_origin->type == XRT_TRACKING_TYPE_NONE) { 124 right_origin->initial_offset.position.x = 0.2f; 125 right_origin->initial_offset.position.y = 1.3f; 126 right_origin->initial_offset.position.z = -0.5f; 127 } 128 129 if (gamepad_origin != NULL && gamepad_origin->type == XRT_TRACKING_TYPE_NONE) { 130 gamepad_origin->initial_offset.position.x = 0.0f; 131 gamepad_origin->initial_offset.position.y = 1.3f; 132 gamepad_origin->initial_offset.position.z = -0.5f; 133 } 134 135 // Head comes last, because left and right may share tracking origin. 136 if (head_origin != NULL && head_origin->type == XRT_TRACKING_TYPE_NONE) { 137 // "nominal height" 1.6m 138 head_origin->initial_offset.position.x = 0.0f; 139 head_origin->initial_offset.position.y = 1.6f; 140 head_origin->initial_offset.position.z = 0.0f; 141 } 142 143 if (head_origin) { 144 apply_offset(&head_origin->initial_offset.position, global_tracking_origin_offset); 145 } 146 if (left_origin && left_origin != head_origin) { 147 apply_offset(&left->tracking_origin->initial_offset.position, global_tracking_origin_offset); 148 } 149 if (right_origin && right_origin != head_origin && right_origin != left_origin) { 150 apply_offset(&right->tracking_origin->initial_offset.position, global_tracking_origin_offset); 151 } 152 if (gamepad_origin && gamepad_origin != head_origin && gamepad_origin != right_origin && 153 gamepad_origin != left_origin) { 154 apply_offset(&gamepad->tracking_origin->initial_offset.position, global_tracking_origin_offset); 155 } 156} 157 158void 159u_builder_create_space_overseer_legacy(struct xrt_session_event_sink *broadcast, 160 struct xrt_device *head, 161 struct xrt_device *left, 162 struct xrt_device *right, 163 struct xrt_device *gamepad, 164 struct xrt_device **xdevs, 165 uint32_t xdev_count, 166 bool root_is_unbounded, 167 bool per_app_local_spaces, 168 struct xrt_space_overseer **out_xso) 169{ 170 /* 171 * Tracking origins. 172 */ 173 174 struct xrt_vec3 global_tracking_origin_offset = { 175 debug_get_float_option_tracking_origin_offset_x(), 176 debug_get_float_option_tracking_origin_offset_y(), 177 debug_get_float_option_tracking_origin_offset_z(), 178 }; 179 180 u_builder_setup_tracking_origins( // 181 head, // 182 left, // 183 right, // 184 gamepad, // 185 &global_tracking_origin_offset); // 186 187 188 /* 189 * Space overseer. 190 */ 191 192 struct u_space_overseer *uso = u_space_overseer_create(broadcast); 193 194 struct xrt_pose T_stage_local = XRT_POSE_IDENTITY; 195 T_stage_local.position.y = 1.6; 196 197 u_space_overseer_legacy_setup( // 198 uso, // uso 199 xdevs, // xdevs 200 xdev_count, // xdev_count 201 head, // head 202 &T_stage_local, // local_offset 203 root_is_unbounded, // root_is_unbounded 204 per_app_local_spaces // per_app_local_spaces 205 ); 206 207 *out_xso = (struct xrt_space_overseer *)uso; 208} 209 210xrt_result_t 211u_builder_roles_helper_open_system(struct xrt_builder *xb, 212 cJSON *config, 213 struct xrt_prober *xp, 214 struct xrt_session_event_sink *broadcast, 215 struct xrt_system_devices **out_xsysd, 216 struct xrt_space_overseer **out_xso, 217 u_builder_open_system_fn fn) 218{ 219 struct u_builder_roles_helper ubrh = XRT_STRUCT_INIT; 220 xrt_result_t xret; 221 222 // Use the static system devices helper, no dynamic roles. 223 struct u_system_devices_static *usysds = u_system_devices_static_allocate(); 224 struct xrt_tracking_origin *origin = &usysds->base.origin; 225 struct xrt_system_devices *xsysd = &usysds->base.base; 226 struct xrt_frame_context *xfctx = &usysds->base.xfctx; 227 228 xret = fn( // 229 xb, // xb 230 config, // config 231 xp, // xp 232 origin, // origin 233 xsysd, // xsysd 234 xfctx, // xfctx 235 &ubrh); // ubrh 236 if (xret != XRT_SUCCESS) { 237 xrt_system_devices_destroy(&xsysd); 238 return xret; 239 } 240 241 /* 242 * Assign to role(s). 243 */ 244 245 xsysd->static_roles.head = ubrh.head; 246#define U_SET_HT_ROLE(SRC) \ 247 xsysd->static_roles.hand_tracking.SRC.left = ubrh.hand_tracking.SRC.left; \ 248 xsysd->static_roles.hand_tracking.SRC.right = ubrh.hand_tracking.SRC.right; 249 U_SET_HT_ROLE(unobstructed) 250 U_SET_HT_ROLE(conforming) 251#undef U_SET_HT_ROLE 252 253 u_system_devices_static_finalize( // 254 usysds, // usysds 255 ubrh.left, // left 256 ubrh.right, // right 257 ubrh.gamepad); // gamepad 258 259 260 /* 261 * Create the space overseer. 262 */ 263 264 *out_xsysd = xsysd; 265 u_builder_create_space_overseer_legacy( // 266 broadcast, // broadcast 267 ubrh.head, // head 268 ubrh.left, // left 269 ubrh.right, // right 270 ubrh.gamepad, // gamepad 271 xsysd->xdevs, // xdevs 272 xsysd->xdev_count, // xdev_count 273 false, // root_is_unbounded 274 true, // per_app_local_spaces 275 out_xso); // out_xso 276 277 return XRT_SUCCESS; 278} 279 280xrt_result_t 281u_builder_open_system_static_roles(struct xrt_builder *xb, 282 cJSON *config, 283 struct xrt_prober *xp, 284 struct xrt_session_event_sink *broadcast, 285 struct xrt_system_devices **out_xsysd, 286 struct xrt_space_overseer **out_xso) 287{ 288 struct u_builder *ub = (struct u_builder *)xb; 289 290 return u_builder_roles_helper_open_system( // 291 xb, // 292 config, // 293 xp, // 294 broadcast, // 295 out_xsysd, // 296 out_xso, // 297 ub->open_system_static_roles); // 298}