bootproof/src/graphics/display/gop.rs

68 lines
2.2 KiB
Rust

use crate::println;
use crate::graphics::color::{Color, RGB};
use crate::graphics::display::Display;
use crate::graphics::tty::Tty;
use uefi::proto::console::gop::{FrameBuffer, GraphicsOutput, ModeInfo, PixelFormat};
const PIXEL_WIDTH_BYTES: usize = 4;
pub struct GopDisplay<'a> {
fb: FrameBuffer<'a>,
mode: ModeInfo,
}
impl GopDisplay<'_> {
pub fn init<'boot>(bs: &'boot uefi::table::boot::BootServices) -> GopDisplay<'boot> {
let gop = bs.locate_protocol::<GraphicsOutput>()
.expect("UEFI Graphics Output Protocol (GOP) is not present.")
.unwrap();
let gop = unsafe { &mut *gop.get() };
let mut mode = None;
for gop_mode in gop.modes() {
let gop_mode = gop_mode.unwrap();
if let PixelFormat::BGR = gop_mode.info().pixel_format() {
mode = Some(gop_mode);
}
}
let mode = mode.expect("No usable pixel formats found.");
let (width, height) = mode.info().resolution();
println!("Using mode: {}x{} {:?}", width, height, mode.info().pixel_format());
gop.set_mode(&mode).expect("Failed to set UEFI Graphics Output mode.").unwrap();
let info = gop.current_mode_info();
GopDisplay {
fb: gop.frame_buffer(),
mode: info,
}
}
// Convert a color to a BGR-formatted byte array.
fn make_pixel(&self, color: impl Color) -> [u8; 4] {
[color.b(), color.g(), color.r(), 0]
}
fn pixel_index(&self, x: usize, y: usize) -> usize {
PIXEL_WIDTH_BYTES * (self.mode.stride() * y + x)
}
}
impl Display for GopDisplay<'_> {
fn resolution(&self) -> (usize, usize) { self.mode.resolution() }
unsafe fn set_pixel(&mut self, color: RGB, x: usize, y: usize) {
self.fb.write_value(self.pixel_index(x, y), self.make_pixel(color));
}
fn clear(&mut self, color: RGB) {
let (width, height) = self.resolution();
let px = self.make_pixel(color);
for x in 0..width {
for y in 0..height {
unsafe {
self.fb.write_value(self.pixel_index(x, y), px);
}
}
}
}
}