Merge branch 'gpu_drm44' into 'main'

drivers/graphics/driver-graphics: Implement DRM_IOCTL_MODE_CLOSEFB

See merge request redox-os/base!292
This commit is contained in:
Jeremy Soller
2026-07-01 14:13:58 -06:00
14 changed files with 125 additions and 35 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
name = "driver-graphics"
description = "Shared video and graphics code library"
version = "0.1.0"
edition = "2021"
edition = "2024"
[dependencies]
drm-fourcc.workspace = true
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use drm_sys::{DRM_MODE_CURSOR_BO, DRM_MODE_CURSOR_MOVE};
use syscall::{Error, ENOENT, ENXIO};
use syscall::{ENOENT, ENXIO, Error};
use crate::{DrmHandle, GraphicsAdapter, VtState};
@@ -1,7 +1,8 @@
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use drm_fourcc::DrmFourcc;
use syscall::{Error, EINVAL};
use syscall::{EINVAL, Error};
use crate::kms::objects::{KmsFramebuffer, KmsObjectId, KmsObjects};
use crate::{Damage, DrmHandle, GraphicsAdapter, VtState};
@@ -11,7 +12,7 @@ pub(super) fn mode_get_fb<T: GraphicsAdapter>(
handle: &mut DrmHandle<T>,
mut data: redox_ioctl::drm::DrmModeFbCmd<'_>,
) -> Result<usize, Error> {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
let fb = objects.get_framebuffer_maybe_closed(KmsObjectId(data.fb_id()))?;
let (bpp, depth) = match fb.pixel_format {
DrmFourcc::Xrgb8888 => (32, 24),
@@ -54,6 +55,7 @@ pub(super) fn mode_add_fb<T: GraphicsAdapter>(
let fb = adapter.create_framebuffer(buffer);
let id = objects.add_framebuffer(KmsFramebuffer {
closed: AtomicBool::new(false),
width: data.width(),
height: data.height(),
pixel_format,
@@ -162,6 +164,7 @@ pub(super) fn mode_add_fb2<T: GraphicsAdapter>(
let fb = adapter.create_framebuffer(buffer);
let id = objects.add_framebuffer(KmsFramebuffer {
closed: AtomicBool::new(false),
width: data.width(),
height: data.height(),
pixel_format: DrmFourcc::try_from(data.pixel_format()).map_err(|_| Error::new(EINVAL))?,
@@ -180,7 +183,7 @@ pub(super) fn mode_get_fb2<T: GraphicsAdapter>(
handle: &mut DrmHandle<T>,
mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>,
) -> Result<usize, Error> {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
let fb = objects.get_framebuffer_maybe_closed(KmsObjectId(data.fb_id()))?;
handle.next_id += 1;
handle.buffers.insert(handle.next_id, fb.buffer.clone());
@@ -194,3 +197,19 @@ pub(super) fn mode_get_fb2<T: GraphicsAdapter>(
data.set_modifier([0; 4]);
Ok(0)
}
pub(super) fn mode_close_fb<T: GraphicsAdapter>(
objects: &mut KmsObjects<T>,
vts: &mut HashMap<usize, VtState<T>>,
data: redox_ioctl::drm::DrmModeClosefb<'_>,
) -> Result<usize, Error> {
let fb_id = KmsObjectId(data.fb_id());
let fb = objects.get_framebuffer(fb_id)?;
fb.closed.store(true, Ordering::SeqCst);
if !VtState::fb_has_any_use(vts, fb_id) {
objects.remove_framebuffer(fb_id).unwrap();
}
Ok(0)
}
@@ -4,10 +4,10 @@ use std::mem;
use std::sync::Arc;
use drm_fourcc::DrmFourcc;
use syscall::{Error, EINVAL, ENOENT};
use syscall::{EINVAL, ENOENT, Error};
use crate::kms::objects::{KmsObjectId, KmsObjects, KmsRect};
use crate::{Buffer, Damage, DrmHandle, GraphicsAdapter, VtState, MAP_FAKE_OFFSET_MULTIPLIER};
use crate::{Buffer, Damage, DrmHandle, GraphicsAdapter, MAP_FAKE_OFFSET_MULTIPLIER, VtState};
mod cursor;
mod framebuffer;
@@ -144,7 +144,9 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
.map(|&id| KmsObjectId(id))
.collect();
let fb_id = if data.fb_id() != 0 {
Some(KmsObjectId(data.fb_id()))
let fb_id = KmsObjectId(data.fb_id());
objects.get_framebuffer(fb_id)?;
Some(fb_id)
} else {
None
};
@@ -159,6 +161,7 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
let mut new_crtc_state = crtc.lock().unwrap().state.clone();
new_crtc_state.mode = mode;
let mut new_plane_state = plane.lock().unwrap().state.clone();
let old_fb_id = new_plane_state.fb_id;
new_plane_state.fb_id = fb_id;
new_plane_state.crtc_id = Some(crtc_id);
if handle.vt == active_vt {
@@ -189,6 +192,13 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
new_crtc_state;
vts.get_mut(&handle.vt).unwrap().plane_state
[plane.lock().unwrap().plane_index as usize] = new_plane_state;
if let Some(old_fb_id) = old_fb_id {
if !VtState::fb_has_any_use(vts, old_fb_id) {
objects.remove_framebuffer_if_closed(old_fb_id);
}
}
Ok(0)
}),
ipc::MODE_CURSOR => ipc::DrmModeCursor::with(payload, |data| {
@@ -305,11 +315,14 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
plane.state.clone()
};
let fb_id = if data.fb_id() != 0 {
KmsObjectId(data.fb_id())
let fb_id = KmsObjectId(data.fb_id());
objects.get_framebuffer(fb_id)?;
Some(fb_id)
} else {
KmsObjectId::INVALID
None
};
new_state.fb_id = Some(fb_id);
let old_fb_id = new_state.fb_id;
new_state.fb_id = fb_id;
new_state.crtc_id = Some(crtc_id);
new_state.src_rect = KmsRect {
x: data.src_x(),
@@ -339,6 +352,13 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
}
vts.get_mut(&handle.vt).unwrap().plane_state
[plane.lock().unwrap().plane_index as usize] = new_state;
if let Some(old_fb_id) = old_fb_id {
if !VtState::fb_has_any_use(vts, old_fb_id) {
objects.remove_framebuffer_if_closed(old_fb_id);
}
}
Ok(0)
}),
ipc::MODE_GET_PLANE => ipc::DrmModeGetPlane::with(payload, |mut data| {
@@ -365,6 +385,9 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |data| {
framebuffer::mode_get_fb2(objects, handle, data)
}),
ipc::MODE_CLOSE_FB => ipc::DrmModeClosefb::with(payload, |data| {
framebuffer::mode_close_fb(objects, vts, data)
}),
_ => return Err(Error::new(EINVAL)),
}
}
@@ -1,13 +1,13 @@
use drm_sys::{
drm_mode_property_enum, 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_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_mode_property_enum,
};
use syscall::Error;
use crate::GraphicsAdapter;
use crate::kms::objects::{KmsObjectId, KmsObjects};
use crate::kms::properties::KmsPropertyKind;
use crate::GraphicsAdapter;
pub(super) fn mode_get_property<T: GraphicsAdapter>(
objects: &mut KmsObjects<T>,
@@ -3,14 +3,14 @@ use std::fmt::Debug;
use std::sync::Mutex;
use drm_sys::{
drm_mode_modeinfo, DRM_MODE_CONNECTOR_Unknown, DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON,
DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND, DRM_MODE_TYPE_PREFERRED,
DRM_MODE_CONNECTOR_Unknown, DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY,
DRM_MODE_DPMS_SUSPEND, DRM_MODE_TYPE_PREFERRED, drm_mode_modeinfo,
};
use syscall::Result;
use crate::kms::objects::{KmsObjectId, KmsObjects};
use crate::kms::properties::{define_object_props, KmsPropertyData, CRTC_ID, DPMS, EDID, TILE};
use crate::GraphicsAdapter;
use crate::kms::objects::{KmsObjectId, KmsObjects};
use crate::kms::properties::{CRTC_ID, DPMS, EDID, KmsPropertyData, TILE, define_object_props};
impl<T: GraphicsAdapter> KmsObjects<T> {
pub fn add_connector(
@@ -1,22 +1,23 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, Ordering};
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_PLANE, DRM_MODE_OBJECT_PROPERTY,
DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_PRIMARY,
DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_ENCODER,
DRM_MODE_OBJECT_FB, DRM_MODE_OBJECT_PLANE, DRM_MODE_OBJECT_PROPERTY, DRM_PLANE_TYPE_CURSOR,
DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_PRIMARY, drm_mode_modeinfo,
};
use syscall::{Error, Result, ENOENT};
use syscall::{ENOENT, Error, Result};
use crate::GraphicsAdapter;
use crate::kms::connector::{KmsConnector, KmsEncoder};
use crate::kms::properties::{
define_object_props, init_standard_props, type_, KmsBlob, KmsProperty, KmsPropertyData, ACTIVE,
CRTC_H, CRTC_ID, CRTC_W, CRTC_X, CRTC_Y, FB_ID, SRC_H, SRC_W, SRC_X, SRC_Y,
ACTIVE, CRTC_H, CRTC_ID, CRTC_W, CRTC_X, CRTC_Y, FB_ID, KmsBlob, KmsProperty, KmsPropertyData,
SRC_H, SRC_W, SRC_X, SRC_Y, define_object_props, init_standard_props, type_,
};
use crate::GraphicsAdapter;
#[derive(Debug)]
pub struct KmsObjects<T: GraphicsAdapter> {
@@ -192,12 +193,31 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
self.remove::<KmsFramebuffer<T>>(id)
}
pub fn remove_framebuffer_if_closed(&mut self, id: KmsObjectId) {
if self
.get_framebuffer_maybe_closed(id)
.unwrap()
.closed
.load(Ordering::SeqCst)
{
self.remove::<KmsFramebuffer<T>>(id).unwrap();
}
}
pub fn fb_ids(&self) -> &[KmsObjectId] {
&self.framebuffers
}
pub fn get_framebuffer(&self, id: KmsObjectId) -> Result<&KmsFramebuffer<T>> {
self.get(id)
let fb = self.get::<KmsFramebuffer<T>>(id)?;
if fb.closed.load(Ordering::SeqCst) {
return Err(Error::new(ENOENT));
}
Ok(fb)
}
pub fn get_framebuffer_maybe_closed(&self, id: KmsObjectId) -> Result<&KmsFramebuffer<T>> {
self.get::<KmsFramebuffer<T>>(id)
}
}
@@ -395,6 +415,15 @@ pub struct KmsRect<T> {
#[derive(Debug)]
pub struct KmsFramebuffer<T: GraphicsAdapter> {
/// Was this framebuffer closed using the CLOSEFB ioctl or implicitly
/// created by the CURSOR or CURSOR2 ioctls or similar?
///
/// A closed framebuffer will be destroyed as soon as the last plane that
/// uses it switches to a different framebuffer. In the mean time the GETFB
/// and GETFB2 ioctls still function on it, but anything else will result
/// in ENOENT, including another CLOSEFB call.
pub closed: AtomicBool,
pub width: u32,
pub height: u32,
pub pixel_format: DrmFourcc,
@@ -7,10 +7,10 @@ use drm_sys::{
DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_FB, DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY,
DRM_PLANE_TYPE_PRIMARY, DRM_PROP_NAME_LEN,
};
use syscall::{Error, Result, ENOENT};
use syscall::{ENOENT, Error, Result};
use crate::kms::objects::{KmsObject, KmsObjectId, KmsObjects};
use crate::GraphicsAdapter;
use crate::kms::objects::{KmsObject, KmsObjectId, KmsObjects};
impl<T: GraphicsAdapter> KmsObjects<T> {
pub fn add_property(
+18 -3
View File
@@ -10,11 +10,11 @@ use std::sync::{Arc, Mutex};
use inputd::{DisplayHandle, VtEventKind};
use libredox::Fd;
use redox_scheme::scheme::{register_scheme_inner, SchemeState, SchemeSync};
use redox_scheme::scheme::{SchemeState, SchemeSync, register_scheme_inner};
use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket};
use scheme_utils::{FpathWriter, HandleMap};
use syscall::schemev2::NewFdFlags;
use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EINVAL, ENOENT, EOPNOTSUPP};
use syscall::{EACCES, EAGAIN, EINVAL, ENOENT, EOPNOTSUPP, Error, MapFlags, Result};
use crate::kms::connector::{KmsConnectorDriver, KmsConnectorState};
use crate::kms::objects::{
@@ -284,6 +284,21 @@ struct VtState<T: GraphicsAdapter> {
cursor_plane: Option<CursorPlane<T::Buffer>>,
}
impl<T: GraphicsAdapter> VtState<T> {
fn fb_has_any_use(vts: &HashMap<usize, Self>, fb_id: KmsObjectId) -> bool {
let mut has_any_use = false;
for vt_data in vts.values() {
for plane_state in vt_data.plane_state.iter() {
if plane_state.fb_id == Some(fb_id) {
has_any_use = true;
break;
}
}
}
has_any_use
}
}
enum Handle<T: GraphicsAdapter> {
V2(DrmHandle<T>),
SchemeRoot,
@@ -377,7 +392,7 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
let fb = plane_state.fb_id.map(|fb_id| {
self.objects
.get_framebuffer(fb_id)
.get_framebuffer_maybe_closed(fb_id)
.expect("removed framebuffers should be unset")
});
+2
View File
@@ -7,6 +7,7 @@ use driver_graphics::kms::objects::{KmsFramebuffer, KmsObjects};
use drm_fourcc::DrmFourcc;
use pcid_interface::{PciFunction, PciFunctionHandle};
use range_alloc::RangeAllocator;
use std::sync::atomic::AtomicBool;
use std::{collections::VecDeque, fmt, mem, sync::Arc};
use syscall::error::{Error, Result, EIO, ENODEV, ERANGE};
@@ -776,6 +777,7 @@ impl Device {
GpuBuffer::alloc_dumb(&self.gm, &mut self.ggtt, width, height)?;
let fb = KmsFramebuffer {
closed: AtomicBool::new(true),
width,
height,
pixel_format: DrmFourcc::Argb8888,
@@ -1,3 +1,4 @@
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use common::io::{Io, MmioPtr};
@@ -93,6 +94,7 @@ impl Plane {
let buffer = unsafe { GpuBuffer::new(gm, surf, stride * height, true) };
KmsFramebuffer {
closed: AtomicBool::new(true),
width,
height,
pixel_format: DrmFourcc::Argb8888,
+1 -1
View File
@@ -121,7 +121,7 @@ impl GraphicsAdapter for Device {
let buffer = new_plane_state
.fb_id
.map(|fb_id| objects.get_framebuffer(fb_id))
.map(|fb_id| objects.get_framebuffer_maybe_closed(fb_id))
.transpose()?;
plane.state = new_plane_state;
+1 -1
View File
@@ -130,7 +130,7 @@ impl GraphicsAdapter for FbAdapter {
let buffer = new_plane_state
.fb_id
.map(|fb_id| objects.get_framebuffer(fb_id))
.map(|fb_id| objects.get_framebuffer_maybe_closed(fb_id))
.transpose()?;
plane.state = new_plane_state;
+1 -1
View File
@@ -452,7 +452,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
let framebuffer = new_plane_state
.fb_id
.map(|fb_id| objects.get_framebuffer(fb_id))
.map(|fb_id| objects.get_framebuffer_maybe_closed(fb_id))
.transpose()?;
plane.state = new_plane_state;