mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-07-12 12:01:34 +00:00
Compare commits
No commits in common. "main" and "3.0.0" have entirely different histories.
29 changed files with 209 additions and 714 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -445,16 +445,6 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "delicious-adwaita"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53548c789a95211e0ce6d26c213067002b9b4360f8de69046d84de78ad9da3f"
|
||||
dependencies = [
|
||||
"gtk4",
|
||||
"libadwaita",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
@ -573,11 +563,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "envision"
|
||||
version = "3.1.1"
|
||||
version = "3.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ash",
|
||||
"delicious-adwaita",
|
||||
"gettext-rs",
|
||||
"git2",
|
||||
"gtk4",
|
||||
|
@ -1084,9 +1073,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gtk4"
|
||||
version = "0.9.6"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af1c491051f030994fd0cde6f3c44f3f5640210308cff1298c7673c47408091d"
|
||||
checksum = "9376d14d7e33486c54823a42bef296e882b9f25cb4c52b52f4d1d57bbadb5b6d"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"field-offset",
|
||||
|
@ -1117,9 +1106,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gtk4-sys"
|
||||
version = "0.9.6"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41e03b01e54d77c310e1d98647d73f996d04b2f29b9121fe493ea525a7ec03d6"
|
||||
checksum = "e653b0a9001ba9be1ffddb9373bfe9a111f688222f5aeee2841481300d91b55a"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
|
@ -1534,9 +1523,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libadwaita"
|
||||
version = "0.7.2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "500135d29c16aabf67baafd3e7741d48e8b8978ca98bac39e589165c8dc78191"
|
||||
checksum = "8611ee9fb85e7606c362b513afcaf5b59853f79e4d98caaaf581d99465014247"
|
||||
dependencies = [
|
||||
"gdk4",
|
||||
"gio",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "envision"
|
||||
version = "3.1.1"
|
||||
version = "3.0.0"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"Gabriele Musco <gabmus@disroot.org>",
|
||||
|
@ -44,4 +44,3 @@ tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] }
|
|||
tracing = "0.1.41"
|
||||
tracing-appender = "0.2.3"
|
||||
serde_yaml = "0.9.34"
|
||||
delicious-adwaita = { version = "0.3.0", features = ["all_themes"] }
|
||||
|
|
|
@ -30,43 +30,6 @@
|
|||
<url type="bugtracker">@REPO_URL@/issues</url>
|
||||
<content_rating type="oars-1.0" />
|
||||
<releases>
|
||||
<release version="3.1.1" date="2025-04-22">
|
||||
<description>
|
||||
<p>Fixes</p>
|
||||
<ul>
|
||||
<li>add libusb and libusb-dev deps</li>
|
||||
<li>Revert "disable and blacklist wayvr dashboard plugin"</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="3.1.0" date="2025-04-08">
|
||||
<description>
|
||||
<p>What's new</p>
|
||||
<ul>
|
||||
<li>don't set openvrpaths as read only during profile startup</li>
|
||||
<li>small design changes to build window ui</li>
|
||||
<li>add support for vapor openvr compatibility module</li>
|
||||
<li>remove monado vulkan layers check for nvidia</li>
|
||||
</ul>
|
||||
<p>Fixes</p>
|
||||
<ul>
|
||||
<li>disable and blacklist wayvr dashboard plugin</li>
|
||||
<li>monado dependencies: use wayland-protocols-devel on Fedora</li>
|
||||
</ul>
|
||||
<p>Other changes</p>
|
||||
<ul>
|
||||
<li>clippy</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="3.0.1" date="2025-03-02">
|
||||
<description>
|
||||
<p>Fixes</p>
|
||||
<ul>
|
||||
<li>libnotify headers path in wivrn depcheck</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="3.0.0" date="2025-03-01">
|
||||
<description>
|
||||
<p>Breaking changes</p>
|
||||
|
|
1
dist/arch/PKGBUILD
vendored
1
dist/arch/PKGBUILD
vendored
|
@ -33,6 +33,7 @@ makedepends=(
|
|||
)
|
||||
optdepends=(
|
||||
'libudev0-shim: steamvr_lh lighthouse driver support'
|
||||
'monado-vulkan-layers-git: Vulkan layers for NVIDIA users'
|
||||
)
|
||||
provides=(envision)
|
||||
conflicts=(envision)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
project(
|
||||
'envision',
|
||||
'rust',
|
||||
version: '3.1.1', # version number row
|
||||
version: '3.0.0', # version number row
|
||||
meson_version: '>= 0.59',
|
||||
license: 'AGPL-3.0-or-later',
|
||||
)
|
||||
|
|
|
@ -5,10 +5,7 @@ use crate::{
|
|||
ui::job_worker::job::WorkerJob,
|
||||
util::file_utils::rm_rf,
|
||||
};
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
num::NonZero,
|
||||
};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<WorkerJob> {
|
||||
let mut jobs = VecDeque::<WorkerJob>::new();
|
||||
|
@ -43,23 +40,11 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
|||
env: Some({
|
||||
let mut cmake_env: HashMap<String, String> = HashMap::new();
|
||||
for (k, v) in [
|
||||
// The basalt build uses a lot of RAM, so we have to limit the number of
|
||||
// build processes to not starve the system of memory
|
||||
// Limit to 6 build processes at most
|
||||
(
|
||||
"CMAKE_BUILD_PARALLEL_LEVEL",
|
||||
std::cmp::min(
|
||||
6,
|
||||
std::thread::available_parallelism()
|
||||
.map(NonZero::get)
|
||||
.unwrap_or(2),
|
||||
)
|
||||
.to_string(),
|
||||
),
|
||||
("CMAKE_BUILD_TYPE", "RelWithDebInfo".into()),
|
||||
("BUILD_TESTS", "off".into()),
|
||||
("CMAKE_BUILD_PARALLEL_LEVEL", "2"),
|
||||
("CMAKE_BUILD_TYPE", "RelWithDebInfo"),
|
||||
("BUILD_TESTS", "off"),
|
||||
] {
|
||||
cmake_env.insert(k.to_string(), v);
|
||||
cmake_env.insert(k.to_string(), v.to_string());
|
||||
}
|
||||
cmake_env
|
||||
}),
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
use crate::{
|
||||
build_tools::{cmake::Cmake, git::Git},
|
||||
profile::Profile,
|
||||
termcolor::TermColor,
|
||||
ui::job_worker::job::WorkerJob,
|
||||
util::file_utils::rm_rf,
|
||||
};
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
pub fn get_build_vapor_jobs(profile: &Profile, clean_build: bool) -> VecDeque<WorkerJob> {
|
||||
let mut jobs = VecDeque::<WorkerJob>::new();
|
||||
jobs.push_back(WorkerJob::new_printer(
|
||||
"Building VapoR...",
|
||||
Some(TermColor::Blue),
|
||||
));
|
||||
|
||||
let git = Git {
|
||||
repo: profile
|
||||
.ovr_comp
|
||||
.repo
|
||||
.as_ref()
|
||||
.unwrap_or(&"https://github.com/micheal65536/VapoR.git".into())
|
||||
.clone(),
|
||||
dir: profile.ovr_comp.path.clone(),
|
||||
branch: profile
|
||||
.ovr_comp
|
||||
.branch
|
||||
.as_ref()
|
||||
.unwrap_or(&"master".into())
|
||||
.clone(),
|
||||
};
|
||||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = profile.ovr_comp.path.join("build");
|
||||
let install_dir = build_dir.join("install_pfx");
|
||||
let cmake = Cmake {
|
||||
env: None,
|
||||
vars: Some({
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
for (k, v) in [
|
||||
("VAPOR_LOG_SILENT", "ON"),
|
||||
("USE_SYSTEM_OPENXR", "OFF"),
|
||||
("CMAKE_BUILD_TYPE", "RelWithDebInfo"),
|
||||
] {
|
||||
cmake_vars.insert(k.to_string(), v.to_string());
|
||||
}
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_PREFIX".into(),
|
||||
install_dir.to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars
|
||||
}),
|
||||
source_dir: profile.ovr_comp.path.clone(),
|
||||
build_dir: build_dir.clone(),
|
||||
};
|
||||
if !Path::new(&build_dir).is_dir() || clean_build {
|
||||
rm_rf(&build_dir);
|
||||
jobs.push_back(cmake.get_prepare_job());
|
||||
}
|
||||
jobs.push_back(cmake.get_build_job());
|
||||
jobs.push_back(cmake.get_install_job());
|
||||
|
||||
jobs
|
||||
}
|
|
@ -4,6 +4,5 @@ pub mod build_mercury;
|
|||
pub mod build_monado;
|
||||
pub mod build_opencomposite;
|
||||
pub mod build_openhmd;
|
||||
pub mod build_vapor;
|
||||
pub mod build_wivrn;
|
||||
pub mod build_xrizer;
|
||||
|
|
|
@ -45,10 +45,6 @@ const fn default_win_size() -> [i32; 2] {
|
|||
DEFAULT_WIN_SIZE
|
||||
}
|
||||
|
||||
fn default_theme_name() -> String {
|
||||
"Follow system".into()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub selected_profile_uuid: String,
|
||||
|
@ -58,8 +54,6 @@ pub struct Config {
|
|||
pub win_size: [i32; 2],
|
||||
#[serde(default)]
|
||||
pub plugins: HashMap<String, PluginConfig>,
|
||||
#[serde(default = "default_theme_name")]
|
||||
pub theme_name: String,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
@ -71,7 +65,6 @@ impl Default for Config {
|
|||
user_profiles: Vec::default(),
|
||||
win_size: DEFAULT_WIN_SIZE,
|
||||
plugins: HashMap::default(),
|
||||
theme_name: default_theme_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{
|
||||
boost_deps::boost_deps,
|
||||
common::{dep_cmake, dep_eigen, dep_gpp, dep_libgl, dep_ninja, dep_opencv},
|
||||
DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult,
|
||||
DepType, Dependency, DependencyCheckResult,
|
||||
};
|
||||
use crate::linux_distro::LinuxDistro;
|
||||
use std::collections::HashMap;
|
||||
|
@ -181,5 +181,9 @@ pub fn check_basalt_deps() -> Vec<DependencyCheckResult> {
|
|||
}
|
||||
|
||||
pub fn get_missing_basalt_deps() -> Vec<Dependency> {
|
||||
check_basalt_deps().filter_missing_deps()
|
||||
check_basalt_deps()
|
||||
.iter()
|
||||
.filter(|res| !res.found)
|
||||
.map(|res| res.dependency.clone())
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -303,35 +303,3 @@ pub fn dep_adb() -> Dependency {
|
|||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dep_getcap_setcap() -> Dependency {
|
||||
Dependency {
|
||||
name: "libcap".into(),
|
||||
dep_type: DepType::Executable,
|
||||
filename: "setcap".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "libcap".into()),
|
||||
(LinuxDistro::Debian, "libcap2-bin".into()),
|
||||
(LinuxDistro::Fedora, "libcap".into()),
|
||||
(LinuxDistro::Alpine, "libcap".into()),
|
||||
(LinuxDistro::Gentoo, "sys-libs/libcap".into()),
|
||||
(LinuxDistro::Suse, "libcap-progs".into()),
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dep_glslc() -> Dependency {
|
||||
Dependency {
|
||||
name: "glslc".into(),
|
||||
dep_type: DepType::Executable,
|
||||
filename: "glslc".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "shaderc".into()),
|
||||
(LinuxDistro::Debian, "glslc".into()),
|
||||
(LinuxDistro::Fedora, "glslc".into()),
|
||||
(LinuxDistro::Alpine, "shaderc".into()),
|
||||
(LinuxDistro::Gentoo, "media-libs/shaderc".into()),
|
||||
(LinuxDistro::Suse, "shaderc".into()),
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
common::{dep_cmake, dep_eigen, dep_gcc, dep_git, dep_gpp, dep_ninja},
|
||||
DepcheckResultGetMissing, Dependency, DependencyCheckResult,
|
||||
Dependency, DependencyCheckResult,
|
||||
};
|
||||
|
||||
fn libsurvive_deps() -> Vec<Dependency> {
|
||||
|
@ -19,5 +19,9 @@ pub fn check_libsurvive_deps() -> Vec<DependencyCheckResult> {
|
|||
}
|
||||
|
||||
pub fn get_missing_libsurvive_deps() -> Vec<Dependency> {
|
||||
check_libsurvive_deps().filter_missing_deps()
|
||||
check_libsurvive_deps()
|
||||
.iter()
|
||||
.filter(|res| !res.found)
|
||||
.map(|res| res.dependency.clone())
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use super::{
|
||||
common::dep_opencv, DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult,
|
||||
};
|
||||
use super::{common::dep_opencv, DepType, Dependency, DependencyCheckResult};
|
||||
use crate::linux_distro::LinuxDistro;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -41,5 +39,9 @@ pub fn check_mercury_deps() -> Vec<DependencyCheckResult> {
|
|||
}
|
||||
|
||||
pub fn get_missing_mercury_deps() -> Vec<Dependency> {
|
||||
check_mercury_deps().filter_missing_deps()
|
||||
check_mercury_deps()
|
||||
.iter()
|
||||
.filter(|res| !res.found)
|
||||
.map(|res| res.dependency.clone())
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ pub mod mercury_deps;
|
|||
pub mod monado_deps;
|
||||
pub mod openhmd_deps;
|
||||
pub mod wivrn_deps;
|
||||
pub mod xrizer_deps;
|
||||
|
||||
use crate::linux_distro::LinuxDistro;
|
||||
use std::{collections::HashMap, env, fmt::Display, path::Path};
|
||||
|
@ -109,24 +108,6 @@ impl Display for DependencyCheckResult {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait DepcheckResultGetMissing {
|
||||
fn filter_missing_deps(self) -> Vec<Dependency>;
|
||||
}
|
||||
|
||||
impl DepcheckResultGetMissing for Vec<DependencyCheckResult> {
|
||||
fn filter_missing_deps(self) -> Vec<Dependency> {
|
||||
self.into_iter()
|
||||
.filter_map(|res| {
|
||||
if !res.found {
|
||||
Some(res.dependency)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn shared_obj_paths() -> Vec<String> {
|
||||
vec![
|
||||
"/lib".into(),
|
||||
|
@ -136,24 +117,6 @@ fn shared_obj_paths() -> Vec<String> {
|
|||
"/usr/local/lib64".into(),
|
||||
"/usr/lib/x86_64-linux-gnu".into(),
|
||||
"/usr/lib/aarch64-linux-gnu".into(),
|
||||
// Debian puts libclang in /usr/lib/llvm-[llvm major version]/lib.
|
||||
"/usr/lib/llvm-15/lib".into(),
|
||||
"/usr/lib/llvm-16/lib".into(),
|
||||
"/usr/lib/llvm-19/lib".into(),
|
||||
// Fedora puts libclang in /usr/lib64/llvm[llvm major version]/lib as well as /usr/lib64.
|
||||
"/usr/lib64/llvm15/lib".into(),
|
||||
"/usr/lib64/llvm16/lib".into(),
|
||||
"/usr/lib64/llvm17/lib".into(),
|
||||
"/usr/lib64/llvm18/lib".into(),
|
||||
"/usr/lib64/llvm19/lib".into(),
|
||||
"/usr/lib64/llvm20/lib".into(),
|
||||
// Gentoo puts libclang in /usr/lib/llvm/[llvm major version]/lib64.
|
||||
"/usr/lib/llvm/15/lib64".into(),
|
||||
"/usr/lib/llvm/16/lib64".into(),
|
||||
"/usr/lib/llvm/17/lib64".into(),
|
||||
"/usr/lib/llvm/18/lib64".into(),
|
||||
"/usr/lib/llvm/19/lib64".into(),
|
||||
"/usr/lib/llvm/20/lib64".into(),
|
||||
"/lib/x86_64-linux-gnu".into(),
|
||||
"/lib/aarch64-linux-gnu".into(),
|
||||
"/app/lib".into(),
|
||||
|
@ -177,8 +140,6 @@ fn include_paths() -> Vec<String> {
|
|||
"/usr/include/ffmpeg/libpostproc".into(),
|
||||
"/usr/include/ffmpeg/libswresample".into(),
|
||||
"/usr/include/ffmpeg/libswscale".into(),
|
||||
// opensuse puts wayland-client.h here
|
||||
"/usr/include/wayland".into(),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,9 @@ use super::{
|
|||
dep_libgl, dep_libudev, dep_libx11, dep_libxcb, dep_ninja, dep_openxr, dep_vulkan_headers,
|
||||
dep_vulkan_icd_loader,
|
||||
},
|
||||
DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult,
|
||||
};
|
||||
use crate::{
|
||||
depcheck::common::{dep_glslc, dep_libxrandr},
|
||||
linux_distro::LinuxDistro,
|
||||
DepType, Dependency, DependencyCheckResult,
|
||||
};
|
||||
use crate::{depcheck::common::dep_libxrandr, linux_distro::LinuxDistro};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn monado_deps() -> Vec<Dependency> {
|
||||
|
@ -40,7 +37,7 @@ fn monado_deps() -> Vec<Dependency> {
|
|||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "wayland-protocols".into()),
|
||||
(LinuxDistro::Debian, "wayland-protocols".into()),
|
||||
(LinuxDistro::Fedora, "wayland-protocols-devel".into()),
|
||||
(LinuxDistro::Fedora, "wayland-protocols".into()),
|
||||
(LinuxDistro::Gentoo, "dev-libs/wayland-protocols".into()),
|
||||
(LinuxDistro::Suse, "wayland-protocols-devel".into()),
|
||||
]),
|
||||
|
@ -63,7 +60,19 @@ fn monado_deps() -> Vec<Dependency> {
|
|||
dep_ninja(),
|
||||
dep_gcc(),
|
||||
dep_gpp(),
|
||||
dep_glslc(),
|
||||
Dependency {
|
||||
name: "glslc".into(),
|
||||
dep_type: DepType::Executable,
|
||||
filename: "glslc".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "shaderc".into()),
|
||||
(LinuxDistro::Debian, "glslc".into()),
|
||||
(LinuxDistro::Fedora, "glslc".into()),
|
||||
(LinuxDistro::Alpine, "shaderc".into()),
|
||||
(LinuxDistro::Gentoo, "media-libs/shaderc".into()),
|
||||
(LinuxDistro::Suse, "shaderc".into()),
|
||||
]),
|
||||
},
|
||||
dep_glslang_validator(),
|
||||
Dependency {
|
||||
name: "sdl2".into(),
|
||||
|
@ -74,34 +83,10 @@ fn monado_deps() -> Vec<Dependency> {
|
|||
(LinuxDistro::Debian, "libsdl2-dev".into()),
|
||||
(LinuxDistro::Fedora, "SDL2-devel".into()),
|
||||
(LinuxDistro::Gentoo, "media-libs/libsdl2".into()),
|
||||
(LinuxDistro::Suse, "sdl2-compat-devel".into()),
|
||||
(LinuxDistro::Suse, "SDL2-devel".into()),
|
||||
]),
|
||||
},
|
||||
dep_libudev(),
|
||||
Dependency {
|
||||
name: "libusb".into(),
|
||||
dep_type: DepType::SharedObject,
|
||||
filename: "libusb-1.0.so".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "libusb".into()),
|
||||
(LinuxDistro::Debian, "libusb-1.0-0".into()),
|
||||
(LinuxDistro::Fedora, "libusb1".into()),
|
||||
(LinuxDistro::Gentoo, "dev-libs/libusb".into()),
|
||||
(LinuxDistro::Suse, "libusb-1_0-0".into()),
|
||||
]),
|
||||
},
|
||||
Dependency {
|
||||
name: "libusb-dev".into(),
|
||||
dep_type: DepType::Include,
|
||||
filename: "libusb-1.0/libusb.h".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "libusb".into()),
|
||||
(LinuxDistro::Debian, "libusb-1.0-0-dev".into()),
|
||||
(LinuxDistro::Fedora, "libusb1-devel".into()),
|
||||
(LinuxDistro::Gentoo, "dev-libs/libusb".into()),
|
||||
(LinuxDistro::Suse, "libusb-1_0-devel".into()),
|
||||
]),
|
||||
},
|
||||
Dependency {
|
||||
name: "mesa-common-dev".into(),
|
||||
dep_type: DepType::Include,
|
||||
|
@ -122,5 +107,9 @@ pub fn check_monado_deps() -> Vec<DependencyCheckResult> {
|
|||
}
|
||||
|
||||
pub fn get_missing_monado_deps() -> Vec<Dependency> {
|
||||
check_monado_deps().filter_missing_deps()
|
||||
check_monado_deps()
|
||||
.iter()
|
||||
.filter(|res| !res.found)
|
||||
.map(|res| res.dependency.clone())
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
common::{dep_gcc, dep_git, dep_gpp, dep_ninja},
|
||||
DepcheckResultGetMissing, Dependency, DependencyCheckResult,
|
||||
Dependency, DependencyCheckResult,
|
||||
};
|
||||
use crate::linux_distro::LinuxDistro;
|
||||
use std::collections::HashMap;
|
||||
|
@ -31,5 +31,9 @@ pub fn check_openhmd_deps() -> Vec<DependencyCheckResult> {
|
|||
}
|
||||
|
||||
pub fn get_missing_openhmd_deps() -> Vec<Dependency> {
|
||||
check_openhmd_deps().filter_missing_deps()
|
||||
check_openhmd_deps()
|
||||
.iter()
|
||||
.filter(|res| !res.found)
|
||||
.map(|res| res.dependency.clone())
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::{
|
|||
dep_libudev, dep_libx11, dep_libxcb, dep_ninja, dep_openxr, dep_vulkan_headers,
|
||||
dep_vulkan_icd_loader,
|
||||
},
|
||||
DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult,
|
||||
DepType, Dependency, DependencyCheckResult,
|
||||
};
|
||||
use crate::{
|
||||
depcheck::common::{dep_libgl, dep_libxrandr},
|
||||
|
@ -253,7 +253,7 @@ fn wivrn_deps() -> Vec<Dependency> {
|
|||
Dependency {
|
||||
name: "libnotify-dev".into(),
|
||||
dep_type: DepType::Include,
|
||||
filename: "libnotify/notify.h".into(),
|
||||
filename: "openssl/ssl3.h".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "libnotify".into()),
|
||||
(LinuxDistro::Alpine, "libnotify-dev".into()),
|
||||
|
@ -270,5 +270,9 @@ pub fn check_wivrn_deps() -> Vec<DependencyCheckResult> {
|
|||
}
|
||||
|
||||
pub fn get_missing_wivrn_deps() -> Vec<Dependency> {
|
||||
check_wivrn_deps().filter_missing_deps()
|
||||
check_wivrn_deps()
|
||||
.iter()
|
||||
.filter(|res| !res.found)
|
||||
.map(|res| res.dependency.clone())
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
use super::{DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult};
|
||||
use crate::{depcheck::common::dep_glslc, linux_distro::LinuxDistro};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn xrizer_deps() -> Vec<Dependency> {
|
||||
vec![
|
||||
dep_glslc(),
|
||||
Dependency {
|
||||
name: "cargo".into(),
|
||||
dep_type: DepType::Executable,
|
||||
filename: "cargo".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "rust".into()),
|
||||
(LinuxDistro::Debian, "cargo".into()),
|
||||
(LinuxDistro::Fedora, "cargo".into()),
|
||||
(LinuxDistro::Alpine, "cargo".into()),
|
||||
(LinuxDistro::Suse, "cargo".into()),
|
||||
]),
|
||||
},
|
||||
Dependency {
|
||||
name: "libxcb-glx".into(),
|
||||
dep_type: DepType::Include,
|
||||
filename: "xcb/glx.h".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "libxcb".into()),
|
||||
(LinuxDistro::Debian, "libxcb-glx0-dev".into()),
|
||||
(LinuxDistro::Fedora, "libxcb-devel".into()),
|
||||
(LinuxDistro::Gentoo, "x11-libs/libxcb".into()),
|
||||
(LinuxDistro::Suse, "libxcb-devel".into()),
|
||||
]),
|
||||
},
|
||||
Dependency {
|
||||
name: "libclang".into(),
|
||||
dep_type: DepType::SharedObject,
|
||||
filename: "libclang.so".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "clang".into()),
|
||||
(LinuxDistro::Debian, "libclang-19-dev".into()),
|
||||
(LinuxDistro::Fedora, "clang19-devel".into()),
|
||||
(LinuxDistro::Gentoo, "llvm-core/clang-runtime".into()),
|
||||
(LinuxDistro::Suse, "clang19-devel".into()),
|
||||
]),
|
||||
},
|
||||
Dependency {
|
||||
name: "wayland-dev".into(),
|
||||
dep_type: DepType::Include,
|
||||
filename: "wayland-client.h".into(),
|
||||
packages: HashMap::from([
|
||||
(LinuxDistro::Arch, "wayland".into()),
|
||||
(LinuxDistro::Debian, "libwayland-dev".into()),
|
||||
(LinuxDistro::Fedora, "wayland-devel".into()),
|
||||
(LinuxDistro::Gentoo, "dev-libs/wayland".into()),
|
||||
(LinuxDistro::Suse, "wayland-devel".into()),
|
||||
]),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub fn check_xrizer_deps() -> Vec<DependencyCheckResult> {
|
||||
Dependency::check_many(xrizer_deps())
|
||||
}
|
||||
|
||||
pub fn get_missing_xrizer_deps() -> Vec<Dependency> {
|
||||
check_xrizer_deps().filter_missing_deps()
|
||||
}
|
|
@ -85,7 +85,6 @@ fn build_steam_openvrpaths() -> OpenVrPaths {
|
|||
}
|
||||
|
||||
pub fn set_current_openvrpaths_to_steam() -> anyhow::Result<()> {
|
||||
// removing readonly flag just in case, remove this line in the future
|
||||
set_file_readonly(&get_openvrpaths_vrpath_path(), false)?;
|
||||
dump_current_openvrpaths(&build_steam_openvrpaths())?;
|
||||
Ok(())
|
||||
|
@ -105,18 +104,19 @@ pub fn build_profile_openvrpaths(profile: &Profile) -> OpenVrPaths {
|
|||
|
||||
pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> anyhow::Result<()> {
|
||||
let dest = get_openvrpaths_vrpath_path();
|
||||
// removing readonly flag just in case, remove this line in the future
|
||||
set_file_readonly(&dest, false)?;
|
||||
backup_steam_openvrpaths();
|
||||
dump_current_openvrpaths(&build_profile_openvrpaths(profile))?;
|
||||
set_file_readonly(&dest, true)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{dump_openvrpaths_to_path, get_openvrpaths_from_path, OpenVrPaths};
|
||||
use std::path::Path;
|
||||
|
||||
use super::{dump_openvrpaths_to_path, get_openvrpaths_from_path, OpenVrPaths};
|
||||
|
||||
#[test]
|
||||
fn can_read_openvrpaths_vrpath_steamvr() {
|
||||
let ovrp = get_openvrpaths_from_path(Path::new("./test/files/openvrpaths.vrpath")).unwrap();
|
||||
|
|
|
@ -49,13 +49,13 @@ impl LinuxDistro {
|
|||
Ok(_) if buf.starts_with("PRETTY_NAME=\"") => {
|
||||
return buf
|
||||
.split('=')
|
||||
.next_back()
|
||||
.last()
|
||||
.map(|b| b.trim().trim_matches('"').trim().to_string());
|
||||
}
|
||||
Ok(_) if buf.starts_with("NAME=\"") => {
|
||||
name = buf
|
||||
.split('=')
|
||||
.next_back()
|
||||
.last()
|
||||
.map(|b| b.trim().trim_matches('"').trim().to_string());
|
||||
}
|
||||
_ => {}
|
||||
|
@ -79,7 +79,7 @@ impl LinuxDistro {
|
|||
{
|
||||
let name = buf
|
||||
.split('=')
|
||||
.next_back()
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.trim()
|
||||
.trim_matches('"')
|
||||
|
@ -115,7 +115,6 @@ impl LinuxDistro {
|
|||
|| s.contains("steamos")
|
||||
|| s.contains("steam os")
|
||||
|| s.contains("endeavour")
|
||||
|| s.contains("cachyos")
|
||||
|| s.contains("garuda")
|
||||
{
|
||||
return Some(Self::Arch);
|
||||
|
@ -151,33 +150,7 @@ impl LinuxDistro {
|
|||
Self::Alpine => format!("sudo apk add {}", packages.join(" ")),
|
||||
Self::Debian => format!("sudo apt install {}", packages.join(" ")),
|
||||
Self::Gentoo => format!("sudo emerge -av {}", packages.join(" ")),
|
||||
Self::Suse => {
|
||||
let mut opi_pkgs = Vec::new();
|
||||
let mut zypper_pkgs = Vec::new();
|
||||
for pkg in packages {
|
||||
if ["OpenXR-SDK-devel"].contains(&pkg.as_str()) {
|
||||
opi_pkgs.push(pkg.clone());
|
||||
} else {
|
||||
zypper_pkgs.push(pkg.clone());
|
||||
}
|
||||
}
|
||||
[
|
||||
if opi_pkgs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format!("opi {}", opi_pkgs.join(" ")))
|
||||
},
|
||||
if zypper_pkgs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format!("sudo zypper install {}", zypper_pkgs.join(" ")))
|
||||
},
|
||||
]
|
||||
.iter()
|
||||
.filter_map(|c| c.clone())
|
||||
.collect::<Vec<String>>()
|
||||
.join(" && ")
|
||||
}
|
||||
Self::Suse => format!("sudo zypper install {}", packages.join(" ")),
|
||||
Self::Fedora => {
|
||||
let mut install_rpmfusion_cmd: Option<String> = None;
|
||||
let mut swap_ffmpeg_cmd: Option<String> = None;
|
||||
|
@ -217,10 +190,10 @@ impl LinuxDistro {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::LinuxDistro;
|
||||
use crate::depcheck::common::{dep_openxr, dep_pkexec, dep_vulkan_icd_loader};
|
||||
use std::path::Path;
|
||||
|
||||
use super::LinuxDistro;
|
||||
|
||||
#[test]
|
||||
fn can_detect_arch_linux_from_etc_os_release() {
|
||||
assert_eq!(
|
||||
|
@ -230,34 +203,4 @@ mod tests {
|
|||
Some(LinuxDistro::Arch)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_account_for_opensuse_opi_packages() {
|
||||
assert_eq!(
|
||||
LinuxDistro::Suse
|
||||
.install_command(
|
||||
&[dep_openxr(), dep_vulkan_icd_loader()]
|
||||
.iter()
|
||||
.map(|dep| dep.package_name_for_distro(Some(&LinuxDistro::Suse)))
|
||||
.collect::<Vec<String>>()
|
||||
)
|
||||
.as_str(),
|
||||
"opi OpenXR-SDK-devel && sudo zypper install vulkan-devel"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opensuse_opi_does_not_interfere_if_not_needed() {
|
||||
assert_eq!(
|
||||
LinuxDistro::Suse
|
||||
.install_command(
|
||||
&[dep_pkexec(), dep_vulkan_icd_loader()]
|
||||
.iter()
|
||||
.map(|dep| dep.package_name_for_distro(Some(&LinuxDistro::Suse)))
|
||||
.collect::<Vec<String>>()
|
||||
)
|
||||
.as_str(),
|
||||
"sudo zypper install polkit vulkan-devel"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
57
src/main.rs
57
src/main.rs
|
@ -11,14 +11,9 @@ use relm4::{
|
|||
gtk::{self, gdk, gio, glib, prelude::*},
|
||||
MessageBroker, RelmApp,
|
||||
};
|
||||
use std::{
|
||||
env,
|
||||
fs::{read_dir, remove_file},
|
||||
os::unix::fs::MetadataExt,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::env;
|
||||
use steam_linux_runtime_injector::restore_runtime_entrypoint;
|
||||
use tracing::{error, warn};
|
||||
use tracing::warn;
|
||||
use tracing_subscriber::{
|
||||
filter::LevelFilter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer,
|
||||
};
|
||||
|
@ -71,55 +66,11 @@ fn restore_steam_xr_files() {
|
|||
restore_runtime_entrypoint();
|
||||
}
|
||||
|
||||
const LOGS_MAX_SIZE_BYTES: u64 = 1000000000; // 1GB
|
||||
|
||||
fn remove_old_logs(dir: &Path, log_files: Option<Vec<PathBuf>>) -> anyhow::Result<()> {
|
||||
let log_files: Vec<PathBuf> = log_files
|
||||
.map::<anyhow::Result<Vec<PathBuf>>, _>(Ok)
|
||||
.unwrap_or_else(|| {
|
||||
let mut files: Vec<PathBuf> = read_dir(dir)?
|
||||
.filter_map(|de| {
|
||||
let p = de.ok()?.path();
|
||||
if p.is_file() && !p.is_symlink() {
|
||||
Some(p)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
files.sort_unstable();
|
||||
Ok(files)
|
||||
})?;
|
||||
let total_size = log_files
|
||||
.iter()
|
||||
.filter_map(|p| Some(p.metadata().ok()?.size()))
|
||||
.reduce(u64::saturating_add)
|
||||
.unwrap_or(0);
|
||||
// if size is under threshold, finish
|
||||
if total_size < LOGS_MAX_SIZE_BYTES {
|
||||
return Ok(());
|
||||
}
|
||||
// keep a minimum of 3 logs
|
||||
if log_files.len() <= 3 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
remove_file(log_files.first().ok_or_else(||
|
||||
anyhow::Error::msg(
|
||||
"Could not get first item in log files list, but they should be more than 3! This is a bug!"
|
||||
)
|
||||
)?)?;
|
||||
|
||||
remove_old_logs(dir, Some(log_files))
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
if env::var("USER").unwrap_or_else(|_| env::var("USERNAME").unwrap_or_default()) == "root" {
|
||||
panic!("{APP_NAME} cannot run as root");
|
||||
}
|
||||
restore_steam_xr_files();
|
||||
// deferring error logging for this since tracing isn't initialized yet
|
||||
let old_logs_removal_res = remove_old_logs(&get_logs_dir(), None);
|
||||
|
||||
let rolling_log_writer = tracing_appender::rolling::daily(get_logs_dir(), "log");
|
||||
let (non_blocking_appender, _appender_guard) =
|
||||
|
@ -139,10 +90,6 @@ fn main() -> Result<()> {
|
|||
)
|
||||
.init();
|
||||
|
||||
if let Err(e) = old_logs_removal_res {
|
||||
error!("Failed to remove old log files: {e}");
|
||||
}
|
||||
|
||||
// Prepare i18n
|
||||
gettextrs::setlocale(LocaleCategory::LcAll, "");
|
||||
gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR).expect("Unable to bind the text domain");
|
||||
|
|
|
@ -2,8 +2,7 @@ use crate::{
|
|||
depcheck::{
|
||||
basalt_deps::get_missing_basalt_deps, libsurvive_deps::get_missing_libsurvive_deps,
|
||||
mercury_deps::get_missing_mercury_deps, monado_deps::get_missing_monado_deps,
|
||||
openhmd_deps::get_missing_openhmd_deps, wivrn_deps::get_missing_wivrn_deps,
|
||||
xrizer_deps::get_missing_xrizer_deps, Dependency,
|
||||
openhmd_deps::get_missing_openhmd_deps, wivrn_deps::get_missing_wivrn_deps, Dependency,
|
||||
},
|
||||
file_builders::active_runtime_json::ActiveRuntime,
|
||||
paths::{get_data_dir, BWRAP_SYSTEM_PREFIX, SYSTEM_PREFIX},
|
||||
|
@ -15,7 +14,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Display,
|
||||
fs::{remove_dir_all, File},
|
||||
fs::File,
|
||||
io::BufReader,
|
||||
path::{Path, PathBuf},
|
||||
slice::Iter,
|
||||
|
@ -266,7 +265,6 @@ pub enum OvrCompatibilityModuleType {
|
|||
#[default]
|
||||
Opencomposite,
|
||||
Xrizer,
|
||||
Vapor,
|
||||
}
|
||||
|
||||
impl Display for OvrCompatibilityModuleType {
|
||||
|
@ -274,23 +272,13 @@ impl Display for OvrCompatibilityModuleType {
|
|||
f.write_str(match self {
|
||||
Self::Opencomposite => "OpenComposite",
|
||||
Self::Xrizer => "xrizer",
|
||||
Self::Vapor => "VapoR",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl OvrCompatibilityModuleType {
|
||||
pub fn iter() -> Iter<'static, Self> {
|
||||
[Self::Opencomposite, Self::Xrizer, Self::Vapor].iter()
|
||||
}
|
||||
|
||||
pub fn get_missing_deps(&self) -> Vec<Dependency> {
|
||||
match self {
|
||||
OvrCompatibilityModuleType::Xrizer => get_missing_xrizer_deps(),
|
||||
OvrCompatibilityModuleType::Opencomposite | OvrCompatibilityModuleType::Vapor => {
|
||||
Vec::default()
|
||||
}
|
||||
}
|
||||
[Self::Opencomposite, Self::Xrizer].iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,7 +289,6 @@ impl FromStr for OvrCompatibilityModuleType {
|
|||
match s.to_lowercase().trim() {
|
||||
"opencomposite" => Ok(Self::Opencomposite),
|
||||
"xrizer" => Ok(Self::Xrizer),
|
||||
"vapor" => Ok(Self::Vapor),
|
||||
_ => Err(format!("no match for ovr compatibility module `{s}`")),
|
||||
}
|
||||
}
|
||||
|
@ -312,8 +299,7 @@ impl From<u32> for OvrCompatibilityModuleType {
|
|||
match value {
|
||||
0 => Self::Opencomposite,
|
||||
1 => Self::Xrizer,
|
||||
2 => Self::Vapor,
|
||||
_ => panic!("OvrCompatibilityModuleType index out of bounds"),
|
||||
_ => panic!("OvrCompatibilityModuleType index out of bounds"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +328,6 @@ impl ProfileOvrCompatibilityModule {
|
|||
pub fn runtime_dir(&self) -> PathBuf {
|
||||
match self.mod_type {
|
||||
OvrCompatibilityModuleType::Opencomposite => self.path.join("build"),
|
||||
OvrCompatibilityModuleType::Vapor => self.path.join("build/install_pfx/lib/VapoR"),
|
||||
OvrCompatibilityModuleType::Xrizer => self.path.join("target/release"),
|
||||
}
|
||||
}
|
||||
|
@ -459,29 +444,6 @@ impl Profile {
|
|||
get_data_dir().join("prefixes").join(uuid)
|
||||
}
|
||||
|
||||
/// deletes files and folders associated to this profile (mostly repo clones)
|
||||
pub fn delete_files(&self) -> Vec<std::io::Result<()>> {
|
||||
[
|
||||
Some(&self.xrservice_path),
|
||||
Some(&self.ovr_comp.path),
|
||||
self.features.libsurvive.path.as_ref(),
|
||||
self.features.basalt.path.as_ref(),
|
||||
self.features.openhmd.path.as_ref(),
|
||||
]
|
||||
.iter()
|
||||
.map(|dir| match dir {
|
||||
Some(dir) => {
|
||||
if dir.try_exists().unwrap_or_default() {
|
||||
remove_dir_all(dir)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
None => Ok(()),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn xr_runtime_json_env_var(&self) -> String {
|
||||
format!(
|
||||
"XR_RUNTIME_JSON=\"{prefix}/share/openxr/1/openxr_{runtime}.json\"",
|
||||
|
@ -746,7 +708,7 @@ impl Profile {
|
|||
if self.features.mercury_enabled {
|
||||
missing_deps.extend(get_missing_mercury_deps());
|
||||
}
|
||||
missing_deps.extend(self.ovr_comp.mod_type.get_missing_deps());
|
||||
// no listed deps for opencomp
|
||||
}
|
||||
missing_deps.sort_unstable();
|
||||
missing_deps.dedup(); // dedup only works if sorted, hence the above
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn create_about_dialog() -> adw::AboutDialog {
|
|||
const UNKNOWN: &str = "UNKNOWN";
|
||||
|
||||
pub fn populate_debug_info(dialog: &adw::AboutDialog, vkinfo: Option<&VulkanInfo>) {
|
||||
if !dialog.debug_info().is_empty() {
|
||||
if dialog.debug_info().len() > 0 {
|
||||
return;
|
||||
}
|
||||
let distro_family = LinuxDistro::get();
|
||||
|
@ -70,7 +70,7 @@ pub fn populate_debug_info(dialog: &adw::AboutDialog, vkinfo: Option<&VulkanInfo
|
|||
.and_then(|s| {
|
||||
s.split("\n")
|
||||
.find(|line| line.starts_with("model name"))
|
||||
.map(|line| line.split(':').next_back().map(|s| s.trim().to_string()))
|
||||
.map(|line| line.split(':').last().map(|s| s.trim().to_string()))
|
||||
})
|
||||
.flatten()
|
||||
.unwrap_or(UNKNOWN.into())
|
||||
|
@ -81,6 +81,12 @@ pub fn populate_debug_info(dialog: &adw::AboutDialog, vkinfo: Option<&VulkanInfo
|
|||
.map(|i| i.gpu_names.join(", "))
|
||||
.unwrap_or(UNKNOWN.into())
|
||||
),
|
||||
format!(
|
||||
"Monado Vulkan Layers: {}",
|
||||
vkinfo
|
||||
.map(|i| i.has_monado_vulkan_layers.to_string())
|
||||
.unwrap_or(UNKNOWN.into())
|
||||
),
|
||||
format!("Detected XR Devices: {}", {
|
||||
let devs = PhysicalXRDevice::from_usb();
|
||||
if devs.is_empty() {
|
||||
|
|
|
@ -20,8 +20,7 @@ use crate::{
|
|||
build_basalt::get_build_basalt_jobs, build_libsurvive::get_build_libsurvive_jobs,
|
||||
build_mercury::get_build_mercury_jobs, build_monado::get_build_monado_jobs,
|
||||
build_opencomposite::get_build_opencomposite_jobs, build_openhmd::get_build_openhmd_jobs,
|
||||
build_vapor::get_build_vapor_jobs, build_wivrn::get_build_wivrn_jobs,
|
||||
build_xrizer::get_build_xrizer_jobs,
|
||||
build_wivrn::get_build_wivrn_jobs, build_xrizer::get_build_xrizer_jobs,
|
||||
},
|
||||
config::{Config, PluginConfig},
|
||||
constants::APP_NAME,
|
||||
|
@ -43,7 +42,6 @@ use crate::{
|
|||
steam_linux_runtime_injector::{
|
||||
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile,
|
||||
},
|
||||
termcolor::TermColor,
|
||||
util::file_utils::{
|
||||
setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd, verify_cap_sys_nice_eip,
|
||||
},
|
||||
|
@ -52,7 +50,6 @@ use crate::{
|
|||
xr_devices::XRDevice,
|
||||
};
|
||||
use adw::{prelude::*, ResponseAppearance};
|
||||
use delicious_adwaita::{theme::Theme, ThemeEngine};
|
||||
use gtk::glib::{self, clone};
|
||||
use notify_rust::NotificationHandle;
|
||||
use relm4::{
|
||||
|
@ -98,8 +95,6 @@ pub struct App {
|
|||
|
||||
inhibit_fail_notif: Option<NotificationHandle>,
|
||||
pluginstore: Option<AsyncController<PluginStore>>,
|
||||
|
||||
theme_engine: ThemeEngine,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -117,8 +112,7 @@ pub enum Msg {
|
|||
StartWithDebug,
|
||||
RestartXRService,
|
||||
ProfileSelected(Profile),
|
||||
/// bool param: delete files
|
||||
DeleteProfile(bool),
|
||||
DeleteProfile,
|
||||
SaveProfile(Profile),
|
||||
RunSetCap,
|
||||
OpenLibsurviveSetup,
|
||||
|
@ -134,8 +128,6 @@ pub enum Msg {
|
|||
WivrnCheckPairMode,
|
||||
OpenPluginStore,
|
||||
UpdateConfigPlugins(HashMap<String, PluginConfig>),
|
||||
ShowThemeManager,
|
||||
SaveThemeConfig,
|
||||
NoOp,
|
||||
}
|
||||
|
||||
|
@ -373,7 +365,7 @@ impl AsyncComponent for App {
|
|||
set_content: Some(&adw::NavigationPage::new(model.debug_view.widget(), "Debug View")),
|
||||
set_show_content: false,
|
||||
set_collapsed: !model.config.debug_view_enabled,
|
||||
},
|
||||
}
|
||||
},
|
||||
connect_close_request[sender] => move |win| {
|
||||
sender.input(Msg::SaveWinSize(win.width(), win.height()));
|
||||
|
@ -397,27 +389,6 @@ impl AsyncComponent for App {
|
|||
) {
|
||||
match message {
|
||||
Msg::NoOp => {}
|
||||
Msg::ShowThemeManager => {
|
||||
let dialog = self
|
||||
.theme_engine
|
||||
.theme_chooser_dialog(Theme::default_themes().as_ref());
|
||||
dialog.set_content_height(2000);
|
||||
dialog.present(Some(&self.app_win));
|
||||
dialog.connect_closed(clone!(
|
||||
#[strong]
|
||||
sender,
|
||||
move |_| {
|
||||
sender.input(Msg::SaveThemeConfig);
|
||||
}
|
||||
));
|
||||
}
|
||||
Msg::SaveThemeConfig => {
|
||||
let name = self.theme_engine.current_theme_name();
|
||||
if self.config.theme_name != name {
|
||||
self.config.theme_name = name;
|
||||
self.config.save();
|
||||
}
|
||||
}
|
||||
Msg::OnServiceLog(rows) => {
|
||||
if !rows.is_empty() {
|
||||
self.debug_view
|
||||
|
@ -562,9 +533,6 @@ impl AsyncComponent for App {
|
|||
OvrCompatibilityModuleType::Xrizer => {
|
||||
get_build_xrizer_jobs(&profile, clean_build)
|
||||
}
|
||||
OvrCompatibilityModuleType::Vapor => {
|
||||
get_build_vapor_jobs(&profile, clean_build)
|
||||
}
|
||||
});
|
||||
let missing_deps = profile.missing_dependencies();
|
||||
if !(self.skip_depcheck || profile.skip_dependency_check || missing_deps.is_empty())
|
||||
|
@ -654,10 +622,6 @@ impl AsyncComponent for App {
|
|||
if dep_pkexec().check() {
|
||||
self.setcap_confirm_dialog.present(Some(&self.app_win));
|
||||
} else {
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateContent(vec![TermColor::Red
|
||||
.colorize("pkexec not found, cannot set capabilities\n")]));
|
||||
alert_w_widget(
|
||||
"pkexec not found",
|
||||
Some(&format!(
|
||||
|
@ -690,16 +654,9 @@ impl AsyncComponent for App {
|
|||
w.stop();
|
||||
}
|
||||
}
|
||||
Msg::DeleteProfile(delete_files) => {
|
||||
Msg::DeleteProfile => {
|
||||
let todel = self.get_selected_profile();
|
||||
if todel.editable {
|
||||
if delete_files {
|
||||
for res in todel.delete_files() {
|
||||
if let Err(e) = res {
|
||||
error!("Error deleting profile directory: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
self.config.user_profiles.retain(|p| p.uuid != todel.uuid);
|
||||
self.config.save();
|
||||
self.profiles = self.config.profiles();
|
||||
|
@ -739,7 +696,6 @@ impl AsyncComponent for App {
|
|||
}
|
||||
Msg::RunSetCap => {
|
||||
if !dep_pkexec().check() {
|
||||
// there's a precheck ahead of this, this should likely never happen
|
||||
error!("pkexec not found, skipping setcap");
|
||||
} else {
|
||||
let profile = self.get_selected_profile();
|
||||
|
@ -757,26 +713,8 @@ impl AsyncComponent for App {
|
|||
if let Err(e) = setcap_cap_sys_nice_eip(&profile).await {
|
||||
setcap_failed_dialog();
|
||||
error!("failed running setcap: {e}");
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateContent(vec![
|
||||
TermColor::Red.colorize("Setting capabilities failed\n")
|
||||
]));
|
||||
} else if !verify_cap_sys_nice_eip(&profile).await {
|
||||
setcap_failed_dialog();
|
||||
error!("setcap succeeded but capabilities were reset");
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateContent(vec![TermColor::Red
|
||||
.colorize(
|
||||
"Setting capabilities succeeded, but capabilities have been reset\n",
|
||||
)]));
|
||||
} else {
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateContent(vec![
|
||||
TermColor::Green.colorize("Capabilities set correctly\n")
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1024,17 +962,6 @@ impl AsyncComponent for App {
|
|||
}
|
||||
)
|
||||
);
|
||||
stateless_action!(
|
||||
actions,
|
||||
ThemeManagerAction,
|
||||
clone!(
|
||||
#[strong]
|
||||
sender,
|
||||
move |_| {
|
||||
sender.input(Msg::ShowThemeManager);
|
||||
}
|
||||
)
|
||||
);
|
||||
// this bypasses the macro because I need the underlying gio action
|
||||
// to enable/disable it in update()
|
||||
let configure_wivrn_action = {
|
||||
|
@ -1071,12 +998,13 @@ impl AsyncComponent for App {
|
|||
config: config.clone(),
|
||||
selected_profile: selected_profile.clone(),
|
||||
root_win: root.clone().into(),
|
||||
vkinfo: vkinfo.clone(),
|
||||
})
|
||||
.forward(sender.input_sender(), |message| match message {
|
||||
MainViewOutMsg::DoStartStopXRService => Msg::DoStartStopXRService,
|
||||
MainViewOutMsg::RestartXRService => Msg::RestartXRService,
|
||||
MainViewOutMsg::ProfileSelected(uuid) => Msg::ProfileSelected(uuid),
|
||||
MainViewOutMsg::DeleteProfile(delete_files) => Msg::DeleteProfile(delete_files),
|
||||
MainViewOutMsg::DeleteProfile => Msg::DeleteProfile,
|
||||
MainViewOutMsg::SaveProfile(p) => Msg::SaveProfile(p),
|
||||
MainViewOutMsg::OpenLibsurviveSetup => Msg::OpenLibsurviveSetup,
|
||||
MainViewOutMsg::BuildProfile(clean) => Msg::BuildProfile(clean),
|
||||
|
@ -1103,17 +1031,6 @@ impl AsyncComponent for App {
|
|||
.detach(),
|
||||
split_view: None,
|
||||
setcap_confirm_dialog,
|
||||
theme_engine: ThemeEngine::new_with_theme(&{
|
||||
if config.theme_name == "Follow system" {
|
||||
Theme::default()
|
||||
} else {
|
||||
Theme::default_themes()
|
||||
.into_iter()
|
||||
.find(|t| t.name == config.theme_name)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
})
|
||||
.unwrap(),
|
||||
config,
|
||||
profiles,
|
||||
xrservice_worker: None,
|
||||
|
@ -1202,7 +1119,6 @@ new_stateless_action!(pub QuitAction, AppActionGroup, "quit");
|
|||
new_stateful_action!(pub DebugViewToggleAction, AppActionGroup, "debugviewtoggle", (), bool);
|
||||
new_stateless_action!(pub ConfigureWivrnAction, AppActionGroup, "configurewivrn");
|
||||
new_stateless_action!(pub PluginStoreAction, AppActionGroup, "store");
|
||||
new_stateless_action!(pub ThemeManagerAction, AppActionGroup, "thememanager");
|
||||
|
||||
new_stateless_action!(pub DebugOpenDataAction, AppActionGroup, "debugopendata");
|
||||
new_stateless_action!(pub DebugOpenPrefixAction, AppActionGroup, "debugopenprefix");
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use crate::termcolor::TermColor;
|
||||
|
||||
use super::{term_widget::TermWidget, SENDER_IO_ERR_MSG};
|
||||
use adw::prelude::*;
|
||||
use relm4::prelude::*;
|
||||
|
@ -90,54 +88,43 @@ impl SimpleComponent for BuildWindow {
|
|||
gtk::Label {
|
||||
#[track = "model.changed(BuildWindow::build_status())"]
|
||||
set_markup: match &model.build_status {
|
||||
BuildStatus::Building => String::default(),
|
||||
BuildStatus::Done => "Build done, you can close this window".into(),
|
||||
BuildStatus::Building => "Build in progress...".to_string(),
|
||||
BuildStatus::Done => "Build done, you can close this window".to_string(),
|
||||
BuildStatus::Error(code) => {
|
||||
format!("Build failed: \"{c}\"", c = code)
|
||||
}
|
||||
}.as_str(),
|
||||
#[track = "model.changed(BuildWindow::build_status())"]
|
||||
set_visible: match &model.build_status {
|
||||
BuildStatus::Building => false,
|
||||
BuildStatus::Done | BuildStatus::Error(_) => true,
|
||||
},
|
||||
add_css_class: "title-2",
|
||||
set_wrap: true,
|
||||
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||
set_justify: gtk::Justification::Center,
|
||||
},
|
||||
gtk::Button {
|
||||
#[track = "model.changed(BuildWindow::build_status())"]
|
||||
set_visible: matches!(&model.build_status, BuildStatus::Building),
|
||||
add_css_class: "destructive-action",
|
||||
add_css_class: "circular",
|
||||
set_icon_name: "window-close-symbolic",
|
||||
set_tooltip_text: Some("Cancel build"),
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(Self::Output::CancelBuild).expect(SENDER_IO_ERR_MSG);
|
||||
}
|
||||
},
|
||||
},
|
||||
model.term.container.clone(),
|
||||
},
|
||||
add_bottom_bar: bottom_bar = >k::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
add_bottom_bar: bottom_bar = >k::Button {
|
||||
add_css_class: "pill",
|
||||
set_halign: gtk::Align::Center,
|
||||
set_hexpand: true,
|
||||
set_margin_bottom: 24,
|
||||
set_spacing: 12,
|
||||
gtk::Button {
|
||||
add_css_class: "pill",
|
||||
set_halign: gtk::Align::Center,
|
||||
set_label: "Close",
|
||||
#[track = "model.changed(BuildWindow::can_close())"]
|
||||
set_visible: model.can_close,
|
||||
connect_clicked[win] => move |_| {
|
||||
win.close();
|
||||
},
|
||||
set_label: "Close",
|
||||
set_margin_all: 12,
|
||||
#[track = "model.changed(BuildWindow::can_close())"]
|
||||
set_sensitive: model.can_close,
|
||||
connect_clicked[win] => move |_| {
|
||||
|
||||
win.close();
|
||||
},
|
||||
// this
|
||||
gtk::Button {
|
||||
#[track = "model.changed(BuildWindow::build_status())"]
|
||||
set_visible: matches!(&model.build_status, BuildStatus::Building),
|
||||
add_css_class: "destructive-action",
|
||||
add_css_class: "pill",
|
||||
set_label: "Cancel build",
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(Self::Output::CancelBuild).expect(SENDER_IO_ERR_MSG);
|
||||
}
|
||||
},
|
||||
// ^^^
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,18 +153,8 @@ impl SimpleComponent for BuildWindow {
|
|||
label.remove_css_class("success");
|
||||
label.remove_css_class("error");
|
||||
match status {
|
||||
BuildStatus::Done => {
|
||||
label.add_css_class("success");
|
||||
sender.input(BuildWindowMsg::UpdateContent(vec![
|
||||
TermColor::Blue.colorize("Build completed!\n")
|
||||
]));
|
||||
}
|
||||
BuildStatus::Error(_) => {
|
||||
label.add_css_class("error");
|
||||
sender.input(BuildWindowMsg::UpdateContent(vec![
|
||||
TermColor::Blue.colorize("Build failed!\n")
|
||||
]));
|
||||
}
|
||||
BuildStatus::Done => label.add_css_class("success"),
|
||||
BuildStatus::Error(_) => label.add_css_class("error"),
|
||||
_ => {}
|
||||
}
|
||||
if status != BuildStatus::Building {
|
||||
|
|
|
@ -21,11 +21,11 @@ use crate::{
|
|||
paths::{get_data_dir, get_home_dir},
|
||||
profile::{LighthouseDriver, Profile, XRServiceType},
|
||||
stateless_action,
|
||||
ui::app::ThemeManagerAction,
|
||||
util::{
|
||||
file_utils::{get_writer, mount_has_nosuid},
|
||||
steamvr_utils::chaperone_info_exists,
|
||||
},
|
||||
vulkaninfo::VulkanInfo,
|
||||
wivrn_dbus,
|
||||
xr_devices::XRDevice,
|
||||
};
|
||||
|
@ -75,6 +75,8 @@ pub struct MainView {
|
|||
#[tracker::do_not_track]
|
||||
profile_export_action: gtk::gio::SimpleAction,
|
||||
xrservice_ready: bool,
|
||||
#[tracker::do_not_track]
|
||||
vkinfo: Option<VulkanInfo>,
|
||||
wivrn_pairing_mode: bool,
|
||||
wivrn_pin: Option<String>,
|
||||
wivrn_supports_pairing: bool,
|
||||
|
@ -113,8 +115,7 @@ pub enum MainViewOutMsg {
|
|||
DoStartStopXRService,
|
||||
RestartXRService,
|
||||
ProfileSelected(Profile),
|
||||
/// bool param: delete files
|
||||
DeleteProfile(bool),
|
||||
DeleteProfile,
|
||||
SaveProfile(Profile),
|
||||
OpenLibsurviveSetup,
|
||||
/// params: clean
|
||||
|
@ -125,6 +126,7 @@ pub struct MainViewInit {
|
|||
pub config: Config,
|
||||
pub selected_profile: Profile,
|
||||
pub root_win: gtk::Window,
|
||||
pub vkinfo: Option<VulkanInfo>,
|
||||
}
|
||||
|
||||
impl MainView {
|
||||
|
@ -160,7 +162,6 @@ impl AsyncComponent for MainView {
|
|||
"Configure _WiVRn" => ConfigureWivrnAction,
|
||||
},
|
||||
section! {
|
||||
"Change _Theme" => ThemeManagerAction,
|
||||
"_About" => AboutAction,
|
||||
},
|
||||
},
|
||||
|
@ -460,6 +461,34 @@ impl AsyncComponent for MainView {
|
|||
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||
}
|
||||
},
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_hexpand: true,
|
||||
set_vexpand: false,
|
||||
set_spacing: 12,
|
||||
add_css_class: "card",
|
||||
add_css_class: "padded",
|
||||
set_visible: model
|
||||
.vkinfo
|
||||
.as_ref()
|
||||
.is_some_and(
|
||||
|i| i.has_nvidia_gpu && !i.has_monado_vulkan_layers
|
||||
),
|
||||
warning_heading(),
|
||||
gtk::Label {
|
||||
set_label: concat!(
|
||||
"An Nvidia GPU has been detected, but it ",
|
||||
"seems you don't have the Monado Vulkan Layers ",
|
||||
"installed on your system.\n\nInstall the ",
|
||||
"Monado Vulkan Layers or your XR session will ",
|
||||
"crash."
|
||||
),
|
||||
add_css_class: "warning",
|
||||
set_xalign: 0.0,
|
||||
set_wrap: true,
|
||||
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||
}
|
||||
},
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_hexpand: true,
|
||||
|
@ -934,13 +963,6 @@ impl AsyncComponent for MainView {
|
|||
|
||||
let profile_delete_confirm_dialog = adw::AlertDialog::builder()
|
||||
.heading("Are you sure you want to delete this profile?")
|
||||
.extra_child(
|
||||
>k::CheckButton::builder()
|
||||
.label("Delete all files and folders associated with profile")
|
||||
.halign(gtk::Align::Center)
|
||||
.hexpand(true)
|
||||
.build(),
|
||||
)
|
||||
.build();
|
||||
profile_delete_confirm_dialog.add_response("no", "_No");
|
||||
profile_delete_confirm_dialog.add_response("yes", "_Yes");
|
||||
|
@ -952,19 +974,10 @@ impl AsyncComponent for MainView {
|
|||
clone!(
|
||||
#[strong]
|
||||
sender,
|
||||
move |dialog, res| {
|
||||
let delete_files_checkbox = dialog
|
||||
.extra_child()
|
||||
.and_then(|child| child.downcast::<gtk::CheckButton>().ok());
|
||||
let delete_files = delete_files_checkbox
|
||||
.as_ref()
|
||||
.is_some_and(|c| c.is_active());
|
||||
if let Some(check) = delete_files_checkbox {
|
||||
check.set_active(false);
|
||||
}
|
||||
move |_, res| {
|
||||
if res == "yes" {
|
||||
sender
|
||||
.output(Self::Output::DeleteProfile(delete_files))
|
||||
.output(Self::Output::DeleteProfile)
|
||||
.expect("Sender output failed");
|
||||
}
|
||||
}
|
||||
|
@ -1090,6 +1103,7 @@ impl AsyncComponent for MainView {
|
|||
xrservice_ready: false,
|
||||
profile_delete_action,
|
||||
profile_export_action,
|
||||
vkinfo: init.vkinfo,
|
||||
wivrn_pairing_mode: false,
|
||||
wivrn_supports_pairing: false,
|
||||
wivrn_pin: None,
|
||||
|
|
|
@ -165,8 +165,8 @@ impl Plugin {
|
|||
/// each manifest should be json and the link should always point to the latest version
|
||||
const MANIFESTS: [&str;3] = [
|
||||
"https://github.com/galister/wlx-overlay-s/raw/refs/heads/meta/com.github.galister.wlx-overlay-s.json",
|
||||
"https://github.com/StardustXR/telescope/raw/refs/heads/main/envision/org.stardustxr.telescope.json",
|
||||
"https://github.com/olekolek1000/wayvr-dashboard/raw/refs/heads/meta/dev.oo8.wayvr_dashboard.json",
|
||||
"https://github.com/StardustXR/telescope/raw/refs/heads/main/envision/org.stardustxr.telescope.json",
|
||||
];
|
||||
|
||||
pub async fn refresh_plugins() -> anyhow::Result<Vec<anyhow::Result<Plugin>>> {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{async_process::async_process, depcheck::common::dep_getcap_setcap, profile::Profile};
|
||||
use crate::{async_process::async_process, profile::Profile};
|
||||
use anyhow::bail;
|
||||
use nix::{
|
||||
errno::Errno,
|
||||
|
@ -79,29 +79,9 @@ pub fn set_file_readonly(path: &Path, readonly: bool) -> anyhow::Result<()> {
|
|||
Ok(fs::set_permissions(path, perms)?)
|
||||
}
|
||||
|
||||
pub fn setcap_executable() -> Option<String> {
|
||||
if dep_getcap_setcap().check() {
|
||||
Some("setcap".into())
|
||||
} else if Path::new("/sbin/setcap").try_exists().unwrap_or_default() {
|
||||
Some("/sbin/setcap".into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getcap_executable() -> Option<String> {
|
||||
if dep_getcap_setcap().check() {
|
||||
Some("getcap".into())
|
||||
} else if Path::new("/sbin/getcap").try_exists().unwrap_or_default() {
|
||||
Some("/sbin/getcap".into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setcap_cap_sys_nice_eip_cmd(profile: &Profile) -> Vec<String> {
|
||||
vec![
|
||||
setcap_executable().unwrap_or("setcap".into()),
|
||||
"setcap".into(),
|
||||
"CAP_SYS_NICE=eip".into(),
|
||||
profile
|
||||
.prefix
|
||||
|
@ -113,29 +93,24 @@ pub fn setcap_cap_sys_nice_eip_cmd(profile: &Profile) -> Vec<String> {
|
|||
|
||||
pub async fn verify_cap_sys_nice_eip(profile: &Profile) -> bool {
|
||||
let xrservice_binary = profile.xrservice_binary().to_string_lossy().to_string();
|
||||
if let Some(getcap_exec) = getcap_executable() {
|
||||
match async_process(&getcap_exec, Some(&[&xrservice_binary]), None).await {
|
||||
Err(e) => {
|
||||
error!("failed to run `getcap {xrservice_binary}`: {e:?}");
|
||||
match async_process("getcap", Some(&[&xrservice_binary]), None).await {
|
||||
Err(e) => {
|
||||
error!("failed to run `getcap {xrservice_binary}`: {e:?}");
|
||||
false
|
||||
}
|
||||
Ok(out) => {
|
||||
debug!("getcap {xrservice_binary} stdout: {}", out.stdout);
|
||||
debug!("getcap {xrservice_binary} stderr: {}", out.stderr);
|
||||
if out.exit_code != 0 {
|
||||
error!(
|
||||
"command `getcap {xrservice_binary}` failed with status code {}",
|
||||
out.exit_code
|
||||
);
|
||||
false
|
||||
}
|
||||
Ok(out) => {
|
||||
debug!("getcap {xrservice_binary} stdout: {}", out.stdout);
|
||||
debug!("getcap {xrservice_binary} stderr: {}", out.stderr);
|
||||
if out.exit_code != 0 {
|
||||
error!(
|
||||
"command `getcap {xrservice_binary}` failed with status code {}",
|
||||
out.exit_code
|
||||
);
|
||||
false
|
||||
} else {
|
||||
out.stdout.to_lowercase().contains("cap_sys_nice=eip")
|
||||
}
|
||||
} else {
|
||||
out.stdout.to_lowercase().contains("cap_sys_nice=eip")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("getcap executable does not exist");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@ use ash::{
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VulkanInfo {
|
||||
pub has_nvidia_gpu: bool,
|
||||
pub has_monado_vulkan_layers: bool,
|
||||
pub gpu_names: Vec<String>,
|
||||
}
|
||||
|
||||
// const NVIDIA_VENDOR_ID: u32 = 0x10de;
|
||||
const NVIDIA_VENDOR_ID: u32 = 0x10de;
|
||||
|
||||
impl VulkanInfo {
|
||||
/// # Safety
|
||||
|
@ -23,19 +25,40 @@ impl VulkanInfo {
|
|||
None,
|
||||
)
|
||||
}?;
|
||||
let mut has_nvidia_gpu = false;
|
||||
let mut has_monado_vulkan_layers = false;
|
||||
let gpu_names = unsafe { instance.enumerate_physical_devices() }?
|
||||
.into_iter()
|
||||
.filter_map(|d| {
|
||||
Some(
|
||||
unsafe { instance.get_physical_device_properties(d) }
|
||||
.device_name_as_c_str()
|
||||
.ok()?
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
)
|
||||
let props = unsafe { instance.get_physical_device_properties(d) };
|
||||
if props.vendor_id == NVIDIA_VENDOR_ID {
|
||||
has_nvidia_gpu = true;
|
||||
}
|
||||
if !has_monado_vulkan_layers {
|
||||
has_monado_vulkan_layers =
|
||||
unsafe { instance.enumerate_device_layer_properties(d) }
|
||||
.ok()
|
||||
.map(|layerprops| {
|
||||
layerprops.iter().any(|lp| {
|
||||
lp.layer_name_as_c_str().is_ok_and(|name| {
|
||||
name.to_string_lossy()
|
||||
== "VK_LAYER_MND_enable_timeline_semaphore"
|
||||
})
|
||||
})
|
||||
})
|
||||
== Some(true);
|
||||
}
|
||||
props
|
||||
.device_name_as_c_str()
|
||||
.ok()
|
||||
.map(|cs| cs.to_string_lossy().to_string())
|
||||
})
|
||||
.collect();
|
||||
unsafe { instance.destroy_instance(None) };
|
||||
Ok(Self { gpu_names })
|
||||
Ok(Self {
|
||||
gpu_names,
|
||||
has_nvidia_gpu,
|
||||
has_monado_vulkan_layers,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue