rough draft of something to manipulate the FB
This commit is contained in:
33
src/main.rs
33
src/main.rs
@@ -28,6 +28,7 @@ use uefi::{
|
|||||||
AllocateType, BootServices, MemoryType, OpenProtocolAttributes, OpenProtocolParams,
|
AllocateType, BootServices, MemoryType, OpenProtocolAttributes, OpenProtocolParams,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use uefi_fb::UefiFb;
|
||||||
|
|
||||||
mod uefi_fb;
|
mod uefi_fb;
|
||||||
mod sync;
|
mod sync;
|
||||||
@@ -68,36 +69,14 @@ pub fn efi_main(_image: Handle, mut st: SystemTable<Boot>) -> Status {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fb = uefi_fb::UefiFb::new();
|
||||||
|
uefifb_test(&fb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uefifb_test(fb: &UefiFb) -> Status {
|
||||||
|
|
||||||
|
// run tests here
|
||||||
let handle = bt.get_handle_for_protocol::<GraphicsOutput>()
|
|
||||||
.expect("missing GraphicsOutput protocol");
|
|
||||||
|
|
||||||
|
|
||||||
let mut gop = unsafe {
|
|
||||||
let mut gop_proto = st.boot_services().open_protocol::<GraphicsOutput>(
|
|
||||||
OpenProtocolParams {
|
|
||||||
handle,
|
|
||||||
agent: st.boot_services().image_handle(),
|
|
||||||
controller: None,
|
|
||||||
},
|
|
||||||
// For this test, don't open in exclusive mode. That
|
|
||||||
// would break the connection between stdout and the
|
|
||||||
// video console.
|
|
||||||
OpenProtocolAttributes::GetProtocol,
|
|
||||||
)
|
|
||||||
.expect("failed to open Graphics Output Protocol");
|
|
||||||
|
|
||||||
gop_proto
|
|
||||||
};
|
|
||||||
|
|
||||||
set_graphics_mode(&mut gop);
|
|
||||||
fill_color(&mut gop);
|
|
||||||
draw_fb(&mut gop);
|
|
||||||
info!("GOP Framebuffer test complete");
|
info!("GOP Framebuffer test complete");
|
||||||
|
|
||||||
// Return success status
|
|
||||||
Status::SUCCESS
|
Status::SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ use uefi::{
|
|||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use crate::sync;
|
use crate::sync;
|
||||||
use crate::sync::Spinlock::*;
|
use crate::sync::{Spinlock, SpinlockGuard};
|
||||||
|
|
||||||
struct UefiFb {
|
pub struct UefiFb<'a> {
|
||||||
gop: Arc<ScopedProtocol<GraphicsOutput>>
|
gop: ScopedProtocol<'a, GraphicsOutput<'a>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UefiFb {
|
impl UefiFb<'_> {
|
||||||
|
|
||||||
pub fn new() -> UefiFb {
|
pub fn new() -> UefiFb<'static> {
|
||||||
let st_ref = unsafe { uefi_services::system_table().as_ref() };
|
let st_ref = unsafe { uefi_services::system_table().as_ref() };
|
||||||
let bt = st_ref.boot_services();
|
let bt = st_ref.boot_services();
|
||||||
|
|
||||||
@@ -45,27 +45,15 @@ impl UefiFb {
|
|||||||
gop_proto
|
gop_proto
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UefiFb { gop }
|
||||||
|
|
||||||
UefiFb {
|
|
||||||
gop: Arc::new(gop)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
set_graphics_mode(&mut gop);
|
|
||||||
fill_color(&mut gop);
|
|
||||||
draw_fb(&mut gop);
|
|
||||||
info!("GOP Framebuffer test complete");
|
|
||||||
|
|
||||||
// Return success status
|
|
||||||
Status::SUCCESS
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a larger graphics mode.
|
// Set a larger graphics mode.
|
||||||
pub fn set_graphics_mode(&mut self) {
|
pub fn set_graphics_mode(&mut self, mode_tuple: Option<(i16,i16,i16)>) {
|
||||||
// We know for sure QEMU has a 1024x768 mode.
|
if mode_tuple == None {
|
||||||
let mode = self.gop
|
// We know for sure QEMU has a 1024x768 mode.
|
||||||
|
let mode = self.gop
|
||||||
.modes()
|
.modes()
|
||||||
.find(|mode| {
|
.find(|mode| {
|
||||||
let info = mode.info();
|
let info = mode.info();
|
||||||
@@ -73,42 +61,38 @@ impl UefiFb {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
self.gop.set_mode(&mode).expect("Failed to set graphics mode");
|
self.gop.set_mode(&mode).expect("Failed to set graphics mode");
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill the screen with color.
|
// Fill the screen with color.
|
||||||
fn fill_color(&mut self) {
|
fn fb_blt_fill(&mut self, color: BltPixel, dest: (usize, usize), dims: (usize, usize)) {
|
||||||
let op = BltOp::VideoFill {
|
let op = BltOp::VideoFill {
|
||||||
// Cornflower blue.
|
color,
|
||||||
color: BltPixel::new(100, 149, 237),
|
dest,
|
||||||
dest: (0, 0),
|
dims
|
||||||
dims: (1024, 768),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.gop.blt(op).expect("Failed to fill screen with color");
|
self.gop.blt(op).expect("Failed to fill screen with color");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Draw directly to the frame buffer.
|
// Draw directly to the frame buffer.
|
||||||
fn draw_fb(&mut self) {
|
fn draw_fb(&mut self, index: usize, rgb: [u8; 3]) {
|
||||||
// The `virtio-gpu-pci` graphics device we use on aarch64 doesn't
|
|
||||||
// support `PixelFormat::BltOnly`.
|
|
||||||
if cfg!(target_arch = "aarch64") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mi = self.gop.current_mode_info();
|
let mi = self.gop.current_mode_info();
|
||||||
let stride = mi.stride();
|
|
||||||
let (width, height) = mi.resolution();
|
|
||||||
|
|
||||||
let mut fb = self.gop.frame_buffer();
|
let mut fb = self.gop.frame_buffer();
|
||||||
|
|
||||||
type PixelWriter = unsafe fn(&mut FrameBuffer, usize, [u8; 3]);
|
type PixelWriter = unsafe fn(&mut FrameBuffer, usize, [u8; 3]);
|
||||||
unsafe fn write_pixel_rgb(fb: &mut FrameBuffer, pixel_base: usize, rgb: [u8; 3]) {
|
|
||||||
fb.write_value(pixel_base, rgb);
|
unsafe fn write_pixel_rgb(fb: &mut FrameBuffer, index: usize, rgb: [u8; 3]) {
|
||||||
|
fb.write_value(index, rgb);
|
||||||
}
|
}
|
||||||
unsafe fn write_pixel_bgr(fb: &mut FrameBuffer, pixel_base: usize, rgb: [u8; 3]) {
|
unsafe fn write_pixel_bgr(fb: &mut FrameBuffer, index: usize, rgb: [u8; 3]) {
|
||||||
fb.write_value(pixel_base, [rgb[2], rgb[1], rgb[0]]);
|
fb.write_value(index, [rgb[2], rgb[1], rgb[0]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let write_pixel: PixelWriter = match mi.pixel_format() {
|
let write_pixel: PixelWriter = match mi.pixel_format() {
|
||||||
PixelFormat::Rgb => write_pixel_rgb,
|
PixelFormat::Rgb => write_pixel_rgb,
|
||||||
PixelFormat::Bgr => write_pixel_bgr,
|
PixelFormat::Bgr => write_pixel_bgr,
|
||||||
@@ -118,21 +102,6 @@ impl UefiFb {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut fill_rectangle = |(x1, y1), (x2, y2), color| {
|
unsafe { write_pixel(&mut fb, index, rgb) };
|
||||||
assert!((x1 < width) && (x2 < width), "Bad X coordinate");
|
|
||||||
assert!((y1 < height) && (y2 < height), "Bad Y coordinate");
|
|
||||||
for row in y1..y2 {
|
|
||||||
for column in x1..x2 {
|
|
||||||
unsafe {
|
|
||||||
let pixel_index = (row * stride) + column;
|
|
||||||
let pixel_base = 4 * pixel_index;
|
|
||||||
write_pixel(&mut fb, pixel_base, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fill_rectangle((50, 30), (150, 600), [250, 128, 64]);
|
|
||||||
fill_rectangle((400, 120), (750, 450), [16, 128, 255]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user