Skip to main content

cosmic/desktop/
gpu.rs

1// Copyright 2026 System76 <info@system76.com>
2// SPDX-License-Identifier: MPL-2.0
3
4use std::collections::HashMap;
5
6/// An available GPU that can be selected by a launcher.
7#[derive(Debug, Clone)]
8pub struct Descriptor {
9    pub name: String,
10    pub environment: HashMap<String, String>,
11    pub default: bool,
12    pub discrete: bool,
13}
14
15/// A preference to use when choosing a GPU to launch with.
16#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
17pub enum Preference {
18    #[default]
19    Default,
20    NonDefault,
21}
22
23impl Preference {
24    /// Find the preferred default GPU for this preference.
25    pub fn preferred(self, gpus: &[Descriptor]) -> Option<usize> {
26        let default_idx = gpus.iter().position(|gpu| gpu.default);
27        if matches!(self, Preference::Default) {
28            return default_idx;
29        }
30
31        let default_discrete = gpus.iter().position(|gpu| gpu.default && gpu.discrete);
32        if default_discrete.is_some() {
33            return default_discrete;
34        }
35
36        let non_default_discrete = gpus.iter().position(|gpu| gpu.discrete);
37        let non_default = || gpus.iter().position(|gpu| !gpu.default);
38        non_default_discrete.or_else(non_default).or(default_idx)
39    }
40
41    /// Select the GPU override to launch with.
42    pub fn select(self, gpus: &[Descriptor]) -> Option<usize> {
43        if matches!(self, Preference::Default) {
44            return None;
45        }
46
47        let default_discrete = gpus.iter().position(|gpu| gpu.default && gpu.discrete);
48        if default_discrete.is_some() {
49            return None;
50        }
51
52        let non_default_discrete = gpus.iter().position(|gpu| gpu.discrete);
53        let non_default = || gpus.iter().position(|gpu| !gpu.default);
54        non_default_discrete.or_else(non_default)
55    }
56}