From 79f47fda1204b470b08ee881f11a8789916d7343 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Fri, 29 Dec 2023 19:27:56 +0100 Subject: [PATCH] Use `embedded-graphics` crate to draw shapes and text --- Cargo.lock | 54 ++++++++++++++++++++++++++++++++++ kernel/Cargo.toml | 1 + kernel/src/framebuffer.rs | 62 +++++++++++++++++++++++++++++++++++++++ kernel/src/main.rs | 39 ++++++++++++++---------- 4 files changed, 141 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ddf1877..64c363a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,6 +133,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "bincode" version = "1.3.3" @@ -270,6 +276,29 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "embedded-graphics" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0" +dependencies = [ + "az", + "byteorder", + "embedded-graphics-core", + "float-cmp", + "micromath", +] + +[[package]] +name = "embedded-graphics-core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044" +dependencies = [ + "az", + "byteorder", +] + [[package]] name = "errno" version = "0.3.8" @@ -344,6 +373,15 @@ dependencies = [ "log", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "funty" version = "2.0.0" @@ -537,6 +575,7 @@ name = "kernel" version = "0.1.0" dependencies = [ "bootloader_api", + "embedded-graphics", ] [[package]] @@ -588,6 +627,21 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "micromath" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + [[package]] name = "ovmf-prebuilt" version = "0.1.0-alpha.1" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index dfcd139f..db5ea789 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -10,3 +10,4 @@ bench = false [dependencies] bootloader_api = "0.11.0" +embedded-graphics = "0.8.1" diff --git a/kernel/src/framebuffer.rs b/kernel/src/framebuffer.rs index 0c82e1b9..ef7394ab 100644 --- a/kernel/src/framebuffer.rs +++ b/kernel/src/framebuffer.rs @@ -1,4 +1,66 @@ use bootloader_api::info::{FrameBuffer, PixelFormat}; +use embedded_graphics::{ + draw_target::DrawTarget, + geometry::{self, Point}, + pixelcolor::{Rgb888, RgbColor}, + Pixel, +}; + +pub struct Display { + framebuffer: &'static mut FrameBuffer, +} + +impl Display { + pub fn new(framebuffer: &'static mut FrameBuffer) -> Display { + Self { framebuffer } + } + + fn draw_pixel(&mut self, coordinates: Point, color: Rgb888) { + // ignore any pixels that are out of bounds. + let (width, height) = { + let info = self.framebuffer.info(); + (info.width, info.height) + }; + + let position = match (coordinates.x.try_into(), coordinates.y.try_into()) { + (Ok(x), Ok(y)) if x < width && y < height => Position { x, y }, + _ => return, // ignore out-of-bounds pixel + }; + let color = Color { + red: color.r(), + green: color.g(), + blue: color.b(), + }; + set_pixel_in(self.framebuffer, position, color); + } +} + +impl DrawTarget for Display { + type Color = Rgb888; + + /// Drawing operations can never fail. + type Error = core::convert::Infallible; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for Pixel(coordinates, color) in pixels.into_iter() { + self.draw_pixel(coordinates, color); + } + Ok(()) + } +} + +impl geometry::OriginDimensions for Display { + fn size(&self) -> geometry::Size { + let info = self.framebuffer.info(); + geometry::Size::new( + info.width.try_into().unwrap(), + info.height.try_into().unwrap(), + ) + } +} #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Position { diff --git a/kernel/src/main.rs b/kernel/src/main.rs index d616a8dc..a599af2a 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -1,9 +1,18 @@ #![no_std] #![no_main] -use core::panic::PanicInfo; +use core::{convert::Infallible, panic::PanicInfo}; use bootloader_api::BootInfo; +use embedded_graphics::{ + draw_target::DrawTarget, + geometry::Point, + mono_font::{self, MonoTextStyle}, + pixelcolor::{Rgb888, RgbColor, WebColors}, + primitives::{Circle, PrimitiveStyle, StyledDrawable}, + text::Text, + Drawable, +}; mod framebuffer; @@ -11,20 +20,16 @@ bootloader_api::entry_point!(kernel_main); fn kernel_main(boot_info: &'static mut BootInfo) -> ! { if let Some(framebuffer) = boot_info.framebuffer.as_mut() { - let color = framebuffer::Color { - red: 0, - green: 0, - blue: 255, - }; - for x in 0..100 { - for y in 0..100 { - let position = framebuffer::Position { - x: 20 + x, - y: 100 + y, - }; - framebuffer::set_pixel_in(framebuffer, position, color); - } - } + let mut display = framebuffer::Display::new(framebuffer); + display.clear(Rgb888::RED).unwrap_or_else(infallible); + let style = PrimitiveStyle::with_fill(Rgb888::YELLOW); + Circle::new(Point::new(50, 50), 400) + .draw_styled(&style, &mut display) + .unwrap_or_else(infallible); + + let character_style = MonoTextStyle::new(&mono_font::ascii::FONT_10X20, Rgb888::BLUE); + let text = Text::new("Hello, world!", Point::new(190, 250), character_style); + text.draw(&mut display).unwrap_or_else(infallible); } loop {} } @@ -34,3 +39,7 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! { fn panic(_info: &PanicInfo) -> ! { loop {} } + +fn infallible(v: Infallible) -> T { + match v {} +}