drivers/graphics: Introduce UPDATE_CURSOR ioctl

Orbital needs this as we don't implement cursor planes yet.
This commit is contained in:
bjorn3
2026-03-11 23:17:38 +01:00
parent 511c6080ca
commit f01d0fe8a1
3 changed files with 99 additions and 63 deletions
+83 -49
View File
@@ -349,6 +349,67 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
},
);
}
fn handle_cursor_update(
&mut self,
vt: usize,
cursor_damage: &graphics_ipc::v2::ipc::UpdateCursor,
) -> Result<()> {
let vt_state = self.vts.get_mut(&vt).unwrap();
let Some(cursor_plane) = &mut vt_state.cursor_plane else {
// Hardware cursor not supported
return Err(Error::new(EINVAL));
};
cursor_plane.x = cursor_damage.x;
cursor_plane.y = cursor_damage.y;
if cursor_damage.header == 0 {
if vt != self.active_vt {
return Ok(());
}
self.adapter.handle_cursor(cursor_plane, false);
} else {
cursor_plane.hot_x = cursor_damage.hot_x;
cursor_plane.hot_y = cursor_damage.hot_y;
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_cursor_framebuffer(&cursor_plane.framebuffer);
//Clear previous image from backing storage
unsafe {
core::ptr::write_bytes(cursor_ptr as *mut u8, 0, 64 * 64 * 4);
}
//Write image to backing storage
for row in 0..h {
let start: usize = (w * row) as usize;
let end: usize = (w * row + w) as usize;
unsafe {
core::ptr::copy_nonoverlapping(
cursor_image[start..end].as_ptr(),
cursor_ptr.cast::<u32>().offset(64 * row as isize),
w as usize,
);
}
}
if vt != self.active_vt {
return Ok(());
}
self.adapter.handle_cursor(cursor_plane, true);
}
return Ok(());
}
}
const MAP_FAKE_OFFSET_MULTIPLIER: usize = 0x10_000_000;
@@ -495,6 +556,14 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
) -> Result<usize> {
match self.handles.get(&id).ok_or(Error::new(EBADF))? {
Handle::V1Screen { vt, screen } => {
if size_of_val(buf) == std::mem::size_of::<CursorDamage>() {
let cursor_damage = unsafe { &*buf.as_ptr().cast::<CursorDamage>() };
self.handle_cursor_update(*vt, cursor_damage)?;
return Ok(buf.len());
}
if *vt != self.active_vt {
// This is a protection against background VT's spamming us with flush requests. We will
// flush the framebuffer on the next VT switch anyway
@@ -503,55 +572,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
let vt_state = self.vts.get_mut(vt).unwrap();
if size_of_val(buf) == std::mem::size_of::<CursorDamage>() {
let Some(cursor_plane) = &mut vt_state.cursor_plane else {
// Hardware cursor not supported
return Err(Error::new(EINVAL));
};
let cursor_damage = unsafe { *buf.as_ptr().cast::<CursorDamage>() };
cursor_plane.x = cursor_damage.x;
cursor_plane.y = cursor_damage.y;
if cursor_damage.header == 0 {
self.adapter.handle_cursor(cursor_plane, false);
} else {
cursor_plane.hot_x = cursor_damage.hot_x;
cursor_plane.hot_y = cursor_damage.hot_y;
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_cursor_framebuffer(&cursor_plane.framebuffer);
//Clear previous image from backing storage
unsafe {
core::ptr::write_bytes(cursor_ptr as *mut u8, 0, 64 * 64 * 4);
}
//Write image to backing storage
for row in 0..h {
let start: usize = (w * row) as usize;
let end: usize = (w * row + w) as usize;
unsafe {
core::ptr::copy_nonoverlapping(
cursor_image[start..end].as_ptr(),
cursor_ptr.cast::<u32>().offset(64 * row as isize),
w as usize,
);
}
}
self.adapter.handle_cursor(cursor_plane, true);
}
return Ok(buf.len());
}
assert_eq!(buf.len(), std::mem::size_of::<Damage>());
let damage = unsafe { *buf.as_ptr().cast::<Damage>() };
@@ -935,6 +955,20 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Ok(size_of::<ipc::UpdatePlane>())
}
ipc::UPDATE_CURSOR => {
if payload.len() < size_of::<ipc::UpdateCursor>() {
return Err(Error::new(EINVAL));
}
let payload = unsafe {
transmute::<&mut [u8; size_of::<ipc::UpdateCursor>()], &mut ipc::UpdateCursor>(
payload.as_mut_array().unwrap(),
)
};
let vt = *vt;
self.handle_cursor_update(vt, payload)?;
Ok(size_of::<ipc::UpdateCursor>())
}
_ => return Err(Error::new(EINVAL)),
},
}
+1 -13
View File
@@ -1,14 +1,2 @@
pub use crate::common::Damage;
#[derive(Debug, Copy, Clone)]
#[repr(C, packed)]
pub struct CursorDamage {
pub header: u32,
pub x: i32,
pub y: i32,
pub hot_x: i32,
pub hot_y: i32,
pub width: i32,
pub height: i32,
pub cursor_img_bytes: [u32; 4096],
}
pub use crate::v2::ipc::UpdateCursor as CursorDamage;
+15 -1
View File
@@ -69,11 +69,25 @@ pub mod ipc {
pub use redox_ioctl::drm::*;
// FIXME replace these with proper drm interfaces
pub const UPDATE_PLANE: u64 = 6;
pub const UPDATE_PLANE: u64 = 0x12345670;
#[repr(C, packed)]
pub struct UpdatePlane {
pub display_id: usize,
pub fb_id: u32,
pub damage: Damage,
}
pub const UPDATE_CURSOR: u64 = 0x12345671;
#[derive(Debug, Copy, Clone)]
#[repr(C, packed)]
pub struct UpdateCursor {
pub header: u32,
pub x: i32,
pub y: i32,
pub hot_x: i32,
pub hot_y: i32,
pub width: i32,
pub height: i32,
pub cursor_img_bytes: [u32; 4096],
}
}