Update kernel with graphics and font support
This commit is contained in:
54
nel_os_kernel/Cargo.lock
generated
54
nel_os_kernel/Cargo.lock
generated
@ -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"
|
||||||
|
@ -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 }
|
||||||
|
BIN
nel_os_kernel/Tamzen7x14r.ttf
Normal file
BIN
nel_os_kernel/Tamzen7x14r.ttf
Normal file
Binary file not shown.
133
nel_os_kernel/src/graphics.rs
Normal file
133
nel_os_kernel/src/graphics.rs
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user