From 05e0443fe59f99500587169680f4f70cdf9c0b6a Mon Sep 17 00:00:00 2001 From: Pujun Lun Date: Mon, 19 Sep 2022 10:58:19 -0700 Subject: [PATCH] gpu: add a serializer for context mask. Apart from being used for arg parsing, GpuParameters is also sent through a Tube on Windows. Since we've added a deserializer for the context_mask field, we also need a serializer for it. BUG=b:233676779 TEST=cargo test -p devices --features=all-linux virtio::gpu::parameters::tests::context_mask_serialize_deserialize Change-Id: Ic0a01acc07ac39b5962e3cfad970dae1ae8c8b27 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3906468 Commit-Queue: Pujun Lun Reviewed-by: Alexandre Courbot --- devices/src/virtio/gpu/parameters.rs | 58 ++++++++++++++++++++++++---- rutabaga_gfx/src/lib.rs | 1 + rutabaga_gfx/src/rutabaga_core.rs | 8 ++++ 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/devices/src/virtio/gpu/parameters.rs b/devices/src/virtio/gpu/parameters.rs index 2ee032146a..f410ba53cc 100644 --- a/devices/src/virtio/gpu/parameters.rs +++ b/devices/src/virtio/gpu/parameters.rs @@ -11,6 +11,7 @@ use rutabaga_gfx::RutabagaWsi; use serde::Deserialize; use serde::Deserializer; use serde::Serialize; +use serde::Serializer; use serde_keyvalue::FromKeyValues; pub use super::sys::DisplayMode; @@ -109,11 +110,24 @@ fn default_refresh_rate() -> u32 { DEFAULT_REFRESH_RATE } -fn deserialize_context_mask<'de, D: Deserializer<'de>>(deserializer: D) -> Result { - let s = String::deserialize(deserializer)?; - let context_types: Vec = s.split(':').map(|s| s.to_string()).collect(); +mod serde_context_mask { + use super::*; - Ok(rutabaga_gfx::calculate_context_mask(context_types)) + pub fn serialize(context_mask: &u64, serializer: S) -> Result + where + S: Serializer, + { + let context_types = rutabaga_gfx::calculate_context_types(*context_mask).join(":"); + + serializer.serialize_str(context_types.as_str()) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let s = String::deserialize(deserializer)?; + let context_types: Vec = s.split(':').map(|s| s.to_string()).collect(); + + Ok(rutabaga_gfx::calculate_context_mask(context_types)) + } } #[derive(Debug, Serialize, Deserialize, FromKeyValues)] @@ -147,10 +161,7 @@ pub struct GpuParameters { pub cache_path: Option, pub cache_size: Option, pub pci_bar_size: u64, - #[serde( - rename = "context-types", - deserialize_with = "deserialize_context_mask" - )] + #[serde(rename = "context-types", with = "serde_context_mask")] pub context_mask: u64, } @@ -181,3 +192,34 @@ impl Default for GpuParameters { } } } + +#[cfg(test)] +mod tests { + use serde_json::*; + + use super::*; + + #[test] + fn context_mask_serialize_deserialize() { + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct ContextMask { + #[serde(rename = "context-types", with = "serde_context_mask")] + pub value: u64, + } + + // Capset "virgl", id: 1, context_mask: 0b0010 + // Capset "gfxstream", id: 3, context_mask: 0b1000 + const CONTEXT_MASK: u64 = 0b1010; + const SERIALIZED_CONTEXT_MASK: &str = "{\"context-types\":\"virgl:gfxstream\"}"; + + let context_mask = ContextMask { + value: CONTEXT_MASK, + }; + + assert_eq!(to_string(&context_mask).unwrap(), SERIALIZED_CONTEXT_MASK); + assert_eq!( + from_str::(SERIALIZED_CONTEXT_MASK).unwrap(), + context_mask + ); + } +} diff --git a/rutabaga_gfx/src/lib.rs b/rutabaga_gfx/src/lib.rs index 73cd1557e4..7f841e80ac 100644 --- a/rutabaga_gfx/src/lib.rs +++ b/rutabaga_gfx/src/lib.rs @@ -19,6 +19,7 @@ mod rutabaga_utils; mod virgl_renderer; pub use crate::rutabaga_core::calculate_context_mask; +pub use crate::rutabaga_core::calculate_context_types; pub use crate::rutabaga_core::Rutabaga; pub use crate::rutabaga_core::RutabagaBuilder; pub use crate::rutabaga_gralloc::DrmFormat; diff --git a/rutabaga_gfx/src/rutabaga_core.rs b/rutabaga_gfx/src/rutabaga_core.rs index e6da085844..b3388bbc98 100644 --- a/rutabaga_gfx/src/rutabaga_core.rs +++ b/rutabaga_gfx/src/rutabaga_core.rs @@ -259,6 +259,14 @@ pub fn calculate_context_mask(context_names: Vec) -> u64 { context_mask } +pub fn calculate_context_types(context_mask: u64) -> Vec { + RUTABAGA_CAPSETS + .iter() + .filter(|capset| context_mask & (1 << capset.capset_id) != 0) + .map(|capset| capset.name.to_string()) + .collect() +} + /// The global libary handle used to query capability sets, create resources and contexts. /// /// Currently, Rutabaga only supports one default component. Many components running at the