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

@@ -47,8 +47,12 @@ fn main() {
libkos::println!("snake: needs the display (see /bin/snake.manifest)");
return;
}
// Takes focus; the game polls every tick, so it never waits on the signal.
let _ = libkos::display::subscribe_input(display_ep());
let Ok(alarm) = syscall::create_notification() else {
libkos::println!("snake: no timer");
return;
};
// Takes focus; keys are polled every tick, the signal only wakes it.
let _ = libkos::display::subscribe(display_ep(), alarm, types::badge::Badge::new(1 << 1));
let mut snake = Snake::new();
let mut commands = [RenderCommand { x: 0, y: 0, w: 0, h: 0, color: 0 }; MAX_RENDER_CMDS];
@@ -67,12 +71,12 @@ fn main() {
flush();
// Any key leaves.
while next_input() == Input::None {
wait_tick();
wait_tick(alarm);
}
return;
}
wait_tick();
wait_tick(alarm);
if handle_input(&mut snake) == Input::Quit {
return;
}
@@ -122,10 +126,17 @@ fn handle_input(snake: &mut Snake) -> Input {
}
}
fn wait_tick() {
let start = syscall::get_time();
let deadline = Ticks::from_raw(start.raw() + TICK_DELAY);
while syscall::get_time().raw() < deadline.raw() {
syscall::yield_now();
/// Sleeps until the next tick on `alarm`, instead of spinning. Keys
/// signal it too (snake has one notification), so it waits again until
/// the tick is really due.
fn wait_tick(alarm: CapSlot) {
let deadline = syscall::get_time().raw() + TICK_DELAY;
if syscall::set_timer(alarm, Ticks::from_raw(deadline)).is_err() {
return;
}
while syscall::get_time().raw() < deadline {
if syscall::wait(alarm).is_err() {
return;
}
}
}