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:
1 parent
500020ce47
commit
182520a585
14 files changed
+549
-3
No files matched your search
@@ -10,6 +10,7 @@
|
||||
#include <Memory/Paging.hpp>
|
||||
#include <Memory/HHDM.hpp>
|
||||
#include <Graphics/Framebuffer.hpp>
|
||||
#include <Drivers/Graphics/IntelGPU.hpp>
|
||||
#include <Terminal/Terminal.hpp>
|
||||
|
||||
#include "Syscall.hpp"
|
||||
@@ -59,9 +60,42 @@ namespace montauk::abi {
|
||||
}
|
||||
}
|
||||
|
||||
// When page flipping is available, map the second scanout buffer
|
||||
// immediately after the first so a double-buffered client can reach
|
||||
// both. Single-buffer clients never touch the extra pages.
|
||||
if (Drivers::Graphics::IntelGPU::FlipSupported()) {
|
||||
uint64_t buf1Phys = Drivers::Graphics::IntelGPU::GetBufferPhys(1);
|
||||
for (uint64_t i = 0; i < numPages; i++) {
|
||||
if (!Memory::VMM::Paging::MapUserInWC(
|
||||
proc->pml4Phys,
|
||||
buf1Phys + i * 0x1000,
|
||||
userVa + (numPages + i) * 0x1000
|
||||
)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return userVa;
|
||||
}
|
||||
|
||||
// SYS_FBFLIP: point scanout at buffer `index` (0 or 1). The hardware
|
||||
// latches the new surface at vblank, so the flip is tear-free.
|
||||
// index == -1 queries support without side effects.
|
||||
static int64_t Sys_FbFlip(uint64_t index, uint64_t flags) {
|
||||
namespace GPU = Drivers::Graphics::IntelGPU;
|
||||
|
||||
if ((int64_t)index == -1) {
|
||||
return GPU::FlipSupported() ? 1 : 0;
|
||||
}
|
||||
if (!GPU::FlipSupported()) return -1;
|
||||
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc != nullptr) GPU::SetFlipOwner(proc->pid);
|
||||
|
||||
return GPU::Flip((int)index, (flags & 1) != 0);
|
||||
}
|
||||
|
||||
static uint64_t Sys_TermSize() {
|
||||
// If the process is redirected to a GUI terminal, return those dimensions
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
|
||||
Reference in new issue
Block a user