drivers/graphics: Move connector<->crtc binding to KmsConnector

A connector can only get input from one CRTC and the CRTC_ID property is
on the connector. There is no CONNECTOR_IDS property on CRTCs.
This commit is contained in:
bjorn3
2026-03-19 23:25:37 +01:00
parent e49dc8e8be
commit 5b88dadc4f
7 changed files with 134 additions and 120 deletions
@@ -9,7 +9,7 @@ use drm_sys::{
use syscall::Result;
use crate::kms::objects::{KmsObjectId, KmsObjects};
use crate::kms::properties::{define_object_props, KmsPropertyData, DPMS, EDID};
use crate::kms::properties::{define_object_props, KmsPropertyData, CRTC_ID, DPMS, EDID};
use crate::GraphicsAdapter;
impl<T: GraphicsAdapter> KmsObjects<T> {
@@ -42,6 +42,7 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
properties: KmsConnector::base_properties(),
dpms: KmsDpms::Off,
edid: KmsObjectId::INVALID,
crtc_id: KmsObjectId::INVALID,
driver_data,
}));
self.connectors.push(connector_id);
@@ -87,6 +88,7 @@ pub struct KmsConnector<T> {
pub properties: Vec<KmsPropertyData<Self>>,
pub dpms: KmsDpms,
pub edid: KmsObjectId,
pub crtc_id: KmsObjectId,
pub driver_data: T,
}
@@ -97,6 +99,9 @@ define_object_props!(object, KmsConnector<T> {
DPMS {
get => object.dpms as u64,
}
CRTC_ID {
get => u64::from(object.crtc_id.0),
}
});
impl<T> KmsConnector<T> {
@@ -70,7 +70,6 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
let crtc_index = self.crtcs.len() as u32;
let id = self.add(Mutex::new(KmsCrtc {
crtc_index,
target_connectors: vec![],
fb_id: KmsObjectId::INVALID,
gamma_size: 0,
mode: None,
@@ -192,8 +191,6 @@ define_object_kinds! { <T>
#[derive(Debug)]
pub struct KmsCrtc<T> {
pub crtc_index: u32,
// FIXME maybe have this on connector instead?
pub target_connectors: Vec<KmsObjectId>,
pub fb_id: KmsObjectId,
pub gamma_size: u32,
pub mode: Option<drm_mode_modeinfo>,
@@ -4,7 +4,8 @@ use std::mem;
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,
DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_FB, DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY,
DRM_PLANE_TYPE_PRIMARY, DRM_PROP_NAME_LEN,
};
use syscall::{Error, Result, EINVAL};
@@ -28,7 +29,7 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
KmsPropertyKind::Bitmask(_bitmask_flags) => {
// FIXME check overlapping flag numbers
}
KmsPropertyKind::Object => {}
KmsPropertyKind::Object { type_: _ } => {}
KmsPropertyKind::SignedRange(start, end) => assert!(start < end),
}
@@ -129,7 +130,7 @@ pub enum KmsPropertyKind {
Enum(Vec<(KmsPropertyName, u64)>),
Blob,
Bitmask(Vec<(KmsPropertyName, u64)>),
Object,
Object { type_: u32 },
SignedRange(i64, i64),
}
@@ -178,8 +179,8 @@ macro_rules! define_properties {
(@prop_kind blob) => {
KmsPropertyKind::Blob
};
(@prop_kind object) => {
KmsPropertyKind::Object
(@prop_kind object { $type:ident }) => {
KmsPropertyKind::Object { type_: $type }
};
(@prop_kind srange { $start:expr, $end:expr }) => {
KmsPropertyKind::SignedRange($start, $end)
@@ -188,7 +189,7 @@ macro_rules! define_properties {
define_properties! {
// Connector + Plane
CRTC_ID: object [atomic],
CRTC_ID: object { DRM_MODE_OBJECT_CRTC } [atomic],
// Connector
EDID: blob [immutable],
@@ -209,7 +210,7 @@ define_properties! {
Primary = u64::from(DRM_PLANE_TYPE_PRIMARY),
Cursor = u64::from(DRM_PLANE_TYPE_CURSOR),
} [immutable],
FB_ID: object [atomic],
FB_ID: object { DRM_MODE_OBJECT_FB } [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],
+22 -19
View File
@@ -103,7 +103,6 @@ pub trait GraphicsAdapter: Sized + Debug {
&mut self,
objects: &KmsObjects<Self>,
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
framebuffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
@@ -238,7 +237,9 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
);
for (display_id, fb) in vt_state.display_fbs.iter().enumerate() {
let crtc = self.inner.objects.crtcs().nth(display_id).unwrap();
let crtc_id = self.inner.objects.crtc_ids()[display_id];
let crtc = self.inner.objects.get_crtc(crtc_id).unwrap();
let connector_id = self.inner.objects.connector_ids()[display_id];
crtc.lock().unwrap().fb_id = fb.unwrap_or(KmsObjectId::INVALID);
@@ -255,7 +256,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
self.inner.adapter.set_crtc(
&self.inner.objects,
crtc,
&[self.inner.objects.connector_ids()[display_id]],
mode,
fb,
Damage {
@@ -266,8 +266,13 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
},
);
crtc.lock().unwrap().target_connectors =
vec![self.inner.objects.connector_ids()[display_id]];
self.inner
.objects
.get_connector(connector_id)
.unwrap()
.lock()
.unwrap()
.crtc_id = crtc_id;
}
if self.inner.adapter.hw_cursor_size().is_some() {
@@ -570,7 +575,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
self.adapter.set_crtc(
&self.objects,
crtc,
&connector_ids,
mode,
fb.as_deref(),
Damage {
@@ -581,7 +585,14 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
},
);
crtc.lock().unwrap().fb_id = KmsObjectId(data.fb_id());
crtc.lock().unwrap().target_connectors = connector_ids;
for connector in connector_ids {
self.objects
.get_connector(connector)?
.lock()
.unwrap()
.crtc_id = KmsObjectId(data.crtc_id());
}
}
self.vts.get_mut(vt).unwrap().display_fbs[display_id] = if data.fb_id() != 0 {
Some(KmsObjectId(data.fb_id()))
@@ -702,9 +713,9 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
.collect::<Vec<_>>(),
);
}
KmsPropertyKind::Object => {
KmsPropertyKind::Object { type_ } => {
data.set_flags(flags | DRM_MODE_PROP_OBJECT);
data.set_values_ptr(&[]);
data.set_values_ptr(&[u64::from(*type_)]);
data.set_enum_blob_ptr(&[]);
}
&KmsPropertyKind::SignedRange(start, end) => {
@@ -773,7 +784,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
self.adapter.set_crtc(
&self.objects,
crtc,
&[self.objects.connector_ids()[display_id]],
None,
None,
Damage {
@@ -811,16 +821,9 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
if *vt == self.active_vt {
for crtc in self.objects.crtcs() {
if crtc.lock().unwrap().fb_id == KmsObjectId(data.fb_id()) {
let connectors = crtc.lock().unwrap().target_connectors.clone();
let mode = crtc.lock().unwrap().mode;
self.adapter.set_crtc(
&self.objects,
crtc,
&connectors,
mode,
Some(fb),
damage,
);
self.adapter
.set_crtc(&self.objects, crtc, mode, Some(fb), damage);
}
}
}
+23 -21
View File
@@ -81,33 +81,35 @@ impl GraphicsAdapter for Device {
&mut self,
objects: &KmsObjects<Self>,
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
buffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
) {
crtc.lock().unwrap().mode = mode;
let mut crtc = crtc.lock().unwrap();
crtc.mode = mode;
let framebuffer_id = objects
.get_connector(connectors[0])
.unwrap()
.lock()
.unwrap()
.driver_data
.framebuffer_id;
for connector in objects.connectors() {
let connector = connector.lock().unwrap();
let framebuffer = &mut self.framebuffers[framebuffer_id];
if let Some(buffer) = buffer {
buffer.buffer.sync(framebuffer, damage)
} else {
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
0,
framebuffer.width,
);
if connector.crtc_id != objects.crtc_ids()[crtc.crtc_index as usize] {
continue;
}
let framebuffer_id = connector.driver_data.framebuffer_id;
let framebuffer = &mut self.framebuffers[framebuffer_id];
if let Some(buffer) = buffer {
buffer.buffer.sync(framebuffer, damage)
} else {
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
0,
framebuffer.width,
);
}
}
}
}
+23 -21
View File
@@ -88,33 +88,35 @@ impl GraphicsAdapter for FbAdapter {
&mut self,
objects: &KmsObjects<Self>,
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
buffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
) {
crtc.lock().unwrap().mode = mode;
let mut crtc = crtc.lock().unwrap();
crtc.mode = mode;
let framebuffer_id = objects
.get_connector(connectors[0])
.unwrap()
.lock()
.unwrap()
.driver_data
.framebuffer_id;
let framebuffer = &mut self.framebuffers[framebuffer_id];
for connector in objects.connectors() {
let connector = connector.lock().unwrap();
if let Some(buffer) = buffer {
buffer.buffer.sync(framebuffer, damage)
} else {
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
0,
framebuffer.width,
);
if connector.crtc_id != objects.crtc_ids()[crtc.crtc_index as usize] {
continue;
}
let framebuffer_id = connector.driver_data.framebuffer_id;
let framebuffer = &mut self.framebuffers[framebuffer_id];
if let Some(buffer) = buffer {
buffer.buffer.sync(framebuffer, damage)
} else {
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
0,
framebuffer.width,
);
}
}
}
}
+52 -48
View File
@@ -402,68 +402,72 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
&mut self,
objects: &KmsObjects<Self>,
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
framebuffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
) {
futures::executor::block_on(async {
crtc.lock().unwrap().mode = mode;
let mut crtc = crtc.lock().unwrap();
crtc.mode = mode;
let display_id = objects
.get_connector(connectors[0])
.unwrap()
.lock()
.unwrap()
.driver_data
.display_id;
for connector in objects.connectors() {
let connector = connector.lock().unwrap();
let Some(framebuffer) = framebuffer else {
let scanout_request = Dma::new(SetScanout::new(
display_id,
ResourceId::NONE,
GpuRect::new(0, 0, 0, 0),
))
.unwrap();
let header = self.send_request(scanout_request).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
self.displays[display_id as usize].active_resource = None;
return;
};
if connector.crtc_id != objects.crtc_ids()[crtc.crtc_index as usize] {
continue;
}
let req = Dma::new(XferToHost2d::new(
framebuffer.buffer.id,
GpuRect {
x: 0,
y: 0,
width: framebuffer.width,
height: framebuffer.height,
},
0,
))
.unwrap();
let header = self.send_request(req).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
let display_id = connector.driver_data.display_id;
// FIXME once we support resizing we also need to check that the current and target size match
if self.displays[display_id as usize].active_resource != Some(framebuffer.buffer.id) {
let scanout_request = Dma::new(SetScanout::new(
display_id,
let Some(framebuffer) = framebuffer else {
let scanout_request = Dma::new(SetScanout::new(
display_id,
ResourceId::NONE,
GpuRect::new(0, 0, 0, 0),
))
.unwrap();
let header = self.send_request(scanout_request).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
self.displays[display_id as usize].active_resource = None;
return;
};
let req = Dma::new(XferToHost2d::new(
framebuffer.buffer.id,
GpuRect::new(0, 0, framebuffer.width, framebuffer.height),
GpuRect {
x: 0,
y: 0,
width: framebuffer.width,
height: framebuffer.height,
},
0,
))
.unwrap();
let header = self.send_request(scanout_request).await.unwrap();
let header = self.send_request(req).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
self.displays[display_id as usize].active_resource = Some(framebuffer.buffer.id);
}
let flush = ResourceFlush::new(
framebuffer.buffer.id,
damage.clip(framebuffer.width, framebuffer.height).into(),
);
let header = self.send_request(Dma::new(flush).unwrap()).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
// FIXME once we support resizing we also need to check that the current and target size match
if self.displays[display_id as usize].active_resource != Some(framebuffer.buffer.id)
{
let scanout_request = Dma::new(SetScanout::new(
display_id,
framebuffer.buffer.id,
GpuRect::new(0, 0, framebuffer.width, framebuffer.height),
))
.unwrap();
let header = self.send_request(scanout_request).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
self.displays[display_id as usize].active_resource =
Some(framebuffer.buffer.id);
}
let flush = ResourceFlush::new(
framebuffer.buffer.id,
damage.clip(framebuffer.width, framebuffer.height).into(),
);
let header = self.send_request(Dma::new(flush).unwrap()).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
}
});
}