diff --git a/drivers/graphics/driver-graphics/Cargo.toml b/drivers/graphics/driver-graphics/Cargo.toml index fee6246dd3..3cf30f4cd0 100644 --- a/drivers/graphics/driver-graphics/Cargo.toml +++ b/drivers/graphics/driver-graphics/Cargo.toml @@ -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 diff --git a/drivers/graphics/driver-graphics/src/ioctl/cursor.rs b/drivers/graphics/driver-graphics/src/ioctl/cursor.rs index 5781fc69bb..ffb79a8a88 100644 --- a/drivers/graphics/driver-graphics/src/ioctl/cursor.rs +++ b/drivers/graphics/driver-graphics/src/ioctl/cursor.rs @@ -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}; diff --git a/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs b/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs index d6ccdd645e..5856388335 100644 --- a/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs +++ b/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs @@ -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( handle: &mut DrmHandle, mut data: redox_ioctl::drm::DrmModeFbCmd<'_>, ) -> Result { - 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( 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( 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( handle: &mut DrmHandle, mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>, ) -> Result { - 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( data.set_modifier([0; 4]); Ok(0) } + +pub(super) fn mode_close_fb( + objects: &mut KmsObjects, + vts: &mut HashMap>, + data: redox_ioctl::drm::DrmModeClosefb<'_>, +) -> Result { + 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) +} diff --git a/drivers/graphics/driver-graphics/src/ioctl/mod.rs b/drivers/graphics/driver-graphics/src/ioctl/mod.rs index 1c050d9b42..649c34d6e3 100644 --- a/drivers/graphics/driver-graphics/src/ioctl/mod.rs +++ b/drivers/graphics/driver-graphics/src/ioctl/mod.rs @@ -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( .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( 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( 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( 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( } 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( 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)), } } diff --git a/drivers/graphics/driver-graphics/src/ioctl/property.rs b/drivers/graphics/driver-graphics/src/ioctl/property.rs index b79d782e96..72489de228 100644 --- a/drivers/graphics/driver-graphics/src/ioctl/property.rs +++ b/drivers/graphics/driver-graphics/src/ioctl/property.rs @@ -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( objects: &mut KmsObjects, diff --git a/drivers/graphics/driver-graphics/src/kms/connector.rs b/drivers/graphics/driver-graphics/src/kms/connector.rs index 96b18dfbd3..b63875ba74 100644 --- a/drivers/graphics/driver-graphics/src/kms/connector.rs +++ b/drivers/graphics/driver-graphics/src/kms/connector.rs @@ -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 KmsObjects { pub fn add_connector( diff --git a/drivers/graphics/driver-graphics/src/kms/objects.rs b/drivers/graphics/driver-graphics/src/kms/objects.rs index fe343e80b7..ffd320800f 100644 --- a/drivers/graphics/driver-graphics/src/kms/objects.rs +++ b/drivers/graphics/driver-graphics/src/kms/objects.rs @@ -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 { @@ -192,12 +193,31 @@ impl KmsObjects { self.remove::>(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::>(id).unwrap(); + } + } + pub fn fb_ids(&self) -> &[KmsObjectId] { &self.framebuffers } pub fn get_framebuffer(&self, id: KmsObjectId) -> Result<&KmsFramebuffer> { - self.get(id) + let fb = self.get::>(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> { + self.get::>(id) } } @@ -395,6 +415,15 @@ pub struct KmsRect { #[derive(Debug)] pub struct KmsFramebuffer { + /// 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, diff --git a/drivers/graphics/driver-graphics/src/kms/properties.rs b/drivers/graphics/driver-graphics/src/kms/properties.rs index deca140d26..7531e5c0f6 100644 --- a/drivers/graphics/driver-graphics/src/kms/properties.rs +++ b/drivers/graphics/driver-graphics/src/kms/properties.rs @@ -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 KmsObjects { pub fn add_property( diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index c9a7b5157d..dddaf9c5e3 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -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 { cursor_plane: Option>, } +impl VtState { + fn fb_has_any_use(vts: &HashMap, 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 { V2(DrmHandle), SchemeRoot, @@ -377,7 +392,7 @@ impl GraphicsSchemeInner { 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") }); diff --git a/drivers/graphics/ihdgd/src/device/mod.rs b/drivers/graphics/ihdgd/src/device/mod.rs index 142d1bc266..941d19f4bb 100644 --- a/drivers/graphics/ihdgd/src/device/mod.rs +++ b/drivers/graphics/ihdgd/src/device/mod.rs @@ -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, diff --git a/drivers/graphics/ihdgd/src/device/pipe.rs b/drivers/graphics/ihdgd/src/device/pipe.rs index dde76a1f2a..cede2d2fd0 100644 --- a/drivers/graphics/ihdgd/src/device/pipe.rs +++ b/drivers/graphics/ihdgd/src/device/pipe.rs @@ -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, diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 4cc81b050a..ad4fe2b296 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -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; diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index 002b112390..56d5d7370e 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -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; diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index f3d0aed693..fd83dc473e 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -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;