perf: fast display (row runs, bulk fills, pixel scroll), terminal draws changed cells only + scrolls pixels, print! batched (was IPC per fmt fragment), snake sleeps on timer
This commit is contained in:
@@ -15,12 +15,15 @@ pub struct Grid {
|
||||
pub row: usize,
|
||||
/// Rows to redraw.
|
||||
dirty: Vec<bool>,
|
||||
/// Rows everything moved up by since the screen last caught up: moving
|
||||
/// the pixels is cheaper than drawing every row again.
|
||||
scrolled: usize,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
pub fn new(cols: usize, rows: usize) -> Self {
|
||||
let (cols, rows) = (cols.clamp(1, MAX_COLS), rows.clamp(1, MAX_ROWS));
|
||||
Self { cells: vec![b' '; cols * rows], cols, rows, col: 0, row: 0, dirty: vec![true; rows] }
|
||||
Self { cells: vec![b' '; cols * rows], cols, rows, col: 0, row: 0, dirty: vec![true; rows], scrolled: 0 }
|
||||
}
|
||||
|
||||
pub fn row(&self, r: usize) -> &[u8] {
|
||||
@@ -37,6 +40,12 @@ impl Grid {
|
||||
self.dirty[..rows].iter_mut().enumerate().filter_map(|(r, d)| core::mem::take(d).then_some(r))
|
||||
}
|
||||
|
||||
/// How far to move the screen up before drawing the dirty rows, which
|
||||
/// already account for it.
|
||||
pub fn take_scrolled(&mut self) -> usize {
|
||||
core::mem::take(&mut self.scrolled)
|
||||
}
|
||||
|
||||
fn mark(&mut self, r: usize) {
|
||||
self.dirty[r] = true;
|
||||
}
|
||||
@@ -53,7 +62,16 @@ impl Grid {
|
||||
self.cells.copy_within(self.cols.., 0);
|
||||
let last = (self.rows - 1) * self.cols;
|
||||
self.cells[last..].fill(b' ');
|
||||
self.dirty.fill(true);
|
||||
// Rows still to redraw move up with their text.
|
||||
self.dirty.copy_within(1.., 0);
|
||||
self.mark(self.rows - 1);
|
||||
if self.scrolled + 1 >= self.rows {
|
||||
// Scrolled a whole screen: just draw it all.
|
||||
self.touch_all();
|
||||
self.scrolled = 0;
|
||||
} else {
|
||||
self.scrolled += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes one byte at the cursor: `\n` moves to the next line, other
|
||||
@@ -90,5 +108,6 @@ impl Grid {
|
||||
self.col = 0;
|
||||
self.row = 0;
|
||||
self.dirty.fill(true);
|
||||
self.scrolled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user