Update kernel with graphics and font support

This commit is contained in:
mii443
2025-07-03 19:02:43 +09:00
parent 457c227456
commit b2b2c13376
6 changed files with 216 additions and 5 deletions

View File

@ -2,6 +2,26 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 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]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.0"
@ -26,6 +46,15 @@ version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 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]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -35,6 +64,12 @@ dependencies = [
"spin 0.9.8", "spin 0.9.8",
] ]
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]] [[package]]
name = "linked_list_allocator" name = "linked_list_allocator"
version = "0.9.1" version = "0.9.1"
@ -62,6 +97,7 @@ version = "0.1.0"
name = "nel_os_kernel" name = "nel_os_kernel"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ab_glyph",
"lazy_static", "lazy_static",
"linked_list_allocator", "linked_list_allocator",
"nel_os_common", "nel_os_common",
@ -70,6 +106,15 @@ dependencies = [
"x86_64", "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]] [[package]]
name = "raw-cpuid" name = "raw-cpuid"
version = "10.7.0" version = "10.7.0"
@ -115,6 +160,15 @@ dependencies = [
"lock_api", "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]] [[package]]
name = "uart_16550" name = "uart_16550"
version = "0.3.2" version = "0.3.2"

View File

@ -10,3 +10,4 @@ uart_16550 = "0.3.2"
x86_64 = "0.15.2" x86_64 = "0.15.2"
nel_os_common = { path = "../nel_os_common" } nel_os_common = { path = "../nel_os_common" }
linked_list_allocator = "0.9.1" linked_list_allocator = "0.9.1"
ab_glyph = { version = "0.2", features = ["libm"], default-features = false }

Binary file not shown.

View File

@ -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<Option<FrameBuffer>> = 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<usize> {
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);
});
}
}
}

View File

@ -5,6 +5,7 @@ extern crate alloc;
pub mod allocator; pub mod allocator;
pub mod constant; pub mod constant;
pub mod graphics;
pub mod logging; pub mod logging;
pub mod memory; pub mod memory;
pub mod paging; pub mod paging;
@ -20,6 +21,7 @@ use x86_64::{structures::paging::OffsetPageTable, VirtAddr};
use crate::{ use crate::{
constant::{BANNER, KERNEL_STACK_SIZE, PKG_VERSION}, constant::{BANNER, KERNEL_STACK_SIZE, PKG_VERSION},
graphics::{FrameBuffer, FRAME_BUFFER},
memory::BitmapMemoryTable, memory::BitmapMemoryTable,
}; };
@ -67,8 +69,6 @@ fn hlt_loop() -> ! {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) { pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
println!("{} v{}", BANNER, PKG_VERSION);
let virt = VirtAddr::new( let virt = VirtAddr::new(
x86_64::registers::control::Cr3::read() x86_64::registers::control::Cr3::read()
.0 .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(); allocator::init_heap(&mut mapper, &mut bitmap_table).unwrap();
let mut test_vec = vec![1, 2, 3, 4, 9]; let frame_buffer = FrameBuffer::from_raw_buffer(&boot_info.frame_buffer);
test_vec.push(10);
info!("Vector test: {:?}", test_vec); 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(); hlt_loop();
} }

View File

@ -1,7 +1,10 @@
use alloc::format;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use spin::Mutex; use spin::Mutex;
use uart_16550::SerialPort; use uart_16550::SerialPort;
use crate::graphics::FRAME_BUFFER;
lazy_static! { lazy_static! {
pub static ref SERIAL1: Mutex<SerialPort> = { pub static ref SERIAL1: Mutex<SerialPort> = {
let mut serial_port = unsafe { SerialPort::new(0x3F8) }; let mut serial_port = unsafe { SerialPort::new(0x3F8) };
@ -19,6 +22,13 @@ pub fn _print(args: ::core::fmt::Arguments) {
.lock() .lock()
.write_fmt(args) .write_fmt(args)
.expect("Printing to serial failed"); .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());
}
}); });
} }