pub struct FbDrawTarget<'proto> { /* private fields */ }Expand description
A single-buffered framebuffer DrawTarget.
See the module-level documentation for more information on the framebuffer
DrawTargets.
§Examples
use embedded_graphics_gop::fb::FbDrawTarget;
use uefi::{prelude::*, proto::console::gop::GraphicsOutput};
// Get the first available handle for the GOP.
let handle = boot::get_handle_for_protocol::<GraphicsOutput>().unwrap();
// Open the protocol in exclusive mode (exclusive mode is for applications, other modes are
// intended for drivers)
let mut protocol = boot::open_protocol_exclusive::<GraphicsOutput>(handle).unwrap();
// Configure protocol here if desired, for example
let mode = protocol.modes().find(|m| m.info().resolution() == (800, 600)).unwrap();
protocol.set_mode(&mode).unwrap();
// Create the draw target utilizing the configured protocol.
let mut target = FbDrawTarget::new(&mut protocol);
// ...draw on it...Implementations§
Source§impl<'proto> FbDrawTarget<'proto>
impl<'proto> FbDrawTarget<'proto>
Sourcepub fn new(protocol: &'proto mut ScopedProtocol<GraphicsOutput>) -> Self
pub fn new(protocol: &'proto mut ScopedProtocol<GraphicsOutput>) -> Self
Create a new FbDrawTarget given a GOP protocol handle.
Fills the framebuffer with black.
Note that one should configure the desired graphics mode for the protocol prior to creating
the FbDrawTarget.
§Panics
- If the pixel format for the current graphics mode is not
PixelFormat::RgborPixelFormat::Bgr. - If the reported resolution of the current graphics mode is ≥ 2^31 - 1 in either dimension.
- If the reported number of pixels addressed by the current graphics mode (width×height)
exceeds
isize::MAX / 4(i.e. largest possible size for an array ofu32s). - If the framebuffer pointer returned from UEFI is not aligned to
align_of::<u32>()(typically four bytes).
Examples found in repository?
25fn main() -> Status {
26 helpers::init().unwrap();
27
28 let handle =
29 boot::get_handle_for_protocol::<GraphicsOutput>().expect("Unable to get GOP handle");
30 let mut gop =
31 boot::open_protocol_exclusive::<GraphicsOutput>(handle).expect("Unable to open GOP handle");
32
33 let mode_800x600 = gop
34 .modes()
35 // one of the standard modes, although some systems may only provide 640×480
36 .find(|m| m.info().resolution() == (800, 600))
37 .expect("Unable to find 800x600 video mode");
38 gop.set_mode(&mode_800x600)
39 .expect("Couldn't switch to 800x600 video mode");
40
41 let mut formats = Vec::new();
42 for (idx, mode) in gop.modes().enumerate() {
43 let mode = mode.info();
44 let (width, height) = mode.resolution();
45 formats.push(alloc::format!(
46 "Mode {:02}: resolution {}x{}, pixel format {:?}, stride {}",
47 idx,
48 width,
49 height,
50 mode.pixel_format(),
51 mode.stride(),
52 ));
53 }
54
55 let mut target = FbDrawTarget::new(&mut gop);
56
57 let font = MonoTextStyle::new(&FONT_10X20, Rgb888::WHITE);
58
59 let mut pos = Point::new(90, 20);
60 for format in &formats {
61 Text::new(format, pos, font)
62 .draw(&mut target)
63 .expect("unable to draw text");
64 pos.y += 15;
65 }
66
67 boot::stall(Duration::from_secs(10));
68 runtime::reset(ResetType::SHUTDOWN, Status::SUCCESS, None);
69}Source§impl FbDrawTarget<'static>
impl FbDrawTarget<'static>
Sourcepub unsafe fn new_free_lifetime(
protocol: &mut ScopedProtocol<GraphicsOutput>,
) -> Self
pub unsafe fn new_free_lifetime( protocol: &mut ScopedProtocol<GraphicsOutput>, ) -> Self
Equivalent to FbDrawTarget::new, but allows the FbDrawTarget to outlive the input
ScopedProtocol.
Allows preserving the framebuffer after closing the GOP handle or even after exiting UEFI boot services (with caveats). See the module-level documentation.
Other than breaking the input protocol lifetime, precisely equivalent to the new method in
behavior.
§Safety
This technically violates the requirements specified in FrameBuffer, as the pointer
outlives the FrameBuffer that created it (in fact, this immediately discards the
Framebuffer so it violates the specified safety requirements even before the protocol gets
dropped). However, per the implementation in uefi-rs 0.36.1, it directly passes through the
pointer given by the UEFI implementation, so the rules for handling it correspond to how it
could be handled in C. The implementation follows all the other safety requirements
specified by FrameBuffer.
Re-opening a specific GOP handle may invalidate all previous framebuffer pointers, and changing the graphics mode will almost certainly invalidate them.
The ability to preserve the framebuffer pointer after exiting boot services is not specified at all in the UEFI Specification as of version 2.11. As such, it is implementation-specific. One must also ensure the system memory map remains set up properly to keep the pointer pointing to the same physical address.
Examples found in repository?
17fn main() -> Status {
18 helpers::init().unwrap();
19
20 let handle =
21 boot::get_handle_for_protocol::<GraphicsOutput>().expect("Unable to get GOP handle");
22 let mut gop =
23 boot::open_protocol_exclusive::<GraphicsOutput>(handle).expect("Unable to open GOP handle");
24
25 let mode_800x600 = gop
26 .modes()
27 // one of the standard modes, although some systems may only provide 640×480
28 .find(|m| m.info().resolution() == (800, 600))
29 .expect("Unable to find 800x600 video mode");
30 gop.set_mode(&mode_800x600)
31 .expect("Couldn't switch to 800x600 video mode");
32
33 // SAFETY: see rules on `FbDrawTarget::new_free_lifetime` for caveats about invalidation,
34 // implementation-specific considerations, and complications with exiting boot services.
35 //
36 // This example does work on QEMU and should work on most real desktop implementations.
37 let mut target = unsafe { FbDrawTarget::new_free_lifetime(&mut gop) };
38 drop(gop);
39 // SAFETY: this is completely disregarding almost everything one needs to do after exiting boot
40 // services, just for demonstration purposes. The example still works after uncommenting this.
41 // unsafe { drop(uefi::boot::exit_boot_services(None)) };
42
43 target
44 .fill_solid(
45 &Rectangle::new(Point::zero(), Size::new(266, 600)),
46 Rgb888::RED,
47 )
48 .expect("infallible");
49 target
50 .fill_solid(
51 &Rectangle::new(Point::new(266, 0), Size::new(267, 600)),
52 Rgb888::GREEN,
53 )
54 .expect("infallible");
55 target
56 .fill_solid(
57 &Rectangle::new(Point::new(533, 0), Size::new(267, 600)),
58 Rgb888::BLUE,
59 )
60 .expect("infallible");
61
62 boot::stall(Duration::from_secs(10));
63 runtime::reset(ResetType::SHUTDOWN, Status::SUCCESS, None);
64}