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(Clone, Debug, Serialize, Deserialize, FromKeyValues)]
41 #[serde(deny_unknown_fields, default, rename_all = "kebab-case")]
42 pub struct GpuParameters {
43 #[serde(rename = "backend")]
44 pub mode: GpuMode,
45 #[serde(default = "default_max_num_displays")]
46 pub max_num_displays: u32,
47 #[serde(rename = "displays")]
48 pub display_params: Vec<DisplayParameters>,
49 // `width` and `height` are supported for CLI backwards compatibility.
50 #[serde(rename = "width")]
51 pub __width_compat: Option<u32>,
52 #[serde(rename = "height")]
53 pub __height_compat: Option<u32>,
54 #[serde(rename = "egl")]
55 pub renderer_use_egl: bool,
56 #[serde(rename = "gles")]
57 pub renderer_use_gles: bool,
58 #[serde(rename = "glx")]
59 pub renderer_use_glx: bool,
60 #[serde(rename = "surfaceless")]
61 pub renderer_use_surfaceless: bool,
62 #[serde(rename = "vulkan")]
63 pub use_vulkan: Option<bool>,
64 pub wsi: Option<GpuWsi>,
65 pub udmabuf: bool,
66 pub cache_path: Option<String>,
67 pub cache_size: Option<String>,
68 pub pci_address: Option<PciAddress>,
69 pub pci_bar_size: u64,
70 #[serde(rename = "context-types", with = "serde_capset_mask")]
71 pub capset_mask: u64,
72 // enforce that blob resources MUST be exportable as file descriptors
73 pub external_blob: bool,
74 pub system_blob: bool,
75 // enable use of descriptor mapping to fixed host VA within a prepared vMMU mapping (e.g. kvm
76 // user memslot)
77 pub fixed_blob_mapping: bool,
78 #[serde(rename = "implicit-render-server")]
79 pub allow_implicit_render_server_exec: bool,
80 // Passthrough parameters sent to the underlying renderer in a renderer-specific format.
81 pub renderer_features: Option<String>,
82 }
83
84 impl Default for GpuParameters {
default() -> Self85 fn default() -> Self {
86 GpuParameters {
87 max_num_displays: default_max_num_displays(),
88 display_params: vec![],
89 __width_compat: None,
90 __height_compat: None,
91 renderer_use_egl: true,
92 renderer_use_gles: true,
93 renderer_use_glx: false,
94 renderer_use_surfaceless: true,
95 use_vulkan: None,
96 mode: Default::default(),
97 wsi: None,
98 cache_path: None,
99 cache_size: None,
100 pci_address: None,
101 pci_bar_size: (1 << 33),
102 udmabuf: false,
103 capset_mask: 0,
104 external_blob: false,
105 system_blob: false,
106 // TODO(b/324649619): not yet fully compatible with other platforms (windows)
107 // TODO(b/246334944): gfxstream may map vulkan opaque blobs directly (without vulkano),
108 // so set the default to disabled when built with the gfxstream feature.
109 fixed_blob_mapping: cfg!(target_os = "linux") && !cfg!(feature = "gfxstream"),
110 allow_implicit_render_server_exec: false,
111 renderer_features: None,
112 }
113 }
114 }
115
default_max_num_displays() -> u32116 fn default_max_num_displays() -> u32 {
117 VIRTIO_GPU_MAX_SCANOUTS as u32
118 }
119
120 #[cfg(test)]
121 mod tests {
122 use serde_json::*;
123
124 use super::*;
125
126 #[test]
capset_mask_serialize_deserialize()127 fn capset_mask_serialize_deserialize() {
128 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
129 struct CapsetMask {
130 #[serde(rename = "context-types", with = "serde_capset_mask")]
131 pub value: u64,
132 }
133
134 // Capset "virgl", id: 1, capset_mask: 0b0010
135 // Capset "gfxstream", id: 3, capset_mask: 0b1000
136 const CAPSET_MASK: u64 = 0b1010;
137 const SERIALIZED_CAPSET_MASK: &str = "{\"context-types\":\"virgl:gfxstream-vulkan\"}";
138
139 let capset_mask = CapsetMask { value: CAPSET_MASK };
140
141 assert_eq!(to_string(&capset_mask).unwrap(), SERIALIZED_CAPSET_MASK);
142 assert_eq!(
143 from_str::<CapsetMask>(SERIALIZED_CAPSET_MASK).unwrap(),
144 capset_mask
145 );
146 }
147 }
148