good_os_framework/drivers/
display.rs

1use core::slice::from_raw_parts_mut;
2use limine::request::FramebufferRequest;
3
4use os_terminal::DrawTarget;
5
6#[used]
7#[link_section = ".requests"]
8static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
9
10#[derive(Debug, Clone, Copy)]
11pub enum PixelFormat {
12    Rgb,
13    Bgr,
14    U8,
15    Unknown,
16}
17
18pub struct Display {
19    buffer: &'static mut [u8],
20    width: usize,
21    height: usize,
22    stride: usize,
23    bytes_per_pixel: usize,
24    pixel_format: PixelFormat,
25}
26
27impl Display {
28    /// Creates a new `Display`
29    pub fn new() -> Self {
30        let response = FRAMEBUFFER_REQUEST.get_response().unwrap();
31        let frame_buffer = response.framebuffers().next().take().unwrap();
32
33        let width = frame_buffer.width() as _;
34        let height = frame_buffer.height() as _;
35
36        let pixel_format = match (
37            frame_buffer.red_mask_shift(),
38            frame_buffer.green_mask_shift(),
39            frame_buffer.blue_mask_shift(),
40        ) {
41            (0x00, 0x08, 0x10) => PixelFormat::Rgb,
42            (0x10, 0x08, 0x00) => PixelFormat::Bgr,
43            (0x00, 0x00, 0x00) => PixelFormat::U8,
44            _ => PixelFormat::Unknown,
45        };
46
47        let pitch = frame_buffer.pitch() as usize;
48        let bpp = frame_buffer.bpp() as usize;
49        let stride = (pitch / 4) as _;
50        let bytes_per_pixel = (bpp / 8) as _;
51
52        let buffer_size = stride * height * bytes_per_pixel;
53        let buffer = unsafe { from_raw_parts_mut(frame_buffer.addr(), buffer_size) };
54
55        Self {
56            buffer,
57            width,
58            height,
59            stride,
60            bytes_per_pixel,
61            pixel_format,
62        }
63    }
64
65    /// Returns a mutable reference to the frame buffer which Limine gives to the kernel.
66    pub fn get_frame_buffer(&self) -> &'static mut [u8] {
67        unsafe { from_raw_parts_mut(self.buffer.as_ptr() as *mut u8, self.buffer.len()) }
68    }
69}
70
71impl DrawTarget for Display {
72    fn size(&self) -> (usize, usize) {
73        (self.width, self.height)
74    }
75
76    fn draw_pixel(&mut self, x: usize, y: usize, color: (u8, u8, u8)) {
77        let byte_offset = (y * self.stride + x) * self.bytes_per_pixel;
78        let write_range = byte_offset..(byte_offset + self.bytes_per_pixel);
79
80        let color = match self.pixel_format {
81            PixelFormat::Rgb => [color.0, color.1, color.2, 0],
82            PixelFormat::Bgr => [color.2, color.1, color.0, 0],
83            PixelFormat::U8 => unimplemented!(),
84            PixelFormat::Unknown => return,
85        };
86
87        self.buffer[write_range].copy_from_slice(&color[..self.bytes_per_pixel]);
88    }
89}