From ac5a73210c60f452e71a30f08316ff0fec0560ad Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Dec 2025 10:35:28 +0100 Subject: [PATCH 1/3] Switch back to redox-os/relibc for redox-ioctl --- Cargo.lock | 15 +++++++++++---- drivers/graphics/graphics-ipc/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c627610e0b..1813b05b16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -813,7 +813,7 @@ dependencies = [ [[package]] name = "generic-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#3ebd43b4ceb77bfee2a9c155993ec2fb5843ad6b" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#13b93e0f901ea61358d80b4cd177601872ef830e" [[package]] name = "getrandom" @@ -1619,7 +1619,7 @@ dependencies = [ [[package]] name = "redox-ioctl" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/Ibuki.O/relibc.git?branch=replace-unlink-rmdir-with-unlinkat#daf01ee12975a5481d2c1302e19eab45013427f4" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#13b93e0f901ea61358d80b4cd177601872ef830e" dependencies = [ "drm-sys", "redox_syscall 0.6.0", @@ -1637,16 +1637,23 @@ dependencies = [ "termion", ] +[[package]] +name = "redox-path" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" + [[package]] name = "redox-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#3ebd43b4ceb77bfee2a9c155993ec2fb5843ad6b" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#13b93e0f901ea61358d80b4cd177601872ef830e" dependencies = [ "bitflags 2.10.0", "generic-rt", "goblin", "plain", - "redox_syscall 0.5.18", + "redox-path", + "redox_syscall 0.6.0", ] [[package]] diff --git a/drivers/graphics/graphics-ipc/Cargo.toml b/drivers/graphics/graphics-ipc/Cargo.toml index 8abc977e04..75e6bd17e1 100644 --- a/drivers/graphics/graphics-ipc/Cargo.toml +++ b/drivers/graphics/graphics-ipc/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] log = "0.4" libredox = "0.1.3" -redox-ioctl = { git = "https://gitlab.redox-os.org/Ibuki.O/relibc.git", branch = "replace-unlink-rmdir-with-unlinkat" } +redox-ioctl = { git = "https://gitlab.redox-os.org/redox-os/relibc.git" } redox_syscall = "0.6" common = { path = "../../common" } 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 2/3] 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 { From a4a5d86efaae4b16aa8374853e45d401afb6b98f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Dec 2025 23:06:39 +0100 Subject: [PATCH 3/3] drivers/graphics: Use drm dumb buffer ioctls --- Cargo.lock | 3 + drivers/graphics/driver-graphics/src/lib.rs | 120 ++++++++---------- drivers/graphics/fbbootlogd/Cargo.toml | 1 + drivers/graphics/fbbootlogd/src/scheme.rs | 130 +++++++++++--------- drivers/graphics/fbcond/Cargo.toml | 1 + drivers/graphics/fbcond/src/display.rs | 115 +++++++++-------- drivers/graphics/fbcond/src/text.rs | 12 +- drivers/graphics/graphics-ipc/Cargo.toml | 1 + drivers/graphics/graphics-ipc/src/v2.rs | 101 ++------------- 9 files changed, 215 insertions(+), 269 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14f7edff25..e1c8cb2f68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -719,6 +719,7 @@ version = "0.1.0" dependencies = [ "console-draw", "daemon", + "drm", "graphics-ipc", "inputd", "libredox", @@ -736,6 +737,7 @@ dependencies = [ "common", "console-draw", "daemon", + "drm", "graphics-ipc", "inputd", "libredox", @@ -925,6 +927,7 @@ version = "0.1.0" dependencies = [ "common", "drm", + "drm-fourcc", "libredox", "log", "redox-ioctl", diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index b6ae903346..25d54b3593 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -83,8 +83,8 @@ enum Handle { }, V2 { vt: usize, - next_id: usize, - fbs: HashMap>, + next_id: u32, + fbs: HashMap>, }, } @@ -463,6 +463,10 @@ impl SchemeSync for GraphicsScheme { id_index(i) | (1 << 13) } + fn dumb_buffer_id(i: u32) -> u32 { + id_index(i) | (1 << 14) + } + 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 @@ -596,6 +600,50 @@ impl SchemeSync for GraphicsScheme { data.set_handle(fb_handle_id(i)); Ok(0) }), + ipc::MODE_CREATE_DUMB => ipc::DrmModeCreateDumb::with(payload, |mut data| { + if data.bpp() != 32 { + return Err(Error::new(EINVAL)); + } + + let fb = self + .adapter + .create_dumb_framebuffer(data.width(), data.height()); + + *next_id += 1; + fbs.insert(*next_id, Arc::new(fb)); + data.set_handle(dumb_buffer_id(*next_id as u32)); + data.set_pitch(data.width() * 4); + data.set_size(u64::from(data.width()) * u64::from(data.height()) * 4); + Ok(0) + }), + ipc::MODE_MAP_DUMB => ipc::DrmModeMapDumb::with(payload, |mut data| { + if data.offset() != 0 { + return Err(Error::new(EINVAL)); + } + + let fb_id = id_index(data.handle()); + + if !fbs.contains_key(&fb_id) { + return Err(Error::new(EINVAL)); + } + + // FIXME use a better scheme for creating map offsets + assert!( + ((fbs[&fb_id].width() * fbs[&fb_id].height() * 4) as usize) + < MAP_FAKE_OFFSET_MULTIPLIER + ); + + data.set_offset((fb_id as usize * MAP_FAKE_OFFSET_MULTIPLIER) as u64); + + Ok(0) + }), + ipc::MODE_DESTROY_DUMB => ipc::DrmModeDestroyDumb::with(payload, |data| { + let fb_id = id_index(data.handle()); + if fbs.remove(&fb_id).is_none() { + return Err(Error::new(ENOENT)); + } + Ok(0) + }), ipc::MODE_GET_PLANE_RES => ipc::DrmModeGetPlaneRes::with(payload, |mut data| { let count = self.adapter.display_count(); let mut ids = Vec::with_capacity(count); @@ -634,70 +682,6 @@ impl SchemeSync for GraphicsScheme { data.set_modifier([0; 4]); Ok(0) }), - ipc::CREATE_DUMB_FRAMEBUFFER => { - if payload.len() < size_of::() { - return Err(Error::new(EINVAL)); - } - let payload = unsafe { - transmute::< - &mut [u8; size_of::()], - &mut ipc::CreateDumbFramebuffer, - >(payload.as_mut_array().unwrap()) - }; - - let fb = self - .adapter - .create_dumb_framebuffer(payload.width, payload.height); - - *next_id += 1; - fbs.insert(*next_id, Arc::new(fb)); - payload.fb_id = *next_id; - Ok(size_of::()) - } - ipc::DUMB_FRAMEBUFFER_MAP_OFFSET => { - if payload.len() < size_of::() { - return Err(Error::new(EINVAL)); - } - let payload = unsafe { - transmute::< - &mut [u8; size_of::()], - &mut ipc::DumbFramebufferMapOffset, - >(payload.as_mut_array().unwrap()) - }; - - let fb_id = payload.fb_id; - - if !fbs.contains_key(&fb_id) { - return Err(Error::new(EINVAL)); - } - - // FIXME use a better scheme for creating map offsets - assert!( - ((fbs[&fb_id].width() * fbs[&fb_id].height() * 4) as usize) - < MAP_FAKE_OFFSET_MULTIPLIER - ); - - payload.offset = fb_id * MAP_FAKE_OFFSET_MULTIPLIER; - - Ok(size_of::()) - } - ipc::DESTROY_DUMB_FRAMEBUFFER => { - if payload.len() < size_of::() { - return Err(Error::new(EINVAL)); - } - let payload = unsafe { - transmute::< - &mut [u8; size_of::()], - &mut ipc::DestroyDumbFramebuffer, - >(payload.as_mut_array().unwrap()) - }; - - if fbs.remove(&{ payload.fb_id }).is_none() { - return Err(Error::new(ENOENT)); - } - - Ok(size_of::()) - } ipc::UPDATE_PLANE => { if payload.len() < size_of::() { return Err(Error::new(EINVAL)); @@ -713,7 +697,7 @@ impl SchemeSync for GraphicsScheme { return Err(Error::new(EINVAL)); } - let Some(framebuffer) = fbs.get(&{ payload.fb_id }) else { + let Some(framebuffer) = fbs.get(&id_index(payload.fb_id)) else { return Err(Error::new(EINVAL)); }; @@ -747,7 +731,7 @@ impl SchemeSync for GraphicsScheme { next_id: _, fbs, } => ( - fbs.get(&(offset as usize / MAP_FAKE_OFFSET_MULTIPLIER)) + fbs.get(&((offset as usize / MAP_FAKE_OFFSET_MULTIPLIER) as u32)) .ok_or(Error::new(EINVAL)) .unwrap(), offset & (MAP_FAKE_OFFSET_MULTIPLIER as u64 - 1), diff --git a/drivers/graphics/fbbootlogd/Cargo.toml b/drivers/graphics/fbbootlogd/Cargo.toml index 44436d0f2c..0df28673a6 100644 --- a/drivers/graphics/fbbootlogd/Cargo.toml +++ b/drivers/graphics/fbbootlogd/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +drm = "0.14.1" orbclient = "0.3.27" ransid = "0.4" redox_event = "0.4" diff --git a/drivers/graphics/fbbootlogd/src/scheme.rs b/drivers/graphics/fbbootlogd/src/scheme.rs index 97caef7a87..3ea92547a3 100644 --- a/drivers/graphics/fbbootlogd/src/scheme.rs +++ b/drivers/graphics/fbbootlogd/src/scheme.rs @@ -1,7 +1,9 @@ use std::collections::VecDeque; -use std::{cmp, ptr}; +use std::{cmp, mem, ptr}; use console_draw::TextScreen; +use drm::buffer::Buffer; +use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; use graphics_ipc::v2::V2GraphicsHandle; use inputd::ConsumerHandle; use orbclient::{Event, EventOption}; @@ -12,8 +14,21 @@ use syscall::{Error, Result, EINVAL, ENOENT}; pub struct DisplayMap { display_handle: V2GraphicsHandle, - fb: usize, - inner: graphics_ipc::v1::DisplayMap, + fb: DumbBuffer, + mapping: DumbMapping<'static>, +} + +impl DisplayMap { + unsafe fn console_map(&mut self) -> console_draw::DisplayMap { + console_draw::DisplayMap { + offscreen: ptr::slice_from_raw_parts_mut( + self.mapping.as_mut_ptr() as *mut u32, + self.mapping.len() / 4, + ), + width: self.fb.size().0 as usize, + height: self.fb.size().1 as usize, + } + } } pub struct FbbootlogScheme { @@ -55,24 +70,27 @@ impl FbbootlogScheme { let (width, height) = new_display_handle .display_size(new_display_handle.first_display().unwrap()) .unwrap(); - let fb = new_display_handle + let mut fb = new_display_handle .create_dumb_framebuffer(width, height) .unwrap(); - match new_display_handle.map_dumb_framebuffer(fb, width, height) { - Ok(display_map) => { - self.display_map = Some(DisplayMap { - display_handle: new_display_handle, - fb, - inner: display_map, - }); - - eprintln!("fbbootlogd: mapped display"); - } + let display_map = match new_display_handle.map_dumb_framebuffer(&mut fb) { + Ok(display_map) => unsafe { + mem::transmute::, DumbMapping<'static>>(display_map) + }, Err(err) => { eprintln!("fbbootlogd: failed to open display: {}", err); + return; } - } + }; + + self.display_map = Some(DisplayMap { + display_handle: new_display_handle, + mapping: display_map, + fb, + }); + + eprintln!("fbbootlogd: mapped display"); } pub fn handle_input(&mut self, ev: &Event) { @@ -127,11 +145,7 @@ impl FbbootlogScheme { return; }; let buffer_len = self.text_buffer.lines.len(); - let dmap = &mut console_draw::DisplayMap { - offscreen: map.inner.ptr_mut(), - width: map.inner.width(), - height: map.inner.height(), - }; + let dmap = unsafe { &mut map.console_map() }; // for both extra space on wrapping text and a scrollback indicator let spare_lines = 3; self.is_scrollback = true; @@ -151,11 +165,15 @@ impl FbbootlogScheme { if i == buffer_len || yd + spare_lines * 16 > dmap.height { // render until end of screen damage.height = (dmap.height as u32) - damage.y; - map.display_handle.update_plane(0, map.fb, damage).unwrap(); + map.display_handle + .update_plane(0, u32::from(map.fb.handle()), damage) + .unwrap(); self.is_scrollback = i < buffer_len; break; } else { - map.display_handle.update_plane(0, map.fb, damage).unwrap(); + map.display_handle + .update_plane(0, u32::from(map.fb.handle()), damage) + .unwrap(); } } } @@ -169,45 +187,47 @@ impl FbbootlogScheme { Ok((width, height)) => (width, height), Err(err) => { eprintln!("fbbootlogd: failed to get display size: {}", err); - (map.inner.width() as u32, map.inner.height() as u32) + map.fb.size() } }; - if width as usize != map.inner.width() || height as usize != map.inner.height() { + if (width, height) != map.fb.size() { match map.display_handle.create_dumb_framebuffer(width, height) { - Ok(fb) => match map.display_handle.map_dumb_framebuffer(fb, width, height) { - Ok(mut new_map) => { - let count = new_map.ptr().len(); - unsafe { - ptr::write_bytes(new_map.ptr_mut() as *mut u32, 0, count); + Ok(mut fb) => { + let mut new_map = match map.display_handle.map_dumb_framebuffer(&mut fb) { + Ok(new_map) => unsafe { + mem::transmute::, DumbMapping<'static>>(new_map) + }, + Err(err) => { + eprintln!("fbbootlogd: failed to open display: {}", err); + return; } + }; - text_screen.resize( - &mut console_draw::DisplayMap { - offscreen: map.inner.ptr_mut(), - width: map.inner.width(), - height: map.inner.height(), - }, - &mut console_draw::DisplayMap { - offscreen: new_map.ptr_mut(), - width: new_map.width(), - height: new_map.height(), - }, - ); + new_map.fill(0); - let _ = map.display_handle.destroy_dumb_framebuffer(map.fb); + text_screen.resize( + unsafe { &mut map.console_map() }, + &mut console_draw::DisplayMap { + offscreen: ptr::slice_from_raw_parts_mut( + new_map.as_mut_ptr() as *mut u32, + new_map.len() / 4, + ), + width: fb.size().0 as usize, + height: fb.size().1 as usize, + }, + ); - map.fb = fb; - map.inner = new_map; + let old_fb = mem::replace(&mut map.fb, fb); + map.mapping = new_map; - eprintln!("fbbootlogd: mapped display"); - } - Err(err) => { - eprintln!("fbbootlogd: failed to open display: {}", err); - } - }, + let _ = map.display_handle.destroy_dumb_framebuffer(old_fb); + + eprintln!("fbbootlogd: mapped display"); + } Err(err) => { eprintln!("fbbootlogd: failed to create framebuffer: {}", err); + return; } } } @@ -267,17 +287,15 @@ impl SchemeSync for FbbootlogScheme { if !self.is_scrollback { let damage = self.text_screen.write( - &mut console_draw::DisplayMap { - offscreen: map.inner.ptr_mut(), - width: map.inner.width(), - height: map.inner.height(), - }, + unsafe { &mut map.console_map() }, buf, &mut VecDeque::new(), ); if let Some(map) = &self.display_map { - map.display_handle.update_plane(0, map.fb, damage).unwrap(); + map.display_handle + .update_plane(0, u32::from(map.fb.handle()), damage) + .unwrap(); } } } diff --git a/drivers/graphics/fbcond/Cargo.toml b/drivers/graphics/fbcond/Cargo.toml index a0a206da8f..6aed8031e7 100644 --- a/drivers/graphics/fbcond/Cargo.toml +++ b/drivers/graphics/fbcond/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +drm = "0.14.1" log = "0.4" orbclient = "0.3.27" ransid = "0.4" diff --git a/drivers/graphics/fbcond/src/display.rs b/drivers/graphics/fbcond/src/display.rs index 333bf2c1c9..0a4d7fb833 100644 --- a/drivers/graphics/fbcond/src/display.rs +++ b/drivers/graphics/fbcond/src/display.rs @@ -1,7 +1,9 @@ use console_draw::TextScreen; +use drm::buffer::Buffer; +use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; use graphics_ipc::v2::{Damage, V2GraphicsHandle}; use inputd::ConsumerHandle; -use std::{io, ptr}; +use std::{io, mem, ptr}; pub struct Display { pub input_handle: ConsumerHandle, @@ -10,8 +12,21 @@ pub struct Display { pub struct DisplayMap { display_handle: V2GraphicsHandle, - fb: usize, - pub inner: graphics_ipc::v2::DisplayMap, + fb: DumbBuffer, + mapping: DumbMapping<'static>, +} + +impl DisplayMap { + pub unsafe fn console_map(&mut self) -> console_draw::DisplayMap { + console_draw::DisplayMap { + offscreen: ptr::slice_from_raw_parts_mut( + self.mapping.as_mut_ptr() as *mut u32, + self.mapping.len() / 4, + ), + width: self.fb.size().0 as usize, + height: self.fb.size().1 as usize, + } + } } impl Display { @@ -36,28 +51,29 @@ impl Display { let (width, height) = new_display_handle .display_size(new_display_handle.first_display().unwrap()) .unwrap(); - let fb = new_display_handle + let mut fb = new_display_handle .create_dumb_framebuffer(width, height) .unwrap(); - match new_display_handle.map_dumb_framebuffer(fb, width, height) { - Ok(map) => { - log::debug!( - "fbcond: Mapped new display with size {}x{}", - map.width(), - map.height() - ); - - self.map = Some(DisplayMap { - display_handle: new_display_handle, - fb, - inner: map, - }); - } + let map = match new_display_handle.map_dumb_framebuffer(&mut fb) { + Ok(map) => unsafe { mem::transmute::, DumbMapping<'static>>(map) }, Err(err) => { log::error!("failed to map display: {}", err); + return; } - } + }; + + log::debug!( + "fbcond: Mapped new display with size {}x{}", + fb.size().0, + fb.size().1, + ); + + self.map = Some(DisplayMap { + display_handle: new_display_handle, + fb, + mapping: map, + }); } pub fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { @@ -69,43 +85,44 @@ impl Display { Ok((width, height)) => (width, height), Err(err) => { log::error!("fbcond: failed to get display size: {}", err); - (map.inner.width() as u32, map.inner.height() as u32) + map.fb.size() } }; - if width as usize != map.inner.width() || height as usize != map.inner.height() { + if (width, height) != map.fb.size() { match map.display_handle.create_dumb_framebuffer(width, height) { - Ok(fb) => match map.display_handle.map_dumb_framebuffer(fb, width, height) { - Ok(mut new_map) => { - let count = new_map.ptr().len(); - unsafe { - ptr::write_bytes(new_map.ptr_mut() as *mut u32, 0, count); + Ok(mut fb) => { + let mut new_map = match map.display_handle.map_dumb_framebuffer(&mut fb) { + Ok(new_map) => unsafe { + mem::transmute::, DumbMapping<'static>>(new_map) + }, + Err(err) => { + eprintln!("fbcond: failed to open display: {}", err); + return; } + }; - text_screen.resize( - &mut console_draw::DisplayMap { - offscreen: map.inner.ptr_mut(), - width: map.inner.width(), - height: map.inner.height(), - }, - &mut console_draw::DisplayMap { - offscreen: new_map.ptr_mut(), - width: new_map.width(), - height: new_map.height(), - }, - ); + new_map.fill(0); - let _ = map.display_handle.destroy_dumb_framebuffer(map.fb); + text_screen.resize( + unsafe { &mut map.console_map() }, + &mut console_draw::DisplayMap { + offscreen: ptr::slice_from_raw_parts_mut( + new_map.as_mut_ptr() as *mut u32, + new_map.len() / 4, + ), + width: fb.size().0 as usize, + height: fb.size().1 as usize, + }, + ); - map.fb = fb; - map.inner = new_map; + let old_fb = mem::replace(&mut map.fb, fb); + map.mapping = new_map; - log::debug!("fbcond: mapped display"); - } - Err(err) => { - log::error!("fbcond: failed to open display: {}", err); - } - }, + let _ = map.display_handle.destroy_dumb_framebuffer(old_fb); + + eprintln!("fbcond: mapped display"); + } Err(err) => { log::error!("fbcond: failed to create framebuffer: {}", err); } @@ -115,7 +132,9 @@ impl Display { pub fn sync_rect(&mut self, damage: Damage) { if let Some(map) = &self.map { - map.display_handle.update_plane(0, map.fb, damage).unwrap(); + map.display_handle + .update_plane(0, u32::from(map.fb.handle()), damage) + .unwrap(); } } } diff --git a/drivers/graphics/fbcond/src/text.rs b/drivers/graphics/fbcond/src/text.rs index 8cbd70b348..438af68912 100644 --- a/drivers/graphics/fbcond/src/text.rs +++ b/drivers/graphics/fbcond/src/text.rs @@ -124,15 +124,9 @@ impl TextScreen { if let Some(map) = &mut self.display.map { Display::handle_resize(map, &mut self.inner); - let damage = self.inner.write( - &mut console_draw::DisplayMap { - offscreen: map.inner.ptr_mut(), - width: map.inner.width(), - height: map.inner.height(), - }, - buf, - &mut self.input, - ); + let damage = self + .inner + .write(unsafe { &mut map.console_map() }, buf, &mut self.input); self.display.sync_rect(damage); } diff --git a/drivers/graphics/graphics-ipc/Cargo.toml b/drivers/graphics/graphics-ipc/Cargo.toml index 5ad5afd9a0..8e8d98503d 100644 --- a/drivers/graphics/graphics-ipc/Cargo.toml +++ b/drivers/graphics/graphics-ipc/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] drm = "0.14" +drm-fourcc = "2.2.0" 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 5ef667d27d..fb9c98b997 100644 --- a/drivers/graphics/graphics-ipc/src/v2.rs +++ b/drivers/graphics/graphics-ipc/src/v2.rs @@ -1,12 +1,13 @@ use std::fs::File; use std::os::fd::{AsFd, BorrowedFd}; use std::os::unix::io::AsRawFd; -use std::{io, mem, ptr}; +use std::{io, mem}; use drm::control::connector::{self, State}; +use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; use drm::control::Device as _; use drm::{ClientCapability, Device as _, DriverCapability}; -use libredox::flag; +use drm_fourcc::DrmFourcc; pub use crate::common::{Damage, DisplayMap}; @@ -79,75 +80,22 @@ impl V2GraphicsHandle { Ok((u32::from(width), u32::from(height))) } - pub fn create_dumb_framebuffer(&self, width: u32, height: u32) -> io::Result { - let mut cmd = ipc::CreateDumbFramebuffer { - width, - height, - - fb_id: 0, - }; - unsafe { - sys_call( - &self.file, - &mut cmd, - 0, - &[ipc::CREATE_DUMB_FRAMEBUFFER, 0, 0], - )?; - } - Ok(cmd.fb_id) + pub fn create_dumb_framebuffer(&self, width: u32, height: u32) -> io::Result { + self.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32) } - pub fn map_dumb_framebuffer( + pub fn map_dumb_framebuffer<'a>( &self, - id: usize, - width: u32, - height: u32, - ) -> io::Result { - let mut cmd = ipc::DumbFramebufferMapOffset { - fb_id: id, - offset: 0, - }; - unsafe { - sys_call( - &self.file, - &mut cmd, - 0, - &[ipc::DUMB_FRAMEBUFFER_MAP_OFFSET, 0, 0], - )?; - } - - let display_ptr = unsafe { - libredox::call::mmap(libredox::call::MmapArgs { - fd: self.file.as_raw_fd() as usize, - offset: cmd.offset as u64, - length: (width * height * 4) as usize, - prot: flag::PROT_READ | flag::PROT_WRITE, - flags: flag::MAP_SHARED, - addr: core::ptr::null_mut(), - })? - }; - let offscreen = ptr::slice_from_raw_parts_mut( - display_ptr as *mut u32, - width as usize * height as usize, - ); - - Ok(unsafe { DisplayMap::new(offscreen, width as usize, height as usize) }) + buffer: &'a mut DumbBuffer, + ) -> io::Result> { + self.map_dumb_buffer(buffer) } - pub fn destroy_dumb_framebuffer(&self, id: usize) -> io::Result { - let mut cmd = ipc::DestroyDumbFramebuffer { fb_id: id }; - unsafe { - sys_call( - &self.file, - &mut cmd, - 0, - &[ipc::DESTROY_DUMB_FRAMEBUFFER, 0, 0], - )?; - } - Ok(cmd.fb_id) + pub fn destroy_dumb_framebuffer(&self, buffer: DumbBuffer) -> io::Result<()> { + self.destroy_dumb_buffer(buffer) } - pub fn update_plane(&self, display_id: usize, fb_id: usize, damage: Damage) -> io::Result<()> { + pub fn update_plane(&self, display_id: usize, fb_id: u32, damage: Damage) -> io::Result<()> { let mut cmd = ipc::UpdatePlane { display_id, fb_id, @@ -166,34 +114,11 @@ pub mod ipc { pub use redox_ioctl::drm::*; // FIXME replace these with proper drm interfaces - pub const CREATE_DUMB_FRAMEBUFFER: u64 = 3; - #[repr(C, packed)] - pub struct CreateDumbFramebuffer { - pub width: u32, - pub height: u32, - - pub fb_id: usize, - } - - pub const DUMB_FRAMEBUFFER_MAP_OFFSET: u64 = 4; - #[repr(C, packed)] - pub struct DumbFramebufferMapOffset { - pub fb_id: usize, - - pub offset: usize, - } - - pub const DESTROY_DUMB_FRAMEBUFFER: u64 = 5; - #[repr(C, packed)] - pub struct DestroyDumbFramebuffer { - pub fb_id: usize, - } - pub const UPDATE_PLANE: u64 = 6; #[repr(C, packed)] pub struct UpdatePlane { pub display_id: usize, - pub fb_id: usize, + pub fb_id: u32, pub damage: Damage, } }