From df845d6566c3e511fc500bab81bba7822fe8d840 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 14 May 2026 17:32:39 +0200 Subject: [PATCH] drivers/graphics/driver-graphics: Move framebuffer ioctls to a separate module --- .../driver-graphics/src/ioctl/framebuffer.rs | 196 ++++++++++++++++++ .../graphics/driver-graphics/src/ioctl/mod.rs | 160 ++------------ 2 files changed, 209 insertions(+), 147 deletions(-) create mode 100644 drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs diff --git a/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs b/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs new file mode 100644 index 0000000000..d6ccdd645e --- /dev/null +++ b/drivers/graphics/driver-graphics/src/ioctl/framebuffer.rs @@ -0,0 +1,196 @@ +use std::collections::HashMap; + +use drm_fourcc::DrmFourcc; +use syscall::{Error, EINVAL}; + +use crate::kms::objects::{KmsFramebuffer, KmsObjectId, KmsObjects}; +use crate::{Damage, DrmHandle, GraphicsAdapter, VtState}; + +pub(super) fn mode_get_fb( + objects: &mut KmsObjects, + handle: &mut DrmHandle, + mut data: redox_ioctl::drm::DrmModeFbCmd<'_>, +) -> Result { + let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?; + + let (bpp, depth) = match fb.pixel_format { + DrmFourcc::Xrgb8888 => (32, 24), + DrmFourcc::Argb8888 => (32, 32), + _ => todo!(), + }; + + handle.next_id += 1; + handle.buffers.insert(handle.next_id, fb.buffer.clone()); + + data.set_width(fb.width); + data.set_height(fb.height); + data.set_pitch(fb.pitch); + data.set_bpp(bpp); + data.set_depth(depth); + data.set_handle(handle.next_id); + Ok(0) +} + +pub(super) fn mode_add_fb( + adapter: &mut T, + objects: &mut KmsObjects, + handle: &mut DrmHandle, + mut data: redox_ioctl::drm::DrmModeFbCmd<'_>, +) -> Result { + let buffer = handle + .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 = adapter.create_framebuffer(buffer); + + let id = objects.add_framebuffer(KmsFramebuffer { + width: data.width(), + height: data.height(), + pixel_format, + pitch: data.pitch(), + buffer: buffer.clone(), + driver_data: fb, + }); + + data.set_fb_id(id.0); + + Ok(0) +} + +pub(super) fn mode_rm_fb( + adapter: &mut T, + objects: &mut KmsObjects, + active_vt: usize, + vts: &mut HashMap>, + data: redox_ioctl::drm::StandinForUint<'_>, +) -> Result { + let fb_id = KmsObjectId(data.inner()); + objects.remove_framebuffer(fb_id)?; + + // Disable planes that use this framebuffer. + for (vt, vt_data) in vts { + for (plane_idx, plane_state) in vt_data.plane_state.iter_mut().enumerate() { + if plane_state.fb_id != Some(fb_id) { + continue; + } + plane_state.fb_id = None; + + if *vt != active_vt { + continue; + } + let plane = objects.planes().nth(plane_idx).unwrap(); + adapter + .set_plane( + &objects, + plane, + plane_state.clone(), + Damage { + x: 0, + y: 0, + width: 0, + height: 0, + }, + ) + .unwrap(); + } + } + + Ok(0) +} + +pub(super) fn mode_dirtyfb( + adapter: &mut T, + objects: &mut KmsObjects, + active_vt: usize, + handle: &mut DrmHandle, + data: redox_ioctl::drm::DrmModeFbDirtyCmd<'_>, +) -> Result { + let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?; + + let damage = data + .clips_ptr() + .iter() + .map(|rect| Damage { + x: u32::from(rect.x1), + y: u32::from(rect.y1), + width: u32::from(rect.x2 - rect.x1), + height: u32::from(rect.y2 - rect.y1), + }) + .reduce(Damage::merge) + .unwrap_or(Damage { + x: 0, + y: 0, + width: fb.width, + height: fb.height, + }); + + if handle.vt == active_vt { + for plane in objects.planes() { + let state = plane.lock().unwrap().state.clone(); + if state.fb_id == Some(KmsObjectId(data.fb_id())) { + adapter.set_plane(&objects, plane, state, damage)?; + } + } + } + + Ok(0) +} + +pub(super) fn mode_add_fb2( + adapter: &mut T, + objects: &mut KmsObjects, + handle: &mut DrmHandle, + mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>, +) -> Result { + // FIXME handle multi-plane framebuffers + + let buffer = handle + .buffers + .get(&data.handles()[0]) + .ok_or(Error::new(EINVAL))?; + + let fb = adapter.create_framebuffer(buffer); + + let id = objects.add_framebuffer(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) +} + +pub(super) fn mode_get_fb2( + objects: &mut KmsObjects, + handle: &mut DrmHandle, + mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>, +) -> Result { + let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?; + + handle.next_id += 1; + handle.buffers.insert(handle.next_id, fb.buffer.clone()); + + data.set_width(fb.width); + data.set_height(fb.height); + data.set_pixel_format(fb.pixel_format as u32); + data.set_handles([handle.next_id, 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/driver-graphics/src/ioctl/mod.rs b/drivers/graphics/driver-graphics/src/ioctl/mod.rs index 20b8732119..eb67e9452d 100644 --- a/drivers/graphics/driver-graphics/src/ioctl/mod.rs +++ b/drivers/graphics/driver-graphics/src/ioctl/mod.rs @@ -11,10 +11,12 @@ use drm_sys::{ }; use syscall::{Error, EINVAL, ENOENT, ENXIO}; -use crate::kms::objects::{self, KmsObjectId, KmsObjects, KmsRect}; +use crate::kms::objects::{KmsObjectId, KmsObjects, KmsRect}; use crate::kms::properties::KmsPropertyKind; use crate::{Buffer, Damage, DrmHandle, GraphicsAdapter, VtState, MAP_FAKE_OFFSET_MULTIPLIER}; +mod framebuffer; + pub(crate) fn call_ioctl( adapter: &mut T, objects: &mut KmsObjects, @@ -322,120 +324,17 @@ pub(crate) fn call_ioctl( data.set_data(&blob); Ok(0) }), - ipc::MODE_GET_FB => ipc::DrmModeFbCmd::with(payload, |mut data| { - let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?; - - let (bpp, depth) = match fb.pixel_format { - DrmFourcc::Xrgb8888 => (32, 24), - DrmFourcc::Argb8888 => (32, 32), - _ => todo!(), - }; - - handle.next_id += 1; - handle.buffers.insert(handle.next_id, fb.buffer.clone()); - - data.set_width(fb.width); - data.set_height(fb.height); - data.set_pitch(fb.pitch); - data.set_bpp(bpp); - data.set_depth(depth); - data.set_handle(handle.next_id); - Ok(0) + ipc::MODE_GET_FB => ipc::DrmModeFbCmd::with(payload, |data| { + framebuffer::mode_get_fb(objects, handle, data) }), - ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |mut data| { - let buffer = handle - .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 = adapter.create_framebuffer(buffer); - - let id = objects.add_framebuffer(objects::KmsFramebuffer { - width: data.width(), - height: data.height(), - pixel_format, - pitch: data.pitch(), - buffer: buffer.clone(), - driver_data: fb, - }); - - data.set_fb_id(id.0); - - Ok(0) + ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |data| { + framebuffer::mode_add_fb(adapter, objects, handle, data) }), ipc::MODE_RM_FB => ipc::StandinForUint::with(payload, |data| { - let fb_id = KmsObjectId(data.inner()); - objects.remove_framebuffer(fb_id)?; - - // Disable planes that use this framebuffer. - for (vt, vt_data) in vts { - for (plane_idx, plane_state) in vt_data.plane_state.iter_mut().enumerate() { - if plane_state.fb_id != Some(fb_id) { - continue; - } - plane_state.fb_id = None; - - if *vt != active_vt { - continue; - } - let plane = objects.planes().nth(plane_idx).unwrap(); - adapter - .set_plane( - &objects, - plane, - plane_state.clone(), - Damage { - x: 0, - y: 0, - width: 0, - height: 0, - }, - ) - .unwrap(); - } - } - - Ok(0) + framebuffer::mode_rm_fb(adapter, objects, active_vt, vts, data) }), ipc::MODE_DIRTYFB => ipc::DrmModeFbDirtyCmd::with(payload, |data| { - let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?; - - let damage = data - .clips_ptr() - .iter() - .map(|rect| Damage { - x: u32::from(rect.x1), - y: u32::from(rect.y1), - width: u32::from(rect.x2 - rect.x1), - height: u32::from(rect.y2 - rect.y1), - }) - .reduce(Damage::merge) - .unwrap_or(Damage { - x: 0, - y: 0, - width: fb.width, - height: fb.height, - }); - - if handle.vt == active_vt { - for plane in objects.planes() { - let state = plane.lock().unwrap().state.clone(); - if state.fb_id == Some(KmsObjectId(data.fb_id())) { - adapter.set_plane(&objects, plane, state, damage)?; - } - } - } - - Ok(0) + framebuffer::mode_dirtyfb(adapter, objects, active_vt, handle, data) }), ipc::MODE_CREATE_DUMB => ipc::DrmModeCreateDumb::with(payload, |mut data| { if data.bpp() != 32 || data.flags() != 0 { @@ -548,29 +447,8 @@ pub(crate) fn call_ioctl( data.set_format_type_ptr(&[DrmFourcc::Argb8888 as u32]); Ok(0) }), - ipc::MODE_ADD_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| { - // FIXME handle multi-plane framebuffers - - let buffer = handle - .buffers - .get(&data.handles()[0]) - .ok_or(Error::new(EINVAL))?; - - let fb = adapter.create_framebuffer(buffer); - - let id = 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_ADD_FB2 => ipc::DrmModeFbCmd2::with(payload, |data| { + framebuffer::mode_add_fb2(adapter, objects, handle, data) }), ipc::MODE_OBJ_GET_PROPERTIES => ipc::DrmModeObjGetProperties::with(payload, |mut data| { let (props, prop_vals) = @@ -609,20 +487,8 @@ pub(crate) fn call_ioctl( Ok(0) }), - ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| { - let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?; - - handle.next_id += 1; - handle.buffers.insert(handle.next_id, fb.buffer.clone()); - - data.set_width(fb.width); - data.set_height(fb.height); - data.set_pixel_format(fb.pixel_format as u32); - data.set_handles([handle.next_id, 0, 0, 0]); - data.set_pitches([fb.pitch, 0, 0, 0]); - data.set_offsets([0; 4]); - data.set_modifier([0; 4]); - Ok(0) + ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |data| { + framebuffer::mode_get_fb2(objects, handle, data) }), _ => return Err(Error::new(EINVAL)), }