drivers/graphics: Introduce CRTC objects

Currently still read-only.
This commit is contained in:
bjorn3
2025-12-20 16:29:26 +01:00
parent fdb4d45e72
commit 63ca9efb8c
6 changed files with 156 additions and 35 deletions
@@ -9,10 +9,19 @@ use crate::kms::objects::{KmsObjectId, KmsObjects};
use crate::GraphicsAdapter;
impl<T: GraphicsAdapter> KmsObjects<T> {
pub fn add_connector(&mut self, driver_data: T::Connector) -> KmsObjectId {
pub fn add_connector(
&mut self,
driver_data: T::Connector,
crtcs: &[KmsObjectId],
) -> KmsObjectId {
let mut possible_crtcs = 0;
for &crtc in crtcs {
possible_crtcs = 1 << self.get_crtc(crtc).unwrap().lock().unwrap().crtc_index;
}
let encoder_id = self.add(KmsEncoder {
crtc_id: KmsObjectId::INVALID,
possible_crtcs: 0,
possible_crtcs: possible_crtcs,
possible_clones: 1 << self.encoders.len(),
});
self.encoders.push(encoder_id);
@@ -118,7 +127,7 @@ impl<T: Debug> KmsConnector<T> {
// FIXME update the EDID property
}
fn modeinfo_for_size(width: u32, height: u32) -> drm_mode_modeinfo {
pub(crate) fn modeinfo_for_size(width: u32, height: u32) -> drm_mode_modeinfo {
let mut modeinfo = drm_mode_modeinfo {
// The actual visible display size
hdisplay: width as u16,
@@ -4,8 +4,8 @@ use std::marker::PhantomData;
use std::sync::{Arc, Mutex};
use drm_sys::{
DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_ENCODER,
DRM_MODE_OBJECT_PROPERTY,
drm_mode_modeinfo, DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC,
DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_PROPERTY,
};
use syscall::{Error, Result, EINVAL};
@@ -18,6 +18,7 @@ pub struct KmsObjects<T: GraphicsAdapter> {
next_id: KmsObjectId,
pub(crate) connectors: Vec<KmsObjectId>,
pub(crate) encoders: Vec<KmsObjectId>,
crtcs: Vec<KmsObjectId>,
pub(crate) objects: HashMap<KmsObjectId, Arc<KmsObjectData<T>>>,
_marker: PhantomData<T>,
}
@@ -28,6 +29,7 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
next_id: KmsObjectId(1),
connectors: vec![],
encoders: vec![],
crtcs: vec![],
objects: HashMap::new(),
_marker: PhantomData,
}
@@ -63,6 +65,34 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?;
Ok(object.kind.object_type())
}
pub fn add_crtc(&mut self, driver_data: T::Crtc) -> KmsObjectId {
let crtc_index = self.crtcs.len() as u32;
let id = self.add(Mutex::new(KmsCrtc {
crtc_index,
fb_id: KmsObjectId::INVALID,
gamma_size: 0,
mode: None,
driver_data,
}));
self.crtcs.push(id);
id
}
pub fn crtc_ids(&self) -> &[KmsObjectId] {
&self.crtcs
}
pub fn crtcs(&self) -> impl Iterator<Item = &Mutex<KmsCrtc<T::Crtc>>> + use<'_, T> {
self.crtcs
.iter()
.map(|&id| self.get::<Mutex<KmsCrtc<T::Crtc>>>(id).unwrap())
}
pub fn get_crtc(&self, id: KmsObjectId) -> Result<&Mutex<KmsCrtc<T::Crtc>>> {
self.get(id)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -124,8 +154,18 @@ macro_rules! define_object_kinds {
}
define_object_kinds! { <T>
Crtc(Mutex<KmsCrtc<T::Crtc>>) = DRM_MODE_OBJECT_CRTC,
Connector(Mutex<KmsConnector<T::Connector>>) = DRM_MODE_OBJECT_CONNECTOR,
Encoder(KmsEncoder) = DRM_MODE_OBJECT_ENCODER,
Property(KmsProperty) = DRM_MODE_OBJECT_PROPERTY,
Blob(KmsBlob) = DRM_MODE_OBJECT_BLOB,
}
#[derive(Debug)]
pub struct KmsCrtc<T> {
pub crtc_index: u32,
pub fb_id: KmsObjectId,
pub gamma_size: u32,
pub mode: Option<drm_mode_modeinfo>,
pub driver_data: T,
}
+44 -19
View File
@@ -11,10 +11,10 @@ use std::os::fd::BorrowedFd;
use std::sync::Arc;
use drm_sys::{
drm_mode_property_enum, 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,
drm_mode_modeinfo, drm_mode_property_enum, 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,
};
use graphics_ipc::v2::Damage;
use inputd::{DisplayHandle, VtEventKind};
@@ -24,6 +24,7 @@ use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket};
use syscall::schemev2::NewFdFlags;
use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP};
use crate::kms::connector::KmsConnector;
use crate::kms::objects::{KmsObjectId, KmsObjects};
use crate::kms::properties::KmsPropertyKind;
@@ -37,6 +38,7 @@ pub struct StandardProperties {
pub trait GraphicsAdapter: Sized + Debug {
type Connector: Debug;
type Crtc: Debug;
type Buffer: Buffer;
@@ -66,7 +68,9 @@ pub trait GraphicsAdapter: Sized + Debug {
fn update_plane(
&mut self,
objects: &KmsObjects<Self>,
display_id: usize,
mode: Option<drm_mode_modeinfo>,
framebuffer: Option<&Self::Buffer>,
damage: Damage,
);
@@ -217,8 +221,14 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
);
for (display_id, fb) in vt_state.display_fbs.iter().enumerate() {
let mode = fb.as_ref().map(|fb| {
KmsConnector::<()>::modeinfo_for_size(fb.width(), fb.height())
});
self.inner.adapter.update_plane(
&self.inner.objects,
display_id,
mode,
fb.as_deref(),
Damage {
x: 0,
@@ -495,10 +505,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
id & 0xFF
}
fn crtc_id(i: u32) -> u32 {
id_index(i) | (1 << 10)
}
fn fb_id(i: u32) -> u32 {
id_index(i) | (1 << 11)
}
@@ -556,7 +562,12 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
.iter()
.map(|id| id.0)
.collect::<Vec<_>>();
let mut crtc_ids = Vec::with_capacity(count);
let crtc_ids = self
.objects
.crtc_ids()
.iter()
.map(|id| id.0)
.collect::<Vec<_>>();
let enc_ids = self
.objects
.encoder_ids()
@@ -565,7 +576,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
.collect::<Vec<_>>();
let mut fb_ids = Vec::with_capacity(count);
for i in 0..(count as u32) {
crtc_ids.push(crtc_id(i));
fb_ids.push(fb_id(i));
}
data.set_fb_id_ptr(&fb_ids);
@@ -579,15 +589,24 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Ok(0)
}),
ipc::MODE_GET_CRTC => ipc::DrmModeCrtc::with(payload, |mut data| {
let i = id_index(data.crtc_id());
//TOOD: connectors
data.set_fb_id(fb_id(i));
let crtc = self
.objects
.get_crtc(KmsObjectId(data.crtc_id()))?
.lock()
.unwrap();
// Don't touch set_connectors, that is only used by MODE_SET_CRTC
data.set_fb_id(crtc.fb_id.0);
// FIXME fill x and y with the data from the primary plane
data.set_x(0);
data.set_y(0);
data.set_gamma_size(0);
data.set_mode_valid(0);
//TODO: mode
data.set_mode(Default::default());
data.set_gamma_size(crtc.gamma_size);
if let Some(mode) = crtc.mode {
data.set_mode_valid(1);
data.set_mode(mode);
} else {
data.set_mode_valid(0);
data.set_mode(Default::default());
}
Ok(0)
}),
ipc::MODE_GET_ENCODER => ipc::DrmModeGetEncoder::with(payload, |mut data| {
@@ -785,7 +804,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
}),
ipc::MODE_GET_PLANE => ipc::DrmModeGetPlane::with(payload, |mut data| {
let i = id_index(data.plane_id());
data.set_crtc_id(crtc_id(i));
data.set_crtc_id(self.objects.crtc_ids()[i as usize].0);
data.set_fb_id(fb_id(i));
data.set_possible_crtcs(1 << i);
data.set_format_type_ptr(&[DRM_FORMAT_ARGB8888]);
@@ -794,7 +813,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
ipc::MODE_OBJ_GET_PROPERTIES => {
ipc::DrmModeObjGetProperties::with(payload, |mut data| {
// FIXME remove once all drm objects are materialized in self.objects
if data.obj_id() >= 1 << 10 {
if data.obj_id() >= 1 << 11 {
data.set_props_ptr(&[]);
data.set_prop_values_ptr(&[]);
return Ok(0);
@@ -852,8 +871,14 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
framebuffer.map(Arc::clone);
if *vt == self.active_vt {
let mode = framebuffer.as_ref().map(|fb| {
KmsConnector::<()>::modeinfo_for_size(fb.width(), fb.height())
});
self.adapter.update_plane(
&self.objects,
display_id,
mode,
framebuffer.map(|fb| &**fb),
payload.damage,
);
+19 -3
View File
@@ -7,7 +7,7 @@ use std::ptr::{self, NonNull};
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{KmsObjectId, KmsObjects};
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties};
use drm_sys::DRM_MODE_DPMS_ON;
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;
use syscall::{error::EINVAL, PAGE_SIZE};
@@ -21,6 +21,7 @@ pub struct Connector {
impl GraphicsAdapter for Device {
type Connector = Connector;
type Crtc = ();
type Buffer = DumbFb;
@@ -35,7 +36,9 @@ impl GraphicsAdapter for Device {
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
// FIXME enumerate actual connectors
for (framebuffer_id, _) in self.framebuffers.iter().enumerate() {
let connector = objects.add_connector(Connector { framebuffer_id });
let crtc = objects.add_crtc(());
let connector = objects.add_connector(Connector { framebuffer_id }, &[crtc]);
objects.add_object_property(
connector,
standard_properties.dpms,
@@ -91,7 +94,20 @@ impl GraphicsAdapter for Device {
framebuffer.ptr.as_ptr().cast::<u8>()
}
fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) {
fn update_plane(
&mut self,
objects: &KmsObjects<Self>,
display_id: usize,
mode: Option<drm_mode_modeinfo>,
buffer: Option<&Self::Buffer>,
damage: Damage,
) {
objects
.get_crtc(objects.crtc_ids()[display_id])
.unwrap()
.lock()
.unwrap()
.mode = mode;
let framebuffer = &mut self.framebuffers[display_id];
if let Some(buffer) = buffer {
buffer.sync(framebuffer, damage)
+25 -6
View File
@@ -5,7 +5,7 @@ use std::ptr::{self, NonNull};
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{KmsObjectId, KmsObjects};
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties};
use drm_sys::DRM_MODE_DPMS_ON;
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;
use syscall::{EINVAL, PAGE_SIZE};
@@ -23,6 +23,7 @@ pub struct Connector {
impl GraphicsAdapter for FbAdapter {
type Connector = Connector;
type Crtc = ();
type Buffer = GraphicScreen;
@@ -36,10 +37,15 @@ impl GraphicsAdapter for FbAdapter {
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
for framebuffer in &self.framebuffers {
let connector = objects.add_connector(Connector {
width: framebuffer.width as u32,
height: framebuffer.height as u32,
});
let crtc = objects.add_crtc(());
let connector = objects.add_connector(
Connector {
width: framebuffer.width as u32,
height: framebuffer.height as u32,
},
&[crtc],
);
objects.add_object_property(
connector,
standard_properties.dpms,
@@ -93,7 +99,20 @@ impl GraphicsAdapter for FbAdapter {
framebuffer.ptr.as_ptr().cast::<u8>()
}
fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) {
fn update_plane(
&mut self,
objects: &KmsObjects<Self>,
display_id: usize,
mode: Option<drm_mode_modeinfo>,
buffer: Option<&Self::Buffer>,
damage: Damage,
) {
objects
.get_crtc(objects.crtc_ids()[display_id])
.unwrap()
.lock()
.unwrap()
.mode = mode;
let framebuffer = &mut self.framebuffers[display_id];
if let Some(buffer) = buffer {
buffer.sync(framebuffer, damage)
+14 -2
View File
@@ -7,7 +7,7 @@ use driver_graphics::kms::objects::{KmsObjectId, KmsObjects};
use driver_graphics::{
Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, StandardProperties,
};
use drm_sys::{DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON};
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;
@@ -266,6 +266,7 @@ impl VirtGpuAdapter<'_> {
impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
type Connector = VirtGpuConnector;
type Crtc = ();
type Buffer = VirtGpuFramebuffer<'a>;
@@ -283,7 +284,9 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
});
for display_id in 0..self.config.num_scanouts.get() {
let connector = objects.add_connector(VirtGpuConnector { display_id });
let crtc = objects.add_crtc(());
let connector = objects.add_connector(VirtGpuConnector { display_id }, &[crtc]);
if self.has_edid {
objects.add_object_property(connector, standard_properties.edid, 0);
}
@@ -417,11 +420,20 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
fn update_plane(
&mut self,
objects: &KmsObjects<Self>,
display_id: usize,
mode: Option<drm_mode_modeinfo>,
framebuffer: Option<&Self::Buffer>,
damage: Damage,
) {
futures::executor::block_on(async {
objects
.get_crtc(objects.crtc_ids()[display_id])
.unwrap()
.lock()
.unwrap()
.mode = mode;
let Some(framebuffer) = framebuffer else {
let scanout_request = Dma::new(SetScanout::new(
display_id as u32,