diff --git a/Cargo.lock b/Cargo.lock index d9b163fe4..55ced166a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "basic-toml" version = "0.1.2" @@ -135,6 +141,16 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[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.1" @@ -550,6 +566,7 @@ name = "uefi" version = "0.21.0" dependencies = [ "bitflags 2.3.1", + "embedded-graphics-core", "log", "ptr_meta", "ucs2", @@ -583,6 +600,7 @@ name = "uefi-services" version = "0.18.0" dependencies = [ "cfg-if", + "embedded-graphics-core", "log", "qemu-exit", "uefi", diff --git a/uefi/Cargo.toml b/uefi/Cargo.toml index 4f6858ade..4d7985d4e 100644 --- a/uefi/Cargo.toml +++ b/uefi/Cargo.toml @@ -12,7 +12,7 @@ license = "MPL-2.0" rust-version = "1.68" [features] -default = ["panic-on-logger-errors"] +default = ["panic-on-logger-errors", "draw_target"] alloc = [] global_allocator = [] logger = [] @@ -20,11 +20,14 @@ logger = [] # were observed on the VirtualBox UEFI implementation (see uefi-rs#121). # In those cases, this feature can be excluded by removing the default features. panic-on-logger-errors = [] +# DrawTarget for GOP protocol +draw_target = ["embedded-graphics-core"] # Generic gate to code that uses unstable features of Rust. You usually need a nightly toolchain. unstable = [] [dependencies] bitflags = "2.0.0" +embedded-graphics-core = { version = "0.4.0", optional = true } log = { version = "0.4.5", default-features = false } ptr_meta = { version = "0.2.0", default-features = false } ucs2 = "0.3.2" diff --git a/uefi/src/proto/console/draw_target.rs b/uefi/src/proto/console/draw_target.rs new file mode 100644 index 000000000..4dd033e8c --- /dev/null +++ b/uefi/src/proto/console/draw_target.rs @@ -0,0 +1,54 @@ +use embedded_graphics_core::prelude::{DrawTarget, OriginDimensions, Size, PixelColor, Pixel, IntoStorage}; + +use super::gop::GraphicsOutput; + +// FIXME: offer conversions from C to current pixel color format? +struct GraphicsDisplay { + color: C, + gop: GraphicsOutput +} + +impl OriginDimensions for GraphicsOutput { + fn size(&self) -> embedded_graphics_core::prelude::Size { + let (width, height) = self.current_mode_info().resolution(); + + Size::from((width as u32, height as u32)) + } +} + +impl OriginDimensions for GraphicsDisplay { + fn size(&self) -> Size { + self.gop.size() + } +} + +impl DrawTarget for GraphicsDisplay { + type Color = C; + type Error = uefi::Error; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator> { + let stride = self.gop.current_mode_info().stride() as u64; + for Pixel(point, color) in pixels.into_iter() { + let bytes = color.into_storage(); + let (x, y) = (point.x as u64, point.y as u64); + let index: usize = (((y * stride) + x) * 4) + .try_into() + .map_err(|_| + uefi::Error::from( + uefi::Status::UNSUPPORTED + ) + )?; + + unsafe { + self.gop.frame_buffer().write_value(index, bytes); + } + } + + Ok(()) + } + + // FIXME: provide a blt technique for fill_solid + // FIXME: fallback to blt when pixelformat is blt-only. +} diff --git a/uefi/src/proto/console/mod.rs b/uefi/src/proto/console/mod.rs index 636eb77b4..b7a37f662 100644 --- a/uefi/src/proto/console/mod.rs +++ b/uefi/src/proto/console/mod.rs @@ -7,3 +7,5 @@ pub mod gop; pub mod pointer; pub mod serial; pub mod text; +#[cfg(feature = "draw_target")] +pub mod draw_target;