The open source OpenXR runtime

d/sample: Clean up sample HMD, use m_relation_history, populate mesh

+116 -86
+91 -64
src/xrt/drivers/sample/sample_hmd.c
··· 1 - // Copyright 2020-2021, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file ··· 12 * @ingroup drv_sample 13 */ 14 15 #include "xrt/xrt_device.h" 16 17 #include "math/m_api.h" 18 #include "math/m_mathinclude.h" // IWYU pragma: keep 19 20 - #include "util/u_var.h" 21 - #include "util/u_time.h" 22 #include "util/u_debug.h" 23 #include "util/u_device.h" 24 #include "util/u_logging.h" 25 - #include "util/u_distortion_mesh.h" 26 #include "util/u_visibility_mask.h" 27 #include "xrt/xrt_results.h" 28 ··· 47 struct xrt_pose pose; 48 49 enum u_logging_level log_level; 50 }; 51 52 ··· 59 60 DEBUG_GET_ONCE_LOG_OPTION(sample_log, "SAMPLE_LOG", U_LOGGING_WARN) 61 62 - #define SH_TRACE(p, ...) U_LOG_XDEV_IFL_T(&sh->base, sh->log_level, __VA_ARGS__) 63 - #define SH_DEBUG(p, ...) U_LOG_XDEV_IFL_D(&sh->base, sh->log_level, __VA_ARGS__) 64 - #define SH_ERROR(p, ...) U_LOG_XDEV_IFL_E(&sh->base, sh->log_level, __VA_ARGS__) 65 66 static void 67 sample_hmd_destroy(struct xrt_device *xdev) 68 { 69 - struct sample_hmd *sh = sample_hmd(xdev); 70 71 // Remove the variable tracking. 72 - u_var_remove_root(sh); 73 74 - u_device_free(&sh->base); 75 } 76 77 static void 78 sample_hmd_update_inputs(struct xrt_device *xdev) 79 { 80 /* 81 - * Empty for the sampler driver, if you need to you should 82 * put code to update the attached inputs fields. If not you can use 83 * the u_device_noop_update_inputs helper to make it a no-op. 84 */ ··· 90 uint64_t at_timestamp_ns, 91 struct xrt_space_relation *out_relation) 92 { 93 - struct sample_hmd *sh = sample_hmd(xdev); 94 95 if (name != XRT_INPUT_GENERIC_HEAD_POSE) { 96 - SH_ERROR(sh, "unknown input name"); 97 return; 98 } 99 100 - // Estimate pose at timestamp at_timestamp_ns! 101 - math_quat_normalize(&sh->pose.orientation); 102 - out_relation->pose = sh->pose; 103 - out_relation->relation_flags = (enum xrt_space_relation_flags)(XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | 104 - XRT_SPACE_RELATION_POSITION_VALID_BIT | 105 - XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT); 106 } 107 108 static void ··· 128 out_poses); // 129 } 130 131 - bool 132 - sample_hmd_compute_distortion( 133 - struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) 134 - { 135 - return u_compute_distortion_none(u, u, out_result); 136 - } 137 - 138 xrt_result_t 139 sample_hmd_get_visibility_mask(struct xrt_device *xdev, 140 enum xrt_visibility_mask_type type, ··· 153 enum u_device_alloc_flags flags = 154 (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE); 155 156 - struct sample_hmd *sh = U_DEVICE_ALLOCATE(struct sample_hmd, flags, 1, 0); 157 158 // This list should be ordered, most preferred first. 159 size_t idx = 0; 160 - sh->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE; 161 - sh->base.hmd->blend_mode_count = idx; 162 163 - sh->base.update_inputs = sample_hmd_update_inputs; 164 - sh->base.get_tracked_pose = sample_hmd_get_tracked_pose; 165 - sh->base.get_view_poses = sample_hmd_get_view_poses; 166 - sh->base.compute_distortion = sample_hmd_compute_distortion; 167 - sh->base.get_visibility_mask = sample_hmd_get_visibility_mask; 168 - sh->base.destroy = sample_hmd_destroy; 169 170 - sh->pose = (struct xrt_pose)XRT_POSE_IDENTITY; 171 - sh->log_level = debug_get_log_option_sample_log(); 172 173 // Print name. 174 - snprintf(sh->base.str, XRT_DEVICE_NAME_LEN, "Sample HMD"); 175 - snprintf(sh->base.serial, XRT_DEVICE_NAME_LEN, "Sample HMD S/N"); 176 177 // Setup input. 178 - sh->base.name = XRT_DEVICE_GENERIC_HMD; 179 - sh->base.device_type = XRT_DEVICE_TYPE_HMD; 180 - sh->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 181 - sh->base.orientation_tracking_supported = true; 182 - sh->base.position_tracking_supported = false; 183 184 // Set up display details 185 // refresh rate 186 - sh->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / 90.0f); 187 188 const double hFOV = 90 * (M_PI / 180.0); 189 const double vFOV = 96.73 * (M_PI / 180.0); ··· 192 const double vCOP = 0.5; 193 if ( 194 /* right eye */ 195 - !math_compute_fovs(1, hCOP, hFOV, 1, vCOP, vFOV, &sh->base.hmd->distortion.fov[1]) || 196 /* 197 * left eye - same as right eye, except the horizontal center of projection is moved in the opposite 198 * direction now 199 */ 200 - !math_compute_fovs(1, 1.0 - hCOP, hFOV, 1, vCOP, vFOV, &sh->base.hmd->distortion.fov[0])) { 201 // If those failed, it means our math was impossible. 202 - SH_ERROR(sh, "Failed to setup basic device info"); 203 - sample_hmd_destroy(&sh->base); 204 return NULL; 205 } 206 const int panel_w = 1080; 207 const int panel_h = 1200; 208 209 // Single "screen" (always the case) 210 - sh->base.hmd->screens[0].w_pixels = panel_w * 2; 211 - sh->base.hmd->screens[0].h_pixels = panel_h; 212 213 // Left, Right 214 for (uint8_t eye = 0; eye < 2; ++eye) { 215 - sh->base.hmd->views[eye].display.w_pixels = panel_w; 216 - sh->base.hmd->views[eye].display.h_pixels = panel_h; 217 - sh->base.hmd->views[eye].viewport.y_pixels = 0; 218 - sh->base.hmd->views[eye].viewport.w_pixels = panel_w; 219 - sh->base.hmd->views[eye].viewport.h_pixels = panel_h; 220 // if rotation is not identity, the dimensions can get more complex. 221 - sh->base.hmd->views[eye].rot = u_device_rotation_ident; 222 } 223 // left eye starts at x=0, right eye starts at x=panel_width 224 - sh->base.hmd->views[0].viewport.x_pixels = 0; 225 - sh->base.hmd->views[1].viewport.x_pixels = panel_w; 226 227 // Distortion information, fills in xdev->compute_distortion(). 228 - u_distortion_mesh_set_none(&sh->base); 229 230 // Setup variable tracker: Optional but useful for debugging 231 - u_var_add_root(sh, "Sample HMD", true); 232 - u_var_add_pose(sh, &sh->pose, "pose"); 233 - u_var_add_log_level(sh, &sh->log_level, "log_level"); 234 235 236 - return &sh->base; 237 }
··· 1 + // Copyright 2020-2024, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file ··· 12 * @ingroup drv_sample 13 */ 14 15 + #include "os/os_time.h" 16 + #include "xrt/xrt_defines.h" 17 #include "xrt/xrt_device.h" 18 19 + #include "math/m_relation_history.h" 20 #include "math/m_api.h" 21 #include "math/m_mathinclude.h" // IWYU pragma: keep 22 23 #include "util/u_debug.h" 24 #include "util/u_device.h" 25 + #include "util/u_distortion_mesh.h" 26 #include "util/u_logging.h" 27 + #include "util/u_misc.h" 28 + #include "util/u_time.h" 29 + #include "util/u_var.h" 30 #include "util/u_visibility_mask.h" 31 #include "xrt/xrt_results.h" 32 ··· 51 struct xrt_pose pose; 52 53 enum u_logging_level log_level; 54 + 55 + // has built-in mutex so thread safe 56 + struct m_relation_history *relation_hist; 57 }; 58 59 ··· 66 67 DEBUG_GET_ONCE_LOG_OPTION(sample_log, "SAMPLE_LOG", U_LOGGING_WARN) 68 69 + #define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__) 70 + #define HMD_DEBUG(hmd, ...) U_LOG_XDEV_IFL_D(&hmd->base, hmd->log_level, __VA_ARGS__) 71 + #define HMD_INFO(hmd, ...) U_LOG_XDEV_IFL_I(&hmd->base, hmd->log_level, __VA_ARGS__) 72 + #define HMD_ERROR(hmd, ...) U_LOG_XDEV_IFL_E(&hmd->base, hmd->log_level, __VA_ARGS__) 73 74 static void 75 sample_hmd_destroy(struct xrt_device *xdev) 76 { 77 + struct sample_hmd *hmd = sample_hmd(xdev); 78 79 // Remove the variable tracking. 80 + u_var_remove_root(hmd); 81 82 + 83 + m_relation_history_destroy(&hmd->relation_hist); 84 + 85 + u_device_free(&hmd->base); 86 } 87 88 static void 89 sample_hmd_update_inputs(struct xrt_device *xdev) 90 { 91 /* 92 + * Empty for the sample driver, if you need to you should 93 * put code to update the attached inputs fields. If not you can use 94 * the u_device_noop_update_inputs helper to make it a no-op. 95 */ ··· 101 uint64_t at_timestamp_ns, 102 struct xrt_space_relation *out_relation) 103 { 104 + struct sample_hmd *hmd = sample_hmd(xdev); 105 106 if (name != XRT_INPUT_GENERIC_HEAD_POSE) { 107 + HMD_ERROR(hmd, "unknown input name"); 108 return; 109 } 110 111 + struct xrt_space_relation relation = XRT_SPACE_RELATION_ZERO; 112 + 113 + enum m_relation_history_result history_result = 114 + m_relation_history_get(hmd->relation_hist, at_timestamp_ns, &relation); 115 + if (history_result == M_RELATION_HISTORY_RESULT_INVALID) { 116 + // If you get in here, it means you did not push any poses into the relation history. 117 + // You may want to handle this differently. 118 + HMD_ERROR(hmd, "Internal error: no poses pushed?"); 119 + } 120 + 121 + if ((relation.relation_flags & XRT_SPACE_RELATION_ORIENTATION_VALID_BIT) != 0) { 122 + // If we provide an orientation, make sure that it is normalized. 123 + math_quat_normalize(&relation.pose.orientation); 124 + } 125 + 126 + *out_relation = relation; 127 } 128 129 static void ··· 149 out_poses); // 150 } 151 152 xrt_result_t 153 sample_hmd_get_visibility_mask(struct xrt_device *xdev, 154 enum xrt_visibility_mask_type type, ··· 167 enum u_device_alloc_flags flags = 168 (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE); 169 170 + struct sample_hmd *hmd = U_DEVICE_ALLOCATE(struct sample_hmd, flags, 1, 0); 171 172 // This list should be ordered, most preferred first. 173 size_t idx = 0; 174 + hmd->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE; 175 + hmd->base.hmd->blend_mode_count = idx; 176 + 177 + hmd->base.update_inputs = sample_hmd_update_inputs; 178 + hmd->base.get_tracked_pose = sample_hmd_get_tracked_pose; 179 + hmd->base.get_view_poses = sample_hmd_get_view_poses; 180 + hmd->base.get_visibility_mask = sample_hmd_get_visibility_mask; 181 + hmd->base.destroy = sample_hmd_destroy; 182 + 183 + // Distortion information, fills in xdev->compute_distortion(). 184 + u_distortion_mesh_set_none(&hmd->base); 185 186 + // populate this with something more complex if required 187 + // hmd->base.compute_distortion = sample_hmd_compute_distortion; 188 189 + hmd->pose = (struct xrt_pose)XRT_POSE_IDENTITY; 190 + hmd->log_level = debug_get_log_option_sample_log(); 191 192 // Print name. 193 + snprintf(hmd->base.str, XRT_DEVICE_NAME_LEN, "Sample HMD"); 194 + snprintf(hmd->base.serial, XRT_DEVICE_NAME_LEN, "Sample HMD S/N"); 195 + 196 + m_relation_history_create(&hmd->relation_hist); 197 198 // Setup input. 199 + hmd->base.name = XRT_DEVICE_GENERIC_HMD; 200 + hmd->base.device_type = XRT_DEVICE_TYPE_HMD; 201 + hmd->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 202 + hmd->base.orientation_tracking_supported = true; 203 + hmd->base.position_tracking_supported = true; 204 205 // Set up display details 206 // refresh rate 207 + hmd->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / 90.0f); 208 209 const double hFOV = 90 * (M_PI / 180.0); 210 const double vFOV = 96.73 * (M_PI / 180.0); ··· 213 const double vCOP = 0.5; 214 if ( 215 /* right eye */ 216 + !math_compute_fovs(1, hCOP, hFOV, 1, vCOP, vFOV, &hmd->base.hmd->distortion.fov[1]) || 217 /* 218 * left eye - same as right eye, except the horizontal center of projection is moved in the opposite 219 * direction now 220 */ 221 + !math_compute_fovs(1, 1.0 - hCOP, hFOV, 1, vCOP, vFOV, &hmd->base.hmd->distortion.fov[0])) { 222 // If those failed, it means our math was impossible. 223 + HMD_ERROR(hmd, "Failed to setup basic device info"); 224 + sample_hmd_destroy(&hmd->base); 225 return NULL; 226 } 227 const int panel_w = 1080; 228 const int panel_h = 1200; 229 230 // Single "screen" (always the case) 231 + hmd->base.hmd->screens[0].w_pixels = panel_w * 2; 232 + hmd->base.hmd->screens[0].h_pixels = panel_h; 233 234 // Left, Right 235 for (uint8_t eye = 0; eye < 2; ++eye) { 236 + hmd->base.hmd->views[eye].display.w_pixels = panel_w; 237 + hmd->base.hmd->views[eye].display.h_pixels = panel_h; 238 + hmd->base.hmd->views[eye].viewport.y_pixels = 0; 239 + hmd->base.hmd->views[eye].viewport.w_pixels = panel_w; 240 + hmd->base.hmd->views[eye].viewport.h_pixels = panel_h; 241 // if rotation is not identity, the dimensions can get more complex. 242 + hmd->base.hmd->views[eye].rot = u_device_rotation_ident; 243 } 244 // left eye starts at x=0, right eye starts at x=panel_width 245 + hmd->base.hmd->views[0].viewport.x_pixels = 0; 246 + hmd->base.hmd->views[1].viewport.x_pixels = panel_w; 247 248 // Distortion information, fills in xdev->compute_distortion(). 249 + u_distortion_mesh_set_none(&hmd->base); 250 + 251 + // Just put an initial identity value in the tracker 252 + struct xrt_space_relation identity = XRT_SPACE_RELATION_ZERO; 253 + identity.relation_flags = (enum xrt_space_relation_flags)(XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | 254 + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT); 255 + uint64_t now = os_monotonic_get_ns(); 256 + m_relation_history_push(hmd->relation_hist, &identity, now); 257 258 // Setup variable tracker: Optional but useful for debugging 259 + u_var_add_root(hmd, "Sample HMD", true); 260 + u_var_add_log_level(hmd, &hmd->log_level, "log_level"); 261 262 263 + return &hmd->base; 264 }
+11 -7
src/xrt/drivers/sample/sample_interface.h
··· 1 - // Copyright 2020-2021, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file 5 - * @brief Interface to sample driver. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 8 * @ingroup drv_sample ··· 15 #endif 16 17 /*! 18 - * @defgroup drv_sample Sample driver 19 * @ingroup drv 20 * 21 - * @brief Simple do-nothing sample driver, that cannot be detected by USB VID/PID 22 * and thus exposes an "auto-prober" to explicitly discover the device. 23 * 24 * See @ref writing-driver for additional information. ··· 30 * you can skip the @ref xrt_auto_prober implementation, and instead implement a 31 * "found" function that matches the signature expected by xrt_prober_entry::found. 32 * See for example @ref hdk_found. 33 */ 34 35 /*! 36 - * Create a auto prober for a sample device. 37 * 38 * @ingroup drv_sample 39 */ ··· 41 sample_create_auto_prober(void); 42 43 /*! 44 - * Create a sample hmd. 45 * 46 * This is only exposed so that the prober (in one source file) 47 - * can call the construction function (in another.) 48 * @ingroup drv_sample 49 */ 50 struct xrt_device *
··· 1 + // Copyright 2020-2024, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file 5 + * @brief Interface to Sample HMD driver. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 8 * @ingroup drv_sample ··· 15 #endif 16 17 /*! 18 + * @defgroup drv_sample Sample HMD driver 19 * @ingroup drv 20 * 21 + * @brief Driver for a Sample HMD. 22 + * 23 + * Does no actual work. 24 + * Assumed to not be detectable by USB VID/PID, 25 * and thus exposes an "auto-prober" to explicitly discover the device. 26 * 27 * See @ref writing-driver for additional information. ··· 33 * you can skip the @ref xrt_auto_prober implementation, and instead implement a 34 * "found" function that matches the signature expected by xrt_prober_entry::found. 35 * See for example @ref hdk_found. 36 + * Alternately, you might create a builder or an instance implementation directly. 37 */ 38 39 /*! 40 + * Create a auto prober for a Sample HMD. 41 * 42 * @ingroup drv_sample 43 */ ··· 45 sample_create_auto_prober(void); 46 47 /*! 48 + * Create a Sample HMD. 49 * 50 * This is only exposed so that the prober (in one source file) 51 + * can call the construction function (in another) 52 * @ingroup drv_sample 53 */ 54 struct xrt_device *
+14 -15
src/xrt/drivers/sample/sample_prober.c
··· 1 - // Copyright 2020-2021, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file 5 - * @brief Sample prober code. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup drv_sample 8 */ ··· 10 #include "xrt/xrt_prober.h" 11 12 #include "util/u_misc.h" 13 - #include "util/u_debug.h" 14 15 #include "sample_interface.h" 16 ··· 25 26 //! @private @memberof sample_auto_prober 27 static inline struct sample_auto_prober * 28 - sample_auto_prober(struct xrt_auto_prober *p) 29 { 30 - return (struct sample_auto_prober *)p; 31 } 32 33 //! @private @memberof sample_auto_prober 34 static void 35 sample_auto_prober_destroy(struct xrt_auto_prober *p) 36 { 37 - struct sample_auto_prober *sap = sample_auto_prober(p); 38 39 - free(sap); 40 } 41 42 //! @public @memberof sample_auto_prober ··· 47 struct xrt_prober *xp, 48 struct xrt_device **out_xdevs) 49 { 50 - struct sample_auto_prober *sap = sample_auto_prober(xap); 51 - (void)sap; 52 53 - // Do not create a sample HMD if we are not looking for HMDs. 54 if (no_hmds) { 55 return 0; 56 } ··· 62 struct xrt_auto_prober * 63 sample_create_auto_prober(void) 64 { 65 - struct sample_auto_prober *sap = U_TYPED_CALLOC(struct sample_auto_prober); 66 - sap->base.name = "Sample"; 67 - sap->base.destroy = sample_auto_prober_destroy; 68 - sap->base.lelo_dallas_autoprobe = sample_auto_prober_autoprobe; 69 70 - return &sap->base; 71 }
··· 1 + // Copyright 2020-2024, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file 5 + * @brief "auto-prober" for Sample HMD that can be autodetected but not through USB VID/PID. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup drv_sample 8 */ ··· 10 #include "xrt/xrt_prober.h" 11 12 #include "util/u_misc.h" 13 14 #include "sample_interface.h" 15 ··· 24 25 //! @private @memberof sample_auto_prober 26 static inline struct sample_auto_prober * 27 + sample_auto_prober(struct xrt_auto_prober *xap) 28 { 29 + return (struct sample_auto_prober *)xap; 30 } 31 32 //! @private @memberof sample_auto_prober 33 static void 34 sample_auto_prober_destroy(struct xrt_auto_prober *p) 35 { 36 + struct sample_auto_prober *ap = sample_auto_prober(p); 37 38 + free(ap); 39 } 40 41 //! @public @memberof sample_auto_prober ··· 46 struct xrt_prober *xp, 47 struct xrt_device **out_xdevs) 48 { 49 + struct sample_auto_prober *ap = sample_auto_prober(xap); 50 + (void)ap; 51 52 + // Do not create an HMD device if we are not looking for HMDs. 53 if (no_hmds) { 54 return 0; 55 } ··· 61 struct xrt_auto_prober * 62 sample_create_auto_prober(void) 63 { 64 + struct sample_auto_prober *ap = U_TYPED_CALLOC(struct sample_auto_prober); 65 + ap->base.name = "Sample HMD Auto-Prober"; 66 + ap->base.destroy = sample_auto_prober_destroy; 67 + ap->base.lelo_dallas_autoprobe = sample_auto_prober_autoprobe; 68 69 + return &ap->base; 70 }