drivers/graphics: Refcount all DRM objects
This is necessary to be able to properly handle objects that reference each other and in doing so keep each other alive.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use std::ffi::c_char;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use drm_sys::{
|
||||
drm_mode_modeinfo, DRM_MODE_CONNECTOR_Unknown, DRM_MODE_OBJECT_CONNECTOR,
|
||||
@@ -19,7 +20,7 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
});
|
||||
self.encoders.push(encoder_id);
|
||||
|
||||
let connector_id = self.add(DrmConnector {
|
||||
let connector_id = self.add(Mutex::new(DrmConnector {
|
||||
encoder_id,
|
||||
modes: vec![],
|
||||
connector_type: DRM_MODE_CONNECTOR_Unknown,
|
||||
@@ -29,7 +30,7 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
mm_height: 0,
|
||||
subpixel: DrmSubpixelOrder::Unknown,
|
||||
driver_data,
|
||||
});
|
||||
}));
|
||||
self.connectors.push(connector_id);
|
||||
|
||||
connector_id
|
||||
@@ -39,21 +40,18 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
&self.connectors
|
||||
}
|
||||
|
||||
pub fn connectors(&self) -> impl Iterator<Item = &DrmConnector<T::Connector>> + use<'_, T> {
|
||||
self.connectors.iter().map(|&id| self.get(id).unwrap())
|
||||
pub fn connectors(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &Mutex<DrmConnector<T::Connector>>> + use<'_, T> {
|
||||
self.connectors
|
||||
.iter()
|
||||
.map(|&id| self.get_connector(id).unwrap())
|
||||
}
|
||||
|
||||
pub fn get_connector(&self, id: DrmObjectId) -> Result<&DrmConnector<T::Connector>> {
|
||||
pub fn get_connector(&self, id: DrmObjectId) -> Result<&Mutex<DrmConnector<T::Connector>>> {
|
||||
self.get(id)
|
||||
}
|
||||
|
||||
pub fn get_connector_mut(
|
||||
&mut self,
|
||||
id: DrmObjectId,
|
||||
) -> Result<&mut DrmConnector<T::Connector>> {
|
||||
self.get_mut(id)
|
||||
}
|
||||
|
||||
pub fn encoder_ids(&self) -> &[DrmObjectId] {
|
||||
&self.encoders
|
||||
}
|
||||
@@ -177,7 +175,7 @@ pub enum DrmSubpixelOrder {
|
||||
None,
|
||||
}
|
||||
|
||||
impl<T: Debug + 'static> DrmObject for DrmConnector<T> {
|
||||
impl<T: Debug + 'static> DrmObject for Mutex<DrmConnector<T>> {
|
||||
fn object_type(&self) -> u32 {
|
||||
DRM_MODE_OBJECT_CONNECTOR
|
||||
}
|
||||
|
||||
@@ -609,12 +609,16 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
|
||||
}
|
||||
let connector = self
|
||||
.objects
|
||||
.get_connector(DrmObjectId(data.connector_id()))?;
|
||||
.get_connector(DrmObjectId(data.connector_id()))?
|
||||
.lock()
|
||||
.unwrap();
|
||||
data.set_encoders_ptr(&[connector.encoder_id.0]);
|
||||
data.set_modes_ptr(&connector.modes);
|
||||
let props = self
|
||||
.objects
|
||||
.get_object_properties(DrmObjectId(data.connector_id()))?;
|
||||
.get_object_properties(DrmObjectId(data.connector_id()))?
|
||||
.lock()
|
||||
.unwrap();
|
||||
data.set_props_ptr(&props.iter().map(|&(id, _)| id.0).collect::<Vec<_>>());
|
||||
data.set_prop_values_ptr(
|
||||
&props.iter().map(|&(_, value)| value).collect::<Vec<_>>(),
|
||||
@@ -800,7 +804,9 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
|
||||
|
||||
let props = self
|
||||
.objects
|
||||
.get_object_properties(DrmObjectId(data.obj_id()))?;
|
||||
.get_object_properties(DrmObjectId(data.obj_id()))?
|
||||
.lock()
|
||||
.unwrap();
|
||||
data.set_props_ptr(&props.iter().map(|&(id, _)| id.0).collect::<Vec<_>>());
|
||||
data.set_prop_values_ptr(
|
||||
&props.iter().map(|&(_, value)| value).collect::<Vec<_>>(),
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use syscall::{Error, Result, EINVAL};
|
||||
|
||||
@@ -12,7 +13,7 @@ pub struct DrmObjects<T: GraphicsAdapter> {
|
||||
next_id: DrmObjectId,
|
||||
pub(crate) connectors: Vec<DrmObjectId>,
|
||||
pub(crate) encoders: Vec<DrmObjectId>,
|
||||
pub(crate) objects: HashMap<DrmObjectId, DrmObjectData>,
|
||||
pub(crate) objects: HashMap<DrmObjectId, Arc<DrmObjectData>>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -31,10 +32,10 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
let id = self.next_id;
|
||||
self.objects.insert(
|
||||
id,
|
||||
DrmObjectData {
|
||||
Arc::new(DrmObjectData {
|
||||
kind: Box::new(data),
|
||||
properties: vec![],
|
||||
},
|
||||
properties: Mutex::new(vec![]),
|
||||
}),
|
||||
);
|
||||
self.next_id.0 += 1;
|
||||
|
||||
@@ -50,15 +51,6 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) 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(object.kind.object_type())
|
||||
@@ -81,7 +73,7 @@ impl From<DrmObjectId> for u64 {
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DrmObjectData {
|
||||
kind: Box<dyn DrmObject + 'static>,
|
||||
pub(crate) properties: Vec<(DrmObjectId, u64)>,
|
||||
pub(crate) properties: Mutex<Vec<(DrmObjectId, u64)>>,
|
||||
}
|
||||
|
||||
pub trait DrmObject: Any + Debug {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ffi::c_char;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use drm_sys::{DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_PROPERTY, DRM_PROP_NAME_LEN};
|
||||
use syscall::{Error, Result, EINVAL};
|
||||
@@ -62,20 +63,23 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
pub fn add_object_property(&mut self, object: DrmObjectId, property: DrmObjectId, value: u64) {
|
||||
let object = self.objects.get_mut(&object).unwrap();
|
||||
// FIXME validate property uniqueness and value
|
||||
object.properties.push((property, value));
|
||||
object.properties.lock().unwrap().push((property, value));
|
||||
}
|
||||
|
||||
pub fn set_object_property(&mut self, object: DrmObjectId, property: DrmObjectId, value: u64) {
|
||||
let object = self.objects.get_mut(&object).unwrap();
|
||||
// FIXME validate property existence and value
|
||||
for (prop, val) in object.properties.iter_mut() {
|
||||
for (prop, val) in object.properties.lock().unwrap().iter_mut() {
|
||||
if *prop == property {
|
||||
*val = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_object_properties(&self, id: DrmObjectId) -> Result<&[(DrmObjectId, u64)]> {
|
||||
pub fn get_object_properties(
|
||||
&self,
|
||||
id: DrmObjectId,
|
||||
) -> Result<&Mutex<Vec<(DrmObjectId, u64)>>> {
|
||||
let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?;
|
||||
Ok(&object.properties)
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ impl GraphicsAdapter for Device {
|
||||
_standard_properties: &StandardProperties,
|
||||
id: DrmObjectId,
|
||||
) {
|
||||
let connector = objects.get_connector_mut(id).unwrap();
|
||||
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
|
||||
let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id];
|
||||
connector.connection = DrmConnectorStatus::Connected;
|
||||
connector.update_from_size(framebuffer.width as u32, framebuffer.height as u32);
|
||||
|
||||
@@ -68,7 +68,8 @@ impl GraphicsAdapter for FbAdapter {
|
||||
_standard_properties: &StandardProperties,
|
||||
id: DrmObjectId,
|
||||
) {
|
||||
let connector = objects.get_connector_mut(id).unwrap();
|
||||
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
|
||||
let connector = &mut *connector;
|
||||
connector.connection = DrmConnectorStatus::Connected;
|
||||
connector.update_from_size(connector.driver_data.width, connector.driver_data.height);
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
id: DrmObjectId,
|
||||
) {
|
||||
futures::executor::block_on(async {
|
||||
let connector = objects.get_connector_mut(id).unwrap();
|
||||
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
|
||||
let display = &self.displays[connector.driver_data.display_id as usize];
|
||||
|
||||
connector.connection = if display.enabled {
|
||||
@@ -320,6 +320,8 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
if self.has_edid {
|
||||
connector.update_from_edid(&display.edid);
|
||||
|
||||
drop(connector);
|
||||
|
||||
let blob = objects.add_blob(display.edid.clone());
|
||||
objects.set_object_property(id, standard_properties.edid, blob.into());
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user