display: layer stack + damage-driven compositor (D3)
Turn the service into a real compositor. A layer is a server-owned surface (its own mmap'd cacheable buffer) with a screen position, z-order, and visibility. Clients create layers, draw into them by command, mark damage, and present; the compositor repaints only the damaged region — clear to the wallpaper, paint the visible layers bottom-to-top (z-sorted), flush that rectangle back -> front (WC). - compositor.zig: the pure, host-tested core — Rect (intersect/unite), Surface, fillRect, composite (opaque, clipped to a damage rect), blitTile (unaligned- safe read of a client tile). No syscall/runtime dependency. - protocol.zig: pack(format, r, g, b) — native pixel encoding for rgbx/bgrx, the shared colour vocabulary of client and server. Host-tested. - display.zig: the layer table + create/configure/destroy/fill_rect/blit_tile/ damage/present ops wired onto the compositor, plus a damage-accumulating present. - Startup self-check: two overlapping layers composited on the real framebuffer, read back to confirm the overlap shows the top layer and outside shows the bottom — logs `display: compositor self-check ok`. Gate: `zig build test` green (compositor + pack), and the display-service case's self-check passes on hardware. Both new pure modules added to the test loop.
This commit is contained in:
+19
-13
@@ -94,23 +94,29 @@ fault cases, since a lone blocking service can't reschedule the in-kernel test c
|
||||
poll). Regression-checked: `usermem`, `heap` (the `mmap` rewrite), `init` (the boot-list
|
||||
addition), and D1's `display` all still pass.
|
||||
|
||||
## D3 — Layer stack + compositor + damage present
|
||||
## D3 — Layer stack + compositor + damage present ✅
|
||||
|
||||
The heart: composite an ordered layer stack, present only what changed.
|
||||
|
||||
- [ ] A layer table (fixed capacity, like the input service's subscriber table): each
|
||||
layer = rect, z-order, visible flag, a server-owned surface (`mmap` cacheable).
|
||||
- [ ] Implement `create_layer` / `configure_layer` / `destroy_layer`, `fill_rect`,
|
||||
`blit_tile` (inline tile in the IPC message), `damage`.
|
||||
- [ ] `composite()`: walk layers bottom-to-top, paint dirty regions into the back buffer
|
||||
(clip to layer rect ∩ damage; handle `rgbx`/`bgrx`; step by `pitch`).
|
||||
- [ ] `present()`: flush merged damage rects back → front (sequential WC writes).
|
||||
- [ ] Host tests (`zig build test`): layer clipping, damage-rect merge, and a
|
||||
`blit`/`fill` against a fake in-memory framebuffer for both pixel formats and a
|
||||
`pitch > width*4` case.
|
||||
- [x] A layer table (16 slots): each `Layer` = position, z, visible, a server-owned
|
||||
`mmap`'d surface (freed on `destroy_layer`). `damage` accumulates the dirty screen
|
||||
region since the last present.
|
||||
- [x] `create_layer` / `configure_layer` (damages old + new footprints) / `destroy_layer`,
|
||||
`fill_rect`, `blit_tile` (reads the inline tile from the IPC payload, unaligned-safe),
|
||||
`damage`, `present`.
|
||||
- [x] Pure, host-tested [compositor.zig](../system/services/display/compositor.zig): `Rect`
|
||||
(intersect/unite), `Surface`, `fillRect`, `composite` (opaque, clipped to a damage
|
||||
rect), `blitTile`. `present` clears the damaged region to the wallpaper, paints the
|
||||
visible layers bottom-to-top (z-sorted), and flushes just that rect back → front (WC).
|
||||
Colour packing (rgbx/bgrx) is `protocol.pack`, also host-tested.
|
||||
- [x] Host tests (`zig build test`, green): rect intersect/unite, `fillRect` clipping +
|
||||
`stride > width` padding, `composite` overlap-shows-top + damage clipping, `blitTile`
|
||||
unaligned read + clipping, and `pack` for both pixel formats.
|
||||
|
||||
**Gate:** `zig build test` green for the compositor unit tests; an in-service self-check
|
||||
composites two overlapping layers and the overlap shows the top layer's colour.
|
||||
**Gate (met):** `zig build test` green for the compositor + pack unit tests, **and** the
|
||||
`display-service` case's startup self-check composites two overlapping layers on the real
|
||||
framebuffer and reads back the composited pixels — overlap = top layer, outside = bottom
|
||||
layer — logging `display: compositor self-check ok` (matched by the harness).
|
||||
|
||||
## D4 — Client API + the demo client
|
||||
|
||||
|
||||
Reference in New Issue
Block a user