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:
2026-10-27 22:09:33 +01:00
parent 7b8258b231
commit c8056ddac6
17 changed files with 308 additions and 40 deletions

View File

@@ -16,15 +16,23 @@ struct Fake {
flushes: usize,
timers: usize,
focus_taken: usize,
scrolled: usize,
/// Every row drawn, with how many cells.
rows_drawn: Vec<(usize, usize)>,
interrupted: Vec<CapSlot>,
}
impl Console for Fake {
fn draw_row(&mut self, _row: usize, _text: &[u8]) {}
fn draw_row(&mut self, row: usize, text: &[u8]) {
self.rows_drawn.push((row, text.len()));
}
fn draw_cursor(&mut self, _col: usize, _row: usize, _under: u8) {}
fn flush(&mut self) {
self.flushes += 1;
}
fn scroll(&mut self, rows: usize) {
self.scrolled += rows;
}
fn flush_later(&mut self) {
self.timers += 1;
}
@@ -143,3 +151,28 @@ fn redraw_takes_focus_back_and_paints_every_row() {
assert_eq!(t.console().focus_taken, 1);
assert_eq!(&t.grid().row(0)[..2], b"hi");
}
#[test]
fn a_full_screen_scrolls_its_pixels_and_draws_one_row() {
let mut t = term(&[]);
for _ in 0..12 {
t.handle_call(1, text_words(b"line\n"), None);
}
// 10 rows: two scrolls so far, then one more line.
t.console_mut_for_test().rows_drawn.clear();
let before = t.console().scrolled;
t.handle_call(1, text_words(b"more\n"), None);
assert_eq!(t.console().scrolled, before + 1, "the screen moved up a row");
let drawn = &t.console().rows_drawn;
assert!(drawn.len() <= 2, "only the rows that changed: {drawn:?}");
}
#[test]
fn rows_are_drawn_only_as_wide_as_their_text_or_what_it_replaces() {
let mut t = term(&[]);
t.handle_call(1, text_words(b"hello"), None);
assert_eq!(t.console().rows_drawn.last(), Some(&(0, 5)));
t.handle_call(1, [types::terminal::CLEAR, 0, 0, 0], None);
// Cleared: the old five cells and the cursor after them are erased.
assert!(t.console().rows_drawn.contains(&(0, 6)), "{:?}", t.console().rows_drawn);
}