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