hal_x86_64/
framebuffer.rs
1use core::{
2 fmt,
3 ops::{Deref, DerefMut},
4};
5use hal_core::framebuffer::{Draw, RgbColor};
6use volatile::Volatile;
7
8pub struct Framebuffer<'buf, B: Deref<Target = [u8]>> {
9 buf: Volatile<B>,
15
16 len: usize,
22
23 cfg: &'buf Config,
25}
26
27#[derive(Debug, Clone)]
28pub struct Config {
29 pub height: usize,
31 pub width: usize,
33 pub px_bytes: usize,
34 pub line_len: usize,
35 pub px_kind: PixelKind,
36}
37
38#[derive(Copy, Clone, Debug, Eq, PartialEq)]
39pub enum PixelKind {
40 Bgr,
41 Rgb,
42 Gray,
43}
44
45impl<'buf, B> Framebuffer<'buf, B>
46where
47 B: Deref<Target = [u8]> + DerefMut,
48{
49 pub fn new(cfg: &'buf Config, buf: B) -> Self {
50 let len = buf[..].len();
51 Self {
52 cfg,
53 buf: Volatile::new(buf),
54 len,
55 }
56 }
57
58 pub fn clear(&mut self) -> &mut Self {
59 self.buf.fill(0);
60 self
61 }
62
63 pub fn set_pixel_rgb(&mut self, x: usize, y: usize, color: RgbColor) -> &mut Self {
64 let px_bytes = self.cfg.px_bytes;
65 let start = (y * self.cfg.line_len + x) * px_bytes;
66 let end = start + px_bytes;
67
68 let px_vals = &self.cfg.px_kind.convert_rgb(color)[..px_bytes];
69 self.buf.index_mut(start..end).copy_from_slice(px_vals);
70 self
71 }
72}
73
74impl<B> Draw for Framebuffer<'_, B>
75where
76 B: Deref<Target = [u8]> + DerefMut,
77{
78 fn height(&self) -> usize {
79 self.cfg.height
80 }
81
82 fn width(&self) -> usize {
83 self.cfg.width
84 }
85
86 fn set_pixel(&mut self, x: usize, y: usize, color: RgbColor) -> &mut Self {
87 self.set_pixel_rgb(x, y, color)
88 }
89
90 fn scroll_vert(&mut self, amount: isize) -> &mut Self {
91 if amount < 0 {
92 todo!("eliza: handle negatives!")
93 }
94 let amount_px = (amount as usize * self.cfg.line_len) * self.cfg.px_bytes;
95 self.buf.copy_within(amount_px.., 0);
96 let revealed_start = self.len - amount_px;
97 self.buf.index_mut(revealed_start..).fill(0);
98 self
99 }
100}
101
102impl<B> fmt::Debug for Framebuffer<'_, B>
105where
106 B: Deref<Target = [u8]>,
107{
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 let Self { cfg, len, buf: _ } = self;
110 f.debug_struct("Framebuffer")
111 .field("len", len)
112 .field("cfg", cfg)
113 .field("buf", &format_args!("[..]"))
115 .finish()
116 }
117}
118
119impl PixelKind {
120 fn convert_rgb(self, RgbColor { red, green, blue }: RgbColor) -> [u8; 4] {
121 match self {
122 PixelKind::Bgr => [blue, green, red, 0],
123 PixelKind::Rgb => [red, green, blue, 0],
124 PixelKind::Gray => [Self::rgb_to_luminance(red, green, blue), 0, 0, 0],
125 }
126 }
127
128 fn rgb_to_luminance(r: u8, g: u8, b: u8) -> u8 {
129 ((21 * (r as u32) + 72 * (g as u32) + 7 * (b as u32)) / 100) as u8
131 }
132}