docs: make display-v2 gates fully automated (unattended-safe)

Rewrite V3/V4/V5 gates so none need a screenshot: the driver/compositor read
their own pixels back (the scanout resource is shm-backed CPU-visible RAM), and a
virtio resource_flush is confirmed by the device's used-ring ack / fence. Pixel
readback + flush-ack is the serial stand-in for "it's on screen," so the whole
V1→V6 plan can run and self-verify without a human eyeballing QEMU.
This commit is contained in:
Daniel Samson 2026-07-14 09:33:00 +01:00
parent 2723b6f778
commit f3342118f5
No known key found for this signature in database
GPG Key ID: A9EB2589C60F7268
1 changed files with 30 additions and 14 deletions

View File

@ -24,10 +24,19 @@ kebab-case file names, no `Co-Authored-By` trailers. New user binaries go throug
## How to verify along the way
- `zig build test` — host unit tests (backend selection logic, virtio structs/encodings).
- `python3 test/qemu_test.py <case>` — boots the kernel in QEMU; assert on serial markers.
The virtio path boots with `-device virtio-gpu` (a new per-case `qemu_extra`).
- The `run-x86-64` target renders to a window for visual confirmation.
**Every gate is serial-checkable — no screenshots** (this plan is built to run unattended).
Where "does it actually display" would otherwise need a human eyeball, the code **reads its
own pixels back**: the scanout resource is CPU-visible RAM (shm-backed) and the back buffer
is cacheable, so a driver/compositor can write a known value, read it back, and log a
pass/fail — and a virtio `resource_flush` is confirmed by the device **acking it on the
used ring**. Those two together (pixel-readback + flush-ack) are the automated stand-in for
"it's on screen."
- `zig build test` — host unit tests (backend selection, virtio struct sizes/encodings,
pixel-check helpers).
- `python3 test/qemu_test.py <case>` — boots the kernel in QEMU; asserts on serial markers.
The virtio cases boot with `-device virtio-gpu` (a per-case `qemu_extra`).
- `run-x86-64` renders to a window — for the human's own satisfaction, **not** a gate.
---
@ -70,9 +79,12 @@ shared physical pages, not a copy). Heartbeat `shm: shared N bytes ok`.
`set_scanout` to CRTC 0, and `resource_flush` a test pattern.
- [ ] Register a `scanout` service (new `ServiceId`).
**Gate:** QEMU `-device virtio-gpu`: the driver comes up and logs
`virtio-gpu: scanout {w}x{h} online`, and a flushed test pattern is visible (screenshot)
— proving virtqueue + resource + set_scanout + flush end to end.
**Gate (automated):** a `virtio-gpu` case (QEMU `-device virtio-gpu`) where the driver
writes a known test pattern into the shm scanout resource, `resource_flush`es it, and
**waits for the device's used-ring ack**, then reads the resource back and checks the
pattern — logging `virtio-gpu: scanout {w}x{h} online` and `virtio-gpu: flush acked, pixel
check ok`. That proves virtqueue + resource + attach + set_scanout + flush end to end
without a screenshot (the used-ring ack is the device confirming it consumed the frame).
## V4 — The native backend + hot-attach
@ -83,10 +95,12 @@ shared physical pages, not a copy). Heartbeat `shm: shared N bytes ok`.
backends and re-presents the current frame full-screen.
- [ ] Boot still starts on `GopBackend`; the upgrade happens on announce.
**Gate:** boot with virtio-gpu + `display-demo`; the compositor logs
`display: scanout upgraded to virtio-gpu`, and the demo animates through the native
backend (serial heartbeat + screenshot). Without `-device virtio-gpu`, it stays on GOP
(the v1 gates still pass).
**Gate (automated):** boot with virtio-gpu + `display-demo`; the compositor logs
`display: scanout upgraded to virtio-gpu`, drives frames through the native backend, and
**reads a pixel back** from the shared scanout resource after a present to confirm the
composited frame landed (`display: native present verified`), while `display-demo: ok`
still fires. Without `-device virtio-gpu`, no `scanout` is announced and it stays on GOP —
the v1 `display-service`/`display-demo` gates still pass unchanged.
## V5 — Mode-setting, EDID, and vsync
@ -95,9 +109,11 @@ backend (serial heartbeat + screenshot). Without `-device virtio-gpu`, it stays
- [ ] A vsync/fenced `resource_flush` present path → genuinely tear-free.
- [ ] The compositor reports the native backend's `canModeSet`/`hasVsync` = true.
**Gate:** a `display-modeset` case changes resolution at runtime and confirms the new mode
(`display: mode set to {w}x{h}`); a vsync present path is exercised without tearing
artifacts in the frame counter/log.
**Gate (automated):** a `display-modeset` case reads the EDID mode list, calls `setMode`
to a different resolution, and confirms the change by reading the driver's scanout geometry
back (`display: mode set to {w}x{h}, verified`); the vsync/fenced present path is exercised
and confirmed by the flush **fence completing** (`display: vsync present ok`) — both from
serial, no eyeballing.
## V6 — Resilience (restart + re-attach) + tests + docs