diff --git a/src/desktop.rs b/src/desktop.rs index 2baa4d97..f79d295b 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -1,6 +1,8 @@ #[cfg(not(windows))] pub use freedesktop_desktop_entry as fde; #[cfg(not(windows))] +pub mod gpu; +#[cfg(not(windows))] pub use mime::Mime; use std::path::{Path, PathBuf}; #[cfg(not(windows))] diff --git a/src/desktop/gpu.rs b/src/desktop/gpu.rs new file mode 100644 index 00000000..e6a911fb --- /dev/null +++ b/src/desktop/gpu.rs @@ -0,0 +1,56 @@ +// Copyright 2026 System76 +// SPDX-License-Identifier: MPL-2.0 + +use std::collections::HashMap; + +/// An available GPU that can be selected by a launcher. +#[derive(Debug, Clone)] +pub struct Descriptor { + pub name: String, + pub environment: HashMap, + pub default: bool, + pub discrete: bool, +} + +/// A preference to use when choosing a GPU to launch with. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum Preference { + #[default] + Default, + NonDefault, +} + +impl Preference { + /// Find the preferred default GPU for this preference. + pub fn preferred(self, gpus: &[Descriptor]) -> Option { + let default_idx = gpus.iter().position(|gpu| gpu.default); + if matches!(self, Preference::Default) { + return default_idx; + } + + let default_discrete = gpus.iter().position(|gpu| gpu.default && gpu.discrete); + if default_discrete.is_some() { + return default_discrete; + } + + let non_default_discrete = gpus.iter().position(|gpu| gpu.discrete); + let non_default = || gpus.iter().position(|gpu| !gpu.default); + non_default_discrete.or_else(non_default).or(default_idx) + } + + /// Select the GPU override to launch with. + pub fn select(self, gpus: &[Descriptor]) -> Option { + if matches!(self, Preference::Default) { + return None; + } + + let default_discrete = gpus.iter().position(|gpu| gpu.default && gpu.discrete); + if default_discrete.is_some() { + return None; + } + + let non_default_discrete = gpus.iter().position(|gpu| gpu.discrete); + let non_default = || gpus.iter().position(|gpu| !gpu.default); + non_default_discrete.or_else(non_default) + } +}