aarch64/fb: improve the performance of ConsoleBuffer::new_line()

master
equation314 6 years ago
parent 7b8359eeef
commit 9dda78d2e3

@ -176,14 +176,43 @@ impl Framebuffer {
} }
} }
/// Clean screen /// Copy buffer `[src_off .. src_off + size]` to `[dst_off .. dst_off + size]`.
pub fn clear(&mut self) { /// `dst_off`, `src_off` and `size` must be aligned with `usize`.
let mut start = self.base_addr(); pub fn copy(&mut self, dst_off: usize, src_off: usize, size: usize) {
let end = start + self.fb_info.screen_size as usize; const USIZE: usize = core::mem::size_of::<usize>();
let mut dst = self.base_addr() + dst_off;
let mut src = self.base_addr() + src_off;
let src_end = src + size;
while src < src_end {
unsafe { *(dst as *mut usize) = *(src as *mut usize) }
dst += USIZE;
src += USIZE;
}
}
/// Fill buffer `[offset .. offset + size]` with `pixel`.
/// `offset` and `size` must be aligned with `usize`.
pub fn fill(&mut self, offset: usize, size: usize, pixel: u32) {
const USIZE: usize = core::mem::size_of::<usize>();
let mut value: usize = 0;
let repeat = USIZE * 8 / self.fb_info.depth as usize;
let mask = ((1u64 << self.fb_info.depth) - 1) as usize;
for i in 0..repeat {
value <<= self.fb_info.depth;
value += pixel as usize & mask;
}
let mut start = self.base_addr() + offset;
let end = start + size;
while start < end { while start < end {
unsafe { *(start as *mut usize) = 0 } unsafe { *(start as *mut usize) = value }
start += core::mem::size_of::<usize>(); start += USIZE;
}
} }
/// Fill the entire buffer with `0`.
pub fn clear(&mut self) {
self.fill(0, self.fb_info.screen_size as usize, 0);
} }
} }

@ -9,10 +9,10 @@ use lazy_static::lazy_static;
use log::*; use log::*;
use spin::Mutex; use spin::Mutex;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq)]
struct Color(u8); struct Color(u8);
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)] #[repr(C)]
pub struct ConsoleChar { pub struct ConsoleChar {
ascii_char: u8, ascii_char: u8,
@ -68,16 +68,23 @@ impl<F: Font> ConsoleBuffer<F> {
self.write(row, col, ConsoleChar::default()); self.write(row, col, ConsoleChar::default());
} }
/// Insert one blank line at the bottom and remove the top line. /// Insert one blank line at the bottom, and scroll up one line.
/// TODO: improve performance /// XXX: read framebuffer is toooo slow, do not use `fb.copy()`.
fn new_line(&mut self) { pub fn new_line(&mut self) {
for i in 1..self.num_row { for i in 1..self.num_row {
for j in 0..self.num_col { for j in 0..self.num_col {
if self.buf[i - 1][j] != self.buf[i][j] {
self.write(i - 1, j, self.buf[i][j]); self.write(i - 1, j, self.buf[i][j]);
} }
} }
}
for j in 0..self.num_col { for j in 0..self.num_col {
self.write(self.num_row - 1, j, ConsoleChar::default()); self.buf[self.num_row - 1][j] = ConsoleChar::default();
}
if let Some(fb) = FRAME_BUFFER.lock().as_mut() {
let rowbytes = F::HEIGHT * fb.fb_info.pitch as usize;
fb.fill(rowbytes * (self.num_row - 1), rowbytes, 0);
} }
} }

Loading…
Cancel
Save