···11-// Copyright 2020-2021, Collabora, Ltd.
11+// Copyright 2020-2024, Collabora, Ltd.
22// SPDX-License-Identifier: BSL-1.0
33/*!
44 * @file
···1212 * @ingroup drv_sample
1313 */
14141515+#include "os/os_time.h"
1616+#include "xrt/xrt_defines.h"
1517#include "xrt/xrt_device.h"
16181919+#include "math/m_relation_history.h"
1720#include "math/m_api.h"
1821#include "math/m_mathinclude.h" // IWYU pragma: keep
19222020-#include "util/u_var.h"
2121-#include "util/u_time.h"
2223#include "util/u_debug.h"
2324#include "util/u_device.h"
2525+#include "util/u_distortion_mesh.h"
2426#include "util/u_logging.h"
2525-#include "util/u_distortion_mesh.h"
2727+#include "util/u_misc.h"
2828+#include "util/u_time.h"
2929+#include "util/u_var.h"
2630#include "util/u_visibility_mask.h"
2731#include "xrt/xrt_results.h"
2832···4751 struct xrt_pose pose;
48524953 enum u_logging_level log_level;
5454+5555+ // has built-in mutex so thread safe
5656+ struct m_relation_history *relation_hist;
5057};
51585259···59666067DEBUG_GET_ONCE_LOG_OPTION(sample_log, "SAMPLE_LOG", U_LOGGING_WARN)
61686262-#define SH_TRACE(p, ...) U_LOG_XDEV_IFL_T(&sh->base, sh->log_level, __VA_ARGS__)
6363-#define SH_DEBUG(p, ...) U_LOG_XDEV_IFL_D(&sh->base, sh->log_level, __VA_ARGS__)
6464-#define SH_ERROR(p, ...) U_LOG_XDEV_IFL_E(&sh->base, sh->log_level, __VA_ARGS__)
6969+#define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__)
7070+#define HMD_DEBUG(hmd, ...) U_LOG_XDEV_IFL_D(&hmd->base, hmd->log_level, __VA_ARGS__)
7171+#define HMD_INFO(hmd, ...) U_LOG_XDEV_IFL_I(&hmd->base, hmd->log_level, __VA_ARGS__)
7272+#define HMD_ERROR(hmd, ...) U_LOG_XDEV_IFL_E(&hmd->base, hmd->log_level, __VA_ARGS__)
65736674static void
6775sample_hmd_destroy(struct xrt_device *xdev)
6876{
6969- struct sample_hmd *sh = sample_hmd(xdev);
7777+ struct sample_hmd *hmd = sample_hmd(xdev);
70787179 // Remove the variable tracking.
7272- u_var_remove_root(sh);
8080+ u_var_remove_root(hmd);
73817474- u_device_free(&sh->base);
8282+8383+ m_relation_history_destroy(&hmd->relation_hist);
8484+8585+ u_device_free(&hmd->base);
7586}
76877788static void
7889sample_hmd_update_inputs(struct xrt_device *xdev)
7990{
8091 /*
8181- * Empty for the sampler driver, if you need to you should
9292+ * Empty for the sample driver, if you need to you should
8293 * put code to update the attached inputs fields. If not you can use
8394 * the u_device_noop_update_inputs helper to make it a no-op.
8495 */
···90101 uint64_t at_timestamp_ns,
91102 struct xrt_space_relation *out_relation)
92103{
9393- struct sample_hmd *sh = sample_hmd(xdev);
104104+ struct sample_hmd *hmd = sample_hmd(xdev);
9410595106 if (name != XRT_INPUT_GENERIC_HEAD_POSE) {
9696- SH_ERROR(sh, "unknown input name");
107107+ HMD_ERROR(hmd, "unknown input name");
97108 return;
98109 }
99110100100- // Estimate pose at timestamp at_timestamp_ns!
101101- math_quat_normalize(&sh->pose.orientation);
102102- out_relation->pose = sh->pose;
103103- out_relation->relation_flags = (enum xrt_space_relation_flags)(XRT_SPACE_RELATION_ORIENTATION_VALID_BIT |
104104- XRT_SPACE_RELATION_POSITION_VALID_BIT |
105105- XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT);
111111+ struct xrt_space_relation relation = XRT_SPACE_RELATION_ZERO;
112112+113113+ enum m_relation_history_result history_result =
114114+ m_relation_history_get(hmd->relation_hist, at_timestamp_ns, &relation);
115115+ if (history_result == M_RELATION_HISTORY_RESULT_INVALID) {
116116+ // If you get in here, it means you did not push any poses into the relation history.
117117+ // You may want to handle this differently.
118118+ HMD_ERROR(hmd, "Internal error: no poses pushed?");
119119+ }
120120+121121+ if ((relation.relation_flags & XRT_SPACE_RELATION_ORIENTATION_VALID_BIT) != 0) {
122122+ // If we provide an orientation, make sure that it is normalized.
123123+ math_quat_normalize(&relation.pose.orientation);
124124+ }
125125+126126+ *out_relation = relation;
106127}
107128108129static void
···128149 out_poses); //
129150}
130151131131-bool
132132-sample_hmd_compute_distortion(
133133- struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result)
134134-{
135135- return u_compute_distortion_none(u, u, out_result);
136136-}
137137-138152xrt_result_t
139153sample_hmd_get_visibility_mask(struct xrt_device *xdev,
140154 enum xrt_visibility_mask_type type,
···153167 enum u_device_alloc_flags flags =
154168 (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE);
155169156156- struct sample_hmd *sh = U_DEVICE_ALLOCATE(struct sample_hmd, flags, 1, 0);
170170+ struct sample_hmd *hmd = U_DEVICE_ALLOCATE(struct sample_hmd, flags, 1, 0);
157171158172 // This list should be ordered, most preferred first.
159173 size_t idx = 0;
160160- sh->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE;
161161- sh->base.hmd->blend_mode_count = idx;
174174+ hmd->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE;
175175+ hmd->base.hmd->blend_mode_count = idx;
176176+177177+ hmd->base.update_inputs = sample_hmd_update_inputs;
178178+ hmd->base.get_tracked_pose = sample_hmd_get_tracked_pose;
179179+ hmd->base.get_view_poses = sample_hmd_get_view_poses;
180180+ hmd->base.get_visibility_mask = sample_hmd_get_visibility_mask;
181181+ hmd->base.destroy = sample_hmd_destroy;
182182+183183+ // Distortion information, fills in xdev->compute_distortion().
184184+ u_distortion_mesh_set_none(&hmd->base);
162185163163- sh->base.update_inputs = sample_hmd_update_inputs;
164164- sh->base.get_tracked_pose = sample_hmd_get_tracked_pose;
165165- sh->base.get_view_poses = sample_hmd_get_view_poses;
166166- sh->base.compute_distortion = sample_hmd_compute_distortion;
167167- sh->base.get_visibility_mask = sample_hmd_get_visibility_mask;
168168- sh->base.destroy = sample_hmd_destroy;
186186+ // populate this with something more complex if required
187187+ // hmd->base.compute_distortion = sample_hmd_compute_distortion;
169188170170- sh->pose = (struct xrt_pose)XRT_POSE_IDENTITY;
171171- sh->log_level = debug_get_log_option_sample_log();
189189+ hmd->pose = (struct xrt_pose)XRT_POSE_IDENTITY;
190190+ hmd->log_level = debug_get_log_option_sample_log();
172191173192 // Print name.
174174- snprintf(sh->base.str, XRT_DEVICE_NAME_LEN, "Sample HMD");
175175- snprintf(sh->base.serial, XRT_DEVICE_NAME_LEN, "Sample HMD S/N");
193193+ snprintf(hmd->base.str, XRT_DEVICE_NAME_LEN, "Sample HMD");
194194+ snprintf(hmd->base.serial, XRT_DEVICE_NAME_LEN, "Sample HMD S/N");
195195+196196+ m_relation_history_create(&hmd->relation_hist);
176197177198 // Setup input.
178178- sh->base.name = XRT_DEVICE_GENERIC_HMD;
179179- sh->base.device_type = XRT_DEVICE_TYPE_HMD;
180180- sh->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE;
181181- sh->base.orientation_tracking_supported = true;
182182- sh->base.position_tracking_supported = false;
199199+ hmd->base.name = XRT_DEVICE_GENERIC_HMD;
200200+ hmd->base.device_type = XRT_DEVICE_TYPE_HMD;
201201+ hmd->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE;
202202+ hmd->base.orientation_tracking_supported = true;
203203+ hmd->base.position_tracking_supported = true;
183204184205 // Set up display details
185206 // refresh rate
186186- sh->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / 90.0f);
207207+ hmd->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / 90.0f);
187208188209 const double hFOV = 90 * (M_PI / 180.0);
189210 const double vFOV = 96.73 * (M_PI / 180.0);
···192213 const double vCOP = 0.5;
193214 if (
194215 /* right eye */
195195- !math_compute_fovs(1, hCOP, hFOV, 1, vCOP, vFOV, &sh->base.hmd->distortion.fov[1]) ||
216216+ !math_compute_fovs(1, hCOP, hFOV, 1, vCOP, vFOV, &hmd->base.hmd->distortion.fov[1]) ||
196217 /*
197218 * left eye - same as right eye, except the horizontal center of projection is moved in the opposite
198219 * direction now
199220 */
200200- !math_compute_fovs(1, 1.0 - hCOP, hFOV, 1, vCOP, vFOV, &sh->base.hmd->distortion.fov[0])) {
221221+ !math_compute_fovs(1, 1.0 - hCOP, hFOV, 1, vCOP, vFOV, &hmd->base.hmd->distortion.fov[0])) {
201222 // If those failed, it means our math was impossible.
202202- SH_ERROR(sh, "Failed to setup basic device info");
203203- sample_hmd_destroy(&sh->base);
223223+ HMD_ERROR(hmd, "Failed to setup basic device info");
224224+ sample_hmd_destroy(&hmd->base);
204225 return NULL;
205226 }
206227 const int panel_w = 1080;
207228 const int panel_h = 1200;
208229209230 // Single "screen" (always the case)
210210- sh->base.hmd->screens[0].w_pixels = panel_w * 2;
211211- sh->base.hmd->screens[0].h_pixels = panel_h;
231231+ hmd->base.hmd->screens[0].w_pixels = panel_w * 2;
232232+ hmd->base.hmd->screens[0].h_pixels = panel_h;
212233213234 // Left, Right
214235 for (uint8_t eye = 0; eye < 2; ++eye) {
215215- sh->base.hmd->views[eye].display.w_pixels = panel_w;
216216- sh->base.hmd->views[eye].display.h_pixels = panel_h;
217217- sh->base.hmd->views[eye].viewport.y_pixels = 0;
218218- sh->base.hmd->views[eye].viewport.w_pixels = panel_w;
219219- sh->base.hmd->views[eye].viewport.h_pixels = panel_h;
236236+ hmd->base.hmd->views[eye].display.w_pixels = panel_w;
237237+ hmd->base.hmd->views[eye].display.h_pixels = panel_h;
238238+ hmd->base.hmd->views[eye].viewport.y_pixels = 0;
239239+ hmd->base.hmd->views[eye].viewport.w_pixels = panel_w;
240240+ hmd->base.hmd->views[eye].viewport.h_pixels = panel_h;
220241 // if rotation is not identity, the dimensions can get more complex.
221221- sh->base.hmd->views[eye].rot = u_device_rotation_ident;
242242+ hmd->base.hmd->views[eye].rot = u_device_rotation_ident;
222243 }
223244 // left eye starts at x=0, right eye starts at x=panel_width
224224- sh->base.hmd->views[0].viewport.x_pixels = 0;
225225- sh->base.hmd->views[1].viewport.x_pixels = panel_w;
245245+ hmd->base.hmd->views[0].viewport.x_pixels = 0;
246246+ hmd->base.hmd->views[1].viewport.x_pixels = panel_w;
226247227248 // Distortion information, fills in xdev->compute_distortion().
228228- u_distortion_mesh_set_none(&sh->base);
249249+ u_distortion_mesh_set_none(&hmd->base);
250250+251251+ // Just put an initial identity value in the tracker
252252+ struct xrt_space_relation identity = XRT_SPACE_RELATION_ZERO;
253253+ identity.relation_flags = (enum xrt_space_relation_flags)(XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT |
254254+ XRT_SPACE_RELATION_ORIENTATION_VALID_BIT);
255255+ uint64_t now = os_monotonic_get_ns();
256256+ m_relation_history_push(hmd->relation_hist, &identity, now);
229257230258 // Setup variable tracker: Optional but useful for debugging
231231- u_var_add_root(sh, "Sample HMD", true);
232232- u_var_add_pose(sh, &sh->pose, "pose");
233233- u_var_add_log_level(sh, &sh->log_level, "log_level");
259259+ u_var_add_root(hmd, "Sample HMD", true);
260260+ u_var_add_log_level(hmd, &hmd->log_level, "log_level");
234261235262236236- return &sh->base;
263263+ return &hmd->base;
237264}
+11-7
src/xrt/drivers/sample/sample_interface.h
···11-// Copyright 2020-2021, Collabora, Ltd.
11+// Copyright 2020-2024, Collabora, Ltd.
22// SPDX-License-Identifier: BSL-1.0
33/*!
44 * @file
55- * @brief Interface to sample driver.
55+ * @brief Interface to Sample HMD driver.
66 * @author Jakob Bornecrantz <jakob@collabora.com>
77 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
88 * @ingroup drv_sample
···1515#endif
16161717/*!
1818- * @defgroup drv_sample Sample driver
1818+ * @defgroup drv_sample Sample HMD driver
1919 * @ingroup drv
2020 *
2121- * @brief Simple do-nothing sample driver, that cannot be detected by USB VID/PID
2121+ * @brief Driver for a Sample HMD.
2222+ *
2323+ * Does no actual work.
2424+ * Assumed to not be detectable by USB VID/PID,
2225 * and thus exposes an "auto-prober" to explicitly discover the device.
2326 *
2427 * See @ref writing-driver for additional information.
···3033 * you can skip the @ref xrt_auto_prober implementation, and instead implement a
3134 * "found" function that matches the signature expected by xrt_prober_entry::found.
3235 * See for example @ref hdk_found.
3636+ * Alternately, you might create a builder or an instance implementation directly.
3337 */
34383539/*!
3636- * Create a auto prober for a sample device.
4040+ * Create a auto prober for a Sample HMD.
3741 *
3842 * @ingroup drv_sample
3943 */
···4145sample_create_auto_prober(void);
42464347/*!
4444- * Create a sample hmd.
4848+ * Create a Sample HMD.
4549 *
4650 * This is only exposed so that the prober (in one source file)
4747- * can call the construction function (in another.)
5151+ * can call the construction function (in another)
4852 * @ingroup drv_sample
4953 */
5054struct xrt_device *
+14-15
src/xrt/drivers/sample/sample_prober.c
···11-// Copyright 2020-2021, Collabora, Ltd.
11+// Copyright 2020-2024, Collabora, Ltd.
22// SPDX-License-Identifier: BSL-1.0
33/*!
44 * @file
55- * @brief Sample prober code.
55+ * @brief "auto-prober" for Sample HMD that can be autodetected but not through USB VID/PID.
66 * @author Jakob Bornecrantz <jakob@collabora.com>
77 * @ingroup drv_sample
88 */
···1010#include "xrt/xrt_prober.h"
11111212#include "util/u_misc.h"
1313-#include "util/u_debug.h"
14131514#include "sample_interface.h"
1615···25242625//! @private @memberof sample_auto_prober
2726static inline struct sample_auto_prober *
2828-sample_auto_prober(struct xrt_auto_prober *p)
2727+sample_auto_prober(struct xrt_auto_prober *xap)
2928{
3030- return (struct sample_auto_prober *)p;
2929+ return (struct sample_auto_prober *)xap;
3130}
32313332//! @private @memberof sample_auto_prober
3433static void
3534sample_auto_prober_destroy(struct xrt_auto_prober *p)
3635{
3737- struct sample_auto_prober *sap = sample_auto_prober(p);
3636+ struct sample_auto_prober *ap = sample_auto_prober(p);
38373939- free(sap);
3838+ free(ap);
4039}
41404241//! @public @memberof sample_auto_prober
···4746 struct xrt_prober *xp,
4847 struct xrt_device **out_xdevs)
4948{
5050- struct sample_auto_prober *sap = sample_auto_prober(xap);
5151- (void)sap;
4949+ struct sample_auto_prober *ap = sample_auto_prober(xap);
5050+ (void)ap;
52515353- // Do not create a sample HMD if we are not looking for HMDs.
5252+ // Do not create an HMD device if we are not looking for HMDs.
5453 if (no_hmds) {
5554 return 0;
5655 }
···6261struct xrt_auto_prober *
6362sample_create_auto_prober(void)
6463{
6565- struct sample_auto_prober *sap = U_TYPED_CALLOC(struct sample_auto_prober);
6666- sap->base.name = "Sample";
6767- sap->base.destroy = sample_auto_prober_destroy;
6868- sap->base.lelo_dallas_autoprobe = sample_auto_prober_autoprobe;
6464+ struct sample_auto_prober *ap = U_TYPED_CALLOC(struct sample_auto_prober);
6565+ ap->base.name = "Sample HMD Auto-Prober";
6666+ ap->base.destroy = sample_auto_prober_destroy;
6767+ ap->base.lelo_dallas_autoprobe = sample_auto_prober_autoprobe;
69687070- return &sap->base;
6969+ return &ap->base;
7170}