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:
@@ -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],
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user