drivers/graphics: Nicer way to define standard properties

All standard properties are now pre-allocated at KmsObjects creation and
given a fixed object id.
This commit is contained in:
bjorn3
2026-03-15 12:24:48 +01:00
parent be6ae85541
commit d7974b3143
7 changed files with 109 additions and 91 deletions
@@ -10,7 +10,7 @@ use drm_sys::{
use syscall::{Error, Result, EINVAL};
use crate::kms::connector::{KmsConnector, KmsEncoder};
use crate::kms::properties::{KmsBlob, KmsProperty};
use crate::kms::properties::{init_standard_props, KmsBlob, KmsProperty};
use crate::GraphicsAdapter;
#[derive(Debug)]
@@ -26,7 +26,7 @@ pub struct KmsObjects<T: GraphicsAdapter> {
impl<T: GraphicsAdapter> KmsObjects<T> {
pub(crate) fn new() -> Self {
KmsObjects {
let mut objects = KmsObjects {
next_id: KmsObjectId(1),
connectors: vec![],
encoders: vec![],
@@ -34,7 +34,9 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
framebuffers: vec![],
objects: HashMap::new(),
_marker: PhantomData,
}
};
init_standard_props(&mut objects);
objects
}
pub(crate) fn add<U: Into<KmsObjectKind<T>>>(&mut self, data: U) -> KmsObjectId {
@@ -2,7 +2,10 @@ use std::ffi::c_char;
use std::fmt::Debug;
use std::sync::Mutex;
use drm_sys::DRM_PROP_NAME_LEN;
use drm_sys::{
DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND,
DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_PRIMARY, DRM_PROP_NAME_LEN,
};
use syscall::{Error, Result, EINVAL};
use crate::kms::objects::{KmsObjectId, KmsObjects};
@@ -115,3 +118,78 @@ pub enum KmsPropertyKind {
pub struct KmsBlob {
data: Vec<u8>,
}
macro_rules! define_properties {
($($prop:ident $($prop_name:literal)?: $prop_type:ident $({$($prop_content:tt)*})? [$($prop_flag:ident)?],)*) => {
$(#[allow(non_upper_case_globals)] pub const $prop: KmsObjectId = KmsObjectId(1 + ${index()});)*
pub(super) fn init_standard_props<T: GraphicsAdapter>(objects: &mut KmsObjects<T>) {
$(
assert_eq!(objects.add_property(
define_properties!(@prop_name $prop $($prop_name)?),
define_properties!(@is_immutable $($prop_flag)?),
define_properties!(@is_atomic $($prop_flag)?),
define_properties!(@prop_kind $prop_type $({$($prop_content)*})?),
), $prop);
)*
}
};
(@prop_name $prop:ident $prop_name:literal) => { $prop_name };
(@prop_name $prop:ident) => { stringify!($prop) };
(@is_immutable) => { false };
(@is_immutable immutable) => { true };
(@is_immutable atomic) => { false };
(@is_atomic) => { false };
(@is_atomic immutable) => { false };
(@is_atomic atomic) => { true };
(@prop_kind range { $start:expr, $end:expr }) => {
KmsPropertyKind::Range($start, $end)
};
(@prop_kind enum { $($variant:ident = $value:expr,)* }) => {
KmsPropertyKind::Enum(vec![$((stringify!($variant), $value)),*])
};
(@prop_kind blob) => {
KmsPropertyKind::Blob
};
(@prop_kind object) => {
KmsPropertyKind::Object
};
(@prop_kind srange { $start:expr, $end:expr }) => {
KmsPropertyKind::SignedRange($start, $end)
};
}
define_properties! {
// Connector + Plane
CRTC_ID: object [atomic],
// Connector
EDID: blob [immutable],
DPMS: enum {
On = u64::from(DRM_MODE_DPMS_ON),
Standby = u64::from(DRM_MODE_DPMS_STANDBY),
Suspend = u64::from(DRM_MODE_DPMS_SUSPEND),
Off = u64::from(DRM_MODE_DPMS_OFF),
} [],
// CRTC
ACTIVE: range { 0,1 } [atomic],
MODE_ID: blob [atomic],
// Plane
type_ "type": enum {
Overlay = u64::from(DRM_PLANE_TYPE_OVERLAY),
Primary = u64::from(DRM_PLANE_TYPE_PRIMARY),
Cursor = u64::from(DRM_PLANE_TYPE_CURSOR),
} [immutable],
FB_ID: object [atomic],
CRTC_X: srange { i64::from(i32::MIN), i64::from(i32::MAX) } [atomic],
CRTC_Y: srange { i64::from(i32::MIN), i64::from(i32::MAX) } [atomic],
CRTC_W: range { 0, u64::from(u32::MAX) } [atomic],
CRTC_H: range { 0, u64::from(u32::MAX) } [atomic],
SRC_X: range { 0, u64::from(u32::MAX) } [atomic],
SRC_Y: range { 0, u64::from(u32::MAX) } [atomic],
SRC_W: range { 0, u64::from(u32::MAX) } [atomic],
SRC_H: range { 0, u64::from(u32::MAX) } [atomic],
FB_DAMAGE_CLIPS: blob [atomic],
}
+7 -42
View File
@@ -1,3 +1,4 @@
#![feature(macro_metavar_expr)]
#![feature(slice_as_array)]
use std::collections::{BTreeMap, HashMap};
@@ -12,7 +13,6 @@ use std::sync::{Arc, Mutex};
use drm_sys::{
drm_mode_modeinfo, drm_mode_property_enum, DRM_MODE_CURSOR_BO, DRM_MODE_CURSOR_MOVE,
DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND,
DRM_MODE_PROP_ATOMIC, DRM_MODE_PROP_BITMASK, DRM_MODE_PROP_BLOB, DRM_MODE_PROP_ENUM,
DRM_MODE_PROP_IMMUTABLE, DRM_MODE_PROP_OBJECT, DRM_MODE_PROP_RANGE, DRM_MODE_PROP_SIGNED_RANGE,
DRM_PROP_NAME_LEN,
@@ -31,12 +31,6 @@ use crate::kms::properties::KmsPropertyKind;
pub mod kms;
#[derive(Debug, Copy, Clone)]
pub struct StandardProperties {
pub edid: KmsObjectId,
pub dpms: KmsObjectId,
}
pub trait GraphicsAdapter: Sized + Debug {
type Connector: Debug;
type Crtc: Debug;
@@ -47,17 +41,12 @@ pub trait GraphicsAdapter: Sized + Debug {
fn name(&self) -> &'static [u8];
fn desc(&self) -> &'static [u8];
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties);
fn init(&mut self, objects: &mut KmsObjects<Self>);
fn get_cap(&self, cap: u32) -> Result<u64>;
fn set_client_cap(&self, cap: u32, value: u64) -> Result<()>;
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
standard_properties: &StandardProperties,
id: KmsObjectId,
);
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId);
/// The maximum amount of displays that could be attached.
///
@@ -118,24 +107,9 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
);
let mut objects = KmsObjects::new();
let edid = objects.add_property("EDID", true, false, KmsPropertyKind::Blob);
let dpms = objects.add_property(
"DPMS",
false,
false,
KmsPropertyKind::Enum(vec![
("On", DRM_MODE_DPMS_ON.into()),
("Standby", DRM_MODE_DPMS_STANDBY.into()),
("Suspend", DRM_MODE_DPMS_SUSPEND.into()),
("Off", DRM_MODE_DPMS_OFF.into()),
]),
);
let standard_properties = StandardProperties { edid, dpms };
adapter.init(&mut objects, &standard_properties);
adapter.init(&mut objects);
for connector_id in objects.connector_ids().to_vec() {
adapter.probe_connector(&mut objects, &standard_properties, connector_id)
adapter.probe_connector(&mut objects, connector_id)
}
let mut inner = GraphicsSchemeInner {
@@ -144,7 +118,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
disable_graphical_debug,
socket,
objects,
standard_properties,
next_id: 0,
handles: BTreeMap::new(),
active_vt: 0,
@@ -196,10 +169,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
(&mut self.inner.adapter, &mut self.inner.objects)
}
pub fn standard_properties(&self) -> StandardProperties {
self.inner.standard_properties
}
pub fn handle_vt_events(&mut self) {
while let Some(vt_event) = self
.inputd_handle
@@ -318,7 +287,6 @@ struct GraphicsSchemeInner<T: GraphicsAdapter> {
disable_graphical_debug: Option<File>,
socket: Socket,
objects: KmsObjects<T>,
standard_properties: StandardProperties,
next_id: usize,
handles: BTreeMap<usize, Handle<T>>,
@@ -599,11 +567,8 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
}),
ipc::MODE_GET_CONNECTOR => ipc::DrmModeGetConnector::with(payload, |mut data| {
if data.count_modes() == 0 {
self.adapter.probe_connector(
&mut self.objects,
&self.standard_properties,
KmsObjectId(data.connector_id()),
);
self.adapter
.probe_connector(&mut self.objects, KmsObjectId(data.connector_id()));
}
let connector = self
.objects
+5 -13
View File
@@ -7,7 +7,8 @@ use std::sync::Mutex;
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties};
use driver_graphics::kms::properties::DPMS;
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter};
use drm_sys::{drm_mode_modeinfo, DRM_MODE_DPMS_ON};
use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT};
use graphics_ipc::v2::Damage;
@@ -35,17 +36,13 @@ impl GraphicsAdapter for Device {
b"Intel HD Graphics"
}
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
fn init(&mut self, objects: &mut KmsObjects<Self>) {
// FIXME enumerate actual connectors
for (framebuffer_id, _) in self.framebuffers.iter().enumerate() {
let crtc = objects.add_crtc(());
let connector = objects.add_connector(Connector { framebuffer_id }, &[crtc]);
objects.add_object_property(
connector,
standard_properties.dpms,
DRM_MODE_DPMS_ON.into(),
);
objects.add_object_property(connector, DPMS, DRM_MODE_DPMS_ON.into());
}
}
@@ -64,12 +61,7 @@ impl GraphicsAdapter for Device {
}
}
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
_standard_properties: &StandardProperties,
id: KmsObjectId,
) {
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId) {
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id];
connector.connection = KmsConnectorStatus::Connected;
+5 -13
View File
@@ -5,7 +5,8 @@ use std::sync::Mutex;
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties};
use driver_graphics::kms::properties::DPMS;
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter};
use drm_sys::{drm_mode_modeinfo, DRM_MODE_DPMS_ON};
use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT};
use graphics_ipc::v2::Damage;
@@ -38,7 +39,7 @@ impl GraphicsAdapter for FbAdapter {
b"VESA"
}
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
fn init(&mut self, objects: &mut KmsObjects<Self>) {
for (framebuffer_id, framebuffer) in self.framebuffers.iter().enumerate() {
let crtc = objects.add_crtc(());
@@ -50,11 +51,7 @@ impl GraphicsAdapter for FbAdapter {
},
&[crtc],
);
objects.add_object_property(
connector,
standard_properties.dpms,
DRM_MODE_DPMS_ON.into(),
);
objects.add_object_property(connector, DPMS, DRM_MODE_DPMS_ON.into());
}
}
@@ -72,12 +69,7 @@ impl GraphicsAdapter for FbAdapter {
}
}
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
_standard_properties: &StandardProperties,
id: KmsObjectId,
) {
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId) {
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
let connector = &mut *connector;
connector.connection = KmsConnectorStatus::Connected;
+1 -2
View File
@@ -586,11 +586,10 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow:
let events = scheme.adapter().config.events_read.get();
if events & VIRTIO_GPU_EVENT_DISPLAY != 0 {
let standard_properties = scheme.standard_properties();
let (adapter, objects) = scheme.adapter_and_kms_objects_mut();
futures::executor::block_on(async { adapter.update_displays().await.unwrap() });
for connector_id in objects.connector_ids().to_vec() {
adapter.probe_connector(objects, &standard_properties, connector_id);
adapter.probe_connector(objects, connector_id);
}
scheme.notify_displays_changed();
scheme
+7 -17
View File
@@ -4,9 +4,8 @@ use std::sync::{Arc, Mutex};
use common::{dma::Dma, sgl};
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::{
Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, StandardProperties,
};
use driver_graphics::kms::properties::{DPMS, EDID};
use driver_graphics::{Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme};
use drm_sys::{drm_mode_modeinfo, DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON};
use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT};
use graphics_ipc::v2::Damage;
@@ -279,7 +278,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
b"VirtIO GPU"
}
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
fn init(&mut self, objects: &mut KmsObjects<Self>) {
futures::executor::block_on(async {
self.update_displays().await.unwrap();
});
@@ -289,13 +288,9 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
let connector = objects.add_connector(VirtGpuConnector { display_id }, &[crtc]);
if self.has_edid {
objects.add_object_property(connector, standard_properties.edid, 0);
objects.add_object_property(connector, EDID, 0);
}
objects.add_object_property(
connector,
standard_properties.dpms,
DRM_MODE_DPMS_ON.into(),
);
objects.add_object_property(connector, DPMS, DRM_MODE_DPMS_ON.into());
}
}
@@ -316,12 +311,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
}
}
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
standard_properties: &StandardProperties,
id: KmsObjectId,
) {
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId) {
futures::executor::block_on(async {
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
let display = &self.displays[connector.driver_data.display_id as usize];
@@ -338,7 +328,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
drop(connector);
let blob = objects.add_blob(display.edid.clone());
objects.set_object_property(id, standard_properties.edid, blob.into());
objects.set_object_property(id, EDID, blob.into());
} else {
connector.update_from_size(display.width, display.height);
}