Skip to content

Commit 8f6b1d7

Browse files
committed
Add an iterator over XFB rows
This emits slices of u16, and allows users to not use unsafe for drawing.
1 parent c107b6a commit 8f6b1d7

3 files changed

Lines changed: 54 additions & 34 deletions

File tree

luma_core/src/allocate.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
use alloc::alloc::{alloc, Layout};
22
use alloc::boxed::Box;
33
use core::pin::Pin;
4+
use core::slice;
45

56
const CACHELINE: usize = 32;
67

78
/// Allocate a slice aligned to a cacheline, and return it pinned.
8-
pub fn alloc_aligned(size: usize) -> Pin<Box<[u8]>> {
9-
let layout = Layout::from_size_align(size, CACHELINE).unwrap();
10-
let ptr = unsafe { alloc(layout) };
11-
let boxed = unsafe { Box::from_raw(ptr) };
12-
let slice = Box::into_boxed_slice(boxed);
13-
Pin::from(slice)
9+
pub fn alloc_aligned<T: Copy>(size: usize) -> Pin<Box<[T]>> {
10+
let layout = Layout::array::<T>(size)
11+
.unwrap()
12+
.align_to(CACHELINE)
13+
.unwrap();
14+
let ptr = unsafe { alloc(layout) } as *mut T;
15+
let slice = unsafe { slice::from_raw_parts(ptr, size) };
16+
let boxed = Box::from(slice);
17+
Pin::from(boxed)
1418
}
1519

1620
/// Allocate an array aligned to a cacheline, and return it pinned.

luma_core/src/vi.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55
use crate::allocate::alloc_aligned;
66
use crate::io::{read16, write16, write32};
77
use alloc::boxed::Box;
8+
use core::slice::{Chunks, ChunksMut};
89
use core::pin::Pin;
910

1011
/// A struct representing the eXternal FrameBuffer, or XFB. It represents the image that will be
1112
/// sent to the screen, in YUYV format. It must be allocated as contiguous physical memory.
1213
pub struct Xfb {
13-
data: Pin<Box<[u8]>>,
14+
data: Pin<Box<[u16]>>,
1415
width: usize,
1516
height: usize,
1617
}
1718

1819
impl Xfb {
1920
/// Allocate an XFB with the given width and height.
2021
pub fn allocate(width: usize, height: usize) -> Xfb {
21-
let stride = width * 2;
22+
let stride = width;
2223
let data = alloc_aligned(stride * height);
2324
Xfb {
2425
data,
@@ -37,19 +38,36 @@ impl Xfb {
3738
self.height
3839
}
3940

40-
/// Get the stride of this XFB, given the YUYV format this is always width × 2.
41-
pub fn stride(&self) -> usize {
42-
// YUYV always takes two bytes per pixel.
43-
self.width * 2
41+
/// Get the stride of this XFB. This is always equal to width for now.
42+
pub fn stride_in_u16(&self) -> usize {
43+
self.width
44+
}
45+
46+
/// Get the stride of this XFB in bytes. Given the YUYV format this is always equal to
47+
/// stride_in_u16() × 2.
48+
pub fn stride_in_u8(&self) -> usize {
49+
self.stride_in_u16() * 2
50+
}
51+
52+
/// Get an immutable iterator over the rows of this XFB.
53+
pub fn iter(&self) -> Chunks<u16> {
54+
let stride = self.stride_in_u16();
55+
self.data.chunks(stride)
56+
}
57+
58+
/// Get a mutable iterator over the rows of this XFB.
59+
pub fn iter_mut(&mut self) -> ChunksMut<u16> {
60+
let stride = self.stride_in_u16();
61+
self.data.chunks_mut(stride)
4462
}
4563

4664
/// Return the raw pointer to this XFB.
47-
pub fn as_ptr(&self) -> *const u8 {
65+
pub fn as_ptr(&self) -> *const u16 {
4866
self.data.as_ptr()
4967
}
5068

5169
/// Return the raw mutable pointer to this XFB.
52-
pub fn as_mut_ptr(&mut self) -> *mut u8 {
70+
pub fn as_mut_ptr(&mut self) -> *mut u16 {
5371
self.data.as_mut_ptr()
5472
}
5573
}
@@ -119,7 +137,7 @@ unsafe fn set_burst_blanking_interval_2(be2: u32, bs2: u32, be4: u32, bs4: u32)
119137
}
120138

121139
unsafe fn set_xfb(addr: u32, xfb: &Xfb, bottom: bool) {
122-
let stride = xfb.stride() as u32;
140+
let stride = xfb.stride_in_u8() as u32;
123141
let xfb = xfb.as_ptr();
124142
let mut xfb = xfb as u32;
125143
let shift;

src/bin/vi-draw.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ const fn rgba2yuyv(pixel: i32, odd: bool) -> u16 {
4040
}
4141

4242
/// Ported from Weston’s clients/simple-shm.c
43-
fn paint_pixels(mut image: *mut u16, padding: i32, width: i32, height: i32, time: i32) {
43+
fn paint_pixels(xfb: &mut Xfb, padding: i32, time: i32) {
44+
let width = xfb.width() as i32;
45+
let height = xfb.height() as i32;
46+
let mut rows = xfb.iter_mut().skip(padding as usize);
47+
4448
let halfh = padding + (height - padding * 2) / 2;
4549
let halfw = padding + (width - padding * 2) / 2;
4650

@@ -50,30 +54,24 @@ fn paint_pixels(mut image: *mut u16, padding: i32, width: i32, height: i32, time
5054
or *= or;
5155
ir *= ir;
5256

53-
image = unsafe { image.offset((padding * width) as isize) };
5457
for y in padding..(height - padding) {
55-
let y2 = (y - halfh) * (y - halfh);
58+
let row = rows.next().unwrap();
5659

57-
image = unsafe { image.offset(padding as isize) };
60+
let y2 = (y - halfh) * (y - halfh);
5861
for x in padding..(width - padding) {
59-
let v;
60-
6162
/* squared distance from center */
6263
let r2 = (x - halfw) * (x - halfw) + y2;
6364

64-
if r2 < ir {
65-
v = (r2 / 32 + time / 4) * 0x0080401;
65+
let v = if r2 < ir {
66+
(r2 / 32 + time / 4) * 0x0080401
6667
} else if r2 < or {
67-
v = (y + time / 2) * 0x0080401;
68+
(y + time / 2) * 0x0080401
6869
} else {
69-
v = (x + time) * 0x0080401;
70-
}
70+
(x + time) * 0x0080401
71+
};
7172

72-
unsafe { *image = rgba2yuyv(v, (x & 1) != 0) };
73-
image = unsafe { image.offset(1) };
73+
row[x as usize] = rgba2yuyv(v, (x & 1) != 0);
7474
}
75-
76-
image = unsafe { image.offset(padding as isize) };
7775
}
7876
}
7977

@@ -83,15 +81,15 @@ fn main() {
8381
let mut vi = Vi::setup(xfb);
8482

8583
// First fill the XFB with white.
86-
let xfb = vi.xfb().as_mut_ptr() as *mut u16;
87-
for i in 0..(640 * 480) {
88-
unsafe { xfb.offset(i).write(0xff80) };
84+
let xfb = vi.xfb();
85+
for row in xfb.iter_mut() {
86+
row.fill(0xff80);
8987
}
9088

9189
// Then draw to it as fast as we can.
9290
let mut i = 0;
9391
loop {
94-
paint_pixels(xfb, 20, 640, 480, i);
92+
paint_pixels(xfb, 20, i);
9593
i += 1;
9694
}
9795
}

0 commit comments

Comments
 (0)