diff --git a/drivers/graphics/driver-graphics/src/kms/connector.rs b/drivers/graphics/driver-graphics/src/kms/connector.rs index 248d9a3b3f..ed36692d08 100644 --- a/drivers/graphics/driver-graphics/src/kms/connector.rs +++ b/drivers/graphics/driver-graphics/src/kms/connector.rs @@ -9,10 +9,19 @@ use crate::kms::objects::{KmsObjectId, KmsObjects}; use crate::GraphicsAdapter; impl KmsObjects { - 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 KmsConnector { // 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, diff --git a/drivers/graphics/driver-graphics/src/kms/objects.rs b/drivers/graphics/driver-graphics/src/kms/objects.rs index 8c5506a24d..c7b16ebf39 100644 --- a/drivers/graphics/driver-graphics/src/kms/objects.rs +++ b/drivers/graphics/driver-graphics/src/kms/objects.rs @@ -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 { next_id: KmsObjectId, pub(crate) connectors: Vec, pub(crate) encoders: Vec, + crtcs: Vec, pub(crate) objects: HashMap>>, _marker: PhantomData, } @@ -28,6 +29,7 @@ impl KmsObjects { next_id: KmsObjectId(1), connectors: vec![], encoders: vec![], + crtcs: vec![], objects: HashMap::new(), _marker: PhantomData, } @@ -63,6 +65,34 @@ impl KmsObjects { 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>> + use<'_, T> { + self.crtcs + .iter() + .map(|&id| self.get::>>(id).unwrap()) + } + + pub fn get_crtc(&self, id: KmsObjectId) -> Result<&Mutex>> { + self.get(id) + } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] @@ -124,8 +154,18 @@ macro_rules! define_object_kinds { } define_object_kinds! { + Crtc(Mutex>) = DRM_MODE_OBJECT_CRTC, Connector(Mutex>) = 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 { + pub crtc_index: u32, + pub fb_id: KmsObjectId, + pub gamma_size: u32, + pub mode: Option, + pub driver_data: T, +} diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 0565fa8f55..a84cde02c5 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -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, display_id: usize, + mode: Option, framebuffer: Option<&Self::Buffer>, damage: Damage, ); @@ -217,8 +221,14 @@ impl GraphicsScheme { ); 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 SchemeSync for GraphicsSchemeInner { 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 SchemeSync for GraphicsSchemeInner { .iter() .map(|id| id.0) .collect::>(); - let mut crtc_ids = Vec::with_capacity(count); + let crtc_ids = self + .objects + .crtc_ids() + .iter() + .map(|id| id.0) + .collect::>(); let enc_ids = self .objects .encoder_ids() @@ -565,7 +576,6 @@ impl SchemeSync for GraphicsSchemeInner { .collect::>(); 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 SchemeSync for GraphicsSchemeInner { 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 SchemeSync for GraphicsSchemeInner { }), 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 SchemeSync for GraphicsSchemeInner { 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 SchemeSync for GraphicsSchemeInner { 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, ); diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 8fd741bb89..d52a35bd43 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -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, 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::() } - fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) { + fn update_plane( + &mut self, + objects: &KmsObjects, + display_id: usize, + mode: Option, + 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) diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index f1bbd60cba..57826869ef 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -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, 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::() } - fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) { + fn update_plane( + &mut self, + objects: &KmsObjects, + display_id: usize, + mode: Option, + 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) diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 7cddf275ae..07e551a007 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -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, display_id: usize, + mode: Option, 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,