Skip to content

Commit c2c1bb8

Browse files
HadrienG2GabrielMajeri
authored andcommitted
Slight redesign of the raw framebuffer interface (#62)
Review the framebuffer interface
1 parent 82d38a8 commit c2c1bb8

File tree

2 files changed

+30
-34
lines changed
  • src/proto/console
  • uefi-test-runner/src/proto/console

2 files changed

+30
-34
lines changed

src/proto/console/gop.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
//! In theory, a buffer with a width of 640 should have (640 * 4) bytes per row,
2424
//! but in practice there might be some extra padding used for efficiency.
2525
26-
use core::{ptr, slice};
26+
use core::ptr;
2727
use crate::{Completion, Result, Status};
2828

2929
/// Provides access to the video hardware's frame buffer.
@@ -249,22 +249,21 @@ impl GraphicsOutput {
249249
*self.mode.info
250250
}
251251

252-
/// Returns a reference to the frame buffer.
252+
/// Returns the base pointer and size (in bytes) of the framebuffer
253253
///
254-
/// This function is inherently unsafe since the wrong format
255-
/// could be used by a UEFI app when reading / writting the buffer.
256-
///
257-
/// It is also the callers responsibilty to use volatile memory accesses,
258-
/// otherwise they could be optimized to nothing.
259-
pub unsafe fn frame_buffer(&mut self) -> &mut [u8] {
254+
/// To use this pointer safely, a caller must...
255+
/// - Honor the pixel format specificed by the mode info
256+
/// - Use volatile writes so that the compiler does not optimize out or
257+
/// aggressively reorder the framebuffer accesses.
258+
pub fn frame_buffer(&mut self) -> (*mut u8, usize) {
260259
assert!(
261260
self.mode.info.format != PixelFormat::BltOnly,
262261
"Cannot access the framebuffer in a Blt-only mode"
263262
);
264263
let data = self.mode.fb_address as *mut u8;
265264
let len = self.mode.fb_size;
266265

267-
slice::from_raw_parts_mut(data, len)
266+
(data, len)
268267
}
269268
}
270269

uefi-test-runner/src/proto/console/gop.rs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use core::ptr;
21
use uefi::prelude::*;
32
use uefi::proto::console::gop::{BltOp, BltPixel, GraphicsOutput, PixelFormat};
43
use uefi::table::boot::BootServices;
@@ -55,46 +54,44 @@ fn draw_fb(gop: &mut GraphicsOutput) {
5554
let stride = mi.stride();
5655
let (width, height) = mi.resolution();
5756

58-
let fb = unsafe { gop.frame_buffer() };
57+
let (fb_base, _fb_size) = gop.frame_buffer();
5958

60-
type PixelWriter<'a> = &'a Fn(&mut [u8], (u8, u8, u8));
61-
let write_pixel_rgb = |pixel: &mut [u8], (r, g, b)| {
62-
let p = pixel.as_mut_ptr();
63-
unsafe {
64-
ptr::write_volatile(p.offset(0), r);
65-
ptr::write_volatile(p.offset(1), g);
66-
ptr::write_volatile(p.offset(2), b);
67-
}
59+
type PixelWriter = unsafe fn(*mut u8, [u8; 3]);
60+
unsafe fn write_pixel_rgb(pixel_base: *mut u8, rgb: [u8; 3]) {
61+
let [r, g, b] = rgb;
62+
pixel_base.add(0).write_volatile(r);
63+
pixel_base.add(1).write_volatile(g);
64+
pixel_base.add(2).write_volatile(b);
6865
};
69-
let write_pixel_bgr = |pixel: &mut [u8], (r, g, b)| {
70-
let p = pixel.as_mut_ptr();
71-
unsafe {
72-
ptr::write_volatile(p.offset(0), b);
73-
ptr::write_volatile(p.offset(1), g);
74-
ptr::write_volatile(p.offset(2), r);
75-
}
66+
unsafe fn write_pixel_bgr(pixel_base: *mut u8, rgb: [u8; 3]) {
67+
let [r, g, b] = rgb;
68+
pixel_base.add(0).write_volatile(b);
69+
pixel_base.add(1).write_volatile(g);
70+
pixel_base.add(2).write_volatile(r);
7671
};
7772
let write_pixel: PixelWriter = match mi.pixel_format() {
78-
PixelFormat::RGB => &write_pixel_rgb,
79-
PixelFormat::BGR => &write_pixel_bgr,
73+
PixelFormat::RGB => write_pixel_rgb,
74+
PixelFormat::BGR => write_pixel_bgr,
8075
_ => {
8176
info!("This pixel format is not supported by the drawing demo");
8277
return;
8378
}
8479
};
8580

86-
let mut fill_rectangle = |(x1, y1), (x2, y2), color| {
81+
let fill_rectangle = |(x1, y1), (x2, y2), color| {
8782
assert!((x1 < width) && (x2 < width), "Bad X coordinate");
8883
assert!((y1 < height) && (y2 < height), "Bad Y coordinate");
8984
for row in y1..y2 {
9085
for column in x1..x2 {
91-
let index = (row * stride) + column;
92-
let pixel = &mut fb[4 * index..4 * index + 3];
93-
write_pixel(pixel, color);
86+
unsafe {
87+
let index = (row * stride) + column;
88+
let pixel_base = fb_base.add(4 * index);
89+
write_pixel(pixel_base, color);
90+
}
9491
}
9592
}
9693
};
9794

98-
fill_rectangle((50, 30), (150, 600), (250, 128, 64));
99-
fill_rectangle((400, 120), (750, 450), (16, 128, 255));
95+
fill_rectangle((50, 30), (150, 600), [250, 128, 64]);
96+
fill_rectangle((400, 120), (750, 450), [16, 128, 255]);
10097
}

0 commit comments

Comments
 (0)