use std::collections::HashMap; use std::fmt::Debug; use std::marker::PhantomData; use std::sync::{Arc, Mutex}; use drm_sys::{ DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_PROPERTY, }; use syscall::{Error, Result, EINVAL}; use crate::kms::connector::{KmsConnector, KmsEncoder}; use crate::kms::properties::{KmsBlob, KmsProperty}; use crate::GraphicsAdapter; #[derive(Debug)] pub struct KmsObjects { next_id: KmsObjectId, pub(crate) connectors: Vec, pub(crate) encoders: Vec, pub(crate) objects: HashMap>>, _marker: PhantomData, } impl KmsObjects { pub(crate) fn new() -> Self { KmsObjects { next_id: KmsObjectId(1), connectors: vec![], encoders: vec![], objects: HashMap::new(), _marker: PhantomData, } } pub(crate) fn add>>(&mut self, data: U) -> KmsObjectId { let id = self.next_id; self.objects.insert( id, Arc::new(KmsObjectData { kind: Box::new(data.into()), properties: Mutex::new(vec![]), }), ); self.next_id.0 += 1; id } pub(crate) fn get<'a, U: 'a>(&'a self, id: KmsObjectId) -> Result<&'a U> where &'a U: TryFrom<&'a KmsObjectKind>, { let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; if let Ok(object) = (&*object.kind).try_into() { Ok(object) } else { Err(Error::new(EINVAL)) } } pub fn object_type(&self, id: KmsObjectId) -> Result { let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; Ok(object.kind.object_type()) } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct KmsObjectId(pub(crate) u32); impl KmsObjectId { pub const INVALID: KmsObjectId = KmsObjectId(0); } impl From for u64 { fn from(value: KmsObjectId) -> Self { value.0.into() } } #[derive(Debug)] pub(crate) struct KmsObjectData { kind: Box>, pub(crate) properties: Mutex>, } macro_rules! define_object_kinds { (<$T:ident> $( $variant:ident($data:ty) = $type:ident, )*) => { #[derive(Debug)] pub(crate) enum KmsObjectKind<$T: GraphicsAdapter> { $($variant($data),)* } impl<$T: GraphicsAdapter> KmsObjectKind<$T> { fn object_type(&self) -> u32 { match self { $(Self::$variant(_) => $type,)* } } } $( impl<$T: GraphicsAdapter> From<$data> for KmsObjectKind<$T> { fn from(value: $data) -> Self { Self::$variant(value) } } impl<'a, $T: GraphicsAdapter> TryFrom<&'a KmsObjectKind<$T>> for &'a $data { type Error = (); fn try_from(value: &'a KmsObjectKind) -> Result { match value { KmsObjectKind::$variant(data) => Ok(data), _ => Err(()), } } } )* }; } define_object_kinds! { Connector(Mutex>) = DRM_MODE_OBJECT_CONNECTOR, Encoder(KmsEncoder) = DRM_MODE_OBJECT_ENCODER, Property(KmsProperty) = DRM_MODE_OBJECT_PROPERTY, Blob(KmsBlob) = DRM_MODE_OBJECT_BLOB, }