drivers/graphics: Introduce DrmObject trait to reduce code duplication
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<T: GraphicsAdapter> {
|
||||
next_id: DrmObjectId,
|
||||
connectors: Vec<DrmObjectId>,
|
||||
encoders: Vec<DrmObjectId>,
|
||||
objects: HashMap<DrmObjectId, DrmObject<T>>,
|
||||
objects: HashMap<DrmObjectId, DrmObjectData>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
@@ -24,17 +28,45 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
connectors: vec![],
|
||||
encoders: vec![],
|
||||
objects: HashMap::new(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn add<U: DrmObject>(&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<U: DrmObject>(&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::<U>() {
|
||||
Ok(object)
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut<U: DrmObject>(&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::<U>() {
|
||||
Ok(object)
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn object_type(&self, id: DrmObjectId) -> Result<u32> {
|
||||
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<T: GraphicsAdapter> DrmObjects<T> {
|
||||
*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<T: GraphicsAdapter> DrmObjects<T> {
|
||||
}
|
||||
|
||||
pub fn add_blob(&mut self, data: Vec<u8>) -> 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::<DrmBlob>(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<T: GraphicsAdapter> DrmObjects<T> {
|
||||
&self.connectors
|
||||
}
|
||||
|
||||
pub fn connectors(&self) -> impl Iterator<Item = &DrmConnector<T>> + use<'_, T> {
|
||||
self.connectors
|
||||
.iter()
|
||||
.map(|&id| match &self.objects[&id].kind {
|
||||
DrmObjectKind::Connector(connector) => connector,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
pub fn connectors(&self) -> impl Iterator<Item = &DrmConnector<T::Connector>> + use<'_, T> {
|
||||
self.connectors.iter().map(|&id| {
|
||||
(&self.objects[&id].kind as &dyn Any)
|
||||
.downcast_ref::<DrmConnector<T::Connector>>()
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_connector(&self, id: DrmObjectId) -> Result<&DrmConnector<T>> {
|
||||
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<T::Connector>> {
|
||||
self.get(id)
|
||||
}
|
||||
|
||||
pub fn get_connector_mut(&mut self, id: DrmObjectId) -> Result<&mut DrmConnector<T>> {
|
||||
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<T::Connector>> {
|
||||
self.get_mut(id)
|
||||
}
|
||||
|
||||
pub fn encoder_ids(&self) -> &[DrmObjectId] {
|
||||
@@ -218,19 +203,11 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
}
|
||||
|
||||
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<DrmObjectId> for u64 {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DrmObject<T: GraphicsAdapter> {
|
||||
kind: DrmObjectKind<T>,
|
||||
struct DrmObjectData {
|
||||
kind: Box<dyn DrmObject + 'static>,
|
||||
properties: Vec<(DrmObjectId, u64)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum DrmObjectKind<T: GraphicsAdapter> {
|
||||
Property(DrmProperty),
|
||||
Blob(Vec<u8>),
|
||||
Connector(DrmConnector<T>),
|
||||
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<T: GraphicsAdapter> {
|
||||
pub struct DrmBlob {
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl DrmObject for DrmBlob {
|
||||
fn object_type(&self) -> u32 {
|
||||
DRM_MODE_OBJECT_BLOB
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DrmConnector<T: Debug + 'static> {
|
||||
pub modes: Vec<drm_mode_modeinfo>,
|
||||
pub encoder_id: DrmObjectId,
|
||||
pub connector_type: u32,
|
||||
@@ -289,7 +279,7 @@ pub struct DrmConnector<T: GraphicsAdapter> {
|
||||
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<T: Debug + 'static> DrmObject for DrmConnector<T> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user