feat: vblank IRQ and double-buffered page flip for Intel GPU

Add tear-free scanout to the Intel GPU driver: a second kernel-allocated
scanout buffer, DSPASURF flips latched at vblank, and a vblank interrupt
delivered over MSI (Gen 11+ master/display/pipe IRQ chain) with a
monotonic vblank counter and WaitVblank().

Expose it as SYS_FBFLIP (150): index selects the front buffer, -1
queries support, flags bit0 waits for the flip to latch. fb_map() now
maps buffer 1 right after buffer 0 when flipping is available, and
gui::Framebuffer draws to the off-screen buffer and flips with vsync,
falling back to the direct copy when unsupported.

Scanout is restored to buffer 0 when the flip-owning process exits and
on panic, so the terminal and panic box never land on the invisible
buffer.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-07-13 21:53:06 +02:00
co-authored by Claude Fable 5
parent 500020ce47
commit 182520a585
14 changed files with 549 additions and 3 deletions
+9
View File
@@ -327,6 +327,15 @@ namespace montauk {
inline void fb_info(montauk::abi::FbInfo* info) { syscall1(montauk::abi::SYS_FBINFO, (uint64_t)info); }
inline void* fb_map() { return (void*)syscall0(montauk::abi::SYS_FBMAP); }
// Page flip between the two scanout buffers. fb_map() maps buffer 1
// directly after buffer 0 (at +page_align(height*pitch)). index selects
// the buffer to show; the hardware latches it at vblank (tear-free).
// flags bit0 = block until the flip has been latched (vsync).
// fb_flip(-1, 0) returns 1 when page flipping is available, 0 when not.
inline int64_t fb_flip(int64_t index, uint64_t flags) {
return syscall2(montauk::abi::SYS_FBFLIP, (uint64_t)index, flags);
}
// Arguments
inline int getargs(char* buf, uint64_t maxLen) {
return (int)syscall2(montauk::abi::SYS_GETARGS, (uint64_t)buf, maxLen);