The open source OpenXR runtime
at prediction-2 214 lines 7.1 kB view raw
1// Copyright 2020-2021, The Board of Trustees of the University of Illinois. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief ILLIXR HMD 6 * @author RSIM Group <illixr@cs.illinois.edu> 7 * @ingroup drv_illixr 8 */ 9 10#include <math.h> 11#include <stdio.h> 12#include <unistd.h> 13#include <stdlib.h> 14#include <string.h> 15#include <assert.h> 16#include <dlfcn.h> 17#include <alloca.h> 18#include <string> 19#include <sstream> 20 21#include "math/m_api.h" 22#include "xrt/xrt_device.h" 23#include "util/u_var.h" 24#include "util/u_misc.h" 25#include "util/u_debug.h" 26#include "util/u_device.h" 27#include "util/u_time.h" 28#include "util/u_distortion_mesh.h" 29 30#include "illixr_component.h" 31#include "common/dynamic_lib.hpp" 32#include "common/runtime.hpp" 33 34/* 35 * 36 * Structs and defines. 37 * 38 */ 39 40struct illixr_hmd 41{ 42 struct xrt_device base; 43 44 struct xrt_pose pose; 45 46 bool print_spew; 47 bool print_debug; 48 49 const char *path; 50 const char *comp; 51 ILLIXR::dynamic_lib *runtime_lib; 52 ILLIXR::runtime *runtime; 53}; 54 55 56/* 57 * 58 * Functions 59 * 60 */ 61 62static inline struct illixr_hmd * 63illixr_hmd(struct xrt_device *xdev) 64{ 65 return (struct illixr_hmd *)xdev; 66} 67 68DEBUG_GET_ONCE_BOOL_OPTION(illixr_spew, "ILLIXR_PRINT_SPEW", false) 69DEBUG_GET_ONCE_BOOL_OPTION(illixr_debug, "ILLIXR_PRINT_DEBUG", false) 70 71#define DH_SPEW(dh, ...) \ 72 do { \ 73 if (dh->print_spew) { \ 74 fprintf(stderr, "%s - ", __func__); \ 75 fprintf(stderr, __VA_ARGS__); \ 76 fprintf(stderr, "\n"); \ 77 } \ 78 } while (false) 79 80#define DH_DEBUG(dh, ...) \ 81 do { \ 82 if (dh->print_debug) { \ 83 fprintf(stderr, "%s - ", __func__); \ 84 fprintf(stderr, __VA_ARGS__); \ 85 fprintf(stderr, "\n"); \ 86 } \ 87 } while (false) 88 89#define DH_ERROR(dh, ...) \ 90 do { \ 91 fprintf(stderr, "%s - ", __func__); \ 92 fprintf(stderr, __VA_ARGS__); \ 93 fprintf(stderr, "\n"); \ 94 } while (false) 95 96static void 97illixr_hmd_destroy(struct xrt_device *xdev) 98{ 99 struct illixr_hmd *dh = illixr_hmd(xdev); 100 dh->runtime->stop(); 101 delete dh->runtime; 102 delete dh->runtime_lib; 103 104 // Remove the variable tracking. 105 u_var_remove_root(dh); 106 107 u_device_free(&dh->base); 108} 109 110static void 111illixr_hmd_get_tracked_pose(struct xrt_device *xdev, 112 enum xrt_input_name name, 113 uint64_t at_timestamp_ns, 114 struct xrt_space_relation *out_relation) 115{ 116 if (name != XRT_INPUT_GENERIC_HEAD_POSE) { 117 DH_ERROR(illixr_hmd(xdev), "unknown input name"); 118 return; 119 } 120 121 out_relation->pose = illixr_read_pose(); 122 out_relation->relation_flags = (enum xrt_space_relation_flags)( 123 XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | 124 XRT_SPACE_RELATION_POSITION_VALID_BIT | XRT_SPACE_RELATION_POSITION_TRACKED_BIT); 125} 126 127std::vector<std::string> 128split(const std::string &s, char delimiter) 129{ 130 std::vector<std::string> tokens; 131 std::string token; 132 std::istringstream tokenStream{s}; 133 while (std::getline(tokenStream, token, delimiter)) { 134 tokens.push_back(token); 135 } 136 return tokens; 137} 138 139static int 140illixr_rt_launch(struct illixr_hmd *dh, const char *path, const char *comp) 141{ 142 dh->runtime_lib = new ILLIXR::dynamic_lib{ILLIXR::dynamic_lib::create(std::string{path})}; 143 dh->runtime = dh->runtime_lib->get<ILLIXR::runtime *(*)()>("runtime_factory")(); 144 dh->runtime->load_so(split(std::string{comp}, ':')); 145 dh->runtime->load_plugin_factory((ILLIXR::plugin_factory)illixr_monado_create_plugin); 146 147 return 0; 148} 149 150extern "C" struct xrt_device * 151illixr_hmd_create(const char *path_in, const char *comp_in) 152{ 153 struct illixr_hmd *dh; 154 enum u_device_alloc_flags flags = 155 (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE); 156 dh = U_DEVICE_ALLOCATE(struct illixr_hmd, flags, 1, 0); 157 dh->base.update_inputs = u_device_noop_update_inputs; 158 dh->base.get_tracked_pose = illixr_hmd_get_tracked_pose; 159 dh->base.get_view_poses = u_device_get_view_poses; 160 dh->base.destroy = illixr_hmd_destroy; 161 dh->base.name = XRT_DEVICE_GENERIC_HMD; 162 dh->base.device_type = XRT_DEVICE_TYPE_HMD; 163 164 size_t idx = 0; 165 dh->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE; 166 dh->base.hmd->blend_mode_count = idx; 167 168 dh->pose.orientation.w = 1.0f; // All other values set to zero. 169 dh->print_spew = debug_get_bool_option_illixr_spew(); 170 dh->print_debug = debug_get_bool_option_illixr_debug(); 171 dh->path = path_in; 172 dh->comp = comp_in; 173 174 // Print name. 175 snprintf(dh->base.str, XRT_DEVICE_NAME_LEN, "ILLIXR"); 176 snprintf(dh->base.serial, XRT_DEVICE_NAME_LEN, "ILLIXR"); 177 178 // Setup input. 179 dh->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 180 181 // Setup info. 182 struct u_device_simple_info info; 183 info.display.w_pixels = 2048; 184 info.display.h_pixels = 1024; 185 info.display.w_meters = 0.14f; 186 info.display.h_meters = 0.07f; 187 info.lens_horizontal_separation_meters = 0.13f / 2.0f; 188 info.lens_vertical_position_meters = 0.07f / 2.0f; 189 info.fov[0] = 85.0f * (M_PI / 180.0f); 190 info.fov[1] = 85.0f * (M_PI / 180.0f); 191 192 if (!u_device_setup_split_side_by_side(&dh->base, &info)) { 193 DH_ERROR(dh, "Failed to setup basic device info"); 194 illixr_hmd_destroy(&dh->base); 195 return NULL; 196 } 197 198 // Setup variable tracker. 199 u_var_add_root(dh, "ILLIXR", true); 200 u_var_add_pose(dh, &dh->pose, "pose"); 201 202 if (dh->base.hmd->distortion.preferred == XRT_DISTORTION_MODEL_NONE) { 203 // Setup the distortion mesh. 204 u_distortion_mesh_set_none(&dh->base); 205 } 206 207 // start ILLIXR runtime 208 if (illixr_rt_launch(dh, dh->path, dh->comp) != 0) { 209 DH_ERROR(dh, "Failed to load ILLIXR Runtime"); 210 illixr_hmd_destroy(&dh->base); 211 } 212 213 return &dh->base; 214}