lifeblood_os/src/dev/framebuffer/mod.rs
2025-09-11 16:28:11 -07:00

106 lines
3 KiB
Rust

use crate::dev::virtio::framebuffer_update;
use crate::dev::{FRAMEBUFFER_ADDR, FRAMEBUFFER_BPP, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_WIDTH};
use crate::trafficcontrol::TrafficControl;
use core::sync::atomic::Ordering;
pub mod console;
pub const VAPFONT: &[u8] = include_bytes!("./vapfont.data");
pub const VAPFONT_W: usize = 256;
pub const VAPFONT_H: usize = 112;
pub struct FBColor {
pub red: u8,
pub green: u8,
pub blue: u8,
}
pub const FB_BG_COLOR: FBColor = FBColor {
red: 216,
green: 216,
blue: 216,
};
pub const FB_FG_COLOR: FBColor = FBColor {
red: 0,
green: 0,
blue: 0,
};
impl FBColor {
#[inline]
pub const fn to_bytes(&self) -> [u8; 3] {
[self.red, self.green, self.blue]
}
}
pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, y: usize, chars: &[char]) {
let ogx = x;
let ogy = y;
const BYTES: [u8; 3] = FB_FG_COLOR.to_bytes();
let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed);
if fbaddr == 0 {
return;
}
let fbstride = FRAMEBUFFER_BPP.load(Ordering::Relaxed) * FRAMEBUFFER_WIDTH;
const CHAR_SIZE: usize = 16;
for c in chars {
let c = *c;
if c == ' ' {
x += CHAR_SIZE;
} else if c as u8 > 32 {
let c = c as u8 - 32;
let cx = (c % 16) as usize * CHAR_SIZE;
let cy = (c / 16) as usize * CHAR_SIZE;
for row in 0..CHAR_SIZE {
for col in 0..CHAR_SIZE {
let coff = (VAPFONT_W * (cy + row)) + (cx + col);
let draw = VAPFONT[coff / 8] & (0x80 >> (coff % 8));
if draw != 0 {
unsafe {
let fb = (fbaddr as *mut u8)
.add(((y + row) * fbstride) + ((x + col) * 4))
as *mut u32;
fb.write_volatile(u32::from_ne_bytes([
0, BYTES[0], BYTES[1], BYTES[2],
]));
}
}
}
}
x += CHAR_SIZE;
}
}
framebuffer_update(
tc,
0,
0,
FRAMEBUFFER_WIDTH as u32,
FRAMEBUFFER_HEIGHT as u32,
);
}
pub fn fb_clearscreen(tc: &mut TrafficControl) {
const BYTES: [u8; 3] = FB_BG_COLOR.to_bytes();
let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed);
if fbaddr == 0 {
return;
}
let fbstride = FRAMEBUFFER_BPP.load(Ordering::Relaxed) * FRAMEBUFFER_WIDTH;
for y in 0..FRAMEBUFFER_HEIGHT {
for x in 0..FRAMEBUFFER_WIDTH {
unsafe {
let fb = (fbaddr as *mut u8).add(((y) * fbstride) + ((x) * 4)) as *mut u32;
fb.write_volatile(u32::from_ne_bytes([0, BYTES[0], BYTES[1], BYTES[2]]));
}
}
}
framebuffer_update(
tc,
0,
0,
FRAMEBUFFER_WIDTH as u32,
FRAMEBUFFER_HEIGHT as u32,
);
}