microsoft/openvmm
Publicmirrored fromhttps://github.com/microsoft/openvmmAvailable
guest_test_uefi/src/uefi/splash.rs
82lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | // NOTE: adapted from uefi-rs sierpinski example code: |
| 5 | // https://github.com/rust-osdev/uefi-rs/blob/main/uefi-test-runner/examples/sierpinski.rs |
| 6 | |
| 7 | use alloc::vec::Vec; |
| 8 | use core::num::NonZeroU8; |
| 9 | use uefi::Result; |
| 10 | use uefi::boot; |
| 11 | use uefi::proto::console::gop::BltOp; |
| 12 | use uefi::proto::console::gop::BltPixel; |
| 13 | use uefi::proto::console::gop::BltRegion; |
| 14 | use uefi::proto::console::gop::GraphicsOutput; |
| 15 | |
| 16 | struct Buffer { |
| 17 | width: usize, |
| 18 | height: usize, |
| 19 | pixels: Vec<BltPixel>, |
| 20 | } |
| 21 | |
| 22 | impl Buffer { |
| 23 | /// Create a new `Buffer`. |
| 24 | fn new(width: usize, height: usize) -> Self { |
| 25 | Buffer { |
| 26 | width, |
| 27 | height, |
| 28 | pixels: vec![BltPixel::new(0, 0, 0); width * height], |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | /// Get a single pixel. |
| 33 | fn pixel(&mut self, x: usize, y: usize) -> Option<&mut BltPixel> { |
| 34 | self.pixels.get_mut(y * self.width + x) |
| 35 | } |
| 36 | |
| 37 | /// Blit the buffer to the framebuffer. |
| 38 | fn blit(&self, gop: &mut GraphicsOutput) -> Result { |
| 39 | gop.blt(BltOp::BufferToVideo { |
| 40 | buffer: &self.pixels, |
| 41 | src: BltRegion::Full, |
| 42 | dest: (0, 0), |
| 43 | dims: (self.width, self.height), |
| 44 | }) |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | pub struct Splashes(pub NonZeroU8); |
| 49 | |
| 50 | pub fn draw_splash(splashes: Splashes) { |
| 51 | // The graphic output is not always available. |
| 52 | let gop_handle = if let Ok(handle) = boot::get_handle_for_protocol::<GraphicsOutput>() { |
| 53 | handle |
| 54 | } else { |
| 55 | return; |
| 56 | }; |
| 57 | let mut gop = boot::open_protocol_exclusive::<GraphicsOutput>(gop_handle).expect("can get GOP"); |
| 58 | |
| 59 | // Create a buffer to draw into. |
| 60 | let (resolution_width, resolution_height) = gop.current_mode_info().resolution(); |
| 61 | let mut buffer = Buffer::new(resolution_width, resolution_height); |
| 62 | |
| 63 | let splashes = splashes.0.get() as usize; |
| 64 | let height = resolution_height / splashes; |
| 65 | let width = resolution_width / splashes; |
| 66 | for s in 0..splashes { |
| 67 | // Initialize the buffer with a simple gradient background. |
| 68 | for y in s * height..(s + 1) * height { |
| 69 | let r = ((y as f32) / ((resolution_height - 1) as f32)) * 255.0; |
| 70 | for x in s * width..(s + 1) * width { |
| 71 | let g = ((x as f32) / ((resolution_width - 1) as f32)) * 255.0; |
| 72 | let pixel = buffer.pixel(x, y).expect("Can draw a pixel"); |
| 73 | pixel.red = r as u8; |
| 74 | pixel.green = g as u8; |
| 75 | pixel.blue = 255; |
| 76 | } |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | // Draw the buffer to the screen. |
| 81 | buffer.blit(&mut gop).expect("can draw the image"); |
| 82 | } |
| 83 | |