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 <lunpujun@google.com>
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
This commit is contained in:
Pujun Lun 2022-09-19 10:58:19 -07:00 committed by crosvm LUCI
parent 9a415a2559
commit 05e0443fe5
3 changed files with 59 additions and 8 deletions

View file

@ -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<u64, D::Error> {
let s = String::deserialize(deserializer)?;
let context_types: Vec<String> = 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<S>(context_mask: &u64, serializer: S) -> Result<S::Ok, S::Error>
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<u64, D::Error> {
let s = String::deserialize(deserializer)?;
let context_types: Vec<String> = 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<String>,
pub cache_size: Option<String>,
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::<ContextMask>(SERIALIZED_CONTEXT_MASK).unwrap(),
context_mask
);
}
}

View file

@ -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;

View file

@ -259,6 +259,14 @@ pub fn calculate_context_mask(context_names: Vec<String>) -> u64 {
context_mask
}
pub fn calculate_context_types(context_mask: u64) -> Vec<String> {
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