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 rutabaga_gfx::RutabagaWsi; 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 20 mod serde_capset_mask { 21 use super::*; 22 serialize<S>(capset_mask: &u64, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,23 pub fn serialize<S>(capset_mask: &u64, serializer: S) -> Result<S::Ok, S::Error> 24 where 25 S: Serializer, 26 { 27 let context_types = rutabaga_gfx::calculate_capset_names(*capset_mask).join(":"); 28 29 serializer.serialize_str(context_types.as_str()) 30 } 31 deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u64, D::Error>32 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u64, D::Error> { 33 let s = String::deserialize(deserializer)?; 34 let context_types: Vec<String> = s.split(':').map(|s| s.to_string()).collect(); 35 36 Ok(rutabaga_gfx::calculate_capset_mask(context_types)) 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(rename = "displays")] 46 pub display_params: Vec<DisplayParameters>, 47 // `width` and `height` are supported for CLI backwards compatibility. 48 #[serde(rename = "width")] 49 pub __width_compat: Option<u32>, 50 #[serde(rename = "height")] 51 pub __height_compat: Option<u32>, 52 #[serde(rename = "egl")] 53 pub renderer_use_egl: bool, 54 #[serde(rename = "gles")] 55 pub renderer_use_gles: bool, 56 #[serde(rename = "glx")] 57 pub renderer_use_glx: bool, 58 #[serde(rename = "surfaceless")] 59 pub renderer_use_surfaceless: bool, 60 #[cfg(feature = "gfxstream")] 61 #[serde(rename = "angle")] 62 pub gfxstream_use_guest_angle: Option<bool>, 63 #[serde(rename = "vulkan")] 64 pub use_vulkan: Option<bool>, 65 // It is possible that we compile with the gfxstream feature but don't use the gfxstream 66 // backend, in which case we want to ensure this option is not touched accidentally, so we make 67 // it an `Option` with default value `None`. 68 #[cfg(feature = "gfxstream")] 69 #[serde(rename = "gles31")] 70 pub gfxstream_support_gles31: Option<bool>, 71 pub wsi: Option<RutabagaWsi>, 72 pub udmabuf: bool, 73 pub cache_path: Option<String>, 74 pub cache_size: Option<String>, 75 pub pci_bar_size: u64, 76 #[serde(rename = "context-types", with = "serde_capset_mask")] 77 pub capset_mask: u64, 78 } 79 80 impl Default for GpuParameters { default() -> Self81 fn default() -> Self { 82 GpuParameters { 83 display_params: vec![], 84 __width_compat: None, 85 __height_compat: None, 86 renderer_use_egl: true, 87 renderer_use_gles: true, 88 renderer_use_glx: false, 89 renderer_use_surfaceless: true, 90 #[cfg(feature = "gfxstream")] 91 gfxstream_use_guest_angle: None, 92 use_vulkan: None, 93 mode: Default::default(), 94 #[cfg(feature = "gfxstream")] 95 gfxstream_support_gles31: None, 96 wsi: None, 97 cache_path: None, 98 cache_size: None, 99 pci_bar_size: (1 << 33), 100 udmabuf: false, 101 capset_mask: 0, 102 } 103 } 104 } 105 106 #[cfg(test)] 107 mod tests { 108 use serde_json::*; 109 110 use super::*; 111 112 #[test] capset_mask_serialize_deserialize()113 fn capset_mask_serialize_deserialize() { 114 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] 115 struct CapsetMask { 116 #[serde(rename = "context-types", with = "serde_capset_mask")] 117 pub value: u64, 118 } 119 120 // Capset "virgl", id: 1, capset_mask: 0b0010 121 // Capset "gfxstream", id: 3, capset_mask: 0b1000 122 const CAPSET_MASK: u64 = 0b1010; 123 const SERIALIZED_CAPSET_MASK: &str = "{\"context-types\":\"virgl:gfxstream\"}"; 124 125 let capset_mask = CapsetMask { value: CAPSET_MASK }; 126 127 assert_eq!(to_string(&capset_mask).unwrap(), SERIALIZED_CAPSET_MASK); 128 assert_eq!( 129 from_str::<CapsetMask>(SERIALIZED_CAPSET_MASK).unwrap(), 130 capset_mask 131 ); 132 } 133 } 134