diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index b77af3e4d9..2822e93486 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -35,7 +35,7 @@ pub struct StandardProperties { } pub trait GraphicsAdapter: Sized + Debug { - type Connector: Debug; + type Connector: Debug + 'static; type Framebuffer: Framebuffer; type Cursor: CursorFramebuffer; diff --git a/drivers/graphics/driver-graphics/src/objects.rs b/drivers/graphics/driver-graphics/src/objects.rs index 3cd6ea3730..4dd449e783 100644 --- a/drivers/graphics/driver-graphics/src/objects.rs +++ b/drivers/graphics/driver-graphics/src/objects.rs @@ -1,5 +1,8 @@ +use std::any::Any; use std::collections::HashMap; use std::ffi::c_char; +use std::fmt::Debug; +use std::marker::PhantomData; use drm_sys::{ drm_mode_modeinfo, DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_ENCODER, @@ -14,7 +17,8 @@ pub struct DrmObjects { next_id: DrmObjectId, connectors: Vec, encoders: Vec, - objects: HashMap>, + objects: HashMap, + _marker: PhantomData, } impl DrmObjects { @@ -24,17 +28,45 @@ impl DrmObjects { connectors: vec![], encoders: vec![], objects: HashMap::new(), + _marker: PhantomData, + } + } + + fn add(&mut self, data: U) -> DrmObjectId { + let id = self.next_id; + self.objects.insert( + id, + DrmObjectData { + kind: Box::new(data), + properties: vec![], + }, + ); + self.next_id.0 += 1; + + id + } + + fn get(&self, id: DrmObjectId) -> Result<&U> { + let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; + if let Some(object) = (&*object.kind as &dyn Any).downcast_ref::() { + Ok(object) + } else { + Err(Error::new(EINVAL)) + } + } + + fn get_mut(&mut self, id: DrmObjectId) -> Result<&mut U> { + let object = self.objects.get_mut(&id).ok_or(Error::new(EINVAL))?; + if let Some(object) = (&mut *object.kind as &mut dyn Any).downcast_mut::() { + Ok(object) + } else { + Err(Error::new(EINVAL)) } } pub fn object_type(&self, id: DrmObjectId) -> Result { let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; - Ok(match object.kind { - DrmObjectKind::Property(_) => DRM_MODE_OBJECT_PROPERTY, - DrmObjectKind::Blob(_) => DRM_MODE_OBJECT_BLOB, - DrmObjectKind::Connector(_) => DRM_MODE_OBJECT_CONNECTOR, - DrmObjectKind::Encoder(_) => DRM_MODE_OBJECT_ENCODER, - }) + Ok(object.kind.object_type()) } pub fn add_property( @@ -76,30 +108,16 @@ impl DrmObjects { *to = from as c_char; } - let id = self.next_id; - self.objects.insert( - id, - DrmObject { - kind: DrmObjectKind::Property(DrmProperty { - name: name_bytes, - immutable, - atomic, - kind, - }), - properties: vec![], - }, - ); - self.next_id.0 += 1; - - id + self.add(DrmProperty { + name: name_bytes, + immutable, + atomic, + kind, + }) } pub fn get_property(&self, id: DrmObjectId) -> Result<&DrmProperty> { - let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; - match &object.kind { - DrmObjectKind::Property(drm_property) => Ok(drm_property), - _ => Err(Error::new(EINVAL)), - } + self.get(id) } pub fn add_object_property(&mut self, object: DrmObjectId, property: DrmObjectId, value: u64) { @@ -124,62 +142,35 @@ impl DrmObjects { } pub fn add_blob(&mut self, data: Vec) -> DrmObjectId { - let id = self.next_id; - self.objects.insert( - id, - DrmObject { - kind: DrmObjectKind::Blob(data), - properties: vec![], - }, - ); - self.next_id.0 += 1; - - id + self.add(DrmBlob { data }) } pub fn get_blob(&self, id: DrmObjectId) -> Result<&[u8]> { - let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; - match &object.kind { - DrmObjectKind::Blob(data) => Ok(data), - _ => Err(Error::new(EINVAL)), - } + Ok(&self.get::(id)?.data) } pub fn add_connector(&mut self, driver_data: T::Connector) -> DrmObjectId { - let connector_id = self.next_id; - let encoder_id = DrmObjectId(self.next_id.0 + 1); - self.objects.insert( - connector_id, - DrmObject { - kind: DrmObjectKind::Connector(DrmConnector { - modes: vec![], - encoder_id, - connector_type: 0, - connector_type_id: 0, - connection: DrmConnectorStatus::Unknown, - mm_width: 0, - mm_height: 0, - subpixel: DrmSubpixelOrder::Unknown, - driver_data, - }), - properties: vec![], - }, - ); + let connector_id = self.add(DrmConnector { + modes: vec![], + encoder_id: DrmObjectId::INVALID, + connector_type: 0, + connector_type_id: 0, + connection: DrmConnectorStatus::Unknown, + mm_width: 0, + mm_height: 0, + subpixel: DrmSubpixelOrder::Unknown, + driver_data, + }); self.connectors.push(connector_id); - self.objects.insert( - encoder_id, - DrmObject { - kind: DrmObjectKind::Encoder(DrmEncoder { - crtc_id: DrmObjectId::INVALID, - possible_crtcs: 0, - possible_clones: 0, - }), - properties: vec![], - }, - ); + let encoder_id = self.add(DrmEncoder { + crtc_id: DrmObjectId::INVALID, + possible_crtcs: 0, + possible_clones: 0, + }); self.encoders.push(encoder_id); - self.next_id.0 += 2; + + self.get_connector_mut(connector_id).unwrap().encoder_id = encoder_id; connector_id } @@ -188,29 +179,23 @@ impl DrmObjects { &self.connectors } - pub fn connectors(&self) -> impl Iterator> + use<'_, T> { - self.connectors - .iter() - .map(|&id| match &self.objects[&id].kind { - DrmObjectKind::Connector(connector) => connector, - _ => unreachable!(), - }) + pub fn connectors(&self) -> impl Iterator> + use<'_, T> { + self.connectors.iter().map(|&id| { + (&self.objects[&id].kind as &dyn Any) + .downcast_ref::>() + .unwrap() + }) } - pub fn get_connector(&self, id: DrmObjectId) -> Result<&DrmConnector> { - let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; - match &object.kind { - DrmObjectKind::Connector(drm_connector) => Ok(drm_connector), - _ => Err(Error::new(EINVAL)), - } + pub fn get_connector(&self, id: DrmObjectId) -> Result<&DrmConnector> { + self.get(id) } - pub fn get_connector_mut(&mut self, id: DrmObjectId) -> Result<&mut DrmConnector> { - let object = self.objects.get_mut(&id).ok_or(Error::new(EINVAL))?; - match &mut object.kind { - DrmObjectKind::Connector(drm_connector) => Ok(drm_connector), - _ => Err(Error::new(EINVAL)), - } + pub fn get_connector_mut( + &mut self, + id: DrmObjectId, + ) -> Result<&mut DrmConnector> { + self.get_mut(id) } pub fn encoder_ids(&self) -> &[DrmObjectId] { @@ -218,19 +203,11 @@ impl DrmObjects { } pub fn get_encoder(&self, id: DrmObjectId) -> Result<&DrmEncoder> { - let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; - match &object.kind { - DrmObjectKind::Encoder(drm_encoder) => Ok(drm_encoder), - _ => Err(Error::new(EINVAL)), - } + self.get(id) } pub fn get_encoder_mut(&mut self, id: DrmObjectId) -> Result<&mut DrmEncoder> { - let object = self.objects.get_mut(&id).ok_or(Error::new(EINVAL))?; - match &mut object.kind { - DrmObjectKind::Encoder(drm_encoder) => Ok(drm_encoder), - _ => Err(Error::new(EINVAL)), - } + self.get_mut(id) } } @@ -248,17 +225,13 @@ impl From for u64 { } #[derive(Debug)] -struct DrmObject { - kind: DrmObjectKind, +struct DrmObjectData { + kind: Box, properties: Vec<(DrmObjectId, u64)>, } -#[derive(Debug)] -enum DrmObjectKind { - Property(DrmProperty), - Blob(Vec), - Connector(DrmConnector), - Encoder(DrmEncoder), +pub trait DrmObject: Any + Debug { + fn object_type(&self) -> u32; } #[derive(Debug)] @@ -279,8 +252,25 @@ pub enum DrmPropertyKind { SignedRange(i64, i64), } +impl DrmObject for DrmProperty { + fn object_type(&self) -> u32 { + DRM_MODE_OBJECT_PROPERTY + } +} + #[derive(Debug)] -pub struct DrmConnector { +pub struct DrmBlob { + data: Vec, +} + +impl DrmObject for DrmBlob { + fn object_type(&self) -> u32 { + DRM_MODE_OBJECT_BLOB + } +} + +#[derive(Debug)] +pub struct DrmConnector { pub modes: Vec, pub encoder_id: DrmObjectId, pub connector_type: u32, @@ -289,7 +279,7 @@ pub struct DrmConnector { pub mm_width: u32, pub mm_height: u32, pub subpixel: DrmSubpixelOrder, - pub driver_data: T::Connector, + pub driver_data: T, } #[derive(Debug, Copy, Clone)] @@ -311,6 +301,12 @@ pub enum DrmSubpixelOrder { None, } +impl DrmObject for DrmConnector { + fn object_type(&self) -> u32 { + DRM_MODE_OBJECT_CONNECTOR + } +} + // FIXME can we represent connector and encoder using a single struct? #[derive(Debug)] pub struct DrmEncoder { @@ -318,3 +314,9 @@ pub struct DrmEncoder { pub possible_crtcs: u32, pub possible_clones: u32, } + +impl DrmObject for DrmEncoder { + fn object_type(&self) -> u32 { + DRM_MODE_OBJECT_ENCODER + } +}