good_os_framework/drivers/
display.rs1use 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 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 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}