mycelium_kernel/arch/x86_64/
framebuf.rs1use bootloader_api::{info, BootInfo};
2use core::{
3 mem,
4 ops::{Deref, DerefMut},
5};
6use hal_x86_64::framebuffer::{self, Framebuffer};
7use mycelium_util::sync::{
8 blocking::{Mutex, MutexGuard},
9 spin::Spinlock,
10 InitOnce,
11};
12
13#[derive(Debug)]
14pub struct FramebufGuard(MutexGuard<'static, info::FrameBuffer, Spinlock>);
15pub type FramebufWriter = Framebuffer<'static, FramebufGuard>;
16
17pub(super) unsafe fn mk_framebuf() -> FramebufWriter {
25 let (cfg, buf) = unsafe {
26 FRAMEBUFFER.get_unchecked()
30 };
31 Framebuffer::new(cfg, FramebufGuard(buf.lock()))
32}
33
34pub(super) unsafe fn force_unlock() {
42 if let Some((_, fb)) = FRAMEBUFFER.try_get() {
43 fb.force_unlock();
44 }
45}
46
47pub(super) fn init(bootinfo: &mut BootInfo) -> bool {
54 use info::Optional;
55 if FRAMEBUFFER.try_get().is_some() {
57 return true;
58 }
59
60 let Optional::Some(framebuffer) = mem::replace(&mut bootinfo.framebuffer, Optional::None)
62 else {
63 return false;
66 };
67
68 let info = framebuffer.info();
69 let cfg = framebuffer::Config {
70 height: info.height,
71 width: info.width,
72 px_bytes: info.bytes_per_pixel,
73 line_len: info.stride,
74 px_kind: match info.pixel_format {
75 info::PixelFormat::Rgb => framebuffer::PixelKind::Rgb,
76 info::PixelFormat::Bgr => framebuffer::PixelKind::Bgr,
77 info::PixelFormat::U8 => framebuffer::PixelKind::Gray,
78 x => unimplemented!("hahaha wtf, found a weird pixel format: {:?}", x),
79 },
80 };
81 FRAMEBUFFER.init((cfg, Mutex::new_with_raw_mutex(framebuffer, Spinlock::new())));
82 true
83}
84
85static FRAMEBUFFER: InitOnce<(framebuffer::Config, Mutex<info::FrameBuffer, Spinlock>)> =
86 InitOnce::uninitialized();
87
88impl Deref for FramebufGuard {
89 type Target = [u8];
90
91 #[inline(always)]
92 fn deref(&self) -> &Self::Target {
93 self.0.buffer()
94 }
95}
96
97impl DerefMut for FramebufGuard {
98 #[inline(always)]
99 fn deref_mut(&mut self) -> &mut Self::Target {
100 self.0.buffer_mut()
101 }
102}