• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Definitions and utilities for GPU related parameters.
6 
7 #[cfg(windows)]
8 use std::marker::PhantomData;
9 use std::path::PathBuf;
10 
11 use serde::Deserialize;
12 use serde::Deserializer;
13 use serde::Serialize;
14 use serde::Serializer;
15 use serde_keyvalue::FromKeyValues;
16 use vm_control::gpu::DisplayParameters;
17 
18 use super::GpuMode;
19 use super::GpuWsi;
20 use crate::virtio::gpu::VIRTIO_GPU_MAX_SCANOUTS;
21 use crate::PciAddress;
22 
23 mod serde_capset_mask {
24     use super::*;
25 
serialize<S>(capset_mask: &u64, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,26     pub fn serialize<S>(capset_mask: &u64, serializer: S) -> Result<S::Ok, S::Error>
27     where
28         S: Serializer,
29     {
30         let context_types = rutabaga_gfx::calculate_capset_names(*capset_mask).join(":");
31 
32         serializer.serialize_str(context_types.as_str())
33     }
34 
deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u64, D::Error>35     pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u64, D::Error> {
36         let s = String::deserialize(deserializer)?;
37         Ok(rutabaga_gfx::calculate_capset_mask(s.split(':')))
38     }
39 }
40 
41 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
42 pub enum AudioDeviceMode {
43     #[serde(rename = "per-surface")]
44     PerSurface,
45     #[serde(rename = "one-global")]
46     OneGlobal,
47 }
48 
49 #[derive(Clone, Debug, Serialize, Deserialize, FromKeyValues)]
50 #[serde(deny_unknown_fields, default, rename_all = "kebab-case")]
51 pub struct GpuParameters {
52     #[serde(rename = "backend")]
53     pub mode: GpuMode,
54     #[serde(default = "default_max_num_displays")]
55     pub max_num_displays: u32,
56     #[serde(default = "default_audio_device_mode")]
57     pub audio_device_mode: AudioDeviceMode,
58     #[serde(rename = "displays")]
59     pub display_params: Vec<DisplayParameters>,
60     // `width` and `height` are supported for CLI backwards compatibility.
61     #[serde(rename = "width")]
62     pub __width_compat: Option<u32>,
63     #[serde(rename = "height")]
64     pub __height_compat: Option<u32>,
65     #[serde(rename = "egl")]
66     pub renderer_use_egl: bool,
67     #[serde(rename = "gles")]
68     pub renderer_use_gles: bool,
69     #[serde(rename = "glx")]
70     pub renderer_use_glx: bool,
71     #[serde(rename = "surfaceless")]
72     pub renderer_use_surfaceless: bool,
73     #[serde(rename = "vulkan")]
74     pub use_vulkan: Option<bool>,
75     pub wsi: Option<GpuWsi>,
76     pub udmabuf: bool,
77     pub cache_path: Option<String>,
78     pub cache_size: Option<String>,
79     pub pci_address: Option<PciAddress>,
80     pub pci_bar_size: u64,
81     #[serde(rename = "context-types", with = "serde_capset_mask")]
82     pub capset_mask: u64,
83     // enforce that blob resources MUST be exportable as file descriptors
84     pub external_blob: bool,
85     pub system_blob: bool,
86     // enable use of descriptor mapping to fixed host VA within a prepared vMMU mapping (e.g. kvm
87     // user memslot)
88     pub fixed_blob_mapping: bool,
89     #[serde(rename = "implicit-render-server")]
90     pub allow_implicit_render_server_exec: bool,
91     // Passthrough parameters sent to the underlying renderer in a renderer-specific format.
92     pub renderer_features: Option<String>,
93     // When running with device sandboxing, the path of a directory available for
94     // scratch space.
95     pub snapshot_scratch_path: Option<PathBuf>,
96 }
97 
98 impl Default for GpuParameters {
default() -> Self99     fn default() -> Self {
100         GpuParameters {
101             max_num_displays: default_max_num_displays(),
102             audio_device_mode: default_audio_device_mode(),
103             display_params: vec![],
104             __width_compat: None,
105             __height_compat: None,
106             renderer_use_egl: true,
107             renderer_use_gles: true,
108             renderer_use_glx: false,
109             renderer_use_surfaceless: true,
110             use_vulkan: None,
111             mode: Default::default(),
112             wsi: None,
113             cache_path: None,
114             cache_size: None,
115             pci_address: None,
116             pci_bar_size: (1 << 33),
117             udmabuf: false,
118             capset_mask: 0,
119             external_blob: false,
120             system_blob: false,
121             // TODO(b/324649619): not yet fully compatible with other platforms (windows)
122             // TODO(b/246334944): gfxstream may map vulkan opaque blobs directly (without vulkano),
123             // so set the default to disabled when built with the gfxstream feature.
124             fixed_blob_mapping: cfg!(target_os = "linux") && !cfg!(feature = "gfxstream"),
125             allow_implicit_render_server_exec: false,
126             renderer_features: None,
127             snapshot_scratch_path: None,
128         }
129     }
130 }
131 
default_max_num_displays() -> u32132 fn default_max_num_displays() -> u32 {
133     VIRTIO_GPU_MAX_SCANOUTS as u32
134 }
135 
default_audio_device_mode() -> AudioDeviceMode136 fn default_audio_device_mode() -> AudioDeviceMode {
137     AudioDeviceMode::PerSurface
138 }
139 
140 #[cfg(test)]
141 mod tests {
142     use serde_json::*;
143 
144     use super::*;
145 
146     #[test]
capset_mask_serialize_deserialize()147     fn capset_mask_serialize_deserialize() {
148         #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
149         struct CapsetMask {
150             #[serde(rename = "context-types", with = "serde_capset_mask")]
151             pub value: u64,
152         }
153 
154         // Capset "virgl", id: 1, capset_mask: 0b0010
155         // Capset "gfxstream", id: 3, capset_mask: 0b1000
156         const CAPSET_MASK: u64 = 0b1010;
157         const SERIALIZED_CAPSET_MASK: &str = "{\"context-types\":\"virgl:gfxstream-vulkan\"}";
158 
159         let capset_mask = CapsetMask { value: CAPSET_MASK };
160 
161         assert_eq!(to_string(&capset_mask).unwrap(), SERIALIZED_CAPSET_MASK);
162         assert_eq!(
163             from_str::<CapsetMask>(SERIALIZED_CAPSET_MASK).unwrap(),
164             capset_mask
165         );
166     }
167 }
168