switch to using libmonado-rs

This commit is contained in:
galister
2024-07-31 05:28:34 +09:00
parent dcc2cd0575
commit 3d0611052f
6 changed files with 175 additions and 387 deletions

167
Cargo.lock generated
View File

@@ -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",

View File

@@ -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"]

View File

@@ -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<libloading::Library> {
//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<libloading::Library> {
// 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
}

View File

@@ -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::<RootDestroy>(b"mnd_root_destroy\0") else {
return;
};
root_destroy(&mut self.mnd_root);
}
}
}
impl LibMonado {
pub fn new() -> anyhow::Result<Self> {
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<extern "C" fn(*mut *mut c_void) -> 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<String>,
}
#[derive(Deserialize)]
struct XrRuntimeManifest {
file_format_version: String,
runtime: XrRuntimeManifestRuntime,
}
fn xr_runtime_manifest() -> anyhow::Result<XrRuntimeManifest> {
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)
}

View File

@@ -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<AtomicBool>, 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<AtomicBool>, 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<AtomicBool>, 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 => {

View File

@@ -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<T> {
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<MoverData<Vec3A>>,
rotate: Option<MoverData<Quat>>,
libmonado: Library,
mnd_root: *mut c_void,
api_impl: ApiImpl,
}
impl PlayspaceMover {
pub fn try_new() -> anyhow::Result<Self> {
unsafe {
let libmonado = helpers::find_libmonado()?;
pub fn new(monado: &mut Monado) -> anyhow::Result<Self> {
log::info!("Monado: using space offset API");
let root_create: Symbol<extern "C" fn(*mut *mut c_void) -> 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<OpenXrOverlayData>, state: &AppState) {
pub fn update(
&mut self,
overlays: &mut OverlayContainer<OpenXrOverlayData>,
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);
}
}