From e8bf0d180b652fdf4d463163bf796d3682e44ec5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Dec 2025 22:13:18 +0100 Subject: [PATCH] drivers/graphics: Use DRM_IOCTL_MODE_GETCONNECTOR for getting display size in graphics-ipc --- Cargo.lock | 166 +++++++++++++++++++- Cargo.toml | 5 + drivers/graphics/driver-graphics/src/lib.rs | 68 ++++---- drivers/graphics/fbbootlogd/src/scheme.rs | 10 +- drivers/graphics/fbcond/src/display.rs | 10 +- drivers/graphics/graphics-ipc/Cargo.toml | 1 + drivers/graphics/graphics-ipc/src/v2.rs | 57 +++---- 7 files changed, 243 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1813b05b16..14f7edff25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,7 +156,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -167,7 +167,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -326,6 +326,26 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -596,14 +616,42 @@ dependencies = [ "redox_syscall 0.6.0", ] +[[package]] +name = "drm" +version = "0.14.1" +source = "git+https://github.com/Smithay/drm-rs.git#c51297961755fa9eb3941fdd60bf2b69979cb403" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "bytemuck_derive", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix", +] + +[[package]] +name = "drm-ffi" +version = "0.9.0" +source = "git+https://github.com/Smithay/drm-rs.git#c51297961755fa9eb3941fdd60bf2b69979cb403" +dependencies = [ + "drm-sys", + "rustix", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + [[package]] name = "drm-sys" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c" +source = "git+https://github.com/Smithay/drm-rs.git#c51297961755fa9eb3941fdd60bf2b69979cb403" dependencies = [ "libc", - "linux-raw-sys", + "linux-raw-sys 0.9.4", ] [[package]] @@ -640,6 +688,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "executor" version = "0.1.0" @@ -866,6 +924,7 @@ name = "graphics-ipc" version = "0.1.0" dependencies = [ "common", + "drm", "libredox", "log", "redox-ioctl", @@ -1103,9 +1162,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.6.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "lived" @@ -1822,6 +1887,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "1.1.2" +source = "git+https://github.com/jackpot51/rustix.git?branch=redox-ioctl#e7e66bc77455251463336582c0b97df01054ccb8" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.59.0", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -2517,7 +2594,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2585,6 +2662,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -2594,6 +2680,70 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winnow" version = "0.5.40" diff --git a/Cargo.toml b/Cargo.toml index 8abd8b0109..b8893d4243 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,6 +76,11 @@ exclude = ["bootstrap"] libc = { git = "https://gitlab.redox-os.org/redox-os/liblibc.git", branch = "redox-0.2" } orbclient = { git = "https://gitlab.redox-os.org/redox-os/orbclient.git", version = "0.3.44" } +# Rustix doesn't support ioctls on Redox OS +rustix = { git = "https://github.com/jackpot51/rustix.git", branch = "redox-ioctl" } +drm = { git = "https://github.com/Smithay/drm-rs.git" } +drm-sys = { git = "https://github.com/Smithay/drm-rs.git" } + [patch."https://gitlab.redox-os.org/redox-os/relibc.git"] #redox-rt = { path = "../../relibc/source/redox-rt" } #redox-ioctl = { path = "../../relibc/source/redox-ioctl" } diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 39a11e461b..b6ae903346 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -1,6 +1,7 @@ #![feature(slice_as_array)] use std::collections::{BTreeMap, HashMap}; +use std::ffi::c_char; use std::fs::File; use std::io::{self, Write}; use std::mem; @@ -462,6 +463,40 @@ impl SchemeSync for GraphicsScheme { id_index(i) | (1 << 13) } + fn modeinfo_for_size(width: u32, height: u32) -> drm_sys::drm_mode_modeinfo { + let mut modeinfo = drm_sys::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 + } + match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { Handle::V1Screen { .. } => { return Err(Error::new(EOPNOTSUPP)); @@ -543,7 +578,8 @@ impl SchemeSync for GraphicsScheme { ipc::MODE_GET_CONNECTOR => ipc::DrmModeGetConnector::with(payload, |mut data| { let i = id_index(data.connector_id()); let (width, height) = self.adapter.display_size(i as usize); - data.set_modes_ptr(&[]); + data.set_connection(1 /* connected */); + data.set_modes_ptr(&[modeinfo_for_size(width, height)]); data.set_props_ptr(&[]); data.set_prop_values_ptr(&[]); data.set_encoders_ptr(&[enc_id(i)]); @@ -598,36 +634,6 @@ impl SchemeSync for GraphicsScheme { data.set_modifier([0; 4]); Ok(0) }), - ipc::DISPLAY_COUNT => { - if payload.len() < size_of::() { - return Err(Error::new(EINVAL)); - } - let payload = unsafe { - transmute::<&mut [u8; size_of::()], &mut ipc::DisplayCount>( - payload.as_mut_array().unwrap(), - ) - }; - payload.count = self.adapter.display_count(); - Ok(size_of::()) - } - ipc::DISPLAY_SIZE => { - if payload.len() < size_of::() { - return Err(Error::new(EINVAL)); - } - let payload = unsafe { - transmute::<&mut [u8; size_of::()], &mut ipc::DisplaySize>( - payload.as_mut_array().unwrap(), - ) - }; - let display_id = payload.display_id; - if display_id >= self.adapter.display_count() { - return Err(Error::new(EINVAL)); - } - let (width, height) = self.adapter.display_size(display_id); - payload.width = width; - payload.height = height; - Ok(size_of::()) - } ipc::CREATE_DUMB_FRAMEBUFFER => { if payload.len() < size_of::() { return Err(Error::new(EINVAL)); diff --git a/drivers/graphics/fbbootlogd/src/scheme.rs b/drivers/graphics/fbbootlogd/src/scheme.rs index 58166f906c..97caef7a87 100644 --- a/drivers/graphics/fbbootlogd/src/scheme.rs +++ b/drivers/graphics/fbbootlogd/src/scheme.rs @@ -52,7 +52,9 @@ impl FbbootlogScheme { } }; - let (width, height) = new_display_handle.display_size(0).unwrap(); + let (width, height) = new_display_handle + .display_size(new_display_handle.first_display().unwrap()) + .unwrap(); let fb = new_display_handle .create_dumb_framebuffer(width, height) .unwrap(); @@ -159,7 +161,11 @@ impl FbbootlogScheme { } fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { - let (width, height) = match map.display_handle.display_size(0) { + let (width, height) = match map + .display_handle + .first_display() + .and_then(|handle| map.display_handle.display_size(handle)) + { Ok((width, height)) => (width, height), Err(err) => { eprintln!("fbbootlogd: failed to get display size: {}", err); diff --git a/drivers/graphics/fbcond/src/display.rs b/drivers/graphics/fbcond/src/display.rs index 9ad75e7f63..333bf2c1c9 100644 --- a/drivers/graphics/fbcond/src/display.rs +++ b/drivers/graphics/fbcond/src/display.rs @@ -33,7 +33,9 @@ impl Display { log::debug!("fbcond: Opened new display"); - let (width, height) = new_display_handle.display_size(0).unwrap(); + let (width, height) = new_display_handle + .display_size(new_display_handle.first_display().unwrap()) + .unwrap(); let fb = new_display_handle .create_dumb_framebuffer(width, height) .unwrap(); @@ -59,7 +61,11 @@ impl Display { } pub fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { - let (width, height) = match map.display_handle.display_size(0) { + let (width, height) = match map + .display_handle + .first_display() + .and_then(|handle| map.display_handle.display_size(handle)) + { Ok((width, height)) => (width, height), Err(err) => { log::error!("fbcond: failed to get display size: {}", err); diff --git a/drivers/graphics/graphics-ipc/Cargo.toml b/drivers/graphics/graphics-ipc/Cargo.toml index 75e6bd17e1..5ad5afd9a0 100644 --- a/drivers/graphics/graphics-ipc/Cargo.toml +++ b/drivers/graphics/graphics-ipc/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +drm = "0.14" log = "0.4" libredox = "0.1.3" redox-ioctl = { git = "https://gitlab.redox-os.org/redox-os/relibc.git" } diff --git a/drivers/graphics/graphics-ipc/src/v2.rs b/drivers/graphics/graphics-ipc/src/v2.rs index b8ca1c9c63..5ef667d27d 100644 --- a/drivers/graphics/graphics-ipc/src/v2.rs +++ b/drivers/graphics/graphics-ipc/src/v2.rs @@ -1,7 +1,11 @@ use std::fs::File; +use std::os::fd::{AsFd, BorrowedFd}; use std::os::unix::io::AsRawFd; use std::{io, mem, ptr}; +use drm::control::connector::{self, State}; +use drm::control::Device as _; +use drm::{ClientCapability, Device as _, DriverCapability}; use libredox::flag; pub use crate::common::{Damage, DisplayMap}; @@ -44,29 +48,35 @@ pub struct V2GraphicsHandle { file: File, } +impl AsFd for V2GraphicsHandle { + fn as_fd(&self) -> BorrowedFd<'_> { + self.file.as_fd() + } +} + +impl drm::Device for V2GraphicsHandle {} +impl drm::control::Device for V2GraphicsHandle {} + impl V2GraphicsHandle { pub fn from_file(file: File) -> io::Result { - Ok(V2GraphicsHandle { file }) + let handle = V2GraphicsHandle { file }; + handle.set_client_capability(ClientCapability::CursorPlaneHotspot, true)?; + assert!(handle.get_driver_capability(DriverCapability::DumbBuffer)? == 1); + Ok(handle) } - pub fn display_count(&self) -> io::Result { - let mut cmd = ipc::DisplayCount { count: 0 }; - unsafe { - sys_call(&self.file, &mut cmd, 0, &[ipc::DISPLAY_COUNT, 0, 0])?; + pub fn first_display(&self) -> io::Result { + for &connector in self.resource_handles().unwrap().connectors() { + if self.get_connector(connector, true)?.state() == State::Connected { + return Ok(connector); + } } - Ok(cmd.count) + Err(io::Error::other("no connected display")) } - pub fn display_size(&self, id: usize) -> io::Result<(u32, u32)> { - let mut cmd = ipc::DisplaySize { - display_id: id, - width: 0, - height: 0, - }; - unsafe { - sys_call(&self.file, &mut cmd, 0, &[ipc::DISPLAY_SIZE, 0, 0])?; - } - Ok((cmd.width, cmd.height)) + pub fn display_size(&self, handle: connector::Handle) -> io::Result<(u32, u32)> { + let (width, height) = self.get_connector(handle, true)?.modes()[0].size(); + Ok((u32::from(width), u32::from(height))) } pub fn create_dumb_framebuffer(&self, width: u32, height: u32) -> io::Result { @@ -156,21 +166,6 @@ pub mod ipc { pub use redox_ioctl::drm::*; // FIXME replace these with proper drm interfaces - pub const DISPLAY_COUNT: u64 = 1; - #[repr(C, packed)] - pub struct DisplayCount { - pub count: usize, - } - - pub const DISPLAY_SIZE: u64 = 2; - #[repr(C, packed)] - pub struct DisplaySize { - pub display_id: usize, - - pub width: u32, - pub height: u32, - } - pub const CREATE_DUMB_FRAMEBUFFER: u64 = 3; #[repr(C, packed)] pub struct CreateDumbFramebuffer {