From 3d0611052f8701dd34edd65f3723cc999ecd03c9 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Wed, 31 Jul 2024 05:28:34 +0900 Subject: [PATCH] switch to using libmonado-rs --- Cargo.lock | 167 ++++++++++++++++++++++---------- Cargo.toml | 6 +- src/backend/openxr/helpers.rs | 55 ++--------- src/backend/openxr/libmonado.rs | 149 ---------------------------- src/backend/openxr/mod.rs | 18 +++- src/backend/openxr/playspace.rs | 167 +++++++------------------------- 6 files changed, 175 insertions(+), 387 deletions(-) delete mode 100644 src/backend/openxr/libmonado.rs diff --git a/Cargo.lock b/Cargo.lock index 85a0b93..4c250ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,9 +130,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -145,33 +145,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -571,12 +571,15 @@ dependencies = [ "itertools 0.12.1", "lazy_static", "lazycell", + "log", + "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn 2.0.72", + "which", ] [[package]] @@ -691,9 +694,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" dependencies = [ "jobserver", "libc", @@ -791,9 +794,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.10" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6b81fb3c84f5563d509c59b5a48d935f689e993afa90fe39047f05adef9142" +checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" dependencies = [ "clap_builder", "clap_derive", @@ -801,9 +804,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.10" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca6706fd5224857d9ac5eb9355f6683563cc0541c7cd9d014043b57cbec78ac" +checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" dependencies = [ "anstream", "anstyle", @@ -813,9 +816,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -825,9 +828,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cmake" @@ -850,9 +853,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "combine" @@ -1264,6 +1267,29 @@ dependencies = [ "libloading", ] +[[package]] +name = "dlopen2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "dlv-list" version = "0.5.2" @@ -1418,6 +1444,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flagset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" + [[package]] name = "flexi_logger" version = "0.28.5" @@ -1654,6 +1686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94" dependencies = [ "approx", + "mint", "serde", ] @@ -1725,6 +1758,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "hound" version = "3.5.1" @@ -1859,9 +1901,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -1999,6 +2041,23 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "libmonado-rs" +version = "0.1.0" +source = "git+https://github.com/technobaboo/libmonado-rs?rev=bf1bcf7#bf1bcf74d496679fe51b6ca609f36be7f39d857e" +dependencies = [ + "bindgen", + "cmake", + "convert_case 0.6.0", + "dlopen2", + "flagset", + "mint", + "semver", + "serde", + "serde_json", + "xdg", +] + [[package]] name = "libredox" version = "0.0.2" @@ -2183,6 +2242,12 @@ dependencies = [ "adler", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "moveit" version = "0.6.0" @@ -2312,11 +2377,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2341,18 +2406,18 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate 2.0.2", "proc-macro2", @@ -2574,9 +2639,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -3286,11 +3351,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -3319,9 +3385,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -3833,9 +3899,9 @@ checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vk-parse" @@ -4112,6 +4178,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" @@ -4200,15 +4278,6 @@ dependencies = [ "windows-targets 0.42.2", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -4501,7 +4570,7 @@ dependencies = [ "json", "json5", "libc", - "libloading", + "libmonado-rs", "log", "log-panics", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 4f55693..0d6266c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,14 +23,13 @@ flexi_logger = "0.28.1" fontconfig-rs = "0.1.1" freetype-rs = "0.36.0" # latest version supported on ubuntu 22.04 futures = "0.3.30" -glam = { version = "0.28.0", features = ["approx", "serde"] } +glam = { version = "0.28.0", features = ["approx", "mint", "serde"] } idmap = { version = "0.2.21", features = ["serde"] } idmap-derive = "0.1.2" input-linux = "0.6.0" json = { version = "0.12.4", optional = true } json5 = "0.4.1" libc = "0.2.155" -libloading = "0.8.3" log = "0.4.21" once_cell = "1.19.0" openxr = { git = "https://github.com/galister/openxrs", rev = "af4a55d", features = [ @@ -56,6 +55,7 @@ thiserror = "1.0.61" vulkano = { git = "https://github.com/vulkano-rs/vulkano", rev = "b9f3e89" } vulkano-shaders = { git = "https://github.com/vulkano-rs/vulkano", rev = "b9f3e89" } wlx-capture = { git = "https://github.com/galister/wlx-capture", tag = "v0.3.12", default-features = false } +libmonado-rs = { git = "https://github.com/technobaboo/libmonado-rs", rev = "bf1bcf7", optional = true } winit = { version = "0.30.0", optional = true } xdg = "2.5.2" log-panics = { version = "2.1.0", features = ["with-backtrace"] } @@ -71,7 +71,7 @@ image_dds = { version = "0.5.1", default-features = false, features = [ [features] default = ["openvr", "openxr", "osc", "x11", "wayland"] openvr = ["dep:ovr_overlay", "dep:json"] -openxr = ["dep:openxr"] +openxr = ["dep:openxr", "dep:libmonado-rs"] osc = ["dep:rosc"] x11 = ["dep:xcb", "wlx-capture/xshm", "xkbcommon/x11"] wayland = ["pipewire", "wlx-capture/wlr", "xkbcommon/wayland"] diff --git a/src/backend/openxr/helpers.rs b/src/backend/openxr/helpers.rs index 641d7ae..8f91dbc 100644 --- a/src/backend/openxr/helpers.rs +++ b/src/backend/openxr/helpers.rs @@ -1,9 +1,6 @@ -use std::path::PathBuf; - use anyhow::{bail, ensure}; use glam::{Affine3A, Quat, Vec3, Vec3A}; use openxr as xr; -use sysinfo::Process; use xr::OverlaySessionCreateFlagsEXTX; pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> { @@ -35,6 +32,12 @@ pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> { } else { log::warn!("Missing EXT_hp_mixed_reality_controller extension."); } + if available_extensions.khr_composition_layer_cylinder { + enabled_extensions.khr_composition_layer_cylinder = true; + } else { + log::warn!("Missing EXT_composition_layer_cylinder extension."); + } + if available_extensions.khr_composition_layer_equirect2 { enabled_extensions.khr_composition_layer_equirect2 = true; } else { @@ -178,49 +181,3 @@ pub(super) fn transform_to_posef(transform: &Affine3A) -> xr::Posef { let rotation = transform_to_norm_quat(transform); translation_rotation_to_posef(translation, rotation) } - -pub(super) fn find_libmonado() -> anyhow::Result { - //check env var first - if let Ok(path) = std::env::var("LIBMONADO_PATH") { - let path = PathBuf::from(path); - if path.exists() { - return Ok(unsafe { libloading::Library::new(path)? }); - } else { - bail!("LIBMONADO_PATH points to a non-existing file."); - } - } - - const PROC_NAMES: [&str; 2] = ["monado-service", "wivrn-server"]; - - let mut system = sysinfo::System::new(); - system.refresh_processes(); - for p in system.processes().values() { - for proc_name in PROC_NAMES.iter() { - if p.name().contains(proc_name) { - if let Some(lib) = proc_load_libmonado(p) { - return Ok(lib); - } - } - } - } - bail!("Could not find libmonado."); -} - -fn proc_load_libmonado(proc: &Process) -> Option { - // relative to folder containing binary - const SEARCH_PATHS: [&str; 3] = [ - "../lib/libmonado.so", - "../libmonado/libmonado.so", - "../_deps/monado-build/src/xrt/targets/libmonado/libmonado.so", - ]; - - for &p in SEARCH_PATHS.iter() { - let path = proc.exe()?.parent()?.join(p); - - if path.exists() { - return Some(unsafe { libloading::Library::new(path).ok()? }); - } - } - - None -} diff --git a/src/backend/openxr/libmonado.rs b/src/backend/openxr/libmonado.rs deleted file mode 100644 index 893e96d..0000000 --- a/src/backend/openxr/libmonado.rs +++ /dev/null @@ -1,149 +0,0 @@ -use std::{env, ffi::c_void, fs}; - -use anyhow::bail; -use libloading::{Library, Symbol}; -use serde::Deserialize; - -#[repr(C)] -#[derive(Default, Debug)] -struct MndPose { - orientation: [f32; 4], - position: [f32; 3], -} - -const MND_REFERENCE_TYPE_STAGE: i32 = 3; - -const MND_SUCCESS: i32 = 0; -const MND_ERROR_BAD_SPACE_TYPE: i32 = -7; - -type GetDeviceCount = extern "C" fn(*mut c_void, *mut u32) -> i32; -type GetDeviceInfo = extern "C" fn(*mut c_void, u32, *mut u32, *mut *const char) -> i32; -type GetDeviceFromRole = extern "C" fn(*mut c_void, *const std::os::raw::c_char, *mut i32) -> i32; -type GetDeviceBatteryStatus = - extern "C" fn(*mut c_void, u32, *mut bool, *mut bool, *mut f32) -> i32; - -type PlaySpaceMove = extern "C" fn(*mut c_void, f32, f32, f32) -> i32; -type ApplyStageOffset = extern "C" fn(*mut c_void, *const MndPose) -> i32; - -// New implementation -type GetReferenceSpaceOffset = extern "C" fn(*mut c_void, i32, *mut MndPose) -> i32; -type SetReferenceSpaceOffset = extern "C" fn(*mut c_void, i32, *const MndPose) -> i32; - -// TODO: Clean up after merge into upstream Monado -enum MoverImpl { - None, - PlaySpaceMove(PlaySpaceMove), - ApplyStageOffset(ApplyStageOffset), - SpaceOffsetApi { - get_reference: GetReferenceSpaceOffset, - set_reference: SetReferenceSpaceOffset, - }, -} - -pub struct LibMonado { - libmonado: Library, - mnd_root: *mut c_void, - mover: MoverImpl, -} - -impl Drop for LibMonado { - fn drop(&mut self) { - unsafe { - type RootDestroy = extern "C" fn(*mut *mut c_void) -> i32; - let Ok(root_destroy) = self.libmonado.get::(b"mnd_root_destroy\0") else { - return; - }; - root_destroy(&mut self.mnd_root); - } - } -} - -impl LibMonado { - pub fn new() -> anyhow::Result { - let lib_path = if let Ok(path) = env::var("LIBMONADO_PATH") { - path - } else if let Some(path) = xr_runtime_manifest() - .map(|manifest| manifest.runtime.mnd_libmonado_path) - .ok() - .flatten() - { - path - } else { - bail!("Monado: libmonado not found. Update your Monado/WiVRn or set LIBMONADO_PATH to point at your libmonado.so"); - }; - - let (libmonado, mnd_root) = unsafe { - let libmonado = libloading::Library::new(lib_path)?; - let root_create: Symbol i32> = - libmonado.get(b"mnd_root_create\0")?; - - let mut root: *mut c_void = std::ptr::null_mut(); - let ret = root_create(&mut root); - if ret != 0 { - anyhow::bail!("Failed to create libmonado root, code: {}", ret); - } - - (libmonado, root) - }; - - let space_api = unsafe { - if let (Ok(get_reference), Ok(set_reference)) = ( - libmonado.get(b"mnd_root_get_reference_space_offset\0"), - libmonado.get(b"mnd_root_set_reference_space_offset\0"), - ) { - log::info!("Monado: using space offset API"); - - let get_reference: GetReferenceSpaceOffset = *get_reference; - let set_reference: SetReferenceSpaceOffset = *set_reference; - - MoverImpl::SpaceOffsetApi { - get_reference, - set_reference, - } - } else if let Ok(playspace_move) = libmonado.get(b"mnd_root_playspace_move\0") { - log::warn!("Monado: using playspace_move, which is obsolete. Consider updating."); - MoverImpl::PlaySpaceMove(*playspace_move) - } else if let Ok(apply_stage_offset) = libmonado.get(b"mnd_root_apply_stage_offset\0") { - log::warn!( - "Monado: using apply_stage_offset, which is obsolete. Consider updating." - ); - MoverImpl::ApplyStageOffset(*apply_stage_offset) - } else { - MoverImpl::None - } - }; - - Ok(Self { - libmonado, - mnd_root, - mover: space_api, - }) - } - - pub fn mover_supported(&self) -> bool { - !matches!(self.mover, MoverImpl::None) - } -} - -#[derive(Deserialize)] -struct XrRuntimeManifestRuntime { - name: String, - library_path: String, - mnd_libmonado_path: Option, -} - -#[derive(Deserialize)] -struct XrRuntimeManifest { - file_format_version: String, - runtime: XrRuntimeManifestRuntime, -} - -fn xr_runtime_manifest() -> anyhow::Result { - let xdg_dirs = xdg::BaseDirectories::new()?; // only fails if $HOME unset - let mut file = xdg_dirs.get_config_home(); - file.push("openxr/1/active_runtime.json"); - - let json = fs::read_to_string(file)?; - let manifest = serde_json::from_str(&json)?; - Ok(manifest) -} diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index 1135504..52446b9 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -9,6 +9,7 @@ use std::{ }; use glam::{Affine3A, Vec3}; +use libmonado_rs::Monado; use openxr as xr; use skybox::create_skybox; use vulkano::{command_buffer::CommandBufferUsage, Handle, VulkanObject}; @@ -84,10 +85,17 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), notifications.run_udp(); let mut delete_queue = vec![]; - let mut playspace = playspace::PlayspaceMover::try_new() - .map_err(|e| log::warn!("Will not use Monado playspace mover: {}", e)) + + let mut monado = Monado::auto_connect() + .map_err(|e| log::warn!("Will not use libmonado: {}", e)) .ok(); + let mut playspace = monado.as_mut().and_then(|m| { + playspace::PlayspaceMover::new(m) + .map_err(|e| log::warn!("Will not use Monado playspace mover: {}", e)) + .ok() + }); + #[cfg(feature = "osc")] let mut osc_sender = crate::backend::osc::OscSender::new(app_state.session.config.osc_out_port).ok(); @@ -236,7 +244,7 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), watch_fade(&mut app_state, overlays.mut_by_id(watch_id).unwrap()); // want panic if let Some(ref mut space_mover) = playspace { - space_mover.update(&mut overlays, &app_state); + space_mover.update(&mut overlays, &app_state, monado.as_mut().unwrap()); } for o in overlays.iter_mut() { @@ -416,12 +424,12 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), TaskType::System(task) => match task { SystemTask::FixFloor => { if let Some(ref mut playspace) = playspace { - playspace.fix_floor(&app_state.input_state); + playspace.fix_floor(&app_state.input_state, monado.as_mut().unwrap()); } } SystemTask::ResetPlayspace => { if let Some(ref mut playspace) = playspace { - playspace.reset_offset(); + playspace.reset_offset(monado.as_mut().unwrap()); } } SystemTask::ShowHide => { diff --git a/src/backend/openxr/playspace.rs b/src/backend/openxr/playspace.rs index 3717583..fe34e08 100644 --- a/src/backend/openxr/playspace.rs +++ b/src/backend/openxr/playspace.rs @@ -1,13 +1,12 @@ -use glam::{Affine3A, Quat, Vec3, Vec3A}; -use libloading::{Library, Symbol}; -use std::ffi::c_void; +use glam::{Affine3A, Quat, Vec3A}; +use libmonado_rs::{Monado, Pose, ReferenceSpaceType}; use crate::{ backend::{common::OverlayContainer, input::InputState}, state::AppState, }; -use super::{helpers, overlay::OpenXrOverlayData}; +use super::overlay::OpenXrOverlayData; #[repr(C)] #[derive(Default, Debug)] @@ -16,116 +15,46 @@ struct XrtPose { position: [f32; 3], } -const XRT_REFERENCE_TYPE_STAGE: i32 = 3; - -const MND_SUCCESS: i32 = 0; -const MND_ERROR_BAD_SPACE_TYPE: i32 = -7; - struct MoverData { pose: Affine3A, hand: usize, hand_pose: T, } -// Legacy implementations -type PlaySpaceMove = extern "C" fn(*mut c_void, f32, f32, f32) -> i32; -type ApplyStageOffset = extern "C" fn(*mut c_void, *const XrtPose) -> i32; - -// New implementation -type GetReferenceSpaceOffset = extern "C" fn(*mut c_void, i32, *mut XrtPose) -> i32; -type SetReferenceSpaceOffset = extern "C" fn(*mut c_void, i32, *const XrtPose) -> i32; - -// TODO: Clean up after merge into upstream Monado -enum ApiImpl { - None, - PlaySpaceMove(PlaySpaceMove), - ApplyStageOffset(ApplyStageOffset), - SpaceOffsetApi { - get_reference: GetReferenceSpaceOffset, - set_reference: SetReferenceSpaceOffset, - }, -} - pub(super) struct PlayspaceMover { last_transform: Affine3A, drag: Option>, rotate: Option>, - - libmonado: Library, - mnd_root: *mut c_void, - api_impl: ApiImpl, } impl PlayspaceMover { - pub fn try_new() -> anyhow::Result { - unsafe { - let libmonado = helpers::find_libmonado()?; + pub fn new(monado: &mut Monado) -> anyhow::Result { + log::info!("Monado: using space offset API"); - let root_create: Symbol i32> = - libmonado.get(b"mnd_root_create\0")?; + let Ok(stage) = monado.get_reference_space_offset(ReferenceSpaceType::Stage) else { + anyhow::bail!("Space offsets not supported."); + }; - let mut root: *mut c_void = std::ptr::null_mut(); - let ret = root_create(&mut root); - if ret != 0 { - anyhow::bail!("Failed to create root, code: {}", ret); - } + log::debug!("STAGE is at {:?}, {:?}", stage.position, stage.orientation); - let mut api_impl = ApiImpl::None; - let mut initial_offset = Affine3A::IDENTITY; + // initial offset + let last_transform = + Affine3A::from_rotation_translation(stage.orientation.into(), stage.position.into()); - if let (Ok(get_reference), Ok(set_reference)) = ( - libmonado.get(b"mnd_root_get_reference_space_offset\0"), - libmonado.get(b"mnd_root_set_reference_space_offset\0"), - ) { - log::info!("Monado: using space offset API"); + Ok(Self { + last_transform, - let get_reference: GetReferenceSpaceOffset = *get_reference; - let set_reference: SetReferenceSpaceOffset = *set_reference; - - let mut stage = XrtPose::default(); - match (get_reference)(root, XRT_REFERENCE_TYPE_STAGE, &mut stage) { - MND_SUCCESS => { - log::debug!("STAGE is at {:?}, {:?}", stage.position, stage.orientation); - initial_offset = Affine3A::from_rotation_translation( - Quat::from_slice(&stage.orientation), - Vec3::from_slice(&stage.position), - ); - } - _ => anyhow::bail!("Space offsets not supported."), - }; - - api_impl = ApiImpl::SpaceOffsetApi { - get_reference, - set_reference, - }; - } else if let Ok(playspace_move) = libmonado.get(b"mnd_root_playspace_move\0") { - log::warn!("Monado: using playspace_move, which is obsolete. Consider updating."); - api_impl = ApiImpl::PlaySpaceMove(*playspace_move); - } else if let Ok(apply_stage_offset) = libmonado.get(b"mnd_root_apply_stage_offset\0") { - log::warn!( - "Monado: using apply_stage_offset, which is obsolete. Consider updating." - ); - api_impl = ApiImpl::ApplyStageOffset(*apply_stage_offset); - } - - if let ApiImpl::None = api_impl { - anyhow::bail!("Monado does not support playspace mover."); - } - - Ok(Self { - last_transform: initial_offset, - - drag: None, - rotate: None, - - libmonado, - mnd_root: root, - api_impl, - }) - } + drag: None, + rotate: None, + }) } - pub fn update(&mut self, overlays: &mut OverlayContainer, state: &AppState) { + pub fn update( + &mut self, + overlays: &mut OverlayContainer, + state: &AppState, + monado: &mut Monado, + ) { if let Some(mut data) = self.rotate.take() { let pointer = &state.input_state.pointers[data.hand]; if !pointer.now.space_rotate { @@ -164,7 +93,7 @@ impl PlayspaceMover { data.pose *= space_transform; data.hand_pose = new_hand; - self.apply_offset(data.pose); + self.apply_offset(data.pose, monado); self.rotate = Some(data); } else { for (i, pointer) in state.input_state.pointers.iter().enumerate() { @@ -213,7 +142,7 @@ impl PlayspaceMover { data.pose.translation += relative_pos; data.hand_pose = new_hand; - self.apply_offset(data.pose); + self.apply_offset(data.pose, monado); self.drag = Some(data); } else { for (i, pointer) in state.input_state.pointers.iter().enumerate() { @@ -233,7 +162,7 @@ impl PlayspaceMover { } } - pub fn reset_offset(&mut self) { + pub fn reset_offset(&mut self, monado: &mut Monado) { if self.drag.is_some() { log::info!("Space drag interrupted by manual reset"); self.drag = None; @@ -244,10 +173,10 @@ impl PlayspaceMover { } self.last_transform = Affine3A::IDENTITY; - self.apply_offset(self.last_transform); + self.apply_offset(self.last_transform, monado); } - pub fn fix_floor(&mut self, input: &InputState) { + pub fn fix_floor(&mut self, input: &InputState, monado: &mut Monado) { if self.drag.is_some() { log::info!("Space drag interrupted by fix floor"); self.drag = None; @@ -261,40 +190,14 @@ impl PlayspaceMover { let y2 = input.pointers[1].pose.translation.y; let delta = y1.min(y2) - 0.03; self.last_transform.translation.y += delta; - self.apply_offset(self.last_transform); + self.apply_offset(self.last_transform, monado); } - fn apply_offset(&self, transform: Affine3A) { - match self.api_impl { - ApiImpl::PlaySpaceMove(playspace_move) => { - (playspace_move)( - self.mnd_root, - transform.translation.x, - transform.translation.y, - transform.translation.z, - ); - } - ApiImpl::ApplyStageOffset(apply_stage_offset) => { - let xrt_pose = XrtPose { - orientation: Quat::from_affine3(&transform).into(), - position: transform.translation.into(), - }; - (apply_stage_offset)(self.mnd_root, &xrt_pose); - } - ApiImpl::SpaceOffsetApi { set_reference, .. } => { - let xrt_pose = XrtPose { - orientation: Quat::from_affine3(&transform).into(), - position: transform.translation.into(), - }; - - let mnd_result = - (set_reference)(self.mnd_root, XRT_REFERENCE_TYPE_STAGE, &xrt_pose); - //let mnd_result = (set_offset)(self.mnd_root, 0, &xrt_pose); - if mnd_result != MND_SUCCESS { - log::warn!("Cannot move playspace: MND result code {}", mnd_result); - } - } - ApiImpl::None => {} - } + fn apply_offset(&self, transform: Affine3A, monado: &mut Monado) { + let pose = Pose { + position: transform.translation.into(), + orientation: Quat::from_affine3(&transform).into(), + }; + let _ = monado.set_reference_space_offset(ReferenceSpaceType::Stage, pose); } }