d53661b9a0
I will start working on stack traces tonight and tomorrow. We need to be able to 'unwind' by finding calling functions.
108 lines
2.9 KiB
Rust
108 lines
2.9 KiB
Rust
use limine::request::FramebufferRequest;
|
|
|
|
#[used]
|
|
#[unsafe(link_section = ".requests")]
|
|
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
|
|
|
|
use super::colour::Colour;
|
|
use core::panic;
|
|
|
|
use limine::framebuffer::Framebuffer;
|
|
use spin::{Lazy, Mutex};
|
|
|
|
pub static FRAMEBUFFER_WRITER: Lazy<Mutex<Option<FramebufferWriter>>> =
|
|
Lazy::new(|| {
|
|
Mutex::new(FRAMEBUFFER_REQUEST.get_response().map_or_else(
|
|
|| {
|
|
panic!("Framebuffer request failed");
|
|
},
|
|
|framebuffer_response| {
|
|
let framebuffer =
|
|
framebuffer_response.framebuffers().next().unwrap();
|
|
Some(FramebufferWriter::new(framebuffer))
|
|
},
|
|
))
|
|
});
|
|
|
|
/// The updated writer stores necessary fields from the [Framebuffer].
|
|
/// This ensures that the contained types are Send, as Framebuffer was
|
|
/// not marked as Send.
|
|
///
|
|
/// It also avoids the requirement for lifetimes.
|
|
///
|
|
/// Note this does not implement Writer as these functions only handle drawing
|
|
/// pixels.
|
|
pub struct FramebufferWriter {
|
|
pitch: u64,
|
|
bpp: u16,
|
|
addr: *mut u8,
|
|
width: u64,
|
|
height: u64,
|
|
}
|
|
|
|
unsafe impl Send for FramebufferWriter {}
|
|
unsafe impl Sync for FramebufferWriter {}
|
|
|
|
impl FramebufferWriter {
|
|
pub fn new(framebuffer: Framebuffer) -> Self {
|
|
Self {
|
|
pitch: framebuffer.pitch(),
|
|
bpp: framebuffer.bpp(),
|
|
addr: framebuffer.addr(),
|
|
width: framebuffer.width(),
|
|
height: framebuffer.height(),
|
|
}
|
|
}
|
|
|
|
pub fn write_pixel(&self, x: usize, y: usize, color: Colour) {
|
|
let pitch = self.pitch as usize;
|
|
let bpp = (self.bpp / 8) as usize;
|
|
let pixel_offset = y * pitch + x * bpp;
|
|
|
|
unsafe {
|
|
*(self.addr.add(pixel_offset) as *mut u32) = color.into();
|
|
}
|
|
}
|
|
|
|
pub fn render_frame(&self, buffer: &[&[Colour]]) {
|
|
// TODO: this should return errors
|
|
for (y, &row) in buffer.iter().enumerate() {
|
|
if y >= self.height() as usize {
|
|
break;
|
|
}
|
|
for (x, pixel) in row.iter().enumerate() {
|
|
if x >= self.width() as usize {
|
|
break;
|
|
}
|
|
self.write_pixel(x, y, *pixel);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub const fn width(&self) -> u32 {
|
|
self.width as u32
|
|
}
|
|
|
|
pub const fn height(&self) -> u32 {
|
|
self.height as u32
|
|
}
|
|
|
|
pub fn clear(&self) {
|
|
let width = self.width as usize;
|
|
let height = self.height as usize;
|
|
|
|
for y in 0..height {
|
|
for x in 0..width {
|
|
self.write_pixel(x, y, Colour::Black);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn screensize_px() -> (u32, u32) {
|
|
FRAMEBUFFER_WRITER
|
|
.lock()
|
|
.as_mut()
|
|
.map_or_else(|| (0, 0), |writer| (writer.width(), writer.height()))
|
|
}
|