linux_drm/modeset/
buffer.rs

1use alloc::sync::Weak;
2use core::slice;
3
4use super::{BufferObjectId, FramebufferId};
5
6#[derive(Debug)]
7pub struct DumbBufferRequest {
8    pub width: u32,
9    pub height: u32,
10    pub depth: u32,
11    pub bpp: u32,
12}
13
14#[derive(Debug)]
15pub struct DumbBuffer {
16    pub(crate) ptr: *mut u8,
17    pub(crate) len: usize,
18    pub(crate) file: Weak<linux_io::File<crate::ioctl::DrmCardDevice>>,
19    pub(crate) width: u32,
20    pub(crate) height: u32,
21    pub(crate) bpp: u32,
22    pub(crate) pitch: u32,
23    pub(crate) fb_id: FramebufferId,
24    pub(crate) buffer_handle: BufferObjectId,
25}
26
27impl DumbBuffer {
28    pub fn buffer(&self) -> &[u8] {
29        unsafe { slice::from_raw_parts(self.ptr, self.len) }
30    }
31
32    pub fn buffer_mut(&mut self) -> &mut [u8] {
33        unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
34    }
35
36    pub fn width(&self) -> u32 {
37        self.width
38    }
39
40    pub fn height(&self) -> u32 {
41        self.height
42    }
43
44    pub fn pitch(&self) -> u32 {
45        self.pitch
46    }
47
48    pub fn bpp(&self) -> u32 {
49        self.bpp
50    }
51
52    pub fn framebuffer_id(&self) -> FramebufferId {
53        self.fb_id
54    }
55
56    pub fn pixel_idx(&self, x: u32, y: u32) -> Option<usize> {
57        if x >= self.width || y >= self.height {
58            return None;
59        }
60        Some((y as usize * self.pitch as usize) + (x as usize * (self.bpp / 8) as usize))
61    }
62
63    pub fn clear_to_zero(&mut self) {
64        unsafe { core::ptr::write_bytes(self.ptr, 0, self.len) }
65    }
66}
67
68impl Drop for DumbBuffer {
69    fn drop(&mut self) {
70        let _ = unsafe { linux_unsafe::munmap(self.ptr as *mut _, self.len) };
71
72        // If the associated file is still open then we'll also free the framebuffer and
73        // dumb buffer. Otherwise we'll just hope that the file descriptor associated with
74        // self.file got properly closed so that the kernel could free these automatically.
75        let Some(f) = self.file.upgrade() else {
76            return;
77        };
78        {
79            let mut fb_id = self.fb_id.0;
80            let _ = crate::drm_ioctl(f.as_ref(), crate::ioctl::DRM_IOCTL_MODE_RMFB, &mut fb_id);
81        }
82        {
83            let mut msg = crate::ioctl::DrmModeDestroyDumb::zeroed();
84            msg.handle = self.buffer_handle.0;
85            let _ = crate::drm_ioctl(
86                f.as_ref(),
87                crate::ioctl::DRM_IOCTL_MODE_DESTROY_DUMB,
88                &mut msg,
89            );
90        }
91    }
92}