diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index cefa71bc2b..538b82a257 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -18,7 +18,7 @@ use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket}; use syscall::schemev2::NewFdFlags; use syscall::{Error, MapFlags, Result, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP}; -use crate::objects::{DrmObjectId, DrmObjects}; +use crate::objects::{DrmConnector, DrmObjectId, DrmObjects}; pub mod objects; @@ -36,6 +36,8 @@ pub trait GraphicsAdapter: Sized { fn get_cap(&self, cap: u32) -> Result; fn set_client_cap(&self, cap: u32, value: u64) -> Result<()>; + fn probe_connector(&mut self, connector: &mut DrmConnector); + /// The maximum amount of displays that could be attached. /// /// This must be constant for the lifetime of the graphics adapter. @@ -111,6 +113,9 @@ impl GraphicsScheme { let mut objects = DrmObjects::new(); adapter.init(&mut objects); + for connector in objects.connectors_mut() { + adapter.probe_connector(connector); + } GraphicsScheme { adapter, @@ -523,9 +528,17 @@ impl SchemeSync for GraphicsScheme { }), ipc::MODE_CARD_RES => ipc::DrmModeCardRes::with(payload, |mut data| { let count = self.adapter.display_count(); - let conn_ids = self.objects.connectors().map(|id| id.0).collect::>(); + let conn_ids = self + .objects + .connector_ids() + .map(|id| id.0) + .collect::>(); let mut crtc_ids = Vec::with_capacity(count); - let enc_ids = self.objects.encoders().map(|id| id.0).collect::>(); + let enc_ids = self + .objects + .encoder_ids() + .map(|id| id.0) + .collect::>(); let mut fb_ids = Vec::with_capacity(count); for i in 0..(count as u32) { crtc_ids.push(crtc_id(i)); @@ -563,7 +576,10 @@ impl SchemeSync for GraphicsScheme { ipc::MODE_GET_CONNECTOR => ipc::DrmModeGetConnector::with(payload, |mut data| { let connector = self .objects - .get_connector(DrmObjectId(data.connector_id()))?; + .get_connector_mut(DrmObjectId(data.connector_id()))?; + if data.count_modes() == 0 { + self.adapter.probe_connector(connector); + } data.set_connection(connector.connection as u32); data.set_modes_ptr(&connector.modes); data.set_mm_width(connector.mm_width); diff --git a/drivers/graphics/driver-graphics/src/objects.rs b/drivers/graphics/driver-graphics/src/objects.rs index b65dc41044..562a44817f 100644 --- a/drivers/graphics/driver-graphics/src/objects.rs +++ b/drivers/graphics/driver-graphics/src/objects.rs @@ -47,7 +47,7 @@ impl DrmObjects { connector_id } - pub fn connectors(&self) -> impl Iterator + use<'_, T> { + pub fn connector_ids(&self) -> impl Iterator + use<'_, T> { self.objects .iter() .filter_map(|(&id, object)| match object.kind { @@ -56,6 +56,24 @@ impl DrmObjects { }) } + pub fn connectors(&self) -> impl Iterator> + use<'_, T> { + self.objects + .values() + .filter_map(|object| match &object.kind { + DrmObjectKind::Connector(connector) => Some(connector), + _ => None, + }) + } + + pub fn connectors_mut(&mut self) -> impl Iterator> + use<'_, T> { + self.objects + .values_mut() + .filter_map(|object| match &mut object.kind { + DrmObjectKind::Connector(connector) => Some(connector), + _ => None, + }) + } + pub fn get_connector(&self, id: DrmObjectId) -> Result<&DrmConnector> { let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; match &object.kind { @@ -72,7 +90,7 @@ impl DrmObjects { } } - pub fn encoders(&self) -> impl Iterator + use<'_, T> { + pub fn encoder_ids(&self) -> impl Iterator + use<'_, T> { self.objects .iter() .filter_map(|(&id, object)| match object.kind { diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 7fd2a22636..761c475014 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -16,13 +16,17 @@ use syscall::{error::EINVAL, PAGE_SIZE}; use super::Device; +pub struct Connector { + framebuffer_id: usize, +} + //TODO: use hardware cursor pub enum Cursor {} impl CursorFramebuffer for Cursor {} impl GraphicsAdapter for Device { - type Connector = (); + type Connector = Connector; type Framebuffer = DumbFb; type Cursor = Cursor; @@ -37,12 +41,9 @@ impl GraphicsAdapter for Device { fn init(&mut self, objects: &mut DrmObjects) { // FIXME enumerate actual connectors - for framebuffer in &self.framebuffers { + for (framebuffer_id, _) in self.framebuffers.iter().enumerate() { objects.add_connector(DrmConnector { - modes: vec![modeinfo_for_size( - framebuffer.width as u32, - framebuffer.height as u32, - )], + modes: vec![], encoder_id: DrmObjectId::INVALID, connector_type: 0, connector_type_id: 0, @@ -50,7 +51,7 @@ impl GraphicsAdapter for Device { mm_width: 0, mm_height: 0, subpixel: DrmSubpixelOrder::Unknown, - driver_data: (), + driver_data: Connector { framebuffer_id }, }); } } @@ -70,6 +71,14 @@ impl GraphicsAdapter for Device { } } + fn probe_connector(&mut self, connector: &mut DrmConnector) { + let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id]; + connector.modes = vec![modeinfo_for_size( + framebuffer.width as u32, + framebuffer.height as u32, + )]; + } + fn display_count(&self) -> usize { self.framebuffers.len() } diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index 644e6b9b3f..cf6dcda08f 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -67,6 +67,8 @@ impl GraphicsAdapter for FbAdapter { } } + fn probe_connector(&mut self, _connector: &mut DrmConnector) {} + fn display_count(&self) -> usize { self.framebuffers.len() } diff --git a/drivers/graphics/virtio-gpud/src/main.rs b/drivers/graphics/virtio-gpud/src/main.rs index cbf43e482c..032bf4fdc0 100644 --- a/drivers/graphics/virtio-gpud/src/main.rs +++ b/drivers/graphics/virtio-gpud/src/main.rs @@ -23,6 +23,7 @@ use std::os::fd::AsRawFd; use std::sync::atomic::{AtomicU32, Ordering}; +use driver_graphics::GraphicsAdapter; use event::{user_data, EventQueue}; use pcid_interface::PciFunctionHandle; @@ -542,7 +543,10 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow: if events & VIRTIO_GPU_EVENT_DISPLAY != 0 { let (adapter, objects) = scheme.adapter_and_objects_mut(); - futures::executor::block_on(adapter.update_displays(objects)).unwrap(); + futures::executor::block_on(async { adapter.update_displays().await.unwrap() }); + for connector in objects.connectors_mut() { + adapter.probe_connector(connector); + } scheme.notify_displays_changed(); scheme .adapter_mut() diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 4ab7b88ec4..18977202b5 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -76,6 +76,7 @@ impl CursorFramebuffer for VirtGpuCursor {} #[derive(Debug, Copy, Clone)] pub struct Display { + enabled: bool, width: u32, height: u32, active_resource: Option, @@ -90,13 +91,14 @@ pub struct VirtGpuAdapter<'a> { } impl VirtGpuAdapter<'_> { - pub async fn update_displays(&mut self, objects: &mut DrmObjects) -> Result<(), Error> { + pub async fn update_displays(&mut self) -> Result<(), Error> { let display_info = self.get_display_info().await?; let raw_displays = &display_info.display_info[..self.config.num_scanouts() as usize]; self.displays.resize( raw_displays.len(), Display { + enabled: false, width: 0, height: 0, active_resource: None, @@ -109,6 +111,8 @@ impl VirtGpuAdapter<'_> { info.rect.height ); + self.displays[i].enabled = info.enabled != 0; + if info.rect.width == 0 || info.rect.height == 0 { // QEMU gives all displays other than the first a zero width and height, but trying // to attach a zero sized framebuffer to the display will result an error, so @@ -121,19 +125,6 @@ impl VirtGpuAdapter<'_> { } } - for connector in objects.connectors().collect::>() { - let connector = objects.get_connector_mut(connector).unwrap(); - let display = &self.displays[connector.driver_data.display_id as usize]; - - connector.modes = vec![modeinfo_for_size(display.width, display.height)]; - connector.connection = - if raw_displays[connector.driver_data.display_id as usize].enabled != 0 { - DrmConnectorStatus::Connected - } else { - DrmConnectorStatus::Disconnected - }; - } - Ok(()) } @@ -233,6 +224,10 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { } fn init(&mut self, objects: &mut DrmObjects) { + futures::executor::block_on(async { + self.update_displays().await.unwrap(); + }); + for display_id in 0..self.config.num_scanouts.get() { objects.add_connector(DrmConnector { modes: vec![], @@ -246,10 +241,6 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { driver_data: VirtGpuConnector { display_id }, }); } - - futures::executor::block_on(async { - self.update_displays(objects).await.unwrap(); - }); } fn get_cap(&self, cap: u32) -> syscall::Result { @@ -267,6 +258,19 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { } } + fn probe_connector(&mut self, connector: &mut DrmConnector) { + futures::executor::block_on(async { + let display = &self.displays[connector.driver_data.display_id as usize]; + + connector.modes = vec![modeinfo_for_size(display.width, display.height)]; + connector.connection = if display.enabled { + DrmConnectorStatus::Connected + } else { + DrmConnectorStatus::Disconnected + }; + }); + } + fn display_count(&self) -> usize { self.displays.len() }