diff --git a/CMakeLists.txt b/CMakeLists.txt index 25d7ae3bea67912e77dabc6a91f9aae25dc05504..a637d567d4acf704c4663aa79e77314c750a64a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2018-2019, Collabora, Ltd. +# Copyright 2018-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 cmake_minimum_required(VERSION 3.10.0) @@ -71,6 +71,7 @@ cmake_dependent_option(BUILD_WITH_OPENCV "Enable OpenCV backend" ON "OpenCV_FOUN cmake_dependent_option(BUILD_WITH_LIBUVC "Enable libuvc video driver" ON "LIBUVC_FOUND" OFF) cmake_dependent_option(BUILD_WITH_FFMPEG "Enable ffmpeg testing video driver" ON "FFMPEG_FOUND" OFF) cmake_dependent_option(BUILD_WITH_PSVR "Enable PSVR HMD driver" ON "HIDAPI_FOUND" OFF) +option(BUILD_WITH_DUMMY "Enable dummy driver" ON) cmake_dependent_option(BUILD_WITH_VIVE "Enable Vive driver" ON "ZLIB_FOUND" OFF) cmake_dependent_option(BUILD_WITH_OPENHMD "Enable OpenHMD driver" ON "OPENHMD_FOUND" OFF) cmake_dependent_option(BUILD_WITH_SDL2 "Enable SDL2 based test application" ON "SDL2_FOUND" OFF) @@ -127,6 +128,10 @@ if(BUILD_WITH_SDL2) set(BUILD_TARGET_GUI TRUE) endif() +if(BUILD_WITH_DUMMY) + set(BUILD_DRIVER_DUMMY TRUE) +endif() + if(BUILD_WITH_OPENHMD) add_definitions(-DXRT_HAVE_OPENHMD) diff --git a/meson.build b/meson.build index c23bca33aa491c946951c9bbfd58113976b68762..6f3e47ef63b12c7e5e9d42fa1fceec695a542e1e 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 project( @@ -139,7 +139,7 @@ if 'v4l2' in drivers endif if 'auto' in drivers - drivers += ['psmv', 'hydra', 'hdk'] + drivers += ['dummy', 'hdk', 'hydra', 'psmv'] endif openhmd = dependency('openhmd', required: openhmd_required) diff --git a/meson_options.txt b/meson_options.txt index 5780a175d751f36d0b8e11eb2d1bc570c669b589..abfaaa8a449e9b24fdf474d0a63fc4b89ef5c679 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,9 +1,9 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 option('drivers', type: 'array', - choices: ['auto', 'hdk', 'hydra', 'ohmd', 'psmv', 'psvr', 'v4l2', 'vive'], + choices: ['auto', 'dummy', 'hdk', 'hydra', 'ohmd', 'psmv', 'psvr', 'v4l2', 'vive'], value: ['auto'], description: 'Set of drivers to build') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2c0bb0ffc38dc3232a0d2ec300152429a3b7f7e..a01ae616b05a4c867abbe7637f1fe381a7fd95bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 @@ -6,6 +6,10 @@ if(BUILD_TRACKING) set(XRT_BUILD_TRACKING TRUE) endif() +if(BUILD_DRIVER_DUMMY) + set(XRT_BUILD_DRIVER_DUMMY TRUE) +endif() + if(BUILD_DRIVER_HDK) set(XRT_BUILD_DRIVER_HDK TRUE) endif() diff --git a/src/meson.build b/src/meson.build index f4ad397c05570c3189923244fc024b5d82f2cd69..9edb2351d1b8e029c2093eec6d381fe6da1b440a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,8 +1,9 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 conf_data = configuration_data() conf_data.set('XRT_BUILD_TRACKING', build_tracking) +conf_data.set('XRT_BUILD_DRIVER_DUMMY', 'dummy' in drivers) conf_data.set('XRT_BUILD_DRIVER_HDK', 'hdk' in drivers) conf_data.set('XRT_BUILD_DRIVER_HYDRA', 'hydra' in drivers) conf_data.set('XRT_BUILD_DRIVER_OHMD', 'ohmd' in drivers) diff --git a/src/targets_enabled_drivers.h.cmake_in b/src/targets_enabled_drivers.h.cmake_in index 93f90eaf3af780ca389ab5a038b691bf0171d6da..db6bafecf75ce916e51189bb0ce96ecc88df09d8 100644 --- a/src/targets_enabled_drivers.h.cmake_in +++ b/src/targets_enabled_drivers.h.cmake_in @@ -1,4 +1,4 @@ -// Copyright 2019, Collabora, Ltd. +// Copyright 2019-2020, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -9,6 +9,8 @@ #cmakedefine XRT_BUILD_TRACKING +#cmakedefine XRT_BUILD_DRIVER_DUMMY + #cmakedefine XRT_BUILD_DRIVER_HDK #cmakedefine XRT_BUILD_DRIVER_HYDRA diff --git a/src/targets_enabled_drivers.h.meson_in b/src/targets_enabled_drivers.h.meson_in index f2ef7fb760cd5335682c08d96ba40e249f5e7545..6209d7a07091103c578f724527b3a78f3ddc6f7c 100644 --- a/src/targets_enabled_drivers.h.meson_in +++ b/src/targets_enabled_drivers.h.meson_in @@ -1,4 +1,4 @@ -// Copyright 2019, Collabora, Ltd. +// Copyright 2019-2020, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -9,6 +9,8 @@ #mesondefine XRT_BUILD_TRACKING +#mesondefine XRT_BUILD_DRIVER_DUMMY + #mesondefine XRT_BUILD_DRIVER_HDK #mesondefine XRT_BUILD_DRIVER_HYDRA diff --git a/src/xrt/drivers/CMakeLists.txt b/src/xrt/drivers/CMakeLists.txt index e5cedbd93a298b543e331341f7be2ba184471da6..0e716da6bf0a0bd6d342a9cac39c64a67fc1514e 100644 --- a/src/xrt/drivers/CMakeLists.txt +++ b/src/xrt/drivers/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 @@ -11,6 +11,18 @@ include_directories( set(ENABLED_HEADSET_DRIVERS) set(ENABLED_DRIVERS) +if(BUILD_DRIVER_DUMMY) + set(DUMMY_SOURCE_FILES + dummy/dummy_hmd.c + dummy/dummy_interface.h + dummy/dummy_prober.c + ) + + # Use OBJECT to not create a archive, since it just gets in the way. + add_library(drv_dummy OBJECT ${DUMMY_SOURCE_FILES}) + list(APPEND ENABLED_HEADSET_DRIVERS dummy) +endif() + if(BUILD_DRIVER_HDK) set(HDK_SOURCE_FILES hdk/hdk_device.cpp diff --git a/src/xrt/drivers/dummy/dummy_hmd.c b/src/xrt/drivers/dummy/dummy_hmd.c new file mode 100644 index 0000000000000000000000000000000000000000..54df11da8b4271baaa1813956d43cb2db9dbd369 --- /dev/null +++ b/src/xrt/drivers/dummy/dummy_hmd.c @@ -0,0 +1,198 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Dummy HMD device. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup drv_dummy + */ + + +#include <math.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "math/m_api.h" +#include "xrt/xrt_device.h" +#include "util/u_var.h" +#include "util/u_misc.h" +#include "util/u_debug.h" +#include "util/u_device.h" +#include "util/u_time.h" +#include "util/u_distortion_mesh.h" + +/* + * + * Structs and defines. + * + */ + +struct dummy_hmd +{ + struct xrt_device base; + + struct xrt_pose pose; + + bool print_spew; + bool print_debug; +}; + + +/* + * + * Functions + * + */ + +static inline struct dummy_hmd * +dummy_hmd(struct xrt_device *xdev) +{ + return (struct dummy_hmd *)xdev; +} + +DEBUG_GET_ONCE_BOOL_OPTION(dummy_spew, "DUMMY_PRINT_SPEW", false) +DEBUG_GET_ONCE_BOOL_OPTION(dummy_debug, "DUMMY_PRINT_DEBUG", false) + +#define DH_SPEW(dh, ...) \ + do { \ + if (dh->print_spew) { \ + fprintf(stderr, "%s - ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } \ + } while (false) + +#define DH_DEBUG(dh, ...) \ + do { \ + if (dh->print_debug) { \ + fprintf(stderr, "%s - ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } \ + } while (false) + +#define DH_ERROR(dh, ...) \ + do { \ + fprintf(stderr, "%s - ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (false) + +static void +dummy_hmd_destroy(struct xrt_device *xdev) +{ + struct dummy_hmd *dh = dummy_hmd(xdev); + + // Remove the variable tracking. + u_var_remove_root(dh); + + u_device_free(&dh->base); +} + +static void +dummy_hmd_update_inputs(struct xrt_device *xdev, struct time_state *timekeeping) +{ + // Empty +} + +static void +dummy_hmd_get_tracked_pose(struct xrt_device *xdev, + enum xrt_input_name name, + struct time_state *timekeeping, + int64_t *out_timestamp, + struct xrt_space_relation *out_relation) +{ + struct dummy_hmd *dh = dummy_hmd(xdev); + + if (name != XRT_INPUT_GENERIC_HEAD_POSE) { + DH_ERROR(dh, "unknown input name"); + return; + } + + int64_t now = time_state_get_now(timekeeping); + + *out_timestamp = now; + out_relation->pose = dh->pose; + out_relation->relation_flags = (enum xrt_space_relation_flags)( + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | + XRT_SPACE_RELATION_POSITION_VALID_BIT); +} + +static void +dummy_hmd_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 xrt_device * +dummy_hmd_create(void) +{ + enum u_device_alloc_flags flags = (enum u_device_alloc_flags)( + U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE); + struct dummy_hmd *dh = U_DEVICE_ALLOCATE(struct dummy_hmd, flags, 1, 0); + dh->base.update_inputs = dummy_hmd_update_inputs; + dh->base.get_tracked_pose = dummy_hmd_get_tracked_pose; + dh->base.get_view_pose = dummy_hmd_get_view_pose; + dh->base.destroy = dummy_hmd_destroy; + dh->base.name = XRT_DEVICE_GENERIC_HMD; + dh->pose.orientation.w = 1.0f; // All other values set to zero. + dh->print_spew = debug_get_bool_option_dummy_spew(); + dh->print_debug = debug_get_bool_option_dummy_debug(); + + // Print name. + snprintf(dh->base.str, XRT_DEVICE_NAME_LEN, "Dummy HMD"); + + // Setup input. + dh->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; + + // Setup info. + struct u_device_simple_info info; + info.display.w_pixels = 1920; + info.display.h_pixels = 1080; + info.display.w_meters = 0.13f; + info.display.h_meters = 0.07f; + info.lens_horizontal_separation_meters = 0.13f / 2.0f; + info.lens_vertical_position_meters = 0.07f / 2.0f; + info.views[0].fov = 85.0f * (M_PI / 180.0f); + info.views[1].fov = 85.0f * (M_PI / 180.0f); + + if (!u_device_setup_split_side_by_side(&dh->base, &info)) { + DH_ERROR(dh, "Failed to setup basic device info"); + dummy_hmd_destroy(&dh->base); + return NULL; + } + + // Setup variable tracker. + u_var_add_root(dh, "Dummy HMD", true); + + if (dh->base.hmd->distortion.preferred == XRT_DISTORTION_MODEL_NONE) { + // Setup the distortion mesh. + u_distortion_mesh_none(dh->base.hmd); + } + + return &dh->base; +} diff --git a/src/xrt/drivers/dummy/dummy_interface.h b/src/xrt/drivers/dummy/dummy_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..46767183711357e28826746779cef480fa9745fc --- /dev/null +++ b/src/xrt/drivers/dummy/dummy_interface.h @@ -0,0 +1,48 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Interface to dummy driver. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup drv_dummy + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @defgroup drv_dummy Dummy driver. + * @ingroup drv + * + * @brief Simple do nothing dummy driver. + */ + +/*! + * Create a auto prober for dummy devices. + * + * @ingroup drv_dummy + */ +struct xrt_auto_prober * +dummy_create_auto_prober(void); + +/*! + * Create a dummy hmd. + * + * @ingroup drv_dummy + */ +struct xrt_device * +dummy_hmd_create(void); + +/*! + * @dir drivers/dummy + * + * @brief @ref drv_dummy files. + */ + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/drivers/dummy/dummy_prober.c b/src/xrt/drivers/dummy/dummy_prober.c new file mode 100644 index 0000000000000000000000000000000000000000..3380c2d0e626b3d7a2c31f879504fda583b903ca --- /dev/null +++ b/src/xrt/drivers/dummy/dummy_prober.c @@ -0,0 +1,64 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Dummy prober code. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup drv_ohmd + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "xrt/xrt_prober.h" + +#include "util/u_misc.h" +#include "util/u_debug.h" + +#include "dummy_interface.h" + + +struct dummy_prober +{ + struct xrt_auto_prober base; +}; + +static inline struct dummy_prober * +dummy_prober(struct xrt_auto_prober *p) +{ + return (struct dummy_prober *)p; +} + +static void +dummy_prober_destroy(struct xrt_auto_prober *p) +{ + struct dummy_prober *dp = dummy_prober(p); + + free(dp); +} + +static struct xrt_device * +dummy_prober_autoprobe(struct xrt_auto_prober *xap, + bool no_hmds, + struct xrt_prober *xp) +{ + struct dummy_prober *dp = dummy_prober(xap); + (void)dp; + + // Do not create a dummy HMD if we are not looking for HMDs. + if (no_hmds) { + return NULL; + } + + return dummy_hmd_create(); +} + +struct xrt_auto_prober * +dummy_create_auto_prober() +{ + struct dummy_prober *dp = U_TYPED_CALLOC(struct dummy_prober); + dp->base.destroy = dummy_prober_destroy; + dp->base.lelo_dallas_autoprobe = dummy_prober_autoprobe; + + return &dp->base; +} diff --git a/src/xrt/drivers/meson.build b/src/xrt/drivers/meson.build index a2fcbb6612eca93931a940c4cecd7628d94c20e2..16499dc1700245c2675765f6b8f68f2c0f1d40b7 100644 --- a/src/xrt/drivers/meson.build +++ b/src/xrt/drivers/meson.build @@ -1,8 +1,20 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 drv_include = include_directories('.') +lib_drv_dummy = static_library( + 'drv_dummy', + files( + 'dummy/dummy_hmd.c', + 'dummy/dummy_interface.h', + 'dummy/dummy_prober.c', + ), + include_directories: xrt_include, + dependencies: [aux], + build_by_default: 'dummy' in drivers, +) + lib_drv_hdk = static_library( 'drv_hdk', files( diff --git a/src/xrt/targets/CMakeLists.txt b/src/xrt/targets/CMakeLists.txt index 56c123b1cfe16e9d1e254ef9e7de701cc81b79c0..86330fc97a3ee4d3aab431d437c353bd5d24644d 100644 --- a/src/xrt/targets/CMakeLists.txt +++ b/src/xrt/targets/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 ###### @@ -20,6 +20,10 @@ if(BUILD_WITH_JPEG) list(APPEND DRIVER_LIBRARIES ${JPEG_LIBRARIES}) endif() +if(BUILD_DRIVER_DUMMY) + list(APPEND DRIVER_OBJECTS $<TARGET_OBJECTS:drv_dummy>) +endif() + if(BUILD_DRIVER_HDK) list(APPEND DRIVER_OBJECTS $<TARGET_OBJECTS:drv_hdk>) list(APPEND DRIVER_LIBRARIES ${HIDAPI_LIBRARIES}) diff --git a/src/xrt/targets/common/target_lists.c b/src/xrt/targets/common/target_lists.c index ce972caa1686a692af52beccf844ddd4b701135a..d5af4f6a235f13330e346d356906b11d9e82f06c 100644 --- a/src/xrt/targets/common/target_lists.c +++ b/src/xrt/targets/common/target_lists.c @@ -1,4 +1,4 @@ -// Copyright 2019, Collabora, Ltd. +// Copyright 2019-2020, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -10,6 +10,10 @@ #include "target_lists.h" +#ifdef XRT_BUILD_DRIVER_DUMMY +#include "dummy/dummy_interface.h" +#endif + #ifdef XRT_BUILD_DRIVER_HDK #include "hdk/hdk_interface.h" #endif @@ -88,6 +92,11 @@ xrt_auto_prober_creator target_auto_list[] = { // OpenHMD last as we want to override it with native drivers. oh_create_auto_prober, #endif + +#ifdef XRT_BUILD_DRIVER_DUMMY + // Dummy headset driver last. + dummy_create_auto_prober, +#endif NULL, // Terminate }; diff --git a/src/xrt/targets/meson.build b/src/xrt/targets/meson.build index ed889e98a6af5d844e0870e7438de0e6fcd8854b..c37b6b2d5f07c54b19e5247e13601f80ea9285df 100644 --- a/src/xrt/targets/meson.build +++ b/src/xrt/targets/meson.build @@ -1,4 +1,4 @@ -# Copyright 2019, Collabora, Ltd. +# Copyright 2019-2020, Collabora, Ltd. # SPDX-License-Identifier: BSL-1.0 driver_libs = [] @@ -12,6 +12,10 @@ if libjpeg.found() driver_deps += [libjpeg] endif +if 'dummy' in drivers + driver_libs += [lib_drv_dummy] +endif + if 'hdk' in drivers driver_libs += [lib_drv_hdk] endif