From 075c87d52a4d90c0f00f8ba7ba849677771a9be3 Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 31 Jul 2026 18:08:45 +0200 Subject: vt: defer scrolls and batch framebuffer pushes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streaming output scrolled one framebuffer push per line (each a ~3-8 MB write-only copy). The vt now scrolls the logical grid instantly in RAM and defers the display shift: N pending scrolls are pushed together as one shift_up_n — one push regardless of batch size. - vt: PENDING_SCROLLS counter; scroll_up shifts CELLS only; flush renders nothing while pending (the diff would otherwise re-rasterise the whole screen per line); sync_scroll() does one gop::shift_up_n + RENDERED mirror + normal diff flush (which re-blits just the newly exposed rows and the cursor). - Sync triggers: batch of 16 rows, ~40 ms of stream pause (100 Hz TICKS), any CSI sequence (full-screen apps like the editor render immediately), clear_all/set_cursor_visible, interactive input (tty read_line/read_byte), and the shell before each prompt. - gop: shift_up → shift_up_n(n) (one shadow memcpy + one push). Verified in QEMU: mmap/hexdump streaming renders in coherent batches with the prompt syncing at the end; clear wipes clean; the editor scrolls and redraws immediately (45-line file, gutter + status bar intact, cursor correct); save/exit/cat round-trip unchanged. Release and dev builds pass. --- rsnix/src/tty.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'rsnix/src/tty.rs') diff --git a/rsnix/src/tty.rs b/rsnix/src/tty.rs index 8d745b3..b6b6cc8 100644 --- a/rsnix/src/tty.rs +++ b/rsnix/src/tty.rs @@ -37,6 +37,9 @@ static mut RAW_LEN: usize = 0; /// Read one line in canonical mode: echo every key, ^C cancels the line, /// ^D on an empty line is EOF. Echo goes to the terminal (GOP) and serial. pub fn read_line() -> LineInput { + // Interactive input: make sure deferred scrolls are pushed first so + // the screen shows the current state (no-op when nothing is pending). + crate::vt::sync_scroll(); let mut buf = strbuf::String::::new(); loop { match ps2::poll_key() { @@ -112,6 +115,9 @@ pub fn interrupt_pressed() -> bool { /// Blocking read of the next raw-mode byte. Keys arrive translated to the /// terminal byte protocol; multi-byte sequences are delivered in order. pub fn read_byte() -> u8 { + // Interactive (raw) input: push deferred scrolls so the full-screen + // app draws over a current framebuffer. + crate::vt::sync_scroll(); loop { if let Some(b) = pop_raw() { return b; -- cgit v1.2.3