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.
|
||||
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"
|
||||
|
@ -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 }
|
||||
|
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 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();
|
||||
}
|
||||
|
@ -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<SerialPort> = {
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user