From 6875c90850e9935386f481936f6895b9de4d17f4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 14 May 2026 12:09:55 +0200 Subject: [PATCH 1/3] drivers/graphics/driver-graphics: Implement SET_VERSION and GET_UNIQUE libdrm needs these when searching for drm devices. --- drivers/graphics/driver-graphics/src/lib.rs | 38 +++++++++++++++++++-- drivers/graphics/ihdgd/src/device/mod.rs | 2 ++ drivers/graphics/ihdgd/src/device/scheme.rs | 4 +++ drivers/graphics/vesad/src/scheme.rs | 4 +++ drivers/graphics/virtio-gpud/src/main.rs | 1 + drivers/graphics/virtio-gpud/src/scheme.rs | 7 ++++ 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 2c0b3946e5..347f57057d 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -1,6 +1,7 @@ #![feature(macro_metavar_expr)] use std::collections::HashMap; +use std::ffi::c_char; use std::fmt::Debug; use std::fs::File; use std::io::{self, Write}; @@ -90,6 +91,7 @@ pub trait GraphicsAdapter: Sized + Debug { fn init(&mut self, objects: &mut KmsObjects); + fn get_unique(&self) -> String; fn get_cap(&self, cap: u32) -> Result; fn set_client_cap(&self, cap: u32, value: u64) -> Result<()>; @@ -281,6 +283,7 @@ struct VtState { enum Handle { V2 { vt: usize, + unique: Option, next_id: u32, buffers: HashMap>, }, @@ -414,6 +417,7 @@ impl SchemeSync for GraphicsSchemeInner { Handle::V2 { vt, + unique: None, next_id: 0, buffers: HashMap::new(), } @@ -432,6 +436,7 @@ impl SchemeSync for GraphicsSchemeInner { match self.handles.get(id)? { Handle::V2 { vt, + unique: _, next_id: _, buffers: _, } => write!(w, "v2/{vt}").unwrap(), @@ -462,6 +467,7 @@ impl SchemeSync for GraphicsSchemeInner { Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)), Handle::V2 { vt, + unique, next_id, buffers, } => match metadata[0] { @@ -476,12 +482,39 @@ impl SchemeSync for GraphicsSchemeInner { Ok(0) }), + ipc::GET_UNIQUE => ipc::DrmUnique::with(payload, |mut data| { + if let Some(unique) = unique { + data.set_unique(unsafe { + mem::transmute::<&[u8], &[c_char]>(unique.as_bytes()) + }); + } else { + data.set_unique_len(0); + } + Ok(0) + }), + ipc::SET_VERSION => ipc::DrmSetVersion::with(payload, |mut data| { + // We only support version 1.4 currently + if data.drm_di_major() != 0 || data.drm_di_minor() != 4 { + return Err(Error::new(EINVAL)); + } + if data.drm_dd_major() != 0 || data.drm_dd_minor() != 4 { + return Err(Error::new(EINVAL)); + } + data.set_drm_di_major(1); + data.set_drm_di_minor(4); + data.set_drm_dd_major(1); + data.set_drm_dd_minor(4); + + *unique = Some(self.adapter.get_unique()); + + Ok(0) + }), ipc::GET_CAP => ipc::DrmGetCap::with(payload, |mut data| { data.set_value( self.adapter.get_cap( data.capability() .try_into() - .map_err(|_| syscall::Error::new(EINVAL))?, + .map_err(|_| Error::new(EINVAL))?, )?, ); Ok(0) @@ -490,7 +523,7 @@ impl SchemeSync for GraphicsSchemeInner { self.adapter.set_client_cap( data.capability() .try_into() - .map_err(|_| syscall::Error::new(EINVAL))?, + .map_err(|_| Error::new(EINVAL))?, data.value(), )?; Ok(0) @@ -973,6 +1006,7 @@ impl SchemeSync for GraphicsSchemeInner { let (framebuffer, offset) = match self.handles.get(id)? { Handle::V2 { vt: _, + unique: _, next_id: _, buffers, } => ( diff --git a/drivers/graphics/ihdgd/src/device/mod.rs b/drivers/graphics/ihdgd/src/device/mod.rs index 07fb98e02c..a30b4f7ab7 100644 --- a/drivers/graphics/ihdgd/src/device/mod.rs +++ b/drivers/graphics/ihdgd/src/device/mod.rs @@ -168,6 +168,7 @@ enum VideoInput { } pub struct Device { + unique: String, kind: DeviceKind, alloc_buffers: RangeAllocator, bios: Option, @@ -426,6 +427,7 @@ impl Device { //TODO: get number of available buffers let buffers = 1024; Ok(Self { + unique: format!("pci:{}", pcid_handle.config().func.addr), kind, alloc_buffers: RangeAllocator::new(0..buffers), bios, diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 337314da71..eaa17f2764 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -48,6 +48,10 @@ impl GraphicsAdapter for Device { self.init_inner(objects); } + fn get_unique(&self) -> String { + self.unique.clone() + } + fn get_cap(&self, cap: u32) -> syscall::Result { match cap { DRM_CAP_DUMB_BUFFER => Ok(1), diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index 4b8b31ce83..daa9908855 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -59,6 +59,10 @@ impl GraphicsAdapter for FbAdapter { } } + fn get_unique(&self) -> String { + format!("vesad:{:x}", self.framebuffers[0].phys) + } + fn get_cap(&self, cap: u32) -> syscall::Result { match cap { DRM_CAP_DUMB_BUFFER => Ok(1), diff --git a/drivers/graphics/virtio-gpud/src/main.rs b/drivers/graphics/virtio-gpud/src/main.rs index 57e25ba70c..4f2b177e25 100644 --- a/drivers/graphics/virtio-gpud/src/main.rs +++ b/drivers/graphics/virtio-gpud/src/main.rs @@ -534,6 +534,7 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow: EventQueue::new().expect("virtio-gpud: failed to create event queue"); let mut scheme = scheme::GpuScheme::new( + format!("pci:{}", pcid_handle.config().func.addr), config, control_queue.clone(), cursor_queue.clone(), diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 40a213eea0..e855eb704e 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -88,6 +88,7 @@ pub struct Display { } pub struct VirtGpuAdapter<'a> { + unique: String, pub config: &'a mut GpuConfig, control_queue: Arc>, cursor_queue: Arc>, @@ -364,6 +365,10 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { } } + fn get_unique(&self) -> String { + self.unique.clone() + } + fn get_cap(&self, cap: u32) -> syscall::Result { match cap { DRM_CAP_DUMB_BUFFER => Ok(1), @@ -521,6 +526,7 @@ pub struct GpuScheme {} impl<'a> GpuScheme { pub fn new( + unique: String, config: &'a mut GpuConfig, control_queue: Arc>, cursor_queue: Arc>, @@ -528,6 +534,7 @@ impl<'a> GpuScheme { has_edid: bool, ) -> Result>, Error> { let adapter = VirtGpuAdapter { + unique, config, control_queue, cursor_queue, From 0eb6390fe127947d234ca5b73b9605ff685a27c9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 14 May 2026 12:23:54 +0200 Subject: [PATCH 2/3] drivers/graphics/driver-graphics: Report DRM_MAJOR as device major --- drivers/graphics/driver-graphics/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 347f57057d..71f9f8caef 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -431,6 +431,11 @@ impl SchemeSync for GraphicsSchemeInner { }) } + fn fstat(&mut self, _id: usize, stat: &mut syscall::Stat, _ctx: &CallerCtx) -> Result<()> { + stat.st_dev = 226 /*DRM_MAJOR*/ << 8; + Ok(()) + } + fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result { FpathWriter::with(buf, &self.scheme_name, |w| { match self.handles.get(id)? { From 5f4e5016a88f95cd8f3ff66b5d0c66d87fc4bc49 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 14 May 2026 14:56:33 +0200 Subject: [PATCH 3/3] drivers/graphics/driver-graphics: Implement MODE_ADD_FB2 --- Cargo.lock | 3 +- Cargo.toml | 1 + drivers/graphics/driver-graphics/Cargo.toml | 2 +- .../driver-graphics/src/kms/objects.rs | 4 +- drivers/graphics/driver-graphics/src/lib.rs | 47 ++++++++++++++++--- drivers/graphics/ihdgd/Cargo.toml | 1 + drivers/graphics/ihdgd/src/device/mod.rs | 4 +- drivers/graphics/ihdgd/src/device/pipe.rs | 4 +- 8 files changed, 52 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67ed69189d..117632ba3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1073,6 +1073,7 @@ dependencies = [ "common", "daemon", "driver-graphics", + "drm-fourcc", "drm-sys", "edid", "embedded-hal", @@ -1823,7 +1824,7 @@ dependencies = [ [[package]] name = "redox-ioctl" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#36d2efa33444d26a584d3e6cb17ba108079c24ea" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#546bc6fb21b990ca9195a1115717c9a842fe4909" dependencies = [ "drm-sys", "redox_syscall 0.7.5", diff --git a/Cargo.toml b/Cargo.toml index 68a5b89898..c41de7b05d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ anyhow = "1" bitflags = "2" clap = "4" drm = "0.15.0" +drm-fourcc = "2.2.0" drm-sys = "0.8.1" edid = "0.3.0" #TODO: edid is abandoned, fork it and maintain? fdt = "0.1.5" diff --git a/drivers/graphics/driver-graphics/Cargo.toml b/drivers/graphics/driver-graphics/Cargo.toml index 31e02335c8..fee6246dd3 100644 --- a/drivers/graphics/driver-graphics/Cargo.toml +++ b/drivers/graphics/driver-graphics/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2021" [dependencies] -drm-fourcc = "2.2.0" +drm-fourcc.workspace = true drm-sys.workspace = true edid.workspace = true #TODO: edid is abandoned, fork it and maintain? log.workspace = true diff --git a/drivers/graphics/driver-graphics/src/kms/objects.rs b/drivers/graphics/driver-graphics/src/kms/objects.rs index 156b32af2e..805cea1386 100644 --- a/drivers/graphics/driver-graphics/src/kms/objects.rs +++ b/drivers/graphics/driver-graphics/src/kms/objects.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::marker::PhantomData; use std::sync::{Arc, Mutex}; +use drm_fourcc::DrmFourcc; use drm_sys::{ drm_mode_modeinfo, DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_FB, DRM_MODE_OBJECT_PROPERTY, @@ -235,9 +236,8 @@ define_object_props!(object, KmsCrtc { pub struct KmsFramebuffer { pub width: u32, pub height: u32, + pub pixel_format: DrmFourcc, pub pitch: u32, - pub bpp: u32, - pub depth: u32, pub buffer: Arc, pub driver_data: T::Framebuffer, } diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 71f9f8caef..5652986b22 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -771,28 +771,42 @@ impl SchemeSync for GraphicsSchemeInner { ipc::MODE_GET_FB => ipc::DrmModeFbCmd::with(payload, |mut data| { let fb = self.objects.get_framebuffer(KmsObjectId(data.fb_id()))?; + let (bpp, depth) = match fb.pixel_format { + DrmFourcc::Xrgb8888 => (32, 24), + DrmFourcc::Argb8888 => (32, 32), + _ => todo!(), + }; + *next_id += 1; buffers.insert(*next_id, fb.buffer.clone()); data.set_width(fb.width); data.set_height(fb.height); data.set_pitch(fb.pitch); - data.set_bpp(fb.bpp); - data.set_depth(fb.depth); + data.set_bpp(bpp); + data.set_depth(depth); data.set_handle(*next_id); Ok(0) }), ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |mut data| { let buffer = buffers.get(&data.handle()).ok_or(Error::new(EINVAL))?; + if data.bpp() != 32 { + return Err(Error::new(EINVAL)); + } + let pixel_format = match data.depth() { + 24 => DrmFourcc::Xrgb8888, + 32 => DrmFourcc::Argb8888, + _ => return Err(Error::new(EINVAL)), + }; + let fb = self.adapter.create_framebuffer(buffer); let id = self.objects.add_framebuffer(objects::KmsFramebuffer { width: data.width(), height: data.height(), + pixel_format, pitch: data.pitch(), - bpp: data.bpp(), - depth: data.depth(), buffer: buffer.clone(), driver_data: fb, }); @@ -915,6 +929,27 @@ impl SchemeSync for GraphicsSchemeInner { data.set_plane_id_ptr(&ids); Ok(0) }), + ipc::MODE_ADD_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| { + // FIXME handle multi-plane framebuffers + + let buffer = buffers.get(&data.handles()[0]).ok_or(Error::new(EINVAL))?; + + let fb = self.adapter.create_framebuffer(buffer); + + let id = self.objects.add_framebuffer(objects::KmsFramebuffer { + width: data.width(), + height: data.height(), + pixel_format: DrmFourcc::try_from(data.pixel_format()) + .map_err(|_| Error::new(EINVAL))?, + pitch: data.pitches()[0], + buffer: buffer.clone(), + driver_data: fb, + }); + + data.set_fb_id(id.0); + + Ok(0) + }), ipc::MODE_GET_PLANE => ipc::DrmModeGetPlane::with(payload, |mut data| { let i = id_index(data.plane_id()); let crtc_id = self.objects.crtc_ids()[i as usize]; @@ -987,9 +1022,9 @@ impl SchemeSync for GraphicsSchemeInner { data.set_width(fb.width); data.set_height(fb.height); - data.set_pixel_format(DrmFourcc::Argb8888 as u32); + data.set_pixel_format(fb.pixel_format as u32); data.set_handles([*next_id, 0, 0, 0]); - data.set_pitches([fb.width * 4, 0, 0, 0]); + data.set_pitches([fb.pitch, 0, 0, 0]); data.set_offsets([0; 4]); data.set_modifier([0; 4]); Ok(0) diff --git a/drivers/graphics/ihdgd/Cargo.toml b/drivers/graphics/ihdgd/Cargo.toml index 25d04eac8b..a76ec92e98 100644 --- a/drivers/graphics/ihdgd/Cargo.toml +++ b/drivers/graphics/ihdgd/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] bitbang-hal = "0.3" +drm-fourcc.workspace = true drm-sys.workspace = true edid.workspace = true #TODO: edid is abandoned, fork it and maintain? #TODO: waiting for bitbang-hal to update to embedded-hal 1.0 diff --git a/drivers/graphics/ihdgd/src/device/mod.rs b/drivers/graphics/ihdgd/src/device/mod.rs index a30b4f7ab7..607dcea0ab 100644 --- a/drivers/graphics/ihdgd/src/device/mod.rs +++ b/drivers/graphics/ihdgd/src/device/mod.rs @@ -4,6 +4,7 @@ use common::{ }; use driver_graphics::kms::connector::KmsConnectorStatus; use driver_graphics::kms::objects::{KmsFramebuffer, KmsObjects}; +use drm_fourcc::DrmFourcc; use pcid_interface::{PciFunction, PciFunctionHandle}; use range_alloc::RangeAllocator; use std::{collections::VecDeque, fmt, mem, sync::Arc}; @@ -766,9 +767,8 @@ impl Device { let fb = KmsFramebuffer { width, height, + pixel_format: DrmFourcc::Argb8888, pitch: stride, - bpp: 32, - depth: 32, buffer: Arc::new(buffer), driver_data: (), }; diff --git a/drivers/graphics/ihdgd/src/device/pipe.rs b/drivers/graphics/ihdgd/src/device/pipe.rs index f36b0730a5..dde76a1f2a 100644 --- a/drivers/graphics/ihdgd/src/device/pipe.rs +++ b/drivers/graphics/ihdgd/src/device/pipe.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use common::io::{Io, MmioPtr}; use driver_graphics::kms::objects::KmsFramebuffer; +use drm_fourcc::DrmFourcc; use range_alloc::RangeAllocator; use syscall::error::Result; use syscall::{Error, EIO}; @@ -94,9 +95,8 @@ impl Plane { KmsFramebuffer { width, height, + pixel_format: DrmFourcc::Argb8888, pitch: stride, - bpp: 32, - depth: 32, buffer: Arc::new(buffer), driver_data: (), }