initial commit

This commit is contained in:
2025-05-15 16:33:37 +09:00
commit 3c35bc7fea
18 changed files with 917 additions and 0 deletions

387
Cargo.lock generated Normal file
View File

@@ -0,0 +1,387 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "az"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
[[package]]
name = "bit_field"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[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 = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"spin 0.9.8",
"stable_deref_trait",
]
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "micromath"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
[[package]]
name = "miniz_oxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "png-decoder"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e3e93d4884a2609f2dccbafabd3e25c49e89bb872ab84bfea60feaf17615944"
dependencies = [
"crc32fast",
"miniz_oxide",
"num_enum",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "spin"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinygif"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f1406b710986188de8d393c810213d4bbf940e327d90d52cff9930d007a248"
dependencies = [
"embedded-graphics",
"heapless",
]
[[package]]
name = "ucs2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df79298e11f316400c57ec268f3c2c29ac3c4d4777687955cd3d4f3a35ce7eba"
dependencies = [
"bit_field",
]
[[package]]
name = "uefi"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da7569ceafb898907ff764629bac90ac24ba4203c38c33ef79ee88c74aa35b11"
dependencies = [
"bitflags",
"cfg-if",
"log",
"ptr_meta",
"ucs2",
"uefi-macros",
"uefi-raw",
"uguid",
]
[[package]]
name = "uefi-macros"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3dad47b3af8f99116c0f6d4d669c439487d9aaf1c8d9480d686cda6f3a8aa23"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
name = "uefi-raw"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cad96b8baaf1615d3fdd0f03d04a0b487d857c1b51b19dcbfe05e2e3c447b78"
dependencies = [
"bitflags",
"uguid",
]
[[package]]
name = "uefi-video"
version = "0.1.0"
dependencies = [
"embedded-graphics-core",
"libm",
"log",
"png-decoder",
"spin 0.10.0",
"tinygif",
"uefi",
]
[[package]]
name = "uguid"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"

13
Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "uefi-video"
version = "0.1.0"
edition = "2024"
[dependencies]
embedded-graphics-core = "0.4.0"
libm = "0.2.15"
log = "0.4.27"
png-decoder = "0.1.1"
spin = "0.10.0"
tinygif = "0.0.4"
uefi = { version = "0.35.0", features = ["logger", "panic_handler"] }

BIN
OVMF.fd Normal file

Binary file not shown.

23
src/codec/image.rs Normal file
View File

@@ -0,0 +1,23 @@
use alloc::{boxed::Box, vec::Vec};
use crate::{color::Color, error::RenderError};
use super::transform::Transformer;
pub mod png;
pub struct ImageData {
pub pixels: Vec<Color>,
pub width: usize,
pub height: usize,
}
impl ImageData {
pub fn transform(&self, transformer: &dyn Transformer) -> Self {
transformer.transform(&self)
}
}
pub trait ImageDecoder {
fn decode(&self, bytes: &[u8]) -> Result<ImageData, RenderError>;
}

32
src/codec/image/png.rs Normal file
View File

@@ -0,0 +1,32 @@
use alloc::format;
use png_decoder::DecodeError;
use crate::{color::Color, error::RenderError};
use super::{ImageData, ImageDecoder};
pub struct PngDecoder;
impl ImageDecoder for PngDecoder {
fn decode(&self, bytes: &[u8]) -> Result<super::ImageData, RenderError> {
let (header, rgba_pixels) =
png_decoder::decode(bytes).map_err(|err| RenderError::from(err))?;
let pixels = rgba_pixels
.chunks(4)
.map(|chunk| Color::new(chunk[0].into(), chunk[1].into(), chunk[2].into()))
.collect();
Ok(ImageData {
width: header.width as usize,
height: header.height as usize,
pixels,
})
}
}
impl From<DecodeError> for RenderError {
fn from(value: DecodeError) -> Self {
RenderError::new("PngDecoder", &format!("{:?}", value))
}
}

3
src/codec/mod.rs Normal file
View File

@@ -0,0 +1,3 @@
pub mod image;
pub mod transform;
pub mod video;

8
src/codec/transform.rs Normal file
View File

@@ -0,0 +1,8 @@
use crate::codec::image::ImageData;
pub mod crop;
pub mod scale;
pub trait Transformer {
fn transform(&self, original: &ImageData) -> ImageData;
}

View File

@@ -0,0 +1,43 @@
use alloc::vec;
use crate::{codec::image::ImageData, color::Color};
use super::Transformer;
pub struct CropTransformer {
pub new_resolution: (usize, usize),
}
impl CropTransformer {
pub fn new(w: usize, h: usize) -> CropTransformer {
CropTransformer {
new_resolution: (w, h),
}
}
}
impl Transformer for CropTransformer {
fn transform(&self, original: &ImageData) -> ImageData {
let new_resolution = self.new_resolution;
let new_pixels = (0..new_resolution.0 * new_resolution.1)
.map(|i| {
let x = i % new_resolution.0;
let y = i / new_resolution.0;
if x < original.width && y < original.height {
Some(original.pixels[y * original.width + x].clone())
} else {
None
}
})
.map(|o| o.unwrap_or_else(|| Color::new(0, 0, 0)))
.collect();
ImageData {
width: new_resolution.0,
height: new_resolution.1,
pixels: new_pixels,
}
}
}

View File

@@ -0,0 +1,72 @@
use alloc::vec;
use libm::{floorf, roundf};
use crate::{codec::image::ImageData, color::Color};
use super::Transformer;
pub struct ScaleTransformer {
pub scale: f32,
}
impl ScaleTransformer {
pub fn new(scale: f32) -> Self {
Self { scale }
}
}
impl Transformer for ScaleTransformer {
fn transform(&self, original: &ImageData) -> ImageData {
let width = original.width;
let height = original.height;
let scale = self.scale;
let new_width = roundf(width as f32 * scale) as usize;
let new_height = roundf(height as f32 * scale) as usize;
let mut new_pixels = vec![Color { r: 0, g: 0, b: 0 }; new_width * new_height];
for y in 0..new_height {
for x in 0..new_width {
let src_x = floorf(x as f32 / scale);
let src_y = floorf(y as f32 / scale);
let fx = (x as f32 / scale) - src_x;
let fy = (y as f32 / scale) - src_y;
let x0 = src_x as usize;
let y0 = src_y as usize;
let x1 = (x0 + 1).min(width - 1);
let y1 = (y0 + 1).min(height - 1);
let idx = |x, y| y * width + x;
let c00 = original.pixels[idx(x0, y0)].clone();
let c10 = original.pixels[idx(x1, y0)].clone();
let c01 = original.pixels[idx(x0, y1)].clone();
let c11 = original.pixels[idx(x1, y1)].clone();
let color = bilinear_interpolate(c00, c10, c01, c11, fx, fy);
new_pixels[y * new_width + x] = color;
}
}
ImageData {
width: new_width,
height: new_height,
pixels: new_pixels,
}
}
}
fn bilinear_interpolate(c00: Color, c10: Color, c01: Color, c11: Color, tx: f32, ty: f32) -> Color {
let interpolate = |v00, v10, v01, v11| {
let top = (1.0 - tx) * v00 as f32 + tx * v10 as f32;
let bottom = (1.0 - tx) * v01 as f32 + tx * v11 as f32;
roundf((1.0 - ty) * top + ty * bottom).clamp(0.0, 255.0) as u8
};
Color {
r: interpolate(c00.r, c10.r, c01.r, c11.r),
g: interpolate(c00.g, c10.g, c01.g, c11.g),
b: interpolate(c00.b, c10.b, c01.b, c11.b),
}
}

39
src/codec/video.rs Normal file
View File

@@ -0,0 +1,39 @@
use alloc::vec::Vec;
use crate::{color::Color, error::RenderError, util::time::Milliseconds};
use super::{image::ImageData, transform::Transformer};
pub mod gif;
pub struct Frame {
pub image: ImageData,
pub delay: Milliseconds,
}
pub struct VideoData {
pub width: usize,
pub height: usize,
pub frames: Vec<Frame>,
}
impl VideoData {
pub fn transform(&self, transformer: &dyn Transformer) -> Self {
VideoData {
width: self.width,
height: self.height,
frames: self
.frames
.iter()
.map(|f| Frame {
image: f.image.transform(transformer),
delay: f.delay.clone(),
})
.collect(),
}
}
}
pub trait VideoDecoder {
fn decode(&self, bytes: &[u8]) -> Result<VideoData, RenderError>;
}

95
src/codec/video/gif.rs Normal file
View File

@@ -0,0 +1,95 @@
use alloc::{format, vec::Vec};
use embedded_graphics_core::{
image::ImageDrawable,
pixelcolor::Rgb888,
prelude::{Dimensions, DrawTarget, PixelColor, Point, RgbColor, Size},
primitives::Rectangle,
};
use tinygif::ParseError;
use crate::{codec::image::ImageData, color::Color, error::RenderError, util::time::Milliseconds};
use super::{Frame, VideoData, VideoDecoder};
pub struct GifDecoder;
impl VideoDecoder for GifDecoder {
fn decode(&self, bytes: &[u8]) -> Result<super::VideoData, RenderError> {
let image = tinygif::Gif::from_slice(bytes).map_err(|e| RenderError::from(e))?;
let frames = image
.frames()
.map(|f| {
let mut raw = GifData::new(image.width() as usize, image.height() as usize);
f.draw(&mut raw).unwrap();
Frame {
image: ImageData {
width: image.width() as usize,
height: image.height() as usize,
pixels: raw.pixels,
},
delay: Milliseconds((f.delay_centis * 10) as u32),
}
})
.collect();
Ok(VideoData {
width: image.width() as usize,
height: image.height() as usize,
frames,
})
}
}
impl From<ParseError> for RenderError {
fn from(value: ParseError) -> Self {
RenderError::new("VideoDecoder", &format!("{:?}", value))
}
}
struct GifData {
width: usize,
height: usize,
pixels: Vec<Color>,
}
impl GifData {
pub fn new(width: usize, height: usize) -> GifData {
GifData {
width,
height,
pixels: alloc::vec![Color::new(0, 0, 0); width*height],
}
}
}
impl Dimensions for GifData {
fn bounding_box(&self) -> embedded_graphics_core::primitives::Rectangle {
Rectangle::new(
Point::new(0, 0),
Size::new(self.width as u32, self.height as u32),
)
}
}
impl DrawTarget for GifData {
type Color = Rgb888;
type Error = ();
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = embedded_graphics_core::Pixel<Self::Color>>,
{
for pixel in pixels.into_iter() {
let point = pixel.0;
let color = pixel.1;
let i = (point.y as usize) * self.width + (point.x as usize);
self.pixels[i] = Color::new(color.r(), color.g(), color.b());
}
Ok(())
}
}

20
src/color.rs Normal file
View File

@@ -0,0 +1,20 @@
use uefi::proto::console::gop::BltPixel;
#[derive(Debug, Clone)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl Color {
pub fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
}
impl From<&Color> for BltPixel {
fn from(value: &Color) -> Self {
BltPixel::new(value.r, value.g, value.b)
}
}

15
src/error.rs Normal file
View File

@@ -0,0 +1,15 @@
use alloc::string::{String, ToString};
pub struct RenderError {
ident: String,
message: String,
}
impl RenderError {
pub fn new(ident: &str, message: &str) -> RenderError {
RenderError {
ident: ident.to_string(),
message: message.to_string(),
}
}
}

55
src/graphic.rs Normal file
View File

@@ -0,0 +1,55 @@
use alloc::sync::Arc;
use buffer::Buffer;
use spin::Mutex;
use uefi::{
Result,
boot::{self, ScopedProtocol},
proto::console::gop::GraphicsOutput,
};
use crate::{
codec::{
image::ImageData,
transform::{Transformer, crop::CropTransformer},
video::VideoData,
},
util::time::Microseconds,
};
pub mod buffer;
pub struct GraphicLoader {
gop: Arc<Mutex<Option<ScopedProtocol<GraphicsOutput>>>>,
resolution: Arc<Mutex<Option<(usize, usize)>>>,
}
impl GraphicLoader {
pub fn new() -> Self {
Self {
gop: Arc::new(Mutex::new(None)),
resolution: Arc::new(Mutex::new(None)),
}
}
pub fn render(&self, data: &ImageData) -> Result {
let gop_handle = boot::get_handle_for_protocol::<GraphicsOutput>()?;
let mut gop = boot::open_protocol_exclusive::<GraphicsOutput>(gop_handle)?;
let (width, height) = gop.current_mode_info().resolution();
let new_data = data.transform(&CropTransformer::new(width, height));
let buffer = Buffer::from(new_data);
buffer.blit(&mut gop)
}
pub fn render_video(&self, data: &VideoData) -> Result {
loop {
for frame in data.frames.iter() {
self.render(&frame.image)?;
boot::stall(Microseconds::from(frame.delay.clone()).0 as usize);
}
}
}
}

58
src/graphic/buffer.rs Normal file
View File

@@ -0,0 +1,58 @@
use alloc::vec::Vec;
use uefi::{
Result,
proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput},
};
use crate::codec::image::ImageData;
pub struct Buffer {
width: usize,
height: usize,
pixels: Vec<BltPixel>,
}
impl Buffer {
pub fn new(width: usize, height: usize) -> Self {
Buffer {
width,
height,
pixels: alloc::vec![BltPixel::new(255, 255, 0); width * height],
}
}
pub fn pixel(&mut self, x: usize, y: usize) -> Option<&mut BltPixel> {
self.pixels.get_mut(y * self.width + x)
}
pub fn blit(&self, gop: &mut GraphicsOutput) -> Result {
gop.blt(BltOp::BufferToVideo {
buffer: &self.pixels,
src: BltRegion::Full,
dest: (0, 0),
dims: (self.width, self.height),
})
}
pub fn blit_pixel(&self, gop: &mut GraphicsOutput, coords: (usize, usize)) -> Result {
gop.blt(BltOp::BufferToVideo {
buffer: &self.pixels,
src: BltRegion::SubRectangle {
coords: coords,
px_stride: self.width,
},
dest: coords,
dims: (1, 1),
})
}
}
impl From<ImageData> for Buffer {
fn from(value: ImageData) -> Self {
Buffer {
width: value.width,
height: value.height,
pixels: value.pixels.iter().map(|p| BltPixel::from(p)).collect(),
}
}
}

42
src/main.rs Normal file
View File

@@ -0,0 +1,42 @@
#![no_main]
#![no_std]
extern crate alloc;
use codec::{
image::{ImageDecoder, png::PngDecoder},
transform::scale::ScaleTransformer,
video::{VideoDecoder, gif::GifDecoder},
};
use graphic::GraphicLoader;
use log::info;
use uefi::{allocator::Allocator, prelude::*};
mod codec;
mod color;
mod error;
mod graphic;
mod util;
#[global_allocator]
static ALLOC: Allocator = Allocator;
static IMAGE: &[u8] = include_bytes!("../assets/pet.gif");
#[entry]
fn main() -> Status {
uefi::helpers::init().unwrap();
info!("Hello world!");
let gl = GraphicLoader::new();
let data = GifDecoder.decode(IMAGE);
if let Ok(data) = data {
let data = data.transform(&ScaleTransformer::new(4.0));
gl.render_video(&data);
}
boot::stall(10_000_000);
Status::SUCCESS
}

1
src/util/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod time;

11
src/util/time.rs Normal file
View File

@@ -0,0 +1,11 @@
#[derive(Debug, Clone)]
pub struct Milliseconds(pub u32);
#[derive(Debug, Clone)]
pub struct Microseconds(pub u32);
impl From<Milliseconds> for Microseconds {
fn from(value: Milliseconds) -> Self {
Microseconds(value.0 * 1000)
}
}