diff --git a/nel_os_kernel/Cargo.lock b/nel_os_kernel/Cargo.lock index 4e6a3fe..9d4d162 100644 --- a/nel_os_kernel/Cargo.lock +++ b/nel_os_kernel/Cargo.lock @@ -2,6 +2,26 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ab_glyph" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0f4f6fbdc5ee39f2ede9f5f3ec79477271a6d6a2baff22310d51736bda6cea" +dependencies = [ + "ab_glyph_rasterizer", + "libm", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" +dependencies = [ + "libm", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -26,6 +46,15 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -35,6 +64,12 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "linked_list_allocator" version = "0.9.1" @@ -62,6 +97,7 @@ version = "0.1.0" name = "nel_os_kernel" version = "0.1.0" dependencies = [ + "ab_glyph", "lazy_static", "linked_list_allocator", "nel_os_common", @@ -70,6 +106,15 @@ dependencies = [ "x86_64", ] +[[package]] +name = "owned_ttf_parser" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +dependencies = [ + "ttf-parser", +] + [[package]] name = "raw-cpuid" version = "10.7.0" @@ -115,6 +160,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] + [[package]] name = "uart_16550" version = "0.3.2" diff --git a/nel_os_kernel/Cargo.toml b/nel_os_kernel/Cargo.toml index defe6cb..6cedfb4 100644 --- a/nel_os_kernel/Cargo.toml +++ b/nel_os_kernel/Cargo.toml @@ -10,3 +10,4 @@ uart_16550 = "0.3.2" x86_64 = "0.15.2" nel_os_common = { path = "../nel_os_common" } linked_list_allocator = "0.9.1" +ab_glyph = { version = "0.2", features = ["libm"], default-features = false } diff --git a/nel_os_kernel/Tamzen7x14r.ttf b/nel_os_kernel/Tamzen7x14r.ttf new file mode 100644 index 0000000..75294fa Binary files /dev/null and b/nel_os_kernel/Tamzen7x14r.ttf differ diff --git a/nel_os_kernel/src/graphics.rs b/nel_os_kernel/src/graphics.rs new file mode 100644 index 0000000..f0c6455 --- /dev/null +++ b/nel_os_kernel/src/graphics.rs @@ -0,0 +1,133 @@ +use ab_glyph::{Font, FontRef, ScaleFont}; +use lazy_static::lazy_static; +use nel_os_common::gop::{FrameBuffer as RawFrameBuffer, PixelFormat as RawPixelFormat}; +use spin::Mutex; + +static FONT: &[u8] = include_bytes!("../Tamzen7x14r.ttf"); + +lazy_static! { + pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); +} + +pub enum PixelFormat { + Rgb, + Bgr, +} + +pub struct FrameBuffer { + pub frame_buffer: *mut u8, + pub width: usize, + pub height: usize, + pub stride: usize, + + pub pixel_format: PixelFormat, + + pub text_cursor: (usize, usize), +} + +unsafe impl Send for FrameBuffer {} +unsafe impl Sync for FrameBuffer {} + +impl FrameBuffer { + pub fn from_raw_buffer(raw_buffer: &RawFrameBuffer) -> Self { + Self { + frame_buffer: raw_buffer.frame_buffer, + width: raw_buffer.width, + height: raw_buffer.height, + + stride: raw_buffer.stride, + pixel_format: match raw_buffer.pixl_format { + RawPixelFormat::Rgb => PixelFormat::Rgb, + RawPixelFormat::Bgr => PixelFormat::Bgr, + }, + text_cursor: (0, 0), + } + } + + pub fn pixel_index(&self, x: usize, y: usize) -> Option { + if x < self.width && y < self.height { + Some((y * self.stride + x) * 4) + } else { + None + } + } + + pub fn draw_pixel(&self, r: u8, g: u8, b: u8, x: usize, y: usize) { + if x >= self.width || y >= self.height { + return; + } + + let pixel_index = self.pixel_index(x, y).unwrap(); + unsafe { + let pixel_ptr = self.frame_buffer.add(pixel_index); + match self.pixel_format { + PixelFormat::Rgb => { + *pixel_ptr.add(0) = r; + *pixel_ptr.add(1) = g; + *pixel_ptr.add(2) = b; + } + + PixelFormat::Bgr => { + *pixel_ptr.add(0) = b; + *pixel_ptr.add(1) = g; + *pixel_ptr.add(2) = r; + } + } + } + } + + pub fn print_text(&mut self, text: &str) { + let (mut x, mut y) = self.text_cursor; + + for c in text.chars() { + if c == '\n' { + x = 0; + y += 14; + + continue; + } + + self.draw_char(c, x, y); + x += 8; + if x + 8 > self.width { + x = 0; + y += 14; + } + } + + self.text_cursor = (x, y); + } + + pub fn print_char(&mut self, c: char) { + let (x, y) = self.text_cursor; + + self.draw_char(c, x, y); + self.text_cursor.0 += 8; + if self.text_cursor.0 >= self.width { + self.text_cursor.0 = 0; + self.text_cursor.1 += 14; + } + } + + pub fn draw_char(&self, c: char, x: usize, y: usize) { + let font = FontRef::try_from_slice(FONT).unwrap(); + + let font = font.as_scaled(14.0); + + let mut glyph = font.scaled_glyph(c); + glyph.position = ab_glyph::point(0.0, font.ascent()); + if let Some(glyph) = font.outline_glyph(glyph) { + let min_x = glyph.px_bounds().min.x as usize; + + let min_y = glyph.px_bounds().min.y as usize; + + glyph.draw(|fx, fy, c| { + let pixel_x = fx + min_x as u32 + x as u32; + let pixel_y = fy + min_y as u32 + y as u32; + let color = if c > 0.0 { (c * 255.0) as u8 } else { 64 }; + + self.draw_pixel(color, color, color, pixel_x as usize, pixel_y as usize); + }); + } + } +} diff --git a/nel_os_kernel/src/main.rs b/nel_os_kernel/src/main.rs index 5cbc508..ef1eb1f 100644 --- a/nel_os_kernel/src/main.rs +++ b/nel_os_kernel/src/main.rs @@ -5,6 +5,7 @@ extern crate alloc; pub mod allocator; pub mod constant; +pub mod graphics; pub mod logging; pub mod memory; pub mod paging; @@ -20,6 +21,7 @@ use x86_64::{structures::paging::OffsetPageTable, VirtAddr}; use crate::{ constant::{BANNER, KERNEL_STACK_SIZE, PKG_VERSION}, + graphics::{FrameBuffer, FRAME_BUFFER}, memory::BitmapMemoryTable, }; @@ -67,8 +69,6 @@ fn hlt_loop() -> ! { #[unsafe(no_mangle)] pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) { - println!("{} v{}", BANNER, PKG_VERSION); - let virt = VirtAddr::new( x86_64::registers::control::Cr3::read() .0 @@ -110,9 +110,22 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) { allocator::init_heap(&mut mapper, &mut bitmap_table).unwrap(); - let mut test_vec = vec![1, 2, 3, 4, 9]; - test_vec.push(10); - info!("Vector test: {:?}", test_vec); + let frame_buffer = FrameBuffer::from_raw_buffer(&boot_info.frame_buffer); + + for x in 0..frame_buffer.width { + for y in 0..frame_buffer.height { + frame_buffer.draw_pixel(64, 64, 64, x, y); + } + } + + FRAME_BUFFER.lock().replace(frame_buffer); + + println!("{} v{}", BANNER, PKG_VERSION); + info!( + "Usable memory: {}MiB ({:.1}GiB)", + usable_frame * 4 / 1024, + usable_frame as f64 * 4. / 1024. / 1024. + ); hlt_loop(); } diff --git a/nel_os_kernel/src/serial.rs b/nel_os_kernel/src/serial.rs index 70a1a4a..3d6754e 100644 --- a/nel_os_kernel/src/serial.rs +++ b/nel_os_kernel/src/serial.rs @@ -1,7 +1,10 @@ +use alloc::format; use lazy_static::lazy_static; use spin::Mutex; use uart_16550::SerialPort; +use crate::graphics::FRAME_BUFFER; + lazy_static! { pub static ref SERIAL1: Mutex = { let mut serial_port = unsafe { SerialPort::new(0x3F8) }; @@ -19,6 +22,13 @@ pub fn _print(args: ::core::fmt::Arguments) { .lock() .write_fmt(args) .expect("Printing to serial failed"); + + let mut fb = FRAME_BUFFER.lock(); + let fb = fb.as_mut(); + + if let Some(frame_buffer) = fb { + frame_buffer.print_text(format!("{args}").as_str()); + } }); }