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:
bjorn3
2026-03-13 22:22:11 +01:00
parent 901ec180a7
commit f6a7c194b2
7 changed files with 39 additions and 36 deletions
@@ -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
}
+9 -3
View File
@@ -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)
}
+1 -1
View File
@@ -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);
+2 -1
View File
@@ -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);
}
+3 -1
View File
@@ -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 {