double_buffered/
double_buffered.rs

1// Copyright (c) 2025 nytpu <alex [at] nytpu.com>
2// SPDX-License-Identifier: MPL-2.0
3// For more license details, see LICENSE or <https://www.mozilla.org/en-US/MPL/2.0/>.
4
5//! Example showing usage of a double-buffered `BltDrawTarget`, with other features like
6//! `discard_changes`.
7
8#![no_main]
9#![no_std]
10
11use core::time::Duration;
12use embedded_graphics::{
13	pixelcolor::Rgb888,
14	prelude::*,
15	primitives::{Circle, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle},
16};
17use embedded_graphics_gop::BltDrawTarget;
18use uefi::{helpers, prelude::*, proto::console::gop::GraphicsOutput, runtime::ResetType};
19
20#[entry]
21fn main() -> Status {
22	helpers::init().unwrap();
23
24	let handle =
25		boot::get_handle_for_protocol::<GraphicsOutput>().expect("Unable to get GOP handle");
26	let mut gop =
27		boot::open_protocol_exclusive::<GraphicsOutput>(handle).expect("Unable to open GOP handle");
28
29	let mode_800x600 = gop
30		.modes()
31		// one of the standard modes, although some systems may only provide 640×480
32		.find(|m| m.info().resolution() == (800, 600))
33		.expect("Unable to find 800x600 video mode");
34	gop.set_mode(&mode_800x600)
35		.expect("Couldn't switch to 800x600 video mode");
36
37	let mut target = BltDrawTarget::new(&mut gop).expect("unable to open BLTDrawTarget");
38	target.double_buffer(true).expect("no errors possible");
39
40	let center = Point::new(400, 300);
41
42	let white_fill = PrimitiveStyle::with_fill(Rgb888::WHITE);
43	let (red_outline, green_outline, blue_outline) = {
44		let base = PrimitiveStyleBuilder::new().stroke_width(10);
45		(
46			base.stroke_color(Rgb888::RED).build(),
47			base.stroke_color(Rgb888::GREEN).build(),
48			base.stroke_color(Rgb888::BLUE).build(),
49		)
50	};
51
52	Circle::with_center(center, 500)
53		.into_styled(red_outline)
54		.draw(&mut target)
55		.expect("infallible");
56
57	Circle::with_center(center, 400)
58		.into_styled(green_outline)
59		.draw(&mut target)
60		.expect("infallible");
61
62	target.commit().expect("failed to copy to framebuffer");
63
64	// Would cover circles
65	Rectangle::with_center(Point::new(50, 50), Size::new(700, 500))
66		.into_styled(white_fill)
67		.draw(&mut target)
68		.expect("infallible");
69
70	target
71		.discard_changes()
72		.expect("failed to reset from framebuffer");
73
74	Circle::with_center(center, 300)
75		.into_styled(blue_outline)
76		.draw(&mut target)
77		.expect("infallible");
78
79	// should auto-commit
80	drop(target);
81
82	boot::stall(Duration::from_secs(10));
83	runtime::reset(ResetType::SHUTDOWN, Status::SUCCESS, None);
84}