Skip to content

Commit b83cd7c

Browse files
committed
drm: Add cursor hotspot handling
1 parent b5c354e commit b83cd7c

4 files changed

Lines changed: 73 additions & 8 deletions

File tree

drivers/video/virtio_gpu/src/device.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub struct VirtioGpuDevice {
3737
cursor_resource: AtomicU32, // Resource ID of current cursor image (0 = none)
3838
cursor_x: AtomicU32,
3939
cursor_y: AtomicU32,
40+
cursor_hot_x: AtomicU32,
41+
cursor_hot_y: AtomicU32,
4042
}
4143

4244
struct ScanoutInfo {
@@ -68,6 +70,8 @@ impl VirtioGpuDevice {
6870
cursor_resource: AtomicU32::new(0),
6971
cursor_x: AtomicU32::new(0),
7072
cursor_y: AtomicU32::new(0),
73+
cursor_hot_x: AtomicU32::new(0),
74+
cursor_hot_y: AtomicU32::new(0),
7175
};
7276

7377
// Get display info
@@ -585,12 +589,18 @@ impl Device for VirtioGpuDevice {
585589
buffer: Option<Arc<dyn BufferObject>>,
586590
width: u32,
587591
height: u32,
592+
hot_x: i32,
593+
hot_y: i32,
588594
) -> EResult<()> {
589595
let scanout_id = {
590596
let scanouts = self.scanouts.lock();
591597
scanouts.first().map(|s| s.id).unwrap_or(0)
592598
};
593599

600+
// Store hotspot values
601+
self.cursor_hot_x.store(hot_x as u32, Ordering::SeqCst);
602+
self.cursor_hot_y.store(hot_y as u32, Ordering::SeqCst);
603+
594604
match buffer {
595605
Some(buf) => {
596606
let virtio_buf = (buf.as_ref() as &dyn Any)
@@ -612,8 +622,8 @@ impl Device for VirtioGpuDevice {
612622
padding: 0,
613623
},
614624
resource_id,
615-
hot_x: 0,
616-
hot_y: 0,
625+
hot_x: hot_x as u32,
626+
hot_y: hot_y as u32,
617627
padding: 0,
618628
};
619629
self.send_cursor_command(&cmd)?;
@@ -661,8 +671,8 @@ impl Device for VirtioGpuDevice {
661671
padding: 0,
662672
},
663673
resource_id,
664-
hot_x: 0,
665-
hot_y: 0,
674+
hot_x: self.cursor_hot_x.load(Ordering::SeqCst),
675+
hot_y: self.cursor_hot_y.load(Ordering::SeqCst),
666676
padding: 0,
667677
};
668678
self.send_cursor_command(&cmd)?;

kernel/src/device/drm/mod.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,15 @@ pub trait Device: Send + Sync {
102102

103103
/// Set the cursor image for a CRTC. `buffer` contains ARGB8888 pixel data.
104104
/// If `buffer` is None, the cursor should be hidden.
105+
/// `hot_x` and `hot_y` are the hotspot offsets (pixels from top-left of cursor image).
105106
fn set_cursor(
106107
&self,
107108
_crtc_id: u32,
108109
_buffer: Option<Arc<dyn BufferObject>>,
109110
_width: u32,
110111
_height: u32,
112+
_hot_x: i32,
113+
_hot_y: i32,
111114
) -> EResult<()> {
112115
Err(Errno::ENOSYS)
113116
}
@@ -895,6 +898,10 @@ impl FileOps for DrmFile {
895898
self.rd_event.wake_all();
896899
}
897900
}
901+
drm::DRM_IOCTL_WAIT_VBLANK => {
902+
warn!("DRM_IOCTL_WAIT_VBLANK is not supported");
903+
return Err(Errno::ENOTTY);
904+
}
898905
drm::DRM_IOCTL_CRTC_GET_SEQUENCE => {
899906
return Err(Errno::ENOTTY);
900907
}
@@ -911,7 +918,7 @@ impl FileOps for DrmFile {
911918
if val.flags & DRM_MODE_CURSOR_BO != 0 {
912919
if val.handle == 0 {
913920
// Hide cursor
914-
self.device.set_cursor(val.crtc_id, None, 0, 0)?;
921+
self.device.set_cursor(val.crtc_id, None, 0, 0, 0, 0)?;
915922
} else {
916923
// Set cursor image
917924
let buffers = self.buffers.lock();
@@ -921,8 +928,48 @@ impl FileOps for DrmFile {
921928
.ok_or(Errno::EINVAL)?
922929
.clone();
923930
drop(buffers);
924-
self.device
925-
.set_cursor(val.crtc_id, Some(buffer), val.width, val.height)?;
931+
self.device.set_cursor(
932+
val.crtc_id,
933+
Some(buffer),
934+
val.width,
935+
val.height,
936+
0,
937+
0,
938+
)?;
939+
}
940+
}
941+
if val.flags & DRM_MODE_CURSOR_MOVE != 0 {
942+
self.device.move_cursor(val.crtc_id, val.x, val.y)?;
943+
}
944+
}
945+
drm::DRM_IOCTL_MODE_CURSOR2 => {
946+
let ptr = UserPtr::<drm::drm_mode_cursor2>::new(arg);
947+
let val = ptr.read().ok_or(Errno::EFAULT)?;
948+
949+
const DRM_MODE_CURSOR_BO: u32 = 0x01;
950+
const DRM_MODE_CURSOR_MOVE: u32 = 0x02;
951+
952+
if val.flags & DRM_MODE_CURSOR_BO != 0 {
953+
if val.handle == 0 {
954+
// Hide cursor
955+
self.device.set_cursor(val.crtc_id, None, 0, 0, 0, 0)?;
956+
} else {
957+
// Set cursor image with hotspot
958+
let buffers = self.buffers.lock();
959+
let buffer = buffers
960+
.iter()
961+
.find(|b| b.id() == val.handle)
962+
.ok_or(Errno::EINVAL)?
963+
.clone();
964+
drop(buffers);
965+
self.device.set_cursor(
966+
val.crtc_id,
967+
Some(buffer),
968+
val.width,
969+
val.height,
970+
val.hot_x,
971+
val.hot_y,
972+
)?;
926973
}
927974
}
928975
if val.flags & DRM_MODE_CURSOR_MOVE != 0 {

kernel/src/device/drm/plainfb.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ struct CursorState {
2525
y: i32,
2626
width: u32,
2727
height: u32,
28+
hot_x: i32,
29+
hot_y: i32,
2830
}
2931

3032
struct PlainDevice {
@@ -183,11 +185,15 @@ impl Device for PlainDevice {
183185
buffer: Option<Arc<dyn BufferObject>>,
184186
width: u32,
185187
height: u32,
188+
hot_x: i32,
189+
hot_y: i32,
186190
) -> EResult<()> {
187191
let mut cursor = self.cursor.lock();
188192
cursor.buffer = buffer;
189193
cursor.width = width;
190194
cursor.height = height;
195+
cursor.hot_x = hot_x;
196+
cursor.hot_y = hot_y;
191197
Ok(())
192198
}
193199

@@ -264,6 +270,8 @@ fn PLAINFB_STAGE() {
264270
y: 0,
265271
width: 0,
266272
height: 0,
273+
hot_x: 0,
274+
hot_y: 0,
267275
}),
268276
});
269277

kernel/src/uapi/drm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ pub const DRM_IOCTL_PRIME_FD_TO_HANDLE: u32 = drm_iowr::<drm_prime_handle>(0x2e)
677677
// pub const DRM_IOCTL_AGP_UNBIND: u32 = drm_iow::<drm_agp_binding>(0x37);
678678
// pub const DRM_IOCTL_SG_ALLOC: u32 = drm_iowr::<drm_scatter_gather>(0x38);
679679
// pub const DRM_IOCTL_SG_FREE: u32 = drm_iow::<drm_scatter_gather>(0x39);
680-
// pub const DRM_IOCTL_WAIT_VBLANK: u32 = drm_iowr::<drm_wait_vblank>(0x3a);
680+
pub const DRM_IOCTL_WAIT_VBLANK: u32 = drm_iowr::<[u64; 3]>(0x3a); // TODO
681681
pub const DRM_IOCTL_CRTC_GET_SEQUENCE: u32 = drm_iowr::<drm_crtc_get_sequence>(0x3b);
682682
pub const DRM_IOCTL_CRTC_QUEUE_SEQUENCE: u32 = drm_iowr::<drm_crtc_queue_sequence>(0x3c);
683683
// pub const DRM_IOCTL_UPDATE_DRAW: u32 = drm_iow::<drm_update_draw>(0x3f);

0 commit comments

Comments
 (0)