diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..adf83287cf2e2a0c1f6248b6d9ae7750f5f0dafa --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/external/libsurvive"] + path = src/external/libsurvive + url = https://github.com/cnlohr/libsurvive.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ce1d41a3b5da758808dd676f18f1d09bc9f1956..04bbddb4e4c6102b878aaf5afc0805181166b8f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") pkg_check_modules(XCB xcb xcb-randr) endif() +option(BUILD_WITH_LIBSURVIVE "Enable libsurvive driver" ON) cmake_dependent_option(BUILD_WITH_OPENHMD "Enable OpenHMD driver" ON "OPENHMD_FOUND" OFF) cmake_dependent_option(BUILD_WITH_WAYLAND "Enable Wayland support" ON "WAYLAND_FOUND" OFF) cmake_dependent_option(BUILD_WITH_XLIB "Enable xlib support" ON "X11_FOUND" OFF) diff --git a/README.md b/README.md index c69b62b67ae8d33c4a536e28edbf739b8aab6314..973cb6c66f5b1d16706a9b8737b88c3b0c99870e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Monado - XR Runtime (XRT) +# Monado - XR Runtime (XRT) - experimental libsurvive branch Monado is an open source XR runtime delivering immersive experiences such as VR and AR on on mobile, PC/desktop, and any other device @@ -11,6 +11,26 @@ The project currently is being developed for GNU/Linux and aims to support other operating systems in the near future. "Monado" has no specific meaning and is just a name. +# About the libsurvive Branch + +This branch contains libsurvive as a submodule in src/xrt/external/libsurvive. +Libsurvive is compiled as a shared library and the runtime links to libsurvive. +A device prober using the libsurvive simple api is implemented in src/xrt/drivers/survive. + +When starting an OpenXR application, libsurvive will run calibration and save configuration +and calibration data in the current working directory. + +Make sure the HMD can see both basestations and is not moved during calibration. + +To remove libsurvive's data delete the following files/directories: + + rm -r config.json HMD_config.json calinfo + +Though fully working and usable, support for the libsurvive driver is **experimental**. + +For example it contains many hardcoded values from OpenHMD's configuration for the Vive 1 and +does not behave well yet when no Vive is connected. + ## Monado source tree * `src/xrt/include` - headers that define the internal interfaces of Monado. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7524309dfdc22ab55ad3fde0ecb3ae7f3286fa49..0cc2e4aec7cf6cee220d8a142372eb431924d408 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,8 @@ # Copyright 2019, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 +if (BUILD_WITH_LIBSURVIVE) + add_subdirectory(external/libsurvive) +endif() + add_subdirectory(xrt) diff --git a/src/external/libsurvive b/src/external/libsurvive new file mode 160000 index 0000000000000000000000000000000000000000..f26e88d35c0e278685b99f8e81cc6c4f6cadee0f --- /dev/null +++ b/src/external/libsurvive @@ -0,0 +1 @@ +Subproject commit f26e88d35c0e278685b99f8e81cc6c4f6cadee0f diff --git a/src/xrt/drivers/CMakeLists.txt b/src/xrt/drivers/CMakeLists.txt index f7beac62a4c2c6f52e2dd285a591182e37bb6228..cd721efb77e5e5332ddfdc135074da2981dc69a4 100644 --- a/src/xrt/drivers/CMakeLists.txt +++ b/src/xrt/drivers/CMakeLists.txt @@ -35,3 +35,23 @@ if(HIDAPI_FOUND) PRIVATE ${HIDAPI_INCLUDE_DIRS} ) endif() + +if (BUILD_WITH_LIBSURVIVE) + set(SURVIVE_SOURCE_FILES + survive/survive_device.c + survive/survive_device.h + survive/survive_interface.h + survive/survive_prober.c + ) + + # Use OBJECT to not create a archive, since it just gets in the way. + add_library(drv_survive OBJECT ${SURVIVE_SOURCE_FILES}) + set_property(TARGET drv_survive PROPERTY POSITION_INDEPENDENT_CODE ON) + + target_include_directories(drv_survive SYSTEM + PRIVATE + ${PROJECT_SOURCE_DIR}/src/external/libsurvive/include + ${PROJECT_SOURCE_DIR}/src/external/libsurvive/include/libsurvive + ${PROJECT_SOURCE_DIR}/src/external/libsurvive/redist + ) +endif() diff --git a/src/xrt/drivers/survive/survive_device.c b/src/xrt/drivers/survive/survive_device.c new file mode 100644 index 0000000000000000000000000000000000000000..a806b27b4be899fa996915ee549989c6c43ee2ad --- /dev/null +++ b/src/xrt/drivers/survive/survive_device.c @@ -0,0 +1,421 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: Apache-2.0 +/*! + * @file + * @brief Adaptor to a Libsurvive. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @author Christoph Haag <christoph.haag@collabora.com> + */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "math/m_api.h" +#include "xrt/xrt_device.h" +#include "util/u_debug.h" +#include "util/u_device.h" +#include "util/u_misc.h" + +#include "survive_device.h" + +static void +survive_device_destroy(struct xrt_device *xdev) +{ + struct survive_device *survive = survive_device(xdev); + + if (survive->ctx != NULL) { + survive_simple_close(survive->ctx); + } + + free(survive); +} + +static void +survive_device_get_tracked_pose(struct xrt_device *xdev, + struct xrt_space_relation *out_relation) +{ + struct survive_device *survive = survive_device(xdev); + out_relation->relation_flags = 0; + + bool new_data = false; + + static struct xrt_quat last_rot = {.x = 0, .y = 0, .z = 0, .w = 1}; + static struct xrt_vec3 last_pos = {.x = 0, .y = 0, .z = 0}; + + for (const SurviveSimpleObject *it = + survive_simple_get_next_updated(survive->ctx); + it != 0; it = survive_simple_get_next_updated(survive->ctx)) { + const char *codename = survive_simple_object_name(it); + + if (strcmp(codename, "HMD") != 0) + continue; + + new_data = true; + SurvivePose pose; + + uint32_t timecode = + survive_simple_object_get_latest_pose(it, &pose); + (void)timecode; + + struct xrt_quat out_rot = {.x = pose.Rot[1], + .y = pose.Rot[2], + .z = pose.Rot[3], + .w = pose.Rot[0]}; + + /* libsurvive looks down when it should be looking forward, so + * rotate the quat. + * because the HMD quat is the opposite of the in world + * rotation, we rotate down. */ + struct xrt_quat down_rot; + down_rot.x = sqrtf(2) / 2.; + down_rot.y = 0; + down_rot.z = 0; + down_rot.w = -sqrtf(2) / 2.; + + math_quat_rotate(&down_rot, &out_rot, &out_rot); + + out_relation->pose.orientation = out_rot; + + /* because the quat is rotated, y and z axes are switched. */ + out_relation->pose.position.x = pose.Pos[0]; + out_relation->pose.position.y = pose.Pos[2]; + out_relation->pose.position.z = -pose.Pos[1]; + + out_relation->relation_flags = + (enum xrt_space_relation_flags)( + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | + XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT) | + XRT_SPACE_RELATION_POSITION_VALID_BIT | + XRT_SPACE_RELATION_POSITION_TRACKED_BIT; + + SURVIVE_SPEW( + survive, + "GET_POSITION (%f %f %f) GET_ORIENTATION (%f, %f, %f, %f)", + out_relation->pose.position.x, + out_relation->pose.position.y, + out_relation->pose.position.z, out_rot.x, out_rot.y, + out_rot.z, out_rot.w); + last_rot = out_relation->pose.orientation; + last_pos = out_relation->pose.position; + } + + /// @todo: Handle device supplying data too slowly better + if (!new_data) { + out_relation->pose.orientation = last_rot; + out_relation->pose.position = last_pos; + out_relation->relation_flags = + (enum xrt_space_relation_flags)( + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | + XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT) | + XRT_SPACE_RELATION_POSITION_VALID_BIT | + XRT_SPACE_RELATION_POSITION_TRACKED_BIT; + } +} + +static void +survive_device_get_view_pose(struct xrt_device *xdev, + struct xrt_vec3 *eye_relation, + uint32_t view_index, + struct xrt_pose *out_pose) +{ + struct xrt_pose pose = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}}; + bool adjust = view_index == 0; + + pose.position.x = eye_relation->x / 2.0f; + pose.position.y = eye_relation->y / 2.0f; + pose.position.z = eye_relation->z / 2.0f; + + // Adjust for left/right while also making sure there aren't any -0.f. + if (pose.position.x > 0.0f && adjust) { + pose.position.x = -pose.position.x; + } + if (pose.position.y > 0.0f && adjust) { + pose.position.y = -pose.position.y; + } + if (pose.position.z > 0.0f && adjust) { + pose.position.z = -pose.position.z; + } + + *out_pose = pose; +} + +struct display_info +{ + float w_meters; + float h_meters; + int w_pixels; + int h_pixels; +}; + +struct device_info +{ + struct display_info display; + + float lens_horizontal_separation; + float lens_vertical_position; + + float pano_distortion_k[4]; + float pano_aberration_k[4]; + float pano_warp_scale; + + struct + { + float fov; + + struct display_info display; + + float lens_center_x_meters; + float lens_center_y_meters; + } views[2]; +}; + +static struct device_info +get_info() +{ + struct device_info info = {0}; + + //! @todo: hardcoded values for Vive 1 from openhmd vive driver + info.display.w_meters = 0.122822f; + info.display.h_meters = 0.068234f; + info.lens_horizontal_separation = 0.056; + info.lens_vertical_position = 0.032; + info.views[0].fov = + 2 * atan2f(0.122822f / 2. - 0.056 / 2., 0.023226876441867737); + info.views[1].fov = info.views[0].fov; + info.display.w_pixels = 2160; + info.display.h_pixels = 1200; + info.pano_distortion_k[0] = 1.318397; + info.pano_distortion_k[1] = -1.490242; + info.pano_distortion_k[2] = 0.663824; + info.pano_distortion_k[3] = 0.508021; + info.pano_aberration_k[0] = 1.00010147892f; + info.pano_aberration_k[1] = 1.000f; + info.pano_aberration_k[2] = 1.00019614479f; + + /* + * Assumptions made here: + * + * - There is a single, continuous, flat display serving both eyes, with + * no dead space/gap between eyes. + * - This single panel is (effectively) perpendicular to the forward + * (-Z) direction, with edges aligned with the X and Y axes. + * - Lens position is symmetrical about the center ("bridge of nose"). + * - Pixels are square and uniform across the entirety of the panel. + * + * If any of these are not true, then either the rendering will + * be inaccurate, or the properties will have to be "fudged" to + * make the math work. + */ + + info.views[0].display.w_meters = info.display.w_meters / 2.0; + info.views[0].display.h_meters = info.display.h_meters; + info.views[1].display.w_meters = info.display.w_meters / 2.0; + info.views[1].display.h_meters = info.display.h_meters; + + info.views[0].display.w_pixels = info.display.w_pixels / 2; + info.views[0].display.h_pixels = info.display.h_pixels; + info.views[1].display.w_pixels = info.display.w_pixels / 2; + info.views[1].display.h_pixels = info.display.h_pixels; + + /* + * Assuming the lenses are centered vertically on the + * display. It's not universal, but 0.5 COP on Y is more + * common than on X, and it looked like many of the + * driver lens_vpos values were copy/pasted or marked + * with FIXME. Safer to fix it to 0.5 than risk an + * extreme geometry mismatch. + */ + + const double cop_y = 0.5; + const double h_1 = cop_y * info.display.h_meters; + + //! @todo This are probably all wrong! + info.views[0].lens_center_x_meters = + info.views[0].display.w_meters - + info.lens_horizontal_separation / 2.0; + info.views[0].lens_center_y_meters = h_1; + + info.views[1].lens_center_x_meters = + info.lens_horizontal_separation / 2.0; + info.views[1].lens_center_y_meters = h_1; + + //! @todo This is most definitely wrong! + //! 3Glasses likes the oposite better. + info.pano_warp_scale = (info.views[0].lens_center_x_meters > + info.views[0].lens_center_x_meters) + ? info.views[0].lens_center_x_meters + : info.views[0].lens_center_x_meters; + return info; +} + +struct survive_device * +survive_device_create(bool print_spew, bool print_debug) +{ + char *survive_args[] = { + "Monado-libsurvive", + // Improves the situation when one basestation goes out of view + //"--time-window", "1500000" + }; + SurviveSimpleContext *actx = survive_simple_init( + sizeof(survive_args) / sizeof(survive_args[0]), survive_args); + + //! @todo: when no vive is connected, this prober will behave badly. + // * No calibration present: It segfaults + // * Calibration present. It calls exit() + // it should really return NULL instead. + + if (!actx) + return NULL; + + survive_simple_start_thread(actx); + + struct survive_device *survive = + (struct survive_device *)calloc(1, sizeof(struct survive_device)); + survive->base.destroy = survive_device_destroy; + survive->base.get_tracked_pose = survive_device_get_tracked_pose; + survive->base.get_view_pose = survive_device_get_view_pose; + survive->ctx = actx; + survive->print_spew = print_spew; + survive->print_debug = print_debug; + + const struct device_info info = get_info(); + + { + /* right eye */ + if (!math_compute_fovs(info.views[1].display.w_meters, + info.views[1].lens_center_x_meters, + info.views[1].fov, + info.views[1].display.h_meters, + info.views[1].lens_center_y_meters, 0, + &survive->base.views[1].fov)) { + SURVIVE_ERROR( + survive, + "Failed to compute the partial fields of view."); + free(survive); + return NULL; + } + } + { + /* left eye - just mirroring right eye now */ + survive->base.views[0].fov.angle_up = + survive->base.views[1].fov.angle_up; + survive->base.views[0].fov.angle_down = + survive->base.views[1].fov.angle_down; + + survive->base.views[0].fov.angle_left = + -survive->base.views[1].fov.angle_right; + survive->base.views[0].fov.angle_right = + -survive->base.views[1].fov.angle_left; + } + + // clang-format off + // Main display. + survive->base.distortion.models = XRT_DISTORTION_MODEL_PANOTOOLS; + survive->base.distortion.preferred = XRT_DISTORTION_MODEL_PANOTOOLS; + survive->base.screens[0].w_pixels = info.display.w_pixels; + survive->base.screens[0].h_pixels = info.display.h_pixels; + survive->base.distortion.pano.distortion_k[0] = info.pano_distortion_k[0]; + survive->base.distortion.pano.distortion_k[1] = info.pano_distortion_k[1]; + survive->base.distortion.pano.distortion_k[2] = info.pano_distortion_k[2]; + survive->base.distortion.pano.distortion_k[3] = info.pano_distortion_k[3]; + survive->base.distortion.pano.aberration_k[0] = info.pano_aberration_k[0]; + survive->base.distortion.pano.aberration_k[1] = info.pano_aberration_k[1]; + survive->base.distortion.pano.aberration_k[2] = info.pano_aberration_k[2]; + + // Left + survive->base.views[0].display.w_meters = info.views[0].display.w_meters; + survive->base.views[0].display.h_meters = info.views[0].display.h_meters; + survive->base.views[0].lens_center.x_meters = info.views[0].lens_center_x_meters; + survive->base.views[0].lens_center.y_meters = info.views[0].lens_center_y_meters; + survive->base.views[0].display.w_pixels = info.views[0].display.w_pixels; + survive->base.views[0].display.h_pixels = info.views[0].display.h_pixels; + survive->base.views[0].viewport.x_pixels = 0; + survive->base.views[0].viewport.y_pixels = 0; + survive->base.views[0].viewport.w_pixels = info.views[0].display.w_pixels; + survive->base.views[0].viewport.h_pixels = info.views[0].display.h_pixels; + survive->base.views[0].rot = u_device_rotation_ident; + + // Right + survive->base.views[1].display.w_meters = info.views[1].display.w_meters; + survive->base.views[1].display.h_meters = info.views[1].display.h_meters; + survive->base.views[1].lens_center.x_meters = info.views[1].lens_center_x_meters; + survive->base.views[1].lens_center.y_meters = info.views[1].lens_center_y_meters; + survive->base.views[1].display.w_pixels = info.views[1].display.w_pixels; + survive->base.views[1].display.h_pixels = info.views[1].display.h_pixels; + survive->base.views[1].viewport.x_pixels = info.views[0].display.w_pixels; + survive->base.views[1].viewport.y_pixels = 0; + survive->base.views[1].viewport.w_pixels = info.views[1].display.w_pixels; + survive->base.views[1].viewport.h_pixels = info.views[1].display.h_pixels; + survive->base.views[1].rot = u_device_rotation_ident; + // clang-format on + + // Find any needed quirks. + bool quirk_video_see_through = false; + bool quirk_video_distortion_vive = false; + + quirk_video_distortion_vive = true; + quirk_video_see_through = false; + + // Which blend modes does the device support. + survive->base.blend_mode |= XRT_BLEND_MODE_OPAQUE; + if (quirk_video_see_through) { + survive->base.blend_mode |= XRT_BLEND_MODE_ALPHA_BLEND; + } + + if (quirk_video_distortion_vive) { + survive->base.distortion.models |= XRT_DISTORTION_MODEL_VIVE; + survive->base.distortion.preferred = XRT_DISTORTION_MODEL_VIVE; + + // clang-format off + // These need to be aquired from the vive config + survive->base.distortion.vive.aspect_x_over_y = 0.8999999761581421f; + survive->base.distortion.vive.grow_for_undistort = 0.6000000238418579f; + survive->base.distortion.vive.undistort_r2_cutoff[0] = 1.11622154712677f; + survive->base.distortion.vive.undistort_r2_cutoff[1] = 1.101870775222778f; + survive->base.distortion.vive.center[0][0] = 0.08946027017045266f; + survive->base.distortion.vive.center[0][1] = -0.009002181016260827f; + survive->base.distortion.vive.center[1][0] = -0.08933516629552526f; + survive->base.distortion.vive.center[1][1] = -0.006014565287238661f; + + // left + // green + survive->base.distortion.vive.coefficients[0][0][0] = -0.188236068524731f; + survive->base.distortion.vive.coefficients[0][0][1] = -0.221086205321053f; + survive->base.distortion.vive.coefficients[0][0][2] = -0.2537849057915209f; + + // blue + survive->base.distortion.vive.coefficients[0][1][0] = -0.07316590815739493f; + survive->base.distortion.vive.coefficients[0][1][1] = -0.02332400789561968f; + survive->base.distortion.vive.coefficients[0][1][2] = 0.02469959434698275f; + + // red + survive->base.distortion.vive.coefficients[0][2][0] = -0.02223805567703767f; + survive->base.distortion.vive.coefficients[0][2][1] = -0.04931309279533211f; + survive->base.distortion.vive.coefficients[0][2][2] = -0.07862881939243466f; + + // right + // green + survive->base.distortion.vive.coefficients[1][0][0] = -0.1906209981894497f; + survive->base.distortion.vive.coefficients[1][0][1] = -0.2248896677207884f; + survive->base.distortion.vive.coefficients[1][0][2] = -0.2721364516782803f; + + // blue + survive->base.distortion.vive.coefficients[1][1][0] = -0.07346071902951497f; + survive->base.distortion.vive.coefficients[1][1][1] = -0.02189527566250131f; + survive->base.distortion.vive.coefficients[1][1][2] = 0.0581378652359256f; + + // red + survive->base.distortion.vive.coefficients[1][2][0] = -0.01755850332081247f; + survive->base.distortion.vive.coefficients[1][2][1] = -0.04517245633373419f; + survive->base.distortion.vive.coefficients[1][2][2] = -0.0928909347763f; + // clang-format on + } + + if (survive->print_debug) { + u_device_dump_config(&survive->base, __func__, "libsurvive"); + } + return survive; +} diff --git a/src/xrt/drivers/survive/survive_device.h b/src/xrt/drivers/survive/survive_device.h new file mode 100644 index 0000000000000000000000000000000000000000..51b20de9d7c8319d64468606ec6b1d60c806be38 --- /dev/null +++ b/src/xrt/drivers/survive/survive_device.h @@ -0,0 +1,61 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: Apache-2.0 +/*! + * @file + * @brief Interface to OpenHMD driver code. + * @author Jakob Bornecrantz <jakob@collabora.com> + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include <survive_api.h> + +struct survive_device +{ + struct xrt_device base; + SurviveSimpleContext *ctx; + + bool print_spew; + bool print_debug; +}; + +static inline struct survive_device * +survive_device(struct xrt_device *xdev) +{ + return (struct survive_device *)xdev; +} + +struct survive_device * +survive_device_create(bool print_spew, bool print_debug); + +#define SURVIVE_SPEW(c, ...) \ + do { \ + if (c->print_spew) { \ + fprintf(stderr, "%s - ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } \ + } while (false) +#define SURVIVE_DEBUG(c, ...) \ + do { \ + if (c->print_debug) { \ + fprintf(stderr, "%s - ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } \ + } while (false) + +#define SURVIVE_ERROR(c, ...) \ + do { \ + fprintf(stderr, "%s - ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (false) + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/drivers/survive/survive_interface.h b/src/xrt/drivers/survive/survive_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..0656b6ae6cc3b90d00f1aef7dae6afc51cca13c5 --- /dev/null +++ b/src/xrt/drivers/survive/survive_interface.h @@ -0,0 +1,22 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: Apache-2.0 +/*! + * @file + * @brief Interface to OpenHMD driver code. + * @author Jakob Bornecrantz <jakob@collabora.com> + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + +struct xrt_prober* +survive_create_prober(); + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/drivers/survive/survive_prober.c b/src/xrt/drivers/survive/survive_prober.c new file mode 100644 index 0000000000000000000000000000000000000000..a559b08c1ef84b7f263116c0d5f93102e1b9a0c5 --- /dev/null +++ b/src/xrt/drivers/survive/survive_prober.c @@ -0,0 +1,80 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: Apache-2.0 +/*! + * @file + * @brief OpenHMD prober code. + * @author Jakob Bornecrantz <jakob@collabora.com> + */ + +#include <stdio.h> +#include <stdlib.h> + +#include <survive_api.h> +#include "xrt/xrt_prober.h" + +#include "util/u_misc.h" +#include "util/u_debug.h" + +#include "survive_device.h" + +DEBUG_GET_ONCE_BOOL_OPTION(survive_spew, "SURVIVE_PRINT_SPEW", false) +DEBUG_GET_ONCE_BOOL_OPTION(survive_debug, "SURVIVE_PRINT_DEBUG", false) + +struct survive_prober +{ + struct xrt_prober base; + SurviveSimpleContext *ctx; +}; + +static inline struct survive_prober * +survive_prober(struct xrt_prober *p) +{ + return (struct survive_prober *)p; +} + +static void +survive_prober_destroy(struct xrt_prober *p) +{ + struct survive_prober *sp = survive_prober(p); + + if (sp->ctx != NULL) { + /// @todo: This segfaults + // survive_simple_close(ohp->ctx); + sp->ctx = NULL; + } + + free(sp); +} + +static struct xrt_device * +survive_prober_autoprobe(struct xrt_prober *p) +{ + struct survive_prober *sp = survive_prober(p); + + + bool print_spew = debug_get_bool_option_survive_spew(); + bool print_debug = debug_get_bool_option_survive_debug(); + + /// @todo: with libsurvive, whether a context can be created tells us if + /// a supported device is connected and readable. + + struct survive_device *sd = + survive_device_create(print_spew, print_debug); + + if (sd == NULL || sd->ctx == NULL) + return NULL; + + sp->ctx = sd->ctx; + + return &sd->base; +} + +struct xrt_prober * +survive_create_prober() +{ + struct survive_prober *sp = calloc(1, sizeof(struct survive_prober)); + sp->base.destroy = survive_prober_destroy; + sp->base.lelo_dallas_autoprobe = survive_prober_autoprobe; + + return &sp->base; +} diff --git a/src/xrt/targets/openxr/CMakeLists.txt b/src/xrt/targets/openxr/CMakeLists.txt index d6b04603433cb733e85afb2a95cde77600ff69a5..dd02e38dc5cfaf375684a35a25b58f58e7a67a91 100644 --- a/src/xrt/targets/openxr/CMakeLists.txt +++ b/src/xrt/targets/openxr/CMakeLists.txt @@ -72,9 +72,14 @@ add_library(${RUNTIME_TARGET} SHARED $<TARGET_OBJECTS:st_oxr> ) +if (TARGET drv_survive) + SET(LIBSURVIVE_LIBRARIES survive) +endif() + target_link_libraries(${RUNTIME_TARGET} ${OPENHMD_LIBRARIES} ${Vulkan_LIBRARIES} + ${LIBSURVIVE_LIBRARIES} ${XCB_LIBRARIES} ) @@ -86,6 +91,11 @@ if(TARGET drv_hdk) target_compile_definitions(${RUNTIME_TARGET} PRIVATE XRT_HAVE_HDK) endif() +if (TARGET drv_survive) + target_sources(${RUNTIME_TARGET} PRIVATE $<TARGET_OBJECTS:drv_survive>) + target_compile_definitions(${RUNTIME_TARGET} PRIVATE XRT_HAVE_SURVIVE) +endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") include(GNUInstallDirs) install(TARGETS ${RUNTIME_TARGET} diff --git a/src/xrt/targets/openxr/target.c b/src/xrt/targets/openxr/target.c index 9bdd1613c803e6f093e2740b2ceab1f2ae559d53..765517870ca4f92ac688a0d97772a886a47d6d7e 100644 --- a/src/xrt/targets/openxr/target.c +++ b/src/xrt/targets/openxr/target.c @@ -18,6 +18,10 @@ #include "hdk/hdk_interface.h" #endif +#ifdef XRT_HAVE_SURVIVE +#include "survive/survive_interface.h" +#endif + typedef struct xrt_prober *(*prober_creator)(); @@ -28,6 +32,10 @@ static const prober_creator DRIVERS[] = { hdk_create_prober, #endif +#ifdef XRT_HAVE_SURVIVE + survive_create_prober, +#endif + #ifdef XRT_HAVE_OHMD oh_create_prober, #endif