Merge branch 'gpu_drm40' into 'main'

drivers/graphics/driver-graphics: Implement some things that libdrm needs

See merge request redox-os/base!265
This commit is contained in:
Jeremy Soller
2026-05-14 07:01:32 -06:00
12 changed files with 111 additions and 16 deletions
Generated
+2 -1
View File
@@ -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",
+1
View File
@@ -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"
+1 -1
View File
@@ -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
@@ -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<T: GraphicsAdapter> {
pub struct KmsFramebuffer<T: GraphicsAdapter> {
pub width: u32,
pub height: u32,
pub pixel_format: DrmFourcc,
pub pitch: u32,
pub bpp: u32,
pub depth: u32,
pub buffer: Arc<T::Buffer>,
pub driver_data: T::Framebuffer,
}
+82 -8
View File
@@ -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<Self>);
fn get_unique(&self) -> String;
fn get_cap(&self, cap: u32) -> Result<u64>;
fn set_client_cap(&self, cap: u32, value: u64) -> Result<()>;
@@ -281,6 +283,7 @@ struct VtState<T: GraphicsAdapter> {
enum Handle<T: GraphicsAdapter> {
V2 {
vt: usize,
unique: Option<String>,
next_id: u32,
buffers: HashMap<u32, Arc<T::Buffer>>,
},
@@ -414,6 +417,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Handle::V2 {
vt,
unique: None,
next_id: 0,
buffers: HashMap::new(),
}
@@ -427,11 +431,17 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
})
}
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<usize> {
FpathWriter::with(buf, &self.scheme_name, |w| {
match self.handles.get(id)? {
Handle::V2 {
vt,
unique: _,
next_id: _,
buffers: _,
} => write!(w, "v2/{vt}").unwrap(),
@@ -462,6 +472,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)),
Handle::V2 {
vt,
unique,
next_id,
buffers,
} => match metadata[0] {
@@ -476,12 +487,39 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
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 +528,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
self.adapter.set_client_cap(
data.capability()
.try_into()
.map_err(|_| syscall::Error::new(EINVAL))?,
.map_err(|_| Error::new(EINVAL))?,
data.value(),
)?;
Ok(0)
@@ -733,28 +771,42 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
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,
});
@@ -877,6 +929,27 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
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];
@@ -949,9 +1022,9 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
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)
@@ -973,6 +1046,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
let (framebuffer, offset) = match self.handles.get(id)? {
Handle::V2 {
vt: _,
unique: _,
next_id: _,
buffers,
} => (
+1
View File
@@ -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
+4 -2
View File
@@ -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};
@@ -168,6 +169,7 @@ enum VideoInput {
}
pub struct Device {
unique: String,
kind: DeviceKind,
alloc_buffers: RangeAllocator<u32>,
bios: Option<Bios>,
@@ -426,6 +428,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,
@@ -764,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: (),
};
+2 -2
View File
@@ -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: (),
}
@@ -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<u64> {
match cap {
DRM_CAP_DUMB_BUFFER => Ok(1),
+4
View File
@@ -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<u64> {
match cap {
DRM_CAP_DUMB_BUFFER => Ok(1),
+1
View File
@@ -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(),
@@ -88,6 +88,7 @@ pub struct Display {
}
pub struct VirtGpuAdapter<'a> {
unique: String,
pub config: &'a mut GpuConfig,
control_queue: Arc<Queue<'a>>,
cursor_queue: Arc<Queue<'a>>,
@@ -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<u64> {
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<Queue<'a>>,
cursor_queue: Arc<Queue<'a>>,
@@ -528,6 +534,7 @@ impl<'a> GpuScheme {
has_edid: bool,
) -> Result<GraphicsScheme<VirtGpuAdapter<'a>>, Error> {
let adapter = VirtGpuAdapter {
unique,
config,
control_queue,
cursor_queue,