From 84f6f67a9807de64cc55ec306b96b8182cd48d79 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 14 Mar 2026 13:54:56 +0100 Subject: [PATCH] drivers/graphics: Implement the cursor drm ioctls --- Cargo.lock | 2 +- drivers/graphics/driver-graphics/src/lib.rs | 94 ++++++++++++++++----- drivers/graphics/ihdgd/src/device/scheme.rs | 2 +- drivers/graphics/vesad/src/scheme.rs | 4 +- drivers/graphics/virtio-gpud/src/scheme.rs | 12 +-- 5 files changed, 82 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dfaff86dd..78594176df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1793,7 +1793,7 @@ dependencies = [ [[package]] name = "redox-ioctl" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#f278abbb205803aeb17b022ac6ca20cce88b2843" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#266bf56554403ac36425113af06ea9ea273ce820" dependencies = [ "drm-sys", "redox_syscall 0.7.3", diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index c93d2be209..bad8e93160 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -11,10 +11,11 @@ use std::os::fd::BorrowedFd; use std::sync::{Arc, Mutex}; use drm_sys::{ - drm_mode_modeinfo, drm_mode_property_enum, DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, - DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND, 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_PROP_NAME_LEN, + drm_mode_modeinfo, drm_mode_property_enum, DRM_MODE_CURSOR_BO, DRM_MODE_CURSOR_MOVE, + DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND, + 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_PROP_NAME_LEN, }; use graphics_ipc::v2::Damage; use inputd::{DisplayHandle, VtEventKind}; @@ -77,7 +78,7 @@ pub trait GraphicsAdapter: Sized + Debug { ); fn hw_cursor_size(&self) -> Option<(u32, u32)>; - fn handle_cursor(&mut self, cursor: Option<&CursorPlane>, dirty_fb: bool); + fn handle_cursor(&mut self, cursor: &CursorPlane, dirty_fb: bool); } pub trait Buffer: Debug { @@ -91,7 +92,7 @@ pub struct CursorPlane { pub y: i32, pub hot_x: i32, pub hot_y: i32, - pub framebuffer: C, + pub framebuffer: Option>, } pub struct GraphicsScheme { @@ -246,7 +247,7 @@ impl GraphicsScheme { if self.inner.adapter.hw_cursor_size().is_some() { self.inner .adapter - .handle_cursor(vt_state.cursor_plane.as_ref(), true); + .handle_cursor(&vt_state.cursor_plane, true); } } @@ -313,7 +314,7 @@ struct GraphicsSchemeInner { struct VtState { display_fbs: Vec>>, - cursor_plane: Option>, + cursor_plane: CursorPlane, } enum Handle { @@ -338,7 +339,13 @@ impl GraphicsSchemeInner { ) -> &'a mut VtState { vts.entry(vt).or_insert_with(|| VtState { display_fbs: vec![None; adapter.display_count()], - cursor_plane: None, + cursor_plane: CursorPlane { + x: 0, + y: 0, + hot_x: 0, + hot_y: 0, + framebuffer: None, + }, }) } @@ -353,13 +360,7 @@ impl GraphicsSchemeInner { return Err(Error::new(EINVAL)); }; - let cursor_plane = vt_state.cursor_plane.get_or_insert_with(|| CursorPlane { - x: 0, - y: 0, - hot_x: 0, - hot_y: 0, - framebuffer: self.adapter.create_dumb_buffer(width, height), - }); + let cursor_plane = &mut vt_state.cursor_plane; cursor_plane.x = cursor_damage.x; cursor_plane.y = cursor_damage.y; @@ -369,7 +370,7 @@ impl GraphicsSchemeInner { return Ok(()); } - self.adapter.handle_cursor(Some(cursor_plane), false); + self.adapter.handle_cursor(cursor_plane, false); } else { cursor_plane.hot_x = cursor_damage.hot_x; cursor_plane.hot_y = cursor_damage.hot_y; @@ -377,7 +378,10 @@ impl GraphicsSchemeInner { let w: i32 = cursor_damage.width; let h: i32 = cursor_damage.height; let cursor_image = cursor_damage.cursor_img_bytes; - let cursor_ptr = self.adapter.map_dumb_buffer(&cursor_plane.framebuffer); + let framebuffer = cursor_plane + .framebuffer + .get_or_insert_with(|| Arc::new(self.adapter.create_dumb_buffer(width, height))); + let cursor_ptr = self.adapter.map_dumb_buffer(framebuffer); //Clear previous image from backing storage unsafe { @@ -402,7 +406,7 @@ impl GraphicsSchemeInner { return Ok(()); } - self.adapter.handle_cursor(Some(cursor_plane), true); + self.adapter.handle_cursor(cursor_plane, true); } return Ok(()); @@ -613,6 +617,31 @@ impl SchemeSync for GraphicsSchemeInner { } Ok(0) }), + ipc::MODE_CURSOR => ipc::DrmModeCursor::with(payload, |data| { + let vt_state = self.vts.get_mut(vt).unwrap(); + + let cursor_plane = &mut vt_state.cursor_plane; + + let update_buffer = data.flags() & DRM_MODE_CURSOR_BO != 0; + if update_buffer { + cursor_plane.framebuffer = if data.handle() == 0 { + None + } else if let Some(buffer) = fbs.get(&id_index(data.handle())) { + Some(buffer.clone()) + } else { + return Err(Error::new(EINVAL)); + }; + } + + if data.flags() & DRM_MODE_CURSOR_MOVE != 0 { + cursor_plane.x = data.x(); + cursor_plane.y = data.y(); + } + + self.adapter.handle_cursor(cursor_plane, update_buffer); + + Ok(0) + }), ipc::MODE_GET_ENCODER => ipc::DrmModeGetEncoder::with(payload, |mut data| { let encoder = self.objects.get_encoder(KmsObjectId(data.encoder_id()))?; data.set_crtc_id(encoder.crtc_id.0); @@ -836,6 +865,33 @@ impl SchemeSync for GraphicsSchemeInner { Ok(0) }) } + ipc::MODE_CURSOR2 => ipc::DrmModeCursor2::with(payload, |data| { + let vt_state = self.vts.get_mut(vt).unwrap(); + + let cursor_plane = &mut vt_state.cursor_plane; + + let update_buffer = data.flags() & DRM_MODE_CURSOR_BO != 0; + if update_buffer { + cursor_plane.framebuffer = if data.handle() == 0 { + None + } else if let Some(buffer) = fbs.get(&id_index(data.handle())) { + Some(buffer.clone()) + } else { + return Err(Error::new(EINVAL)); + }; + cursor_plane.hot_x = data.hot_x(); + cursor_plane.hot_y = data.hot_y(); + } + + if data.flags() & DRM_MODE_CURSOR_MOVE != 0 { + cursor_plane.x = data.x(); + cursor_plane.y = data.y(); + } + + self.adapter.handle_cursor(cursor_plane, update_buffer); + + Ok(0) + }), ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| { let i = id_index(data.fb_id()); let (width, height) = self.adapter.display_size(i as usize); diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 555e3ae524..287aa31dea 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -135,7 +135,7 @@ impl GraphicsAdapter for Device { None } - fn handle_cursor(&mut self, _cursor: Option<&CursorPlane>, _dirty_fb: bool) { + fn handle_cursor(&mut self, _cursor: &CursorPlane, _dirty_fb: bool) { unimplemented!("ihdgd does not support this function"); } } diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index 778af0dc3a..6aa1cfc559 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -113,7 +113,7 @@ impl GraphicsAdapter for FbAdapter { ) { crtc.lock().unwrap().mode = mode; - let framebuffer_id = objects + let framebuffer_id = objects .get_connector(connectors[0]) .unwrap() .lock() @@ -142,7 +142,7 @@ impl GraphicsAdapter for FbAdapter { None } - fn handle_cursor(&mut self, _cursor: Option<&CursorPlane>, _dirty_fb: bool) { + fn handle_cursor(&mut self, _cursor: &CursorPlane, _dirty_fb: bool) { unimplemented!("Vesad does not support this function"); } } diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 3f23dd941b..c507ada4a8 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -491,16 +491,10 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { Some((64, 64)) } - fn handle_cursor(&mut self, cursor: Option<&CursorPlane>, dirty_fb: bool) { - if let Some(cursor) = cursor { + fn handle_cursor(&mut self, cursor: &CursorPlane, dirty_fb: bool) { + if let Some(buffer) = &cursor.framebuffer { if dirty_fb { - self.update_cursor( - &cursor.framebuffer, - cursor.x, - cursor.y, - cursor.hot_x, - cursor.hot_y, - ); + self.update_cursor(buffer, cursor.x, cursor.y, cursor.hot_x, cursor.hot_y); } else { self.move_cursor(cursor.x, cursor.y); }