diff --git a/Cargo.lock b/Cargo.lock index fa93034003..7dfaff86dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -592,6 +592,7 @@ version = "0.1.0" dependencies = [ "common", "drm-sys", + "edid", "graphics-ipc", "inputd", "libredox", @@ -2567,7 +2568,6 @@ dependencies = [ "daemon", "driver-graphics", "drm-sys", - "edid", "futures", "graphics-ipc", "libredox", diff --git a/drivers/graphics/driver-graphics/Cargo.toml b/drivers/graphics/driver-graphics/Cargo.toml index c193d759c5..8bea89deda 100644 --- a/drivers/graphics/driver-graphics/Cargo.toml +++ b/drivers/graphics/driver-graphics/Cargo.toml @@ -5,6 +5,8 @@ edition = "2021" [dependencies] drm-sys.workspace = true +#TODO: edid is abandoned, fork it an maintain? +edid = "0.3.0" log.workspace = true redox-scheme.workspace = true redox_syscall.workspace = true diff --git a/drivers/graphics/driver-graphics/src/connector.rs b/drivers/graphics/driver-graphics/src/connector.rs index 26254a6039..7cf4ddd275 100644 --- a/drivers/graphics/driver-graphics/src/connector.rs +++ b/drivers/graphics/driver-graphics/src/connector.rs @@ -1,8 +1,9 @@ +use std::ffi::c_char; use std::fmt::Debug; use drm_sys::{ drm_mode_modeinfo, DRM_MODE_CONNECTOR_Unknown, DRM_MODE_OBJECT_CONNECTOR, - DRM_MODE_OBJECT_ENCODER, + DRM_MODE_OBJECT_ENCODER, DRM_MODE_TYPE_PREFERRED, }; use syscall::Result; @@ -75,6 +76,88 @@ pub struct DrmConnector { pub driver_data: T, } +impl DrmConnector { + pub fn update_from_size(&mut self, width: u32, height: u32) { + self.modes = vec![Self::modeinfo_for_size(width, height)]; + } + + pub fn update_from_edid(&mut self, edid: &[u8]) { + let edid = edid::parse(edid).unwrap().1; + + if let Some(first_detailed_timing) = + edid.descriptors + .iter() + .find_map(|descriptor| match descriptor { + edid::Descriptor::DetailedTiming(detailed_timing) => Some(detailed_timing), + _ => None, + }) + { + self.mm_width = first_detailed_timing.horizontal_size.into(); + self.mm_height = first_detailed_timing.vertical_size.into(); + } else { + log::error!("No edid timing descriptor detected"); + } + + self.modes = edid + .descriptors + .iter() + .filter_map(|descriptor| { + match descriptor { + edid::Descriptor::DetailedTiming(detailed_timing) => { + // FIXME extract full information + Some(Self::modeinfo_for_size( + u32::from(detailed_timing.horizontal_active_pixels), + u32::from(detailed_timing.vertical_active_lines), + )) + } + _ => None, + } + }) + .collect::>(); + + // First detailed timing descriptor indicates preferred mode. + for mode in self.modes.iter_mut().skip(1) { + mode.flags &= !DRM_MODE_TYPE_PREFERRED; + } + + // FIXME update the EDID property + } + + 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, + vdisplay: height as u16, + + // These are used to calculate the refresh rate + clock: 60 * width * height / 1000, + htotal: width as u16, + vtotal: height as u16, + vscan: 0, + vrefresh: 60, + + type_: drm_sys::DRM_MODE_TYPE_PREFERRED | drm_sys::DRM_MODE_TYPE_DRIVER, + name: [0; 32], + + // These only matter when modesetting physical display adapters. For + // those we should be able to parse the EDID blob. + hsync_start: width as u16, + hsync_end: width as u16, + hskew: 0, + vsync_start: height as u16, + vsync_end: height as u16, + flags: 0, + }; + + let name = format!("{width}x{height}").into_bytes(); + for (to, from) in modeinfo.name.iter_mut().zip(name) { + *to = from as c_char; + } + + modeinfo + } +} + #[derive(Debug, Copy, Clone)] #[repr(u32)] pub enum DrmConnectorStatus { diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index c5186467cc..b3425d56d9 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_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, + 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}; @@ -908,37 +908,3 @@ impl GraphicsSchemeInner { self.handles.remove(&id); } } - -pub 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, - vdisplay: height as u16, - - // These are used to calculate the refresh rate - clock: 60 * width * height / 1000, - htotal: width as u16, - vtotal: height as u16, - vscan: 0, - vrefresh: 60, - - type_: drm_sys::DRM_MODE_TYPE_PREFERRED | drm_sys::DRM_MODE_TYPE_DRIVER, - name: [0; 32], - - // These only matter when modesetting physical display adapters. For - // those we should be able to parse the EDID blob. - hsync_start: width as u16, - hsync_end: width as u16, - hskew: 0, - vsync_start: height as u16, - vsync_end: height as u16, - flags: 0, - }; - - let name = format!("{width}x{height}").into_bytes(); - for (to, from) in modeinfo.name.iter_mut().zip(name) { - *to = from as c_char; - } - - modeinfo -} diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index ac32e62af0..44171c8189 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -6,9 +6,7 @@ use std::ptr::{self, NonNull}; use driver_graphics::connector::DrmConnectorStatus; use driver_graphics::objects::{DrmObjectId, DrmObjects}; -use driver_graphics::{ - modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties, -}; +use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties}; use drm_sys::DRM_MODE_DPMS_ON; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; use graphics_ipc::v2::Damage; @@ -70,10 +68,7 @@ impl GraphicsAdapter for Device { let connector = objects.get_connector_mut(id).unwrap(); let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id]; connector.connection = DrmConnectorStatus::Connected; - connector.modes = vec![modeinfo_for_size( - framebuffer.width as u32, - framebuffer.height as u32, - )]; + connector.update_from_size(framebuffer.width as u32, framebuffer.height as u32); // FIXME fetch EDID } diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index e5c8eae997..58124d361a 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -4,9 +4,7 @@ use std::ptr::{self, NonNull}; use driver_graphics::connector::DrmConnectorStatus; use driver_graphics::objects::{DrmObjectId, DrmObjects}; -use driver_graphics::{ - modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties, -}; +use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties}; use drm_sys::DRM_MODE_DPMS_ON; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; use graphics_ipc::v2::Damage; @@ -71,11 +69,8 @@ impl GraphicsAdapter for FbAdapter { id: DrmObjectId, ) { let connector = objects.get_connector_mut(id).unwrap(); - connector.modes = vec![modeinfo_for_size( - connector.driver_data.width, - connector.driver_data.height, - )]; connector.connection = DrmConnectorStatus::Connected; + connector.update_from_size(connector.driver_data.width, connector.driver_data.height); } fn display_count(&self) -> usize { diff --git a/drivers/graphics/virtio-gpud/Cargo.toml b/drivers/graphics/virtio-gpud/Cargo.toml index c67f427f26..00075681ca 100644 --- a/drivers/graphics/virtio-gpud/Cargo.toml +++ b/drivers/graphics/virtio-gpud/Cargo.toml @@ -6,8 +6,6 @@ authors = ["Anhad Singh "] [dependencies] drm-sys.workspace = true -#TODO: edid is abandoned, fork it an maintain? -edid = "0.3.0" log.workspace = true static_assertions = "1.1.0" futures = { version = "0.3.28", features = ["executor"] } diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index ea77e24262..0acfddb4d5 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -5,12 +5,9 @@ use common::{dma::Dma, sgl}; use driver_graphics::connector::DrmConnectorStatus; use driver_graphics::objects::{DrmObjectId, DrmObjects}; use driver_graphics::{ - modeinfo_for_size, Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, - StandardProperties, -}; -use drm_sys::{ - DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON, DRM_MODE_TYPE_PREFERRED, + Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, StandardProperties, }; +use drm_sys::{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; @@ -314,7 +311,6 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { let connector = objects.get_connector_mut(id).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 display.enabled { DrmConnectorStatus::Connected } else { @@ -322,48 +318,12 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { }; if self.has_edid { - let edid = edid::parse(&display.edid).unwrap().1; - - if let Some(first_detailed_timing) = - edid.descriptors - .iter() - .find_map(|descriptor| match descriptor { - edid::Descriptor::DetailedTiming(detailed_timing) => { - Some(detailed_timing) - } - _ => None, - }) - { - connector.mm_width = first_detailed_timing.horizontal_size.into(); - connector.mm_height = first_detailed_timing.vertical_size.into(); - } else { - log::error!("No edid timing descriptor detected"); - } - - connector.modes = edid - .descriptors - .iter() - .filter_map(|descriptor| { - match descriptor { - edid::Descriptor::DetailedTiming(detailed_timing) => { - // FIXME extract full information - Some(modeinfo_for_size( - u32::from(detailed_timing.horizontal_active_pixels), - u32::from(detailed_timing.vertical_active_lines), - )) - } - _ => None, - } - }) - .collect::>(); - - // First detailed timing descriptor indicates preferred mode. - for mode in connector.modes.iter_mut().skip(1) { - mode.flags &= !DRM_MODE_TYPE_PREFERRED; - } + connector.update_from_edid(&display.edid); let blob = objects.add_blob(display.edid.clone()); objects.set_object_property(id, standard_properties.edid, blob.into()); + } else { + connector.update_from_size(display.width, display.height); } }); }