The open source OpenXR runtime
at main 178 lines 4.9 kB view raw
1// Copyright 2020-2023, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief HMD remote driver. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup drv_remote 8 */ 9 10#include "r_internal.h" 11 12#include "os/os_time.h" 13 14#include "util/u_var.h" 15#include "util/u_misc.h" 16#include "util/u_debug.h" 17#include "util/u_device.h" 18#include "util/u_distortion_mesh.h" 19 20#include "math/m_api.h" 21#include "math/m_mathinclude.h" 22 23#include <stdio.h> 24 25 26/* 27 * 28 * Functions 29 * 30 */ 31 32static inline struct r_hmd * 33r_hmd(struct xrt_device *xdev) 34{ 35 return (struct r_hmd *)xdev; 36} 37 38static inline void 39copy_head_center_to_relation(struct r_hmd *rh, struct xrt_space_relation *out_relation) 40{ 41 out_relation->pose = rh->r->latest.head.center; 42 out_relation->relation_flags = (enum xrt_space_relation_flags)( 43 XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | XRT_SPACE_RELATION_POSITION_VALID_BIT | 44 XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | XRT_SPACE_RELATION_POSITION_TRACKED_BIT); 45} 46 47static void 48r_hmd_destroy(struct xrt_device *xdev) 49{ 50 struct r_hmd *rh = r_hmd(xdev); 51 52 // Remove the variable tracking. 53 u_var_remove_root(rh); 54 55 // Free this device with the helper. 56 u_device_free(&rh->base); 57} 58 59static xrt_result_t 60r_hmd_get_tracked_pose(struct xrt_device *xdev, 61 enum xrt_input_name name, 62 int64_t at_timestamp_ns, 63 struct xrt_space_relation *out_relation) 64{ 65 struct r_hmd *rh = r_hmd(xdev); 66 67 switch (name) { 68 case XRT_INPUT_GENERIC_HEAD_POSE: copy_head_center_to_relation(rh, out_relation); break; 69 default: 70 U_LOG_XDEV_UNSUPPORTED_INPUT(&rh->base, u_log_get_global_level(), name); 71 return XRT_ERROR_INPUT_UNSUPPORTED; 72 } 73 74 return XRT_SUCCESS; 75} 76 77static xrt_result_t 78r_hmd_get_view_poses(struct xrt_device *xdev, 79 const struct xrt_vec3 *default_eye_relation, 80 int64_t at_timestamp_ns, 81 enum xrt_view_type view_type, 82 uint32_t view_count, 83 struct xrt_space_relation *out_head_relation, 84 struct xrt_fov *out_fovs, 85 struct xrt_pose *out_poses) 86{ 87 struct r_hmd *rh = r_hmd(xdev); 88 89 if (!rh->r->latest.head.per_view_data_valid) { 90 return u_device_get_view_poses( // 91 xdev, // 92 default_eye_relation, // 93 at_timestamp_ns, // 94 view_type, // 95 view_count, // 96 out_head_relation, // 97 out_fovs, // 98 out_poses); // 99 } 100 101 assert(view_count <= ARRAY_SIZE(rh->r->latest.head.views)); 102 103 copy_head_center_to_relation(rh, out_head_relation); 104 105 for (uint32_t i = 0; i < view_count; i++) { 106 out_poses[i] = rh->r->latest.head.views[i].pose; 107 out_fovs[i] = rh->r->latest.head.views[i].fov; 108 } 109 110 return XRT_SUCCESS; 111} 112 113/*! 114 * @public @memberof r_hmd 115 */ 116struct xrt_device * 117r_hmd_create(struct r_hub *r) 118{ 119 // Allocate. 120 const enum u_device_alloc_flags flags = U_DEVICE_ALLOC_HMD; 121 const uint32_t input_count = 1; 122 const uint32_t output_count = 0; 123 struct r_hmd *rh = U_DEVICE_ALLOCATE( // 124 struct r_hmd, flags, input_count, output_count); 125 126 // Setup the basics. 127 u_device_populate_function_pointers(&rh->base, r_hmd_get_tracked_pose, r_hmd_destroy); 128 rh->base.get_view_poses = r_hmd_get_view_poses; 129 rh->base.tracking_origin = &r->origin; 130 rh->base.supported.orientation_tracking = true; 131 rh->base.supported.position_tracking = true; 132 rh->base.supported.hand_tracking = false; 133 rh->base.name = XRT_DEVICE_GENERIC_HMD; 134 rh->base.device_type = XRT_DEVICE_TYPE_HMD; 135 rh->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 136 rh->base.inputs[0].active = true; 137 rh->base.hmd->view_count = r->view_count; 138 rh->r = r; 139 140 // Print name. 141 snprintf(rh->base.str, sizeof(rh->base.str), "Remote HMD"); 142 snprintf(rh->base.serial, sizeof(rh->base.serial), "Remote HMD"); 143 144 // Setup info. 145 bool ret = true; 146 struct u_device_simple_info info; 147 info.display.w_pixels = 1920; 148 info.display.h_pixels = 1080; 149 info.display.w_meters = 0.13f; 150 info.display.h_meters = 0.07f; 151 info.lens_horizontal_separation_meters = 0.13f / 2.0f; 152 info.lens_vertical_position_meters = 0.07f / 2.0f; 153 154 if (rh->r->view_count == 1) { 155 info.fov[0] = 120.0f * (M_PI / 180.0f); 156 ret = u_device_setup_one_eye(&rh->base, &info); 157 } else if (rh->r->view_count == 2) { 158 info.fov[0] = 85.0f * (M_PI / 180.0f); 159 info.fov[1] = 85.0f * (M_PI / 180.0f); 160 ret = u_device_setup_split_side_by_side(&rh->base, &info); 161 } else { 162 U_LOG_E("Invalid view count"); 163 ret = false; 164 } 165 if (!ret) { 166 U_LOG_E("Failed to setup basic device info"); 167 r_hmd_destroy(&rh->base); 168 return NULL; 169 } 170 171 // Distortion information, fills in xdev->compute_distortion(). 172 u_distortion_mesh_set_none(&rh->base); 173 174 // Setup variable tracker. 175 u_var_add_root(rh, rh->base.str, true); 176 177 return &rh->base; 178}