atagen

monolith

public
Star0
Watch0
1136328fbe69446367dedc105632830334b9d72b
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: research/wry-reports.md

57f44a63d99fatagen2026-10-16 05:34 UTC1
# wry backend research reports
57f44a63d99fatagen2026-10-16 05:34 UTC2
57f44a63d99fatagen2026-10-16 05:34 UTC3
Raw reader reports on wry (jay fork) internals, gathered for monolith planning.
57f44a63d99fatagen2026-10-16 05:34 UTC4
Paths are relative to `/home/bolt/code/wry` at `6df16858`. Wry forked from jay at `f73b4efe` (2026-08-16).
57f44a63d99fatagen2026-10-16 05:34 UTC5
57f44a63d99fatagen2026-10-16 05:34 UTC6
Status
57f44a63d99fatagen2026-10-16 05:34 UTC7
57f44a63d99fatagen2026-10-16 05:34 UTC8
- [x] Executor core (`src/async_engine*`)
57f44a63d99fatagen2026-10-16 05:34 UTC9
- [x] io_uring, timers, cpu_worker, task usage
57f44a63d99fatagen2026-10-16 05:34 UTC10
- [x] DRM/KMS metal backend and frame scheduling
57f44a63d99fatagen2026-10-16 05:34 UTC11
- [x] Wire protocol and client handling
57f44a63d99fatagen2026-10-16 05:34 UTC12
- [x] Vulkan renderer
57f44a63d99fatagen2026-10-16 05:34 UTC13
- [x] Tree, transactions, multiphase animations
57f44a63d99fatagen2026-10-16 05:34 UTC14
- [x] Process model, config, tests, utilities
57f44a63d99fatagen2026-10-16 05:34 UTC15
- [x] Smithay extension points (comparison baseline)
57f44a63d99fatagen2026-10-16 05:34 UTC16
57f44a63d99fatagen2026-10-16 05:34 UTC17
---
57f44a63d99fatagen2026-10-16 05:34 UTC18
57f44a63d99fatagen2026-10-16 05:34 UTC19
## 0. Executor core
57f44a63d99fatagen2026-10-16 05:34 UTC20
57f44a63d99fatagen2026-10-16 05:34 UTC21
`src/async_engine.rs`, `src/async_engine/ae_task.rs`, `src/async_engine/ae_yield.rs`, about 500 lines total.
57f44a63d99fatagen2026-10-16 05:34 UTC22
57f44a63d99fatagen2026-10-16 05:34 UTC23
- Single threaded, `Rc` based, nothing is `Send`. Wakers use a custom `RawWakerVTable` with a non-atomic refcount (`NumCell`), so a waker crossing threads would be UB. The cpu_worker bridges threads with eventfds instead.
57f44a63d99fatagen2026-10-16 05:34 UTC24
- One `Box<Task>` allocation per spawn. A wake pushes a two-word `Runnable` onto a `VecDeque`. No atomics or locks anywhere on the wake path.
57f44a63d99fatagen2026-10-16 05:34 UTC25
- Task state is a bitset (`RUNNING`, `RUN_AGAIN`, `COMPLETED`, `EMPTIED`, `CANCELLED`). A wake while running sets `RUN_AGAIN` instead of double-queueing.
57f44a63d99fatagen2026-10-16 05:34 UTC26
- Dropping the returned `SpawnedFuture` cancels the task, so lifetimes are structured by ownership. Awaiting it yields the task's output.
57f44a63d99fatagen2026-10-16 05:34 UTC27
- Four ordered phases, `EventHandling`, `Layout`, `PostLayout`, `Present`. `dispatch()` drains phase 0 to a fixpoint, then phase 1, and so on. Work woken into an earlier phase by a later one waits for the next pass. After all phases the iteration counter bumps and `yield_now()` waiters wake.
57f44a63d99fatagen2026-10-16 05:34 UTC28
- `now()` / `now_rt()` are cached per pass, so everything in one pass sees the same timestamp.
57f44a63d99fatagen2026-10-16 05:34 UTC29
- `spawn` defaults to `EventHandling`. `spawn2` pins a phase.
57f44a63d99fatagen2026-10-16 05:34 UTC30
57f44a63d99fatagen2026-10-16 05:34 UTC31
How the phases are used (`src/compositor.rs:598-745`). About 38 long-lived global tasks follow a dirty-queue pattern. Example `container_layout` (`src/tree/container.rs:2706`) loops on `state.pending_container_layout.pop().await` and checks a `layout_scheduled` flag. The task lives in `Phase::Layout`, so any number of requests that dirty a container during event handling collapse into one layout pass. The same pattern drives render positions, title textures, output render data, popup positioning, tree serial groups, configurables (all `PostLayout`), and screencast and present loops (`Present`). Client send tasks are `PostLayout` (`src/client/tasks.rs:27`), so events generated during a pass are flushed once after layout.
57f44a63d99fatagen2026-10-16 05:34 UTC32
57f44a63d99fatagen2026-10-16 05:34 UTC33
---
57f44a63d99fatagen2026-10-16 05:34 UTC34
57f44a63d99fatagen2026-10-16 05:34 UTC35
## 1. io_uring, timers, cpu_worker, task usage
57f44a63d99fatagen2026-10-16 05:34 UTC36
57f44a63d99fatagen2026-10-16 05:34 UTC37
### 1.1 io_uring layer (`src/io_uring.rs`, `src/io_uring/ops/`)
57f44a63d99fatagen2026-10-16 05:34 UTC38
57f44a63d99fatagen2026-10-16 05:34 UTC39
Opcodes wrapped, one module each (`src/io_uring/ops.rs:4-19`). `READ`/`WRITE` (`ops/read_write.rs:18-30`), `READ`/`WRITE` no-cancel with explicit offset (`ops/read_write_no_cancel.rs:21-58`), `WRITE` vec (`ops/read_write_vec.rs:29-86`), `WRITEV` (`ops/writev_external.rs:25-47`), `RECVMSG` (`ops/recvmsg.rs:18-83`), `SENDMSG` (`ops/sendmsg.rs:22-85`), `POLL_ADD` (`ops/poll.rs:17-42`, external callback variant `ops/poll_external.rs:35-74`), `TIMEOUT` (`ops/timeout.rs:28-44`, external `ops/timeout_external.rs:49-73`), `LINK_TIMEOUT` (`ops/timeout_link.rs:18-29`), `ACCEPT` (`ops/accept.rs:15-37`), `CONNECT` (`ops/connect.rs:19-39`), `ASYNC_CANCEL` (`ops/async_cancel.rs:16-24`), `FUTEX_WAIT`/`FUTEX_WAKE` (`ops/futex.rs:33-75`), `READ_MULTISHOT` (`ops/read_multishot.rs:49-77`). A provided buffer-ring helper exists (`buffer_ring.rs:79-173`) but outside tests is only wired to multishot reads.
57f44a63d99fatagen2026-10-16 05:34 UTC40
57f44a63d99fatagen2026-10-16 05:34 UTC41
Setup has no `SQPOLL` and no registered fds/buffers on the hot path. `IoUring::new` tries `SUBMIT_ALL|COOP_TASKRUN|SINGLE_ISSUER|DEFER_TASKRUN` then drops one flag at a time on `ENOSYS` (`src/io_uring.rs:131-154`), and hard-requires `NODROP` (`src/io_uring.rs:155-157`). Rings are `mmap`ed directly, queue depth 32 on both main and worker rings (`src/compositor.rs:276`, `src/cpu_worker.rs:367`).
57f44a63d99fatagen2026-10-16 05:34 UTC42
57f44a63d99fatagen2026-10-16 05:34 UTC43
Submit. `encode` (`src/io_uring.rs:488-525`) drains `to_encode` into the SQ while space remains, reserves two slots for `has_timeout` ops, and sets `IOSQE_IO_LINK` on the parent so the following `LINK_TIMEOUT` fires as a link (`src/io_uring.rs:516-518`, `ops/timeout_link.rs:40-46`). Used by `write` and `sendmsg` with absolute `Time` (`ops/read_write.rs:32-61`, `ops/sendmsg.rs:74-83`).
57f44a63d99fatagen2026-10-16 05:34 UTC44
57f44a63d99fatagen2026-10-16 05:34 UTC45
Enter/wait. `run` (`src/io_uring.rs:400-453`) is the only blocking point. An empty queue submits `0` and waits for `1` with `GETEVENTS`. Pending submits with empty `to_encode` submit `to_submit` and wait for `1`. Non-empty `to_encode` submits `u32::MAX` with no wait and loops to encode more (`src/io_uring.rs:417-424`). `yields` force `min_complete=0` (`src/io_uring.rs:425-427`). `EAGAIN|EBUSY|EINTR` are ignored, other `enter` errors are fatal (`src/io_uring.rs:438-443`). A short submit retries with a pure wait (`src/io_uring.rs:444-451`). On teardown `kill` encodes, submits `u32::MAX`, then waits until `tasks` empties (`src/io_uring.rs:594-617`).
57f44a63d99fatagen2026-10-16 05:34 UTC46
57f44a63d99fatagen2026-10-16 05:34 UTC47
Wakeup. Almost every awaitable op takes `pending_results.acquire()` (`src/io_uring/pending_result.rs:21-37`), stores a clone in the task, schedules a pooled task struct, and awaits it (e.g. `ops/read_write.rs:40-60`). `dispatch_completions` matches `user_data` to the task, with `CQE_F_MORE` routed to `complete_partial` for multishot and terminal CQEs routed to `task.complete` (`src/io_uring.rs:455-486`). `PendingResult::complete` stores `res` and wakes the `Waker` (`src/io_uring/pending_result.rs:66-74`). `poll` translates negative `res` to `OsError` (`src/io_uring/pending_result.rs:105-122`). Non-`Future` completions use `PollCallback`, `TimeoutCallback`, `WritevData::done`, `ReadMultishotCallback` (`ops/poll_external.rs:15-17`, `ops/timeout_external.rs:16-18`, `ops/writev_external.rs:20-24`, `ops/read_multishot.rs:28-31`).
57f44a63d99fatagen2026-10-16 05:34 UTC48
57f44a63d99fatagen2026-10-16 05:34 UTC49
Cancel. Dropping an op future cancels it, because the future owns a `Cancellable` whose `Drop` calls `cancel_task` (`src/io_uring.rs:527-544`, `src/io_uring.rs:640-644`). Not-yet-encoded ops complete locally with synthetic `ECANCELED` (`src/io_uring.rs:542-554`). In-kernel ops get an `ASYNC_CANCEL` by `user_data` (`ops/async_cancel.rs:16-24`, `ops/async_cancel.rs:41-44`). `is_cancel` tasks are exempt from `kill` cancellation (`src/io_uring.rs:596-604`). `PendingPoll`, `PendingTimeout`, `PendingReadMultishot` `Drop` impls do the same (`ops/poll_external.rs:25-33`, `ops/timeout_external.rs:26-34`, `ops/read_multishot.rs:39-47`). `read/write_no_cancel` instead forbids userspace cancel with an `on_drop` panic guard, for worker-thread shm I/O (`ops/read_write_no_cancel.rs:92-96`).
57f44a63d99fatagen2026-10-16 05:34 UTC50
57f44a63d99fatagen2026-10-16 05:34 UTC51
No epoll fallback. `CreateUring`/`NoDrop` become `CompositorError::IoUringError` and exit (`src/io_uring.rs:96-102`, `src/compositor.rs:227-241`, `src/compositor.rs:275-276`). Grep finds no epoll/calloop fallback.
57f44a63d99fatagen2026-10-16 05:34 UTC52
57f44a63d99fatagen2026-10-16 05:34 UTC53
### 1.2 Main loop, one iteration (`src/io_uring.rs:400-453`)
57f44a63d99fatagen2026-10-16 05:34 UTC54
57f44a63d99fatagen2026-10-16 05:34 UTC55
Bump `iteration`, wake `yields` wakers, then loop `eng.dispatch()` plus `dispatch_completions()` until no more CQEs were consumed. Then `encode()` queued SQEs, accumulating `to_submit`, then one `io_uring_enter` with the wait policy above. Startup order is engine, ring 32, signal handler, wheel, run-toplevel, cpu worker, eventfd cache, then `ring.run()` (`src/compositor.rs:275-286`, `src/compositor.rs:530-535`). The `compositor` future only runs backend setup. Blocking lives in the ring (`src/compositor.rs:538-588`).
57f44a63d99fatagen2026-10-16 05:34 UTC56
57f44a63d99fatagen2026-10-16 05:34 UTC57
Unusual. Ready futures are drained to quiescence before entering the kernel, and `Debouncer` plus `yields` let hot paths skip the blocking wait (`src/io_uring/debounce.rs:15-34`, `src/io_uring.rs:425-427`).
57f44a63d99fatagen2026-10-16 05:34 UTC58
57f44a63d99fatagen2026-10-16 05:34 UTC59
### 1.3 Timers
57f44a63d99fatagen2026-10-16 05:34 UTC60
57f44a63d99fatagen2026-10-16 05:34 UTC61
`wheel.rs` is a single-`timerfd`, heap-multiplexed wheel (`src/wheel.rs:102-114`). `Wheel::new` creates a `CLOCK_MONOTONIC` `timerfd` and spawns `dispatch` (`src/wheel.rs:117-137`). `timeout(ms)` rounds to ms, re-arms with `TFD_TIMER_ABSTIME` only if earlier than the armed expiry, pushes `{expiration,id}` on a `BinaryHeap`, and registers the waiter (`src/wheel.rs:156-194`, `src/time.rs:34-46`). `dispatch_once` does `ring.read(timerfd)` then completes every due entry and re-arms to the next live entry, skipping cancelled ids (`src/wheel.rs:218-254`). Waiters are manual `Future`s storing a `Waker` (`src/wheel.rs:65-100`). `Drop` unregisters and recycles (`src/wheel.rs:78-87`). Consumers include client shutdown 5s (`src/client/tasks.rs:35`) and cursor tick (`src/tasks/hardware_cursor.rs:17-22`).
57f44a63d99fatagen2026-10-16 05:34 UTC62
57f44a63d99fatagen2026-10-16 05:34 UTC63
Separately, `TimerFd::expired` is `ring.read(timerfd)` plus `timerfd_settime` programming (`src/utils/timer.rs:42-67`), used by idle, 40Hz latch, damage, config, virtual-output (`src/tasks/idle.rs:14-20`, `src/tasks/const_clock.rs:19-35`, `src/virtual_output.rs:731`). Raw `ring.timeout(nsec)` with `IORING_TIMEOUT_ABS` is used for present/vblank, transactions, sqlite, session (`src/io_uring/ops/timeout.rs:27-44`, `src/virtual_output.rs:475`, `src/output_schedule.rs:172-174`, `src/transactions.rs:453`).
57f44a63d99fatagen2026-10-16 05:34 UTC64
57f44a63d99fatagen2026-10-16 05:34 UTC65
### 1.4 cpu_worker (`src/cpu_worker.rs`, `src/cpu_worker/jobs/`)
57f44a63d99fatagen2026-10-16 05:34 UTC66
57f44a63d99fatagen2026-10-16 05:34 UTC67
One background thread named `cpu worker` with its own `AsyncEngine` plus ring depth 32 (`src/cpu_worker.rs:275-294`, `src/cpu_worker.rs:366-386`). `CpuJob::work` returns the thread-side `CpuWork`, and `completed` runs back on the main thread (`src/cpu_worker.rs:33-50`).
57f44a63d99fatagen2026-10-16 05:34 UTC68
57f44a63d99fatagen2026-10-16 05:34 UTC69
Main submits with `submit`, leaking the job box and queueing `Job::New{id, *mut dyn CpuWork}` on an `AsyncQueue`, returning a `PendingJob` (`src/cpu_worker.rs:323-339`). An `equeue_jobs` task moves it under lock to the shared `VecDeque` and writes the `have_new_jobs` eventfd (`src/cpu_worker.rs:249-261`). The worker `ring.read`s that eventfd and runs `CpuWork::run`. `None` completes synchronously, `Some(AsyncCpuWork)` is spawned on the worker engine until `WorkCompletion::complete` (`src/cpu_worker.rs:425-473`, `src/cpu_worker.rs:68-77`). Completion pushes the id to the shared completed queue, signals a condvar for sync waiters, and writes `have_completed_jobs` (`src/cpu_worker.rs:475-487`). The main `wait_for_completions` task `ring.read`s it and invokes `job.completed()` (`src/cpu_worker.rs:216-247`). Dropping a pending job warns, sends `Job::Cancel`, and blocks dispatching until gone. `detach` marks it abandoned (`src/cpu_worker.rs:151-204`).
57f44a63d99fatagen2026-10-16 05:34 UTC70
57f44a63d99fatagen2026-10-16 05:34 UTC71
Call sites, all via `cpu.submit`.
57f44a63d99fatagen2026-10-16 05:34 UTC72
57f44a63d99fatagen2026-10-16 05:34 UTC73
- `CloseMemWork`, munmap off-thread, detached (`src/clientmem.rs:211-215`)
57f44a63d99fatagen2026-10-16 05:34 UTC74
- Text `RenderJob` (`src/text.rs:528`)
57f44a63d99fatagen2026-10-16 05:34 UTC75
- Vulkan allocator `FreeJob` and `AllocJob` (`src/gfx_apis/vulkan/allocator.rs:185`, `src/gfx_apis/vulkan/allocator.rs:303`)
57f44a63d99fatagen2026-10-16 05:34 UTC76
- shm transfers, `ImgCopyWork` for pointer-backed and `ReadWriteWork` for fd-backed mem (`src/gfx_apis/vulkan/transfer.rs:505`, `src/gfx_apis/vulkan/transfer.rs:539`, `src/cpu_worker/jobs/img_copy.rs:32-59`, `src/cpu_worker/jobs/read_write.rs:98-148`)
57f44a63d99fatagen2026-10-16 05:34 UTC77
57f44a63d99fatagen2026-10-16 05:34 UTC78
### 1.5 eventfd_cache (`src/eventfd_cache.rs`)
57f44a63d99fatagen2026-10-16 05:34 UTC79
57f44a63d99fatagen2026-10-16 05:34 UTC80
Avoids `eventfd()` churn and forgotten counter drains. Pools fds, `signaled` bools, and `Readable` callback objects (`src/eventfd_cache.rs:39-45`), with a `recycle` task spawned at creation (`src/eventfd_cache.rs:64-75`). `acquire` reuses or creates (`src/eventfd_cache.rs:77-89`). Async wait is `ring.readable` (`src/eventfd_cache.rs:97-104`). External wait reuses a pooled `Readable` through `readable_external` (`src/eventfd_cache.rs:120-137`). `Drop` of a still-signaled fd pushes it to `recycle`, which `ring.read`s each fd empty before returning it to the pool (`src/eventfd_cache.rs:156-224`). `return_signaled` recycles the bool only when the cache holds the last ref (`src/eventfd_cache.rs:208-215`). Held by `State` and passed to the copy-device registry (`src/compositor.rs:466-469`).
57f44a63d99fatagen2026-10-16 05:34 UTC81
57f44a63d99fatagen2026-10-16 05:34 UTC82
### 1.6 Long-lived tasks in `src/tasks/`
57f44a63d99fatagen2026-10-16 05:34 UTC83
57f44a63d99fatagen2026-10-16 05:34 UTC84
- `handle_backend_events`, demuxes the backend queue into connector/input/drm handlers (`src/tasks.rs:22-25`, `src/tasks/backend.rs:12-28`)
57f44a63d99fatagen2026-10-16 05:34 UTC85
- `handle_slow_clients` / `handle_slow_ei_clients`, backpressure kills via `check_queue_size` (`src/tasks.rs:27-35`, `src/tasks/slow_clients.rs:8-28`)
57f44a63d99fatagen2026-10-16 05:34 UTC86
- `handle_const_40hz_latch`, dummy-output latch clock (`src/tasks.rs:37-44`)
57f44a63d99fatagen2026-10-16 05:34 UTC87
- Per-connector `ConnectorHandler`, output lifecycle (`src/tasks/connector.rs:92-98`, `src/tasks/connector.rs:113-141`)
57f44a63d99fatagen2026-10-16 05:34 UTC88
- Per-DRM-device handler (`src/tasks/drmdev.rs:74`)
57f44a63d99fatagen2026-10-16 05:34 UTC89
- Per-input-device handler (`src/tasks/input_device.rs:48-58`)
57f44a63d99fatagen2026-10-16 05:34 UTC90
- `idle`, `TimerFd`-driven DPMS/idle state machine (`src/tasks/idle.rs:13-32`, `src/compositor.rs:651`)
57f44a63d99fatagen2026-10-16 05:34 UTC91
57f44a63d99fatagen2026-10-16 05:34 UTC92
### 1.7 Spawn survey
57f44a63d99fatagen2026-10-16 05:34 UTC93
57f44a63d99fatagen2026-10-16 05:34 UTC94
`eng.spawn`/`spawn2` has 175 hits in 64 files.
57f44a63d99fatagen2026-10-16 05:34 UTC95
57f44a63d99fatagen2026-10-16 05:34 UTC96
- `start_global_event_handlers` alone spawns about 38 named globals covering backend events, slow clients, cursor tick, layout, render positions/titles/textures, output render, managers, idle, popups, screencast, damage, matchers, seats, sqlite, sessions, transactions (`src/compositor.rs:598-745`).
57f44a63d99fatagen2026-10-16 05:34 UTC97
- Per client, 3 tasks per Wayland client plus 2-3 per EI client (`src/client/tasks.rs:20-28`, `src/ei/ei_client/ei_tasks.rs:21-27`, `src/client.rs:258-260`).
57f44a63d99fatagen2026-10-16 05:34 UTC98
- Acceptors/listeners are async accept loops, Wayland secure and insecure, IPC, tagged, security-context, EI (`src/acceptor.rs:144-153`, `src/acceptor.rs:168-191`, `src/ipc.rs:114`, `src/tagged_acceptor.rs:84`, `src/security_context_acceptor.rs:90-95`, `src/ei/ei_acceptor.rs:124`).
57f44a63d99fatagen2026-10-16 05:34 UTC99
- Protocol I/O is async everywhere. dbus auth/in/out, pipewire in/out, forker in/out, xcon in/out, tool clients (`src/dbus/auth.rs:45-50`, `src/pipewire/pw_con.rs:356-359`, `src/forker.rs:123-135`, `src/xcon.rs:469-522`).
57f44a63d99fatagen2026-10-16 05:34 UTC100
- Xwayland is `xwayland::manage` plus `XWM` plus per-transfer shm copy tasks (`src/state.rs:1636`, `src/xwayland.rs:219`, `src/xwayland/xwm.rs:1788-1901`).
57f44a63d99fatagen2026-10-16 05:34 UTC101
- Rendering/output is phased `spawn2` layout/present work plus per-output schedule, vblank, virtual-output, backend event/present tasks (`src/compositor.rs:611-680`, `src/tasks/connector.rs:186-189`, `src/virtual_output.rs:1023-1024`, `src/backends/x.rs:359-364`, `src/backends/metal/video.rs:1221`).
57f44a63d99fatagen2026-10-16 05:34 UTC102
- Vulkan transfer/vblank await tasks are also spawned (`src/gfx_apis/vulkan/transfer.rs:582-627`).
57f44a63d99fatagen2026-10-16 05:34 UTC103
57f44a63d99fatagen2026-10-16 05:34 UTC104
Rough split of non-test spawns. Client/EI/IPC/dbus/pipewire about 35, render/layout/output/present about 45, backend/connector/DRM/input/seat about 15, xwayland/X11 about 8, global compositor/timer/sqlite/config about 25.
57f44a63d99fatagen2026-10-16 05:34 UTC105
57f44a63d99fatagen2026-10-16 05:34 UTC106
### 1.8 Client sockets
57f44a63d99fatagen2026-10-16 05:34 UTC107
57f44a63d99fatagen2026-10-16 05:34 UTC108
One supervisor plus receive, send, terminate tasks per client (`src/client/tasks.rs:18-44`). Receive parses with `WlBufFdIn` over `ring.recvmsg`, including SCM_RIGHTS fds (`src/client/tasks.rs:59-93`, `src/utils/buffd/wl_buf_in.rs:52-126`). Send buffers into `OutBufferSwapchain`. `commit` moves a non-empty `cur` to `pending`, and the send task waits on `flush_request`, swaps `pending` out, and `BufFdOut::flush`es each buffer with an absolute 5s `sendmsg` linked timeout (`src/client/tasks.rs:112-147`, `src/utils/buffd/buf_out.rs:57-91`, `src/utils/buffd/buf_out.rs:102-131`, `src/io_uring/ops/sendmsg.rs:32-85`). `ECANCELED` becomes `Timeout`, `EPIPE`/`ECONNRESET` become `Closed` (`src/utils/buffd/buf_out.rs:121-130`). Slow clients are reaped when `pending` exceeds 10 (`src/utils/buffd/buf_out.rs:48-59`, `src/client.rs:520`). Direct `recvmsg`/`sendmsg` with no userspace epoll shim. Generic bidirectional connections use the same pair through `BufIo` (`src/utils/bufio.rs:101-114`, `src/utils/bufio.rs:143-179`).
57f44a63d99fatagen2026-10-16 05:34 UTC109
57f44a63d99fatagen2026-10-16 05:34 UTC110
Notable vs calloop. Everything above plus pooled task structs, `PendingResult` slab recycling raw pointers, link-timeouts instead of timer races, and a second full runtime on the worker thread.
57f44a63d99fatagen2026-10-16 05:34 UTC111
57f44a63d99fatagen2026-10-16 05:34 UTC112
---
57f44a63d99fatagen2026-10-16 05:34 UTC113
57f44a63d99fatagen2026-10-16 05:34 UTC114
## 2. DRM/KMS metal backend and frame scheduling
57f44a63d99fatagen2026-10-16 05:34 UTC115
57f44a63d99fatagen2026-10-16 05:34 UTC116
### 2.1 KMS model
57f44a63d99fatagen2026-10-16 05:34 UTC117
57f44a63d99fatagen2026-10-16 05:34 UTC118
Atomic only. Device init enables `DRM_CLIENT_CAP_ATOMIC` with value 2 and then probes resources, planes, CRTCs, encoders (`src/backends/metal/video.rs:2030`, `src/backends/metal/video.rs:2032`, `src/backends/metal/video.rs:2040`). It also tries `DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE` and records support (`src/backends/metal/video.rs:2035`).
57f44a63d99fatagen2026-10-16 05:34 UTC119
57f44a63d99fatagen2026-10-16 05:34 UTC120
Desired state is `BackendConnectorState` in `backend.rs` (`src/backend.rs:785`). Committed DRM state is split into `DrmPlaneState`, `DrmCrtcState`, `DrmConnectorState` plus property structs in transaction (`src/backends/metal/transaction.rs:71`). `create_transaction` clones live `drm_state` for every non-leased plane, CRTC and connector and stores requested connector state separately (`src/backends/metal/transaction.rs:221`).
57f44a63d99fatagen2026-10-16 05:34 UTC121
57f44a63d99fatagen2026-10-16 05:34 UTC122
`calculate_drm_state` assigns CRTCs, primary and cursor planes, checks formats and modifiers, allocates scanout buffers when needed, and picks modes, VRR, tearing, colorspace, EOTF and HDR blobs (`src/backends/metal/transaction.rs:314`). `calculate_change` diffs new property structs against live objects with `differs` and `prepare_conditional` and only emits changed objects (`src/backends/metal/transaction.rs:902`, `src/backends/metal/transaction.rs:928`, `src/backends/metal/transaction.rs:949`). It also resets unknown or vendor default properties when asked (`src/backends/metal/transaction.rs:874`).
57f44a63d99fatagen2026-10-16 05:34 UTC123
57f44a63d99fatagen2026-10-16 05:34 UTC124
`TEST_ONLY` is used in the prepare path. `MetalDeviceTransaction::prepare` calls `calculate_drm_state` then `calculate_change(true,false)` (`src/backends/metal/transaction.rs:1216`). When test is true it calls `Change::test` with `DRM_MODE_ATOMIC_ALLOW_MODESET`, which adds `DRM_MODE_ATOMIC_TEST_ONLY` in `video/drm.rs` (`src/backends/metal/transaction.rs:982`, `src/video/drm.rs:1097`). Failure surfaces as `AtomicTestFailed` (`src/backend/transaction.rs:124`).
57f44a63d99fatagen2026-10-16 05:34 UTC125
57f44a63d99fatagen2026-10-16 05:34 UTC126
Normal apply first commits with flags 0 then retries once with `ALLOW_MODESET` after logging (`src/backends/metal/transaction.rs:993`). After a successful kernel commit it swaps new state into live `drm_state`, connector, CRTC and plane objects with `mem::swap` and bumps the connector version (`src/backends/metal/transaction.rs:1092`, `src/backends/metal/transaction.rs:1100`). Rollback keeps the pre-apply state and reapplies it with `calculate_change(false,false)` (`src/backends/metal/transaction.rs:1194`). The generic wrapper also rolls back on drop (`src/backend/transaction.rs:248`). Device init has an extra recovery loop that retries init while disabling direct scanout, non-XRGB formats and non-default modes (`src/backends/metal/video.rs:2553`, `src/backends/metal/video.rs:2589`).
57f44a63d99fatagen2026-10-16 05:34 UTC127
57f44a63d99fatagen2026-10-16 05:34 UTC128
### 2.2 Planes
57f44a63d99fatagen2026-10-16 05:34 UTC129
57f44a63d99fatagen2026-10-16 05:34 UTC130
Types are `Overlay`, `Primary` and `Cursor` (`src/backends/metal/video.rs:1023`). The transaction carries `primary` plus `cursor` per CRTC (`src/backends/metal/transaction.rs:283`). Overlay planes are explicitly discarded during assignment, so compositing uses at most primary plus cursor (`src/backends/metal/transaction.rs:360`).
57f44a63d99fatagen2026-10-16 05:34 UTC131
57f44a63d99fatagen2026-10-16 05:34 UTC132
Cursor uses fixed `ARGB8888` (`src/backends/metal/transaction.rs:281`) and separate double-buffered cursor scanout buffers (`src/backends/metal/video.rs:628`). Cursor enable, move and swap produce `CursorProgrammingType::Enable` or `Disable` (`src/backends/metal/present.rs:127`).
57f44a63d99fatagen2026-10-16 05:34 UTC133
57f44a63d99fatagen2026-10-16 05:34 UTC134
Direct scanout puts a client dmabuf on the primary plane through `add_fb` instead of the compositor render buffer. It is attempted only when enabled and when `prepare_direct_scanout` succeeds (`src/backends/metal/present.rs:901`). That path rejects cross-device buffers unless the scanout device is the render device, rejects SHM, rejects buffers with pending lazy work, checks plane format and modifier support, and caches failures by a key of buffer ID, plane, CRTC, source and destination color descriptions, intent, gamma, cursor presence and pipeline mode (`src/backends/metal/present.rs:746`, `src/backends/metal/present.rs:778`, `src/backends/metal/present.rs:845`). A failed atomic commit with direct scanout retries once as a full composite and then marks that key impossible (`src/backends/metal/present.rs:337`).
57f44a63d99fatagen2026-10-16 05:34 UTC135
57f44a63d99fatagen2026-10-16 05:34 UTC136
### 2.3 Frame scheduling
57f44a63d99fatagen2026-10-16 05:34 UTC137
57f44a63d99fatagen2026-10-16 05:34 UTC138
Each connector spawns its own `present_loop` in phase `Present` (`src/backends/metal/video.rs:1220`). Page flip events arrive on a per-device task that awaits `DrmMaster::event`, which does an io_uring read on the DRM fd and parses `DRM_EVENT_FLIP_COMPLETE` and `DRM_EVENT_CRTC_SEQUENCE` (`src/backends/metal/video.rs:2268`, `src/video/drm.rs:590`, `src/video/drm.rs:607`).
57f44a63d99fatagen2026-10-16 05:34 UTC139
57f44a63d99fatagen2026-10-16 05:34 UTC140
The loop waits for `present_trigger` then requires both `buffers_idle` and `crtc_idle` (`src/backends/metal/present.rs:189`). For synced flips it computes `next_vblank - pre_commit_margin - post_commit_margin` and sleeps with `ring.timeout` until that deadline (`src/backends/metal/present.rs:203`). If already past the deadline it increments the expected sequence so a missed vblank can be detected (`src/backends/metal/present.rs:210`). Tearing flips skip that wait (`src/backends/metal/present.rs:203`).
57f44a63d99fatagen2026-10-16 05:34 UTC141
57f44a63d99fatagen2026-10-16 05:34 UTC142
It then calls `before_latch` with either now for tearing or `next_vblank_nsec` for synced output (`src/backends/metal/present.rs:218`). It aborts if the connector version changed while yielding (`src/backends/metal/present.rs:226`). Then `present_once` latches damage, renders or selects direct scanout, waits render then scanout fences, programs the atomic commit, and on success marks CRTC busy and buffers busy (`src/backends/metal/present.rs:250`, `src/backends/metal/present.rs:314`, `src/backends/metal/present.rs:387`).
57f44a63d99fatagen2026-10-16 05:34 UTC143
57f44a63d99fatagen2026-10-16 05:34 UTC144
`pre_commit_margin` starts at 16ms and `post_commit_margin` starts at 1.5ms (`src/backends/metal/present.rs:145`). The pre margin tracks the per-second maximum CPU time from wakeup through latch with a geometric decay of 0.5 (`src/backends/metal/present.rs:238`, `src/backends/metal/video.rs:1208`). The post margin grows by 500us per second containing missed flips and decays toward the device minimum otherwise (`src/backends/metal/present.rs:147`, `src/backends/metal/video.rs:2425`). Expected versus actual CRTC sequence decides misses (`src/backends/metal/video.rs:2378`).
57f44a63d99fatagen2026-10-16 05:34 UTC145
57f44a63d99fatagen2026-10-16 05:34 UTC146
Flip completion clears `pending_flip`, promotes `next_framebuffer` to `active_framebuffer`, sets `buffers_idle`, emits presentation feedback with `HW_COMPLETION` plus `VSYNC` and `ZERO_COPY` when applicable, then sets `crtc_idle` and reschedules if damage remains (`src/backends/metal/video.rs:2368`, `src/backends/metal/video.rs:2387`, `src/backends/metal/video.rs:2406`). It also maintains `next_vblank_nsec` from flip timestamps plus refresh interval and continuously queues `CRTC_SEQUENCE` for vblank timing unless emulation is active (`src/backends/metal/video.rs:2347`, `src/backends/metal/video.rs:2418`, `src/backends/metal/video.rs:867`). If queueing sequences returns `EOPNOTSUPP` it switches that output to vblank emulation (`src/backends/metal/video.rs:881`).
57f44a63d99fatagen2026-10-16 05:34 UTC147
57f44a63d99fatagen2026-10-16 05:34 UTC148
`output_schedule.rs` is separate from that pacing loop. It only throttles cursor updates in VRR mode. `latched` records present time and clears awaiting-latch flags (`src/output_schedule.rs:100`). `run_once` sleeps until `last_present + cursor_delta` when VRR plus a cursor change is pending, then damages either the hardware cursor or the connector (`src/output_schedule.rs:157`, `src/output_schedule.rs:187`). Tree latch plumbing calls `schedule.latched` from `OutputNode::latched` (`src/tree/output.rs:355`).
57f44a63d99fatagen2026-10-16 05:34 UTC149
57f44a63d99fatagen2026-10-16 05:34 UTC150
### 2.4 VRR and tearing
57f44a63d99fatagen2026-10-16 05:34 UTC151
57f44a63d99fatagen2026-10-16 05:34 UTC152
State carries `vrr` and `tearing` booleans (`src/backend.rs:792`). The transaction rejects VRR on connectors without `vrr_capable` and rejects tearing without atomic async flip support (`src/backends/metal/transaction.rs:766`, `src/backends/metal/transaction.rs:772`). `vrr_capable` comes from the `vrr_capable` property (`src/backends/metal/video.rs:1423`) and async support comes from `DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP` (`src/video/drm.rs:404`).
57f44a63d99fatagen2026-10-16 05:34 UTC153
57f44a63d99fatagen2026-10-16 05:34 UTC154
Per-frame tearing is `persistent tearing AND supports_async_commit` (`src/backends/metal/present.rs:442`). The atomic commit first tries `NONBLOCK | EVENT | ASYNC`, and on failure falls back to synced `NONBLOCK | EVENT` while also attaching `IN_FENCE_FD` and requesting `OUT_FENCE_PTR` except on Nvidia (`src/backends/metal/present.rs:572`, `src/backends/metal/present.rs:581`). Any plane geometry change or cursor plane change forces the synced path (`src/backends/metal/present.rs:493`, `src/backends/metal/present.rs:516`).
57f44a63d99fatagen2026-10-16 05:34 UTC155
57f44a63d99fatagen2026-10-16 05:34 UTC156
### 2.5 Color management
57f44a63d99fatagen2026-10-16 05:34 UTC157
57f44a63d99fatagen2026-10-16 05:34 UTC158
`metal_cm` selects a KMS programming for each frame from source and destination `ColorDescription` values plus render intent, gamma LUT, cursor presence and pipeline selection (`src/backends/metal/video/metal_cm.rs:100`). It caches programmings, matcher results and blobs (`src/backends/metal/video/metal_cm.rs:60`). A programming can set plane `COLOR_PIPELINE`, plane colorop bypass, type, interpolation, data and multiplier, and CRTC gamma LUT (`src/backends/metal/video/metal_cm.rs:127`, `src/backends/metal/video/metal_cm.rs:138`, `src/backends/metal/video/metal_cm.rs:153`). Matching logic decides whether matrix, source EOTF, destination EOTF or client gamma are needed (`src/backends/metal/video/metal_cm/metal_cm_matcher.rs:124`). The minimum LUT size considered useful is 1024 (`src/backends/metal/video/metal_cm.rs:54`). On AMD with a cursor plane it disables plane pipelines as a driver workaround (`src/backends/metal/video/metal_cm.rs:185`).
57f44a63d99fatagen2026-10-16 05:34 UTC159
57f44a63d99fatagen2026-10-16 05:34 UTC160
`metal_cm_paths/generated.rs` holds generated static tables of `PlaneOpKind`, matrix, LUT and multiply variants used by the matcher (`src/backends/metal/video/metal_cm/metal_cm_paths/generated.rs:12`). The handwritten wrapper defines `Path`, plane and CRTC op accessors and criteria filters (`src/backends/metal/video/metal_cm/metal_cm_paths.rs:15`).
57f44a63d99fatagen2026-10-16 05:34 UTC161
57f44a63d99fatagen2026-10-16 05:34 UTC162
Legacy properties are also handled. CRTC defaults include `CTM`, `DEGAMMA_LUT`, `OUT_FENCE_PTR` and AMD regamma (`src/backends/metal/video.rs:1565`). Plane defaults include AMD blend, shaper, 3D LUT, HDR multiplier, alpha, blend mode, rotation and `COLOR_PIPELINE Bypass` for non-primary planes (`src/backends/metal/video.rs:1680`). Plane pipeline use is opt-in through `use_plane_color_pipelines`, default false (`src/backends/metal/video.rs:2123`, `src/backend.rs:672`).
57f44a63d99fatagen2026-10-16 05:34 UTC163
57f44a63d99fatagen2026-10-16 05:34 UTC164
HDR uses connector `Colorspace` and `HDR_OUTPUT_METADATA` plus EDID-derived PQ and BT2020 support, primaries and luminance (`src/backends/metal/video.rs:1351`, `src/backends/metal/video.rs:1452`, `src/backends/metal/video.rs:1500`). The transaction creates the HDR metadata blob from EOTF, primaries and luminance (`src/backends/metal/transaction.rs:802`, `src/video/drm.rs:919`). The renderer supplies `cd`, linear and blend descriptions per frame, and `metal_cm` maps framebuffer description to output description (`src/backends/metal/present.rs:277`, `src/backends/metal/present.rs:889`).
57f44a63d99fatagen2026-10-16 05:34 UTC165
57f44a63d99fatagen2026-10-16 05:34 UTC166
### 2.6 Allocator and multi-GPU
57f44a63d99fatagen2026-10-16 05:34 UTC167
57f44a63d99fatagen2026-10-16 05:34 UTC168
Allocation is GBM based, not dumb buffers. It creates render and scanout `GbmBo` objects, imports them as gfx textures and framebuffers, and registers display framebuffers with `add_fb2` (`src/backends/metal/allocator.rs:878`, `src/backends/metal/allocator.rs:914`, `src/video/drm.rs:441`). GEM handles are cached (`src/video/drm.rs:484`). Modifier lists come from the plane `IN_FORMATS` blob, with fallback to the legacy plane format list (`src/backends/metal/video.rs:1616`, `src/video/drm.rs:531`).
57f44a63d99fatagen2026-10-16 05:34 UTC169
57f44a63d99fatagen2026-10-16 05:34 UTC170
Same-GPU scanout uses one BO for render and scanout (`src/backends/metal/allocator.rs:454`). Cross-GPU tries configurable prime methods in order `direct-pull`, `direct-push`, `udmabuf`, `direct-sampling` and `indirect-pull`, controlled by `WRY_PRIME_METHODS` (`src/backends/metal/allocator.rs:464`, `src/backends/metal/allocator.rs:615`, `src/backends/metal/allocator.rs:1528`). Each method intersects render write and read modifiers, plane modifiers and copy device source and destination modifiers, with copy paths forced to linear when available (`src/backends/metal/allocator.rs:1224`, `src/backends/metal/allocator.rs:1595`). Buffer kinds are direct sampling versus three copy device topologies plus direct push, which is noted as unsafe on AMD (`src/backends/metal/allocator.rs:85`, `src/backends/metal/allocator.rs:621`). Per-frame `copy_to_dev` performs the needed GPU or copy device transfer (`src/backends/metal/allocator.rs:154`).
57f44a63d99fatagen2026-10-16 05:34 UTC171
57f44a63d99fatagen2026-10-16 05:34 UTC172
### 2.7 Hotplug, session, lease
57f44a63d99fatagen2026-10-16 05:34 UTC173
57f44a63d99fatagen2026-10-16 05:34 UTC174
Hotplug watches `drm` and `input` through udev (`src/backends/metal.rs:307`). A task waits for the monitor fd with io_uring readable readiness and dispatches add versus change (`src/backends/metal/monitor.rs:42`). DRM change diffs kernel connectors against known connectors, emits `Disconnected` plus `Removed`, revokes affected leases, refreshes properties and display data, creates new connector objects and reinitializes the device (`src/backends/metal/video.rs:1844`).
57f44a63d99fatagen2026-10-16 05:34 UTC175
57f44a63d99fatagen2026-10-16 05:34 UTC176
Logind handling takes session control, takes each device fd, and installs pause and resume handlers (`src/backends/metal.rs:295`, `src/logind.rs:76`, `src/backends/metal/monitor.rs:402`). Pause marks the DRM device paused, hides non-desktop outputs and parks leases in `leases_to_break` (`src/backends/metal/monitor.rs:166`). Resume clears paused state, retries lease revocation, refreshes properties and reschedules presents (`src/backends/metal/monitor.rs:97`, `src/backends/metal/video.rs:2248`). Losing DRM master surfaces as `EACCES` on commit and is intentionally ignored per frame (`src/backends/metal/present.rs:379`).
57f44a63d99fatagen2026-10-16 05:34 UTC177
57f44a63d99fatagen2026-10-16 05:34 UTC178
Leases are supported for non-desktop outputs. Creation requires connected non-desktop connectors, allocates an unused CRTC and primary plane per connector, calls the kernel lease ioctl and emits `Unavailable` (`src/backends/metal/video.rs:264`, `src/video/drm.rs:638`). Dropping the lease object revokes it or parks it for later revocation and makes the connector available again (`src/backends/metal/video.rs:550`, `src/backends/metal/video.rs:514`).
57f44a63d99fatagen2026-10-16 05:34 UTC179
57f44a63d99fatagen2026-10-16 05:34 UTC180
### 2.8 Unusual choices
57f44a63d99fatagen2026-10-16 05:34 UTC181
57f44a63d99fatagen2026-10-16 05:34 UTC182
- Overlays are enumerated but never assigned, unlike many compositors (`src/backends/metal/transaction.rs:360`).
57f44a63d99fatagen2026-10-16 05:34 UTC183
- Direct scanout participates in color pipeline search and has its own impossible-cache (`src/backends/metal/present.rs:778`).
57f44a63d99fatagen2026-10-16 05:34 UTC184
- Frame timing uses two adaptive margins rather than a fixed deadline, with the pre margin from measured CPU time and the post margin from missed sequence counts (`src/backends/metal/present.rs:238`, `src/backends/metal/video.rs:2425`).
57f44a63d99fatagen2026-10-16 05:34 UTC185
- The modeset path blocks on buffer clear and copy syncs inside transaction calculation and can synchronously poll a CRTC out fence before blanking (`src/backends/metal/transaction.rs:693`, `src/backends/metal/transaction.rs:843`).
57f44a63d99fatagen2026-10-16 05:34 UTC186
- Init and hotplug paths reset unknown KMS properties to driver defaults, which helps against firmware or desktop leftover state (`src/backends/metal/transaction.rs:886`, `src/backends/metal/video.rs:2589`).
57f44a63d99fatagen2026-10-16 05:34 UTC187
57f44a63d99fatagen2026-10-16 05:34 UTC188
---
57f44a63d99fatagen2026-10-16 05:34 UTC189
57f44a63d99fatagen2026-10-16 05:34 UTC190
## 3. Wire protocol and client handling
57f44a63d99fatagen2026-10-16 05:34 UTC191
57f44a63d99fatagen2026-10-16 05:34 UTC192
### 3.1 Protocol description format
57f44a63d99fatagen2026-10-16 05:34 UTC193
57f44a63d99fatagen2026-10-16 05:34 UTC194
`wire/` holds a custom DSL, one file per interface. `wire/wl_surface.txt:1-8` shows `request destroy`, typed fields, `(destructor)`, `(since = 2)`, `(new)`. No XML is stored in tree. XML appears only at conversion boundaries.
57f44a63d99fatagen2026-10-16 05:34 UTC195
57f44a63d99fatagen2026-10-16 05:34 UTC196
The DSL parser lives in `build/wire/parser.rs:209-224` for `Type` with `Id, U32, I32, U64, U64Rev, Str, OptStr, BStr, Fixed, Fd, Bool, Array, Pod`, plus `build/wire/parser.rs:236-246` for `Message` and `build/wire/parser.rs:350-403` for message parsing.
57f44a63d99fatagen2026-10-16 05:34 UTC197
57f44a63d99fatagen2026-10-16 05:34 UTC198
`xml-to-wire/src/main.rs:9-14` plus `xml-to-wire/src/builder.rs:27-42` converts Wayland XML to `wire/*.txt`. Special handling maps `x_hi` plus `x_lo` pairs to `u64` or `u64_rev` (`xml-to-wire/src/builder.rs:83-106`) and maps untyped arrays or `dev_t` blobs to `array` or `pod` (`xml-to-wire/src/builder.rs:132-160`). `wire-to-xml/src/main.rs:41-60` does the reverse for debugging or interop.
57f44a63d99fatagen2026-10-16 05:34 UTC199
57f44a63d99fatagen2026-10-16 05:34 UTC200
The build script (`build/build.rs:53-67`) runs `wire::main` and emits to `OUT_DIR`. `build/wire.rs:497-539` scans `wire/`, parses every file, and writes `wire/mod.rs` plus one generated `wire/<iface>.rs` per interface. It also emits `id!` plus `Interface` constants (`build/wire.rs:455-494`).
57f44a63d99fatagen2026-10-16 05:34 UTC201
57f44a63d99fatagen2026-10-16 05:34 UTC202
A generated request type is a plain struct with `self_id` plus fields (`build/wire.rs:57-76`). Its `RequestParser` impl is emitted in `build/wire.rs:78-202`. Fixed-size messages destructure `*parser.data()` directly (`build/wire.rs:112-170`). Variable-size messages call `parser.uint`, `str`, `bstr`, `fd`, `binary` and then `parser.eof` (`build/wire.rs:171-198`).
57f44a63d99fatagen2026-10-16 05:34 UTC203
57f44a63d99fatagen2026-10-16 05:34 UTC204
A generated event writer implements `EventFormatter` (`build/wire.rs:203-302`). Fixed events use one `fmt.data` word array (`build/wire.rs:214-250`). Variable events use `fmt.header` plus per-field writers (`build/wire.rs:252-291`). Request and event handler traits are emitted together (`build/wire.rs:311-431`), with server traits using `Object` plus `Client` and client-side traits using `UsrObject` plus `UsrCon` (`build/wire.rs:327-348`).
57f44a63d99fatagen2026-10-16 05:34 UTC205
57f44a63d99fatagen2026-10-16 05:34 UTC206
Parsing is largely zero-copy. `MsgParser` borrows the `&[u32]` body plus fd queue (`src/utils/buffd/parser.rs:33-47`). `str`, `bstr`, `array`, `binary_array` return borrowed `&str`, `&BStr`, `&[u8]`, `&[T]` (`src/utils/buffd/parser.rs:96-146`, `src/utils/buffd/parser.rs:159-176`).
57f44a63d99fatagen2026-10-16 05:34 UTC207
57f44a63d99fatagen2026-10-16 05:34 UTC208
File descriptors travel as ancillary data. `WlBufFdIn` collects them with `recvmsg` (`src/utils/buffd/wl_buf_in.rs:110-126`). `MsgParser::fd` pops from that queue (`src/utils/buffd/parser.rs:122-127`). `MsgFormatter::fd` queues them and `write_len` records their message offset (`src/utils/buffd/formatter.rs:93-96`, `src/utils/buffd/formatter.rs:135-149`). Sending splits at fd boundaries (`src/utils/buffd/buf_out.rs:102-120`). This split-queue design is unusual relative to libwayland.
57f44a63d99fatagen2026-10-16 05:34 UTC209
57f44a63d99fatagen2026-10-16 05:34 UTC210
### 3.2 Object model
57f44a63d99fatagen2026-10-16 05:34 UTC211
57f44a63d99fatagen2026-10-16 05:34 UTC212
Each `Client` owns an `Objects` store (`src/client.rs:355`, `src/client/objects.rs:87-135`). There is one generic `registry` map plus many typed `CopyHashMap` maps for surfaces, buffers, seats and others (`src/client/objects.rs:88-134`).
57f44a63d99fatagen2026-10-16 05:34 UTC213
57f44a63d99fatagen2026-10-16 05:34 UTC214
ID allocation splits the space at `MIN_SERVER_ID 0xff000000` (`src/client/objects.rs:137`). Client-created IDs must be nonzero and below that bound (`src/client/objects.rs:266-282`). Server IDs are allocated from a bitset freelist (`src/client/objects.rs:235-250`, `src/client/objects.rs:314-325`).
57f44a63d99fatagen2026-10-16 05:34 UTC215
57f44a63d99fatagen2026-10-16 05:34 UTC216
Dispatch starts in the receive task. It reads `WlMessage obj_id message body fds` (`src/client/tasks.rs:64-72`), looks up the object (`src/client/tasks.rs:73-80`), then calls `handle_request` (`src/client/tasks.rs:81-90`). Every object forwards through `object_base!` to generated `handle_request_impl` (`src/macros.rs:41-66`). The generated dispatcher matches the opcode and emits a `version >= since` guard (`build/wire.rs:387-411`). Unknown opcodes become `InvalidMethod` (`build/wire.rs:413`, `src/client/error.rs:18-19`).
57f44a63d99fatagen2026-10-16 05:34 UTC217
57f44a63d99fatagen2026-10-16 05:34 UTC218
Versioning is also enforced at bind time. `WlRegistry bind` checks interface name and `version <= global.version` (`src/ifs/wl_registry.rs:64-89`). Globals expose fixed versions, for example compositor version 7 (`src/ifs/wl_compositor.rs:82-86`).
57f44a63d99fatagen2026-10-16 05:34 UTC219
57f44a63d99fatagen2026-10-16 05:34 UTC220
Protocol errors use `wl_display/error`.
57f44a63d99fatagen2026-10-16 05:34 UTC221
57f44a63d99fatagen2026-10-16 05:34 UTC222
- Unknown objects trigger `send_invalid_object` plus shutdown (`src/client/tasks.rs:73-78`, `src/ifs/wl_display.rs:79-82`).
57f44a63d99fatagen2026-10-16 05:34 UTC223
- Unknown requests trigger `send_invalid_request` plus shutdown (`src/client.rs:394-416`, `src/ifs/wl_display.rs:68-77`).
57f44a63d99fatagen2026-10-16 05:34 UTC224
- Handler failures trigger `send_implementation_error` plus shutdown (`src/client/tasks.rs:94-108`, `src/ifs/wl_display.rs:84-86`).
57f44a63d99fatagen2026-10-16 05:34 UTC225
- Explicit `protocol_error` does the same (`src/client.rs:489-494`).
57f44a63d99fatagen2026-10-16 05:34 UTC226
- Method wrapping preserves interface, id, method and source error (`src/client/error.rs:35-42`).
57f44a63d99fatagen2026-10-16 05:34 UTC227
57f44a63d99fatagen2026-10-16 05:34 UTC228
Lifetime uses `Rc` with explicit cycle breaking. `Object` has a default empty `break_loops` (`src/object.rs:25-27`). Client teardown calls `Objects::destroy`, which drains the generic registry through `break_loops` and clears typed maps (`src/client/objects.rs:186-233`). `ClientHolder Drop` drives that plus shutdown, activation token and timeline cleanup (`src/client.rs:320-337`). `WlSurface break_loops` drops children, dnd, cursors, transactions, feedback, viewporter and timelines (`src/ifs/wl_surface.rs:2104-2127`). Server ID removal can emit `delete_id` when symmetric deletion is active (`src/client/objects.rs:284-308`). Typed insertion and lookup go through `dedicated_add_obj!` (`src/macros.rs:341-361`), while simple objects and globals use `simple_add_obj!` and `simple_add_global!` (`src/macros.rs:363-373`). Explicit teardown instead of `Weak` everywhere is unusual relative to wayland-rs.
57f44a63d99fatagen2026-10-16 05:34 UTC229
57f44a63d99fatagen2026-10-16 05:34 UTC230
### 3.3 Client I/O
57f44a63d99fatagen2026-10-16 05:34 UTC231
57f44a63d99fatagen2026-10-16 05:34 UTC232
Input uses `WlBufFdIn` with an 8 KiB buffer and 4 KiB max message (`src/utils/buffd/wl_buf_in.rs:15-29`). It validates word alignment and `8 <= len <= 4096` (`src/utils/buffd/wl_buf_in.rs:69-77`), compacts unconsumed bytes (`src/utils/buffd/wl_buf_in.rs:100-108`), and caps queued fds at 32 (`src/utils/buffd/wl_buf_in.rs:122-124`). Error variants cover oversize, undersize, unaligned, missing and excess fds (`src/utils/buffd.rs:24-44`) with limits `BUF_SIZE 4096` and `MAX_IN_FD 32` (`src/utils/buffd.rs:46-47`).
57f44a63d99fatagen2026-10-16 05:34 UTC233
57f44a63d99fatagen2026-10-16 05:34 UTC234
Output uses `OutBufferSwapchain` with current, pending and free buffers (`src/utils/buffd/buf_out.rs:50-69`). Each output buffer is 8 KiB and considered full past 4 KiB (`src/utils/buffd/buf_out.rs:14`, `src/utils/buffd/buf_out.rs:42-46`). `Client::event` formats into the current buffer, commits on full, then signals the sender (`src/client.rs:496-514`). The sender swaps pending buffers and flushes with a 5 second timeout (`src/client/tasks.rs:112-132`). Used buffers are recycled through `free` (`src/client/tasks.rs:128-131`, `src/utils/buffd/buf_out.rs:62-68`).
57f44a63d99fatagen2026-10-16 05:34 UTC235
57f44a63d99fatagen2026-10-16 05:34 UTC236
Backpressure is bounded but not lossy for compliant clients. More than 10 pending buffers counts as over limit (`src/utils/buffd/buf_out.rs:57-60`). Over-limit clients enter the global slow queue once (`src/client.rs:505-511`). A background handler rechecks after a yield and kills still-slow clients (`src/client.rs:520-530`, `src/tasks/slow_clients.rs:9-14`). Event flushing is otherwise triggered, not synchronous after every request, as seen by the commented-out flush (`src/client/tasks.rs:91`) and trigger use (`src/client.rs:513`).
57f44a63d99fatagen2026-10-16 05:34 UTC237
57f44a63d99fatagen2026-10-16 05:34 UTC238
### 3.4 `clientmem.rs`
57f44a63d99fatagen2026-10-16 05:34 UTC239
57f44a63d99fatagen2026-10-16 05:34 UTC240
SHM pools are mapped with `mmap64`, length rounded up to page size, with an empty mapping for zero length (`src/clientmem.rs:104-124`). Read-only pools use `PROT_READ`, writable pools add `PROT_WRITE`, normally `MAP_SHARED` (`src/clientmem.rs:78-123`). Private mappings are a separate constructor (`src/clientmem.rs:68-76`).
57f44a63d99fatagen2026-10-16 05:34 UTC241
57f44a63d99fatagen2026-10-16 05:34 UTC242
Truncated client memory is handled with `SIGBUS`. Startup installs a `SA_SIGINFO` plus `SA_NODEFER` handler (`src/clientmem.rs:273-284`). Safe access pushes a thread-local record, runs the closure, then reports `Sigbus` if marked failed (`src/clientmem.rs:170-189`). The handler checks whether the fault address lies inside a tracked mapping (`src/clientmem.rs:241-254`), replaces that range with anonymous memory via `MAP_FIXED` (`src/clientmem.rs:255-262`), marks failure and returns (`src/clientmem.rs:266-267`), otherwise restores default and raises `SIGBUS` (`src/clientmem.rs:233-239`, `src/clientmem.rs:269`).
57f44a63d99fatagen2026-10-16 05:34 UTC243
57f44a63d99fatagen2026-10-16 05:34 UTC244
Sealed memfds skip the handler path. If `F_SEAL_SHRINK` plus a large enough `st_size` is observed, the mapping is marked `sigbus_impossible` (`src/clientmem.rs:89-96`). It may first extend the file with `ftruncate` (`src/clientmem.rs:105-109`). Direct pointer access is allowed only in that case, otherwise callers get an fd plus offset (`src/clientmem.rs:319-324`). Destruction unmaps inline or offloads close plus unmap to the CPU worker (`src/clientmem.rs:207-222`).
57f44a63d99fatagen2026-10-16 05:34 UTC245
57f44a63d99fatagen2026-10-16 05:34 UTC246
### 3.5 `leaks.rs`
57f44a63d99fatagen2026-10-16 05:34 UTC247
57f44a63d99fatagen2026-10-16 05:34 UTC248
`track!` registers each new `Rc` against its client (`src/leaks.rs:3-7`). Without `rc_tracking` the tracker is a zero-sized phantom (`src/leaks.rs:9-39`). With `rc_tracking` it assigns tracker IDs, installs a tracing global allocator, records allocation backtraces, and on demand groups unreleased objects by client with containing allocation and stack evidence (`src/leaks.rs:59-178`, `src/leaks.rs:193-240`, `src/leaks.rs:268-299`). This is a debug facility, not a production GC.
57f44a63d99fatagen2026-10-16 05:34 UTC249
57f44a63d99fatagen2026-10-16 05:34 UTC250
### 3.6 Acceptors
57f44a63d99fatagen2026-10-16 05:34 UTC251
57f44a63d99fatagen2026-10-16 05:34 UTC252
The primary acceptor creates two Unix stream sockets, insecure `wayland-N` and secure `wayland-N.wry`, plus a lock file, scanning `1..1000` (`src/acceptor.rs:66-132`). It unlinks stale paths, takes a nonblocking `flock`, binds, listens with backlog 4096 and stores the lock fd (`src/acceptor.rs:81-142`). It then spawns separate secure and insecure accept loops (`src/acceptor.rs:144-156`). Each accepted fd becomes a `Client` (`src/acceptor.rs:168-191`).
57f44a63d99fatagen2026-10-16 05:34 UTC253
57f44a63d99fatagen2026-10-16 05:34 UTC254
Tagged acceptors create extra named sockets on demand for a string tag, starting at `wayland-1000` and skipping locked names (`src/tagged_acceptor.rs:63-101`, `src/tagged_acceptor.rs:156-197`). Their metadata carries the tag and non-sandboxed status (`src/tagged_acceptor.rs:72-79`). Their accept loop is otherwise the same (`src/tagged_acceptor.rs:115-135`).
57f44a63d99fatagen2026-10-16 05:34 UTC255
57f44a63d99fatagen2026-10-16 05:34 UTC256
Security context acceptors do not bind. They accept from a client-supplied listen fd and watch a close fd (`src/security_context_acceptor.rs:22-31`, `src/security_context_acceptor.rs:112-137`). New clients are marked sandboxed with caller-supplied sandbox engine, app id, instance id and bounding caps (`src/security_context_acceptor.rs:59-80`, `src/security_context_acceptor.rs:122-129`). Dual secure plus insecure sockets for one compositor is jay/wry specific.
57f44a63d99fatagen2026-10-16 05:34 UTC257
57f44a63d99fatagen2026-10-16 05:34 UTC258
### 3.7 `wl_usr`
57f44a63d99fatagen2026-10-16 05:34 UTC259
57f44a63d99fatagen2026-10-16 05:34 UTC260
`wl_usr` is a Wayland client stack used by the compositor itself. `UsrCon::new` connects over a Unix socket with io_uring (`src/wl_usr.rs:99-129`). `from_socket` reserves IDs 0 and 1, installs `UsrWlDisplay` object 1, and spawns incoming plus outgoing tasks (`src/wl_usr.rs:131-187`). Outgoing requests reuse the same swapchain and formatter design as server-to-client events (`src/wl_usr.rs:260-279`, `src/wl_usr.rs:281-316`). Incoming events dispatch by object id to `handle_event`, ignoring unknown server IDs but erroring on unknown client IDs (`src/wl_usr.rs:339-357`).
57f44a63d99fatagen2026-10-16 05:34 UTC261
57f44a63d99fatagen2026-10-16 05:34 UTC262
Client-side objects live in `src/wl_usr/usr_ifs/`. For example `UsrWlCompositor::create_surface` sends the request and tracks the new object (`src/wl_usr/usr_ifs/usr_wl_compositor.rs:17-30`). The generated client trait uses `UsrObject`, `UsrCon` and `UsrConError` (`build/wire.rs:339-347`). The portal uses this to connect to nested displays named `wayland-*.wry` (`src/portal/ptl_display.rs:298-343`), then binds compositor, fractional scale, viewporter, dmabuf and other globals (`src/portal/ptl_display.rs:346-373`).
57f44a63d99fatagen2026-10-16 05:34 UTC263
57f44a63d99fatagen2026-10-16 05:34 UTC264
### 3.8 Performance notes
57f44a63d99fatagen2026-10-16 05:34 UTC265
57f44a63d99fatagen2026-10-16 05:34 UTC266
- Fixed messages avoid per-field calls and copy words directly. Variable strings, byte strings and arrays borrow from the input buffer.
57f44a63d99fatagen2026-10-16 05:34 UTC267
- Small inline storage appears widely, including `SmallVec` for rects, syncs, copies and seats and `ArrayVec` for descriptor layouts, barriers and singleton broadcasts (`src/rect.rs:33`, `src/video/dmabuf.rs:327`, `src/ifs/wl_surface/commit_timeline.rs:553-561`, `src/globals.rs:410`, `src/utils/buffd/buf_in.rs:73`).
57f44a63d99fatagen2026-10-16 05:34 UTC268
- Object maps use custom `CopyHashMap` over hashbrown with unsafe interior access (`src/utils/copyhashmap.rs:21-80`).
57f44a63d99fatagen2026-10-16 05:34 UTC269
- Output buffers and `Buf` storage are recycled rather than reallocated in the swapchain and sender paths.
57f44a63d99fatagen2026-10-16 05:34 UTC270
- Slow-client detection avoids blocking the compositor on a non-draining peer.
57f44a63d99fatagen2026-10-16 05:34 UTC271
57f44a63d99fatagen2026-10-16 05:34 UTC272
## 4. Vulkan renderer
57f44a63d99fatagen2026-10-16 05:34 UTC273
57f44a63d99fatagen2026-10-16 05:34 UTC274
The reader returned this one as a single dense block with fewer line citations. It is restructured here. Claims marked (verified) were spot-checked by hand. The "bridge" description was corrected, since the code gates it on `for_rendering` (`src/gfx_apis/vulkan/image.rs:535`).
57f44a63d99fatagen2026-10-16 05:34 UTC275
57f44a63d99fatagen2026-10-16 05:34 UTC276
### 4.1 Abstraction
57f44a63d99fatagen2026-10-16 05:34 UTC277
57f44a63d99fatagen2026-10-16 05:34 UTC278
The compositor is renderer-agnostic. `GfxApiOp` (`src/gfx_api.rs:115`) has `FillRect` (`:117`), `CopyTexture` (`:118`), `RoundedFillRect` (`:119`) and `RoundedCopyTexture` (`:120`). The `FillRect` struct (`src/gfx_api.rs:286`) and `CopyTexture` (`src/gfx_api.rs:304`) carry `acquire_sync` (`:309`) plus `release_sync` and `lazy` (`:318`). The rounded variants (`:323`, `:344`) mirror that shape.
57f44a63d99fatagen2026-10-16 05:34 UTC279
57f44a63d99fatagen2026-10-16 05:34 UTC280
- `LazyTexture` (`src/gfx_api.rs:373`) lets a backend defer work, with `perform_lazy_work` feeding a `Vec<FdSync>`.
57f44a63d99fatagen2026-10-16 05:34 UTC281
- `AcquireSync` (`src/gfx_api.rs:426`) has `None`, `Implicit`, `FdSync` and `Unnecessary`, with `from_fd_sync` (`:434`). `ReleaseSync` (`src/gfx_api.rs:452`) is the release side.
57f44a63d99fatagen2026-10-16 05:34 UTC282
- `GfxFramebuffer` (`src/gfx_api.rs:503`) exposes `render_with_region_impl` (`:506`) and wrappers through `:889`.
57f44a63d99fatagen2026-10-16 05:34 UTC283
- `GfxTexture` (`src/gfx_api.rs:931`) and `GfxContext` (`src/gfx_api.rs:1030`) complete the surface, with `supports_color_management` (`:1108`) and `supports_alpha_modes` (`:1112`).
57f44a63d99fatagen2026-10-16 05:34 UTC284
- Direct scanout filtering lives near `src/gfx_api.rs:1529`, rejecting `FillRect` (`:1536`) and `RoundedCopyTexture` (`:1540`).
57f44a63d99fatagen2026-10-16 05:34 UTC285
57f44a63d99fatagen2026-10-16 05:34 UTC286
A second backend exists. `create_gfx_context` (`src/gfx_apis.rs:17`) tries APIs (`:26`) as OpenGL then Vulkan, looping software false then true (`:29`), with dispatch at `:70`. The GL backend (`src/gfx_apis/gl.rs` plus `src/gfx_apis/gl/`, about 3.3k lines) is a full parallel renderer using EGL images, GL textures, and its own `TexCopyType` and `TexSourceType`.
57f44a63d99fatagen2026-10-16 05:34 UTC287
57f44a63d99fatagen2026-10-16 05:34 UTC288
### 4.2 Frame recording
57f44a63d99fatagen2026-10-16 05:34 UTC289
57f44a63d99fatagen2026-10-16 05:34 UTC290
A frame is an op list turned into one Vulkan submit. `RendererBase` in compositor code emits `FillRect` and `CopyTexture` ops, and `VulkanRenderer` executes them. `convert_ops` (`src/gfx_apis/vulkan/renderer.rs:1007`, verified) sorts by color, z order and index (`:1030`), then groups by pipeline key. `TexPipelineKey` (`src/gfx_apis/vulkan/renderer.rs:416`, verified) includes copy type, source type, alpha mode, EOTF pair, color matrix presence, grayscale and rounded. A separate `OutPipelineKey` (`:434`) covers the resolve pass.
57f44a63d99fatagen2026-10-16 05:34 UTC291
57f44a63d99fatagen2026-10-16 05:34 UTC292
Recording centers on `record_draws` (`src/gfx_apis/vulkan/renderer.rs:1729`), `begin_rendering` (`:1620`), `submit` (`:2393`) and `execute` (`:2475`).
57f44a63d99fatagen2026-10-16 05:34 UTC293
57f44a63d99fatagen2026-10-16 05:34 UTC294
- `begin_rendering` uses Vulkan 1.3 dynamic rendering with `cmd_begin_rendering` (`:1685`).
57f44a63d99fatagen2026-10-16 05:34 UTC295
- Full-area clears use load op `CLEAR` (`:1667`), otherwise partial clears go through `cmd_clear_attachments` (`:1694`). The blend buffer pass uses `DONT_CARE` (`:1668`).
57f44a63d99fatagen2026-10-16 05:34 UTC296
- Viewport and scissor cover the full target (`:1702`).
57f44a63d99fatagen2026-10-16 05:34 UTC297
57f44a63d99fatagen2026-10-16 05:34 UTC298
Vertex data uses device-addressable buffers. `tex.common.glsl` (`src/gfx_apis/vulkan/shaders/tex.common.glsl:8`) declares a `buffer_reference` `Vertices` with push-constant `Data` carrying vertices and `mul` (`:12`). This avoids vertex bindings and lets one instanced draw consume many rects from a data buffer.
57f44a63d99fatagen2026-10-16 05:34 UTC299
57f44a63d99fatagen2026-10-16 05:34 UTC300
Specialization uses seven constants in `frag_spec_const.glsl` (`src/gfx_apis/vulkan/shaders/frag_spec_const.glsl:4`): `src_has_alpha`, `has_alpha_multiplier`, `eotf`, `inv_eotf`, `has_matrix`, `alpha_mode` and `grayscale`. Pipeline creation consumes those as specialization constants.
57f44a63d99fatagen2026-10-16 05:34 UTC301
57f44a63d99fatagen2026-10-16 05:34 UTC302
Descriptors have three tiers. Device probing (`src/gfx_apis/vulkan/device.rs:433`) prefers `descriptor_heap` plus `maintenance5`, falls back to `descriptor_buffer` (`:441`), and finally legacy `push_descriptor`. Enablement (`:481`) adds heap and maintenance5 or buffer names. Features (`:490`) enable timeline semaphores, `synchronization2`, `dynamic_rendering` (`:492`), `buffer_device_address` (`:500`), plus heap or buffer features (`:538`). Color bindings are fixed in `tex_set.glsl` (`src/gfx_apis/vulkan/shaders/tex_set.glsl:4`) with `texture2D tex` plus `ColorManagementData` matrix, `EotfArgs` and `InvEotfArgs`.
57f44a63d99fatagen2026-10-16 05:34 UTC303
57f44a63d99fatagen2026-10-16 05:34 UTC304
Wait setup (`src/gfx_apis/vulkan/renderer.rs:2254`) imports dmabuf sync files and explicit `FdSync` into `TOP_OF_PIPE` waits. Submit uses `queue_submit2` (`:2409`) and stores `release_sync` (`:2417`). Pending frames (`:2439`) retain command buffers, images, semaphores and heap entries and spawn `await_release` on the async engine (`:2463`).
57f44a63d99fatagen2026-10-16 05:34 UTC305
57f44a63d99fatagen2026-10-16 05:34 UTC306
### 4.3 Upload and import
57f44a63d99fatagen2026-10-16 05:34 UTC307
57f44a63d99fatagen2026-10-16 05:34 UTC308
- SHM textures are created `OPTIMAL`, `SAMPLED` plus `TRANSFER_DST`, and filled from staging buffers with `BufferImageCopy2` limited to damage. `transfer.rs` computes copies with queue-family ownership barriers and granularity masks and expands for 4-byte alignment.
57f44a63d99fatagen2026-10-16 05:34 UTC309
- The async path uses `CpuWorker` jobs `IoTransferJob` and `CopyTransferJob` (`src/gfx_apis/vulkan/transfer.rs:633`, `:642`, verified) with ring readable waits for gfx queue release. The sync path submits a buffer-image copy on the gfx queue directly.
57f44a63d99fatagen2026-10-16 05:34 UTC310
- Dmabuf import in `image.rs` uses explicit DRM format modifier creation with per-plane fd import and `bind_image_memory2`, and checks disjoint planes and single-file reuse.
57f44a63d99fatagen2026-10-16 05:34 UTC311
- When a dmabuf's modifier is not renderable, rendering goes into an intermediate "bridge" image and is copied out (`src/gfx_apis/vulkan/image.rs:97`, `:113`, `:535`, verified).
57f44a63d99fatagen2026-10-16 05:34 UTC312
- Shm reuse checks dimensions and format before reallocating. Internal framebuffers, read-write images and blend buffers are cached by size.
57f44a63d99fatagen2026-10-16 05:34 UTC313
- The blend buffer is `ABGR16161616F` (`src/gfx_apis/vulkan/format.rs:100`, verified). It holds linear working space, then an out pass resolves to the framebuffer.
57f44a63d99fatagen2026-10-16 05:34 UTC314
- Staging shells and dmabuf host buffers reduce mapping churn.
57f44a63d99fatagen2026-10-16 05:34 UTC315
57f44a63d99fatagen2026-10-16 05:34 UTC316
### 4.4 Synchronization
57f44a63d99fatagen2026-10-16 05:34 UTC317
57f44a63d99fatagen2026-10-16 05:34 UTC318
`FdSync` (`src/gfx_api.rs:1384`) is `SyncFile` or `Syncobj`, with async wait (`:1392`), blocking wait (`:1408`), poll (`:1434`) and external ring integration (`:1474`).
57f44a63d99fatagen2026-10-16 05:34 UTC319
57f44a63d99fatagen2026-10-16 05:34 UTC320
- The acquire path (`src/gfx_apis/vulkan/renderer.rs:2254`) dups explicit sync files (`:2303`) and exports dmabuf sync files with `DMA_BUF_SYNC_READ` for textures (`:2313`) and `DMA_BUF_SYNC_WRITE` for the framebuffer (`:2322`), plus an extra `FdSync` list (`:2329`).
57f44a63d99fatagen2026-10-16 05:34 UTC321
- The release path (`:2343`) attaches the submit fence or timeline point to buffer reservations (`:2357`) or imports into dmabufs (`:2361`), with a fallback warning relying on implicit sync.
57f44a63d99fatagen2026-10-16 05:34 UTC322
- Async SHM tracking sets `last_gfx_use` (`:2381`).
57f44a63d99fatagen2026-10-16 05:34 UTC323
- Device sync creation (`:2401`) returns a fence or timeline semaphore, and submit signals it.
57f44a63d99fatagen2026-10-16 05:34 UTC324
- Timeline opaque fd export is probed (`src/gfx_apis/vulkan/device.rs:472`) and mapped to DRM syncobj points with a two-point validation handshake in `timeline_semaphore.rs`. Binary semaphores import `SYNC_FD` in `semaphore.rs`.
57f44a63d99fatagen2026-10-16 05:34 UTC325
- Pending frame release uses the async engine and io_uring readable waits.
57f44a63d99fatagen2026-10-16 05:34 UTC326
57f44a63d99fatagen2026-10-16 05:34 UTC327
### 4.5 Memory
57f44a63d99fatagen2026-10-16 05:34 UTC328
57f44a63d99fatagen2026-10-16 05:34 UTC329
Memory uses gpu-alloc, not a custom allocator and not VMA. `Cargo.toml:55` pins `ash` as `jay-ash` 0.12.0, `:56` `gpu-alloc` 0.6.0 and `:57` `gpu-alloc-types` 0.3.0 (verified). `allocator.rs` wraps `AshMemoryDevice` in `VulkanAllocator` and `VulkanThreadedAllocator` with CpuWorker async alloc and free, and zeroed pages via `Config::i_am_prototyping`. Separate small caches exist for shader buffers, uniform buffers and descriptor buffers, plus size-keyed blend buffer and image caches.
57f44a63d99fatagen2026-10-16 05:34 UTC330
57f44a63d99fatagen2026-10-16 05:34 UTC331
### 4.6 Color management and HDR
57f44a63d99fatagen2026-10-16 05:34 UTC332
57f44a63d99fatagen2026-10-16 05:34 UTC333
Color work happens in shaders, driven by CPU-side color descriptions.
57f44a63d99fatagen2026-10-16 05:34 UTC334
57f44a63d99fatagen2026-10-16 05:34 UTC335
`tex.frag` steps in order.
57f44a63d99fatagen2026-10-16 05:34 UTC336
57f44a63d99fatagen2026-10-16 05:34 UTC337
1. Sample with `textureLod` (`src/gfx_apis/vulkan/shaders/tex.frag:18`).
57f44a63d99fatagen2026-10-16 05:34 UTC338
2. Unpremultiply electrical-premultiplied inputs (`:21`).
57f44a63d99fatagen2026-10-16 05:34 UTC339
3. Apply EOTF (`:24`) and handle optical unpremultiply.
57f44a63d99fatagen2026-10-16 05:34 UTC340
4. Apply matrix (`:29`).
57f44a63d99fatagen2026-10-16 05:34 UTC341
5. Optional grayscale with Rec 709 luma (`:31`).
57f44a63d99fatagen2026-10-16 05:34 UTC342
6. Inverse EOTF (`:35`).
57f44a63d99fatagen2026-10-16 05:34 UTC343
7. Repremultiply (`:37`).
57f44a63d99fatagen2026-10-16 05:34 UTC344
8. Alpha multiplier (`:41`).
57f44a63d99fatagen2026-10-16 05:34 UTC345
57f44a63d99fatagen2026-10-16 05:34 UTC346
`out.frag` (`src/gfx_apis/vulkan/shaders/out.frag:16`) fetches from the blend buffer and repeats EOTF, matrix and inverse EOTF (`:17`).
57f44a63d99fatagen2026-10-16 05:34 UTC347
57f44a63d99fatagen2026-10-16 05:34 UTC348
`eotfs.glsl` defines `TF_LINEAR` through `TF_COMPOUND_POWER_2_4` (`src/gfx_apis/vulkan/shaders/eotfs.glsl:7`), with PQ (`:38`), BT1886 with four args (`:20`), ST240, log, ST428, pow and compound variants, dispatched by `apply_eotf` (`:121`) and `apply_inv_eotf` (`:139`). Alpha modes (`src/gfx_apis/vulkan/shaders/alpha_modes.glsl:4`) are premultiplied electrical, premultiplied optical and straight.
57f44a63d99fatagen2026-10-16 05:34 UTC349
57f44a63d99fatagen2026-10-16 05:34 UTC350
### 4.7 copy_device.rs
57f44a63d99fatagen2026-10-16 05:34 UTC351
57f44a63d99fatagen2026-10-16 05:34 UTC352
A separate minimal Vulkan copy engine for multi-GPU movement, used by neither screencast nor the main compositor render path. `PhysicalCopyDevice` and `CopyDevice` classify `TransferType` and direction as Blit, Intra, Download or Upload. Entry points are `create_buffer` (`src/copy_device.rs:1037`, `:1342`), `create_fixed_copy` (`:1233`) and `create_copy` (`:1242`). `State` holds `render_ctx_prime_copy_device` (`src/state.rs:277`), assigned from the DRM device (`src/state.rs:2803`). Metal allocator call sites copy render to device BOs (`src/backends/metal/allocator.rs:1149`, `:1212`, `:1235`, `:1395`), including udmabuf staging (`:1507`). Prime modifier feedback reads `render_ctx_prime_modifiers` (`src/dmabuf_feedback.rs:141`).
57f44a63d99fatagen2026-10-16 05:34 UTC353
57f44a63d99fatagen2026-10-16 05:34 UTC354
### 4.8 Decorations
57f44a63d99fatagen2026-10-16 05:34 UTC355
57f44a63d99fatagen2026-10-16 05:34 UTC356
Effects stop at rounded rectangles and borders. The rounding SDF (`src/gfx_apis/vulkan/shaders/rounding.glsl:1`) returns zero outside bounds, selects corner radius and center per quadrant, and smoothsteps distance with half-pixel width (`:24`). Shader families include `fill`, `rounded_fill`, `tex` and `rounded_tex`, plus legacy variants under `src/gfx_apis/vulkan/shaders/legacy`. No blur and no shadow passes exist. `RendererBase` emits tab bars, borders and highlights as `FillRect` and `RoundedFillRect` ops.
57f44a63d99fatagen2026-10-16 05:34 UTC357
57f44a63d99fatagen2026-10-16 05:34 UTC358
### 4.9 Coupling and requirements
57f44a63d99fatagen2026-10-16 05:34 UTC359
57f44a63d99fatagen2026-10-16 05:34 UTC360
Coupling is broad outside the Vulkan directory. `vulkan.rs`, `renderer.rs`, `image.rs`, `device.rs`, `transfer.rs`, `shm_image.rs` and `pipeline.rs` import crate `backend`, `cmm`, `gfx_api`, `theme`, `utils`, `video`, `allocator`, `state`, async engine, ring and CPU worker types. The GL context (`src/gfx_apis/gl.rs:21`) shows the same pattern. A port would carry color management, dmabuf, syncobj, timeline and worker abstractions or stub them.
57f44a63d99fatagen2026-10-16 05:34 UTC361
57f44a63d99fatagen2026-10-16 05:34 UTC362
- Vulkan 1.3. `VULKAN_API_VERSION` (`src/vulkan_core.rs:356`) equals `API_VERSION_1_3` (`:15`). The loader uses `libvulkan.so.1` (`:67`, `:73`).
57f44a63d99fatagen2026-10-16 05:34 UTC363
- Required instance extensions (`src/vulkan_core.rs:268`) are `debug_utils` only.
57f44a63d99fatagen2026-10-16 05:34 UTC364
- Required device extensions (`src/gfx_apis/vulkan/device.rs:728`) include `external_memory_fd`, `external_semaphore_fd`, `external_fence_fd`, `external_memory_dma_buf`, `queue_family_foreign`, `image_drm_format_modifier` and `push_descriptor`. Optional paths add `descriptor_heap` plus `maintenance5`, or `descriptor_buffer`.
57f44a63d99fatagen2026-10-16 05:34 UTC365
- Shaders compile offline. `compile` (`compile-shaders/compile/src/main.rs:18`) maps frag and vert to shaderc kinds (`:33`) and writes SPIR-V (`:44`), with an include callback (`:27`) and hash tracking via `TREES` (`:9`).
57f44a63d99fatagen2026-10-16 05:34 UTC366
57f44a63d99fatagen2026-10-16 05:34 UTC367
### 4.10 Unusual choices
57f44a63d99fatagen2026-10-16 05:34 UTC368
57f44a63d99fatagen2026-10-16 05:34 UTC369
- Linear fp16 blend buffer with a separate resolve pass.
57f44a63d99fatagen2026-10-16 05:34 UTC370
- Device-address vertex buffers fed through push constants.
57f44a63d99fatagen2026-10-16 05:34 UTC371
- Specialization-constant-driven color pipelines.
57f44a63d99fatagen2026-10-16 05:34 UTC372
- Damage-limited staging copies, optionally on the cpu_worker thread.
57f44a63d99fatagen2026-10-16 05:34 UTC373
- Threaded gpu-alloc.
57f44a63d99fatagen2026-10-16 05:34 UTC374
- Vulkan timeline semaphore to DRM syncobj point mapping.
57f44a63d99fatagen2026-10-16 05:34 UTC375
57f44a63d99fatagen2026-10-16 05:34 UTC376
## 5. Tree, transactions, multiphase animations (jay-port branch, NOT the reference, see round2-reports.md section 6)
57f44a63d99fatagen2026-10-16 05:34 UTC377
57f44a63d99fatagen2026-10-16 05:34 UTC378
### 5.1 Commit timeline
57f44a63d99fatagen2026-10-16 05:34 UTC379
57f44a63d99fatagen2026-10-16 05:34 UTC380
Each client owns `CommitTimelines` (`src/client.rs:229`) and each `WlSurface` owns a `CommitTimeline` (`src/ifs/wl_surface.rs:778`). Shared state is in `src/ifs/wl_surface/commit_timeline.rs:62-70`, with per-surface `own_timeline`, `effective_timeline` plus waiters for fifo, commit time, restore, serial and unmap (`src/ifs/wl_surface/commit_timeline.rs:77-87`).
57f44a63d99fatagen2026-10-16 05:34 UTC381
57f44a63d99fatagen2026-10-16 05:34 UTC382
`wl_surface.commit` validates release protocols then hands `PendingState` to the timeline (`src/ifs/wl_surface.rs:1286-1316`). Sync subsurface commits do not reach the timeline. They merge into the parent pending and abort (`src/ifs/wl_surface/wl_subsurface.rs:414-427`). Sync state is `sync_requested or sync_ancestor` (`src/ifs/wl_surface/wl_subsurface.rs:255-256`). Desync flushes cached child state through the timeline (`src/ifs/wl_surface/wl_subsurface.rs:287-293`).
57f44a63d99fatagen2026-10-16 05:34 UTC383
57f44a63d99fatagen2026-10-16 05:34 UTC384
Immediate apply happens only with no dependencies, an empty queue and no fifo barrier (`src/ifs/wl_surface/commit_timeline.rs:275-282`). Otherwise an `EntryKind::Commit` is queued. Client depth is capped at 256 with a `Depth` error (`src/ifs/wl_surface/commit_timeline.rs:58-60`, `src/ifs/wl_surface/commit_timeline.rs:283-285`).
57f44a63d99fatagen2026-10-16 05:34 UTC385
57f44a63d99fatagen2026-10-16 05:34 UTC386
The collector gathers acquire points, shm uploads, dmabuf presence, prime need, acquire files, commit time and restore flags (`src/ifs/wl_surface/commit_timeline.rs:243-263`, `src/ifs/wl_surface/commit_timeline.rs:963-1005`).
57f44a63d99fatagen2026-10-16 05:34 UTC387
57f44a63d99fatagen2026-10-16 05:34 UTC388
- Explicit acquire points come from `set_acquire_point` (`src/ifs/wl_surface/wp_linux_drm_syncobj_surface_v1.rs:59-63`).
57f44a63d99fatagen2026-10-16 05:34 UTC389
- Implicit dmabuf fences are added as plane fds when neither syncobj sync nor sync-file acquire is present (`src/ifs/wl_surface/commit_timeline.rs:977-984`).
57f44a63d99fatagen2026-10-16 05:34 UTC390
- Sync-file acquire is added in `src/ifs/wl_surface/commit_timeline.rs:986-988`.
57f44a63d99fatagen2026-10-16 05:34 UTC391
- Fifo flags come from `set_barrier` and `wait_barrier` (`src/ifs/wl_surface/wp_fifo_v1.rs:43-50`).
57f44a63d99fatagen2026-10-16 05:34 UTC392
- Commit time comes from `set_timestamp` (`src/ifs/wl_surface/wp_commit_timer_v1.rs:45-61`).
57f44a63d99fatagen2026-10-16 05:34 UTC393
57f44a63d99fatagen2026-10-16 05:34 UTC394
Waits are registered without blocking the main thread. Syncobj uses `wfs.wait` (`src/ifs/wl_surface/commit_timeline.rs:321-331`). Implicit fds use `ring.readable_external` (`src/ifs/wl_surface/commit_timeline.rs:340-350`). Shm uploads, prime copies, commit time, restore, serial and unmap mark `needs_flush` (`src/ifs/wl_surface/commit_timeline.rs:333-364`). The queue head is flushed when previously empty (`src/ifs/wl_surface/commit_timeline.rs:366-368`).
57f44a63d99fatagen2026-10-16 05:34 UTC395
57f44a63d99fatagen2026-10-16 05:34 UTC396
Queues are FIFO (`src/ifs/wl_surface/commit_timeline.rs:569-579`). The head applies only when all dependencies clear (`src/ifs/wl_surface/commit_timeline.rs:582-653`). Other clients have separate `Inner` queues, so one blocked surface does not stop another client except through explicit cross-timeline links. Parent and subsurface timelines are unified through `set_effective_timeline` (`src/ifs/wl_surface/commit_timeline.rs:1008-1034`) using `Wait` and `Signal` entries (`src/ifs/wl_surface/commit_timeline.rs:529-534`). Later wakeups go through per-client `process_flush_requests` (`src/ifs/wl_surface/commit_timeline.rs:1041-1053`).
57f44a63d99fatagen2026-10-16 05:34 UTC397
57f44a63d99fatagen2026-10-16 05:34 UTC398
Completion callbacks decrement counters and retry the list. This covers syncobj (`src/ifs/wl_surface/commit_timeline.rs:430-442`), shm upload (`src/ifs/wl_surface/commit_timeline.rs:453-468`), prime copy (`src/ifs/wl_surface/commit_timeline.rs:470-485`), dmabuf poll (`src/ifs/wl_surface/commit_timeline.rs:487-501`) and commit timer timeout (`src/ifs/wl_surface/commit_timeline.rs:504-521`).
57f44a63d99fatagen2026-10-16 05:34 UTC399
57f44a63d99fatagen2026-10-16 05:34 UTC400
Fifo barrier handling parks `Queued` commits as `Registered` and stores `fifo_waiter` (`src/ifs/wl_surface/commit_timeline.rs:600-612`). Barrier release pushes the waiter (`src/ifs/wl_surface/commit_timeline.rs:376-381`). Latch clears it for normal presentation but defers to vblank under tearing (`src/ifs/wl_surface.rs:2561-2584`), with vblank cleanup in `src/ifs/wl_surface.rs:2543-2552`. Applied commits set the barrier (`src/ifs/wl_surface.rs:1664-1688`).
57f44a63d99fatagen2026-10-16 05:34 UTC401
57f44a63d99fatagen2026-10-16 05:34 UTC402
Commit timer registration subtracts render plus flip margins from the requested time (`src/ifs/wl_surface/commit_timeline.rs:702-730`). It uses `ring.timeout_external` and attaches a `before_latch_listener`, then `before_latch` releases the commit when presentation time has passed (`src/ifs/wl_surface/commit_timeline.rs:405-427`, `src/ifs/wl_surface.rs:2555-2559`).
57f44a63d99fatagen2026-10-16 05:34 UTC403
57f44a63d99fatagen2026-10-16 05:34 UTC404
Destroy versus loop breaking is split (`src/ifs/wl_surface/commit_timeline.rs:210-235`), with dependency state discarded in `src/ifs/wl_surface/commit_timeline.rs:197-208` and destroyed timelines drained through a `Gc` entry (`src/ifs/wl_surface/commit_timeline.rs:660-663`).
57f44a63d99fatagen2026-10-16 05:34 UTC405
57f44a63d99fatagen2026-10-16 05:34 UTC406
### 5.2 Layout transactions
57f44a63d99fatagen2026-10-16 05:34 UTC407
57f44a63d99fatagen2026-10-16 05:34 UTC408
Tree mutation uses `Transactionable` and `TransactionData` (`src/transactions.rs:20-38`, `src/transactions.rs:65-71`). Any op schedules the object and triggers serial groups (`src/transactions.rs:195-209`).
57f44a63d99fatagen2026-10-16 05:34 UTC409
57f44a63d99fatagen2026-10-16 05:34 UTC410
`Transactions::commit` snapshots scheduled objects, surfaces and effects, creates or recycles a `Transaction` plus `Blocker`, queues surface blockers and assigns member ops (`src/transactions.rs:216-282`). Surfaces receive `UnblockCommitsUntil` (`src/transactions.rs:230-237`). Apply runs `before_apply`, member ops, `after_apply`, then recycles the transaction (`src/transactions.rs:284-299`).
57f44a63d99fatagen2026-10-16 05:34 UTC411
57f44a63d99fatagen2026-10-16 05:34 UTC412
`Blocker` drop schedules apply exactly once by version (`src/transactions.rs:345-359`). Timeout applies the same version after a 50ms default (`src/transactions.rs:78-80`, `src/transactions.rs:441-467`). The apply loop is separate (`src/transactions.rs:469-475`).
57f44a63d99fatagen2026-10-16 05:34 UTC413
57f44a63d99fatagen2026-10-16 05:34 UTC414
Per-surface blocking is in `src/transactions.rs:116-127`. `unblock_transactions_until` drops blockers at or before the committed serial (`src/transactions.rs:374-400`). `commit_is_blocked` compares `unblocked_commit` against the needed serial (`src/transactions.rs:417-419`). Disabled means tardy or zero enable count (`src/transactions.rs:421-423`). Missing acks mark `tardy`, clear blockers and force the timeout path (`src/transactions.rs:402-415`).
57f44a63d99fatagen2026-10-16 05:34 UTC415
57f44a63d99fatagen2026-10-16 05:34 UTC416
The commit timeline and layout transaction meet in `maybe_apply` (`src/ifs/wl_surface/commit_timeline.rs:632-638`). The surface first records the serial, then parks on `serial_waiter` if still blocked. Publication calls `serial_unblocked` through `WlSurfaceTransactionOp::UnblockCommitsUntil` (`src/ifs/wl_surface.rs:2696-2702`), with waiter release in `src/ifs/wl_surface/commit_timeline.rs:393-397`.
57f44a63d99fatagen2026-10-16 05:34 UTC417
57f44a63d99fatagen2026-10-16 05:34 UTC418
Each serial group tick allocates one `TreeSerial`, commits transactions, then runs configure groups (`src/tree_serial_groups.rs:18-30`). Configures are grouped by serial (`src/configurable.rs:241-280`). `schedule_configure` also adds the surface to transactions (`src/configurable.rs:91-105`). Readiness counting releases whole groups (`src/configurable.rs:170-189`, `src/configurable.rs:336-410`). Flush sends the serial and records `requested_serial` (`src/configurable.rs:218-239`). The client ack must carry at least that serial before `ready` (`src/ifs/wl_surface.rs:1307-1312`, `src/ifs/wl_surface.rs:1370-1374`). The t0061 test asserts `LiveTL` moves first while `RenderTL` stays old until commit (`src/it/tests/t0061_transactional_layout_animation.rs:35-47`).
57f44a63d99fatagen2026-10-16 05:34 UTC419
57f44a63d99fatagen2026-10-16 05:34 UTC420
### 5.3 Tree
57f44a63d99fatagen2026-10-16 05:34 UTC421
57f44a63d99fatagen2026-10-16 05:34 UTC422
Node behavior is `NodeBase` (`src/tree.rs:445-945`) with dyn wrapper `Node` (`src/tree.rs:947-968`). Visitors are in `src/tree/walker.rs:18-86`. Timelines are `LiveTL` and `RenderTL` (`src/tree.rs:976-981`), with `SplitView` maps (`src/tree.rs:984`). Links carry per-timeline validity (`src/tree.rs:985-1008`).
57f44a63d99fatagen2026-10-16 05:34 UTC423
57f44a63d99fatagen2026-10-16 05:34 UTC424
Layers are ordered `Display` through `OverlayStacked` (`src/tree.rs:343-365`), with linked variants in `src/tree.rs:367-385`. Concrete types include `DisplayNode` (`src/tree/display.rs:47`), `OutputNode` (`src/tree/output.rs:131`), `WorkspaceNode` (`src/tree/workspace.rs:76-98`), containers, floats, toplevels and placeholders. Parents implement `ContainingNode` (`src/tree/containing.rs:7-59`). Toplevel behavior splits into `ToplevelNodeBase` (`src/tree/toplevel.rs:366`) and `ToplevelNode` (`src/tree/toplevel.rs:81-101`).
57f44a63d99fatagen2026-10-16 05:34 UTC425
57f44a63d99fatagen2026-10-16 05:34 UTC426
Rendering walks the same hierarchy through `node_render` and `node_visit_children`. Examples are output (`src/tree/output.rs:2477`), container (`src/tree/container.rs:2953`), workspace (`src/tree/workspace.rs:559`), float (`src/tree/float.rs:972`), display (`src/tree/display.rs:285`) and placeholder (`src/tree/placeholder.rs:229`). The renderer starts from outputs and workspaces, then stacked layers and exit frames (`src/renderer.rs:250-303`).
57f44a63d99fatagen2026-10-16 05:34 UTC427
57f44a63d99fatagen2026-10-16 05:34 UTC428
### 5.4 Multiphase animations
57f44a63d99fatagen2026-10-16 05:34 UTC429
57f44a63d99fatagen2026-10-16 05:34 UTC430
A phase is a `MultiphasePhase` with one action plus steps (`src/presentation/multiphase.rs:204-209`). Each step is classified as horizontal or vertical move or scale (`src/presentation/multiphase.rs:1486-1509`). Diagonal or size-plus-position changes cannot be one phase and force multiphase plans.
57f44a63d99fatagen2026-10-16 05:34 UTC431
57f44a63d99fatagen2026-10-16 05:34 UTC432
The planning entry is `plan_no_overlap` (`src/presentation/multiphase.rs:354-356`), with forward then reversed attempts (`src/presentation/multiphase.rs:364-412`). Strategies include `SingleAction`, `SpaceThenOrthogonalGrowth`, `HierarchyOrderedScales`, `OrientationChange`, `SwapLanes` and reversed plans (`src/presentation/multiphase.rs:159-168`), tried in that order (`src/presentation/multiphase.rs:535-616`). Independent motion groups split first (`src/presentation/multiphase.rs:460-488`).
57f44a63d99fatagen2026-10-16 05:34 UTC433
57f44a63d99fatagen2026-10-16 05:34 UTC434
Validation checks chaining, duplicates, action counts, unknown nodes, stale starts, intra-phase overlap and final rects (`src/presentation/multiphase.rs:1280-1368`). Overlap uses linear edge deltas with rational time intervals (`src/presentation/multiphase.rs:1370-1484`).
57f44a63d99fatagen2026-10-16 05:34 UTC435
57f44a63d99fatagen2026-10-16 05:34 UTC436
Runtime animations store multiple `from to` segments (`src/presentation/layout_animation.rs:160-168`). Total time is duration times phase count (`src/presentation/layout_animation.rs:1292-1296`). Position interpolates within the current phase with the configured curve (`src/presentation/layout_animation.rs:1309-1319`). Interrupts retarget from the current `rect_at` (`src/presentation/layout_animation.rs:846-892`, `src/presentation/layout_animation.rs:894-952`, `src/presentation/layout_animation.rs:1112-1129`). Path validation for reversed interrupts is in `src/presentation/multiphase.rs:414-458`. Appearing windows can wait behind existing phases (`src/presentation/layout_animation.rs:976-1018`).
57f44a63d99fatagen2026-10-16 05:34 UTC437
57f44a63d99fatagen2026-10-16 05:34 UTC438
Ticks are per-output `LatchListener`s (`src/presentation/layout_animation.rs:257-260`, `src/presentation/layout_animation.rs:1945-1960`). Each latch damages active rects and stops when idle (`src/presentation/layout_animation.rs:1218-1248`). Ticks attach to `output.latch_event` (`src/presentation/layout_animation.rs:1250-1269`) and detach in `src/presentation/layout_animation.rs:1271-1289`. The test asserts latch drives damage and that output disconnect or reconnect changes tick count (`src/it/tests/t0061_transactional_layout_animation.rs:69-90`).
57f44a63d99fatagen2026-10-16 05:34 UTC439
57f44a63d99fatagen2026-10-16 05:34 UTC440
Animations are transaction effects. The trait observes pre and post trees without mutating live state (`src/transactions.rs:45-58`). Scheduling adds effects (`src/presentation/layout_animation.rs:561-738`). Single moves capture the before rect plus current visual (`src/presentation/layout_animation.rs:1472-1514`). Batches capture whole container snapshots before and after (`src/presentation/layout_animation.rs:1596-1664`), with coalescing per container (`src/presentation/layout_animation.rs:1666-1671`). Direct manipulation first cancels animations then suppresses new ones for that transaction (`src/presentation/layout_animation.rs:527-559`, `src/presentation/layout_animation.rs:1516-1522`). The test asserts no animation before publication and a multiphase spawn after (`src/it/tests/t0061_transactional_layout_animation.rs:92-127`), plus no animation for direct manipulation (`src/it/tests/t0061_transactional_layout_animation.rs:129-146`).
57f44a63d99fatagen2026-10-16 05:34 UTC441
57f44a63d99fatagen2026-10-16 05:34 UTC442
Old pixels use retained captures. `RetainedToplevel`, `RetainedSurface` and `RetainedContent` hold textures or colors plus subsurface offsets (`src/presentation/layout_animation.rs:107-153`). Capture clones live buffers and subsurface structure (`src/presentation/layout_animation.rs:1355-1469`). Exits expose timed frames (`src/presentation/layout_animation.rs:766-778`). Spawns expose retained frames while resizing (`src/presentation/layout_animation.rs:780-794`). Close while blocked produces no exit until timeout publication (`src/it/tests/t0061_transactional_layout_animation.rs:151-174`). Closing mid-animation hands the presented rect to the exit (`src/it/tests/t0061_transactional_layout_animation.rs:176-201`).
57f44a63d99fatagen2026-10-16 05:34 UTC443
57f44a63d99fatagen2026-10-16 05:34 UTC444
### 5.5 layout_animation computation and render plug-in
57f44a63d99fatagen2026-10-16 05:34 UTC445
57f44a63d99fatagen2026-10-16 05:34 UTC446
It computes curve samples, spawn endpoints, roll edges, batch plans, per-node visual rects, damage and retained frames. Curves include linear and flattened cubic bezier (`src/presentation/layout_animation.rs:281-323`, `src/presentation/layout_animation.rs:326-411`). Spawn endpoints cover grow, fly and roll (`src/presentation/layout_animation.rs:413-450`), with edge helpers in `src/presentation/layout_animation.rs:452-519`. Batch planning filters to moving windows, partitions groups, then plans or falls back to direct interpolation (`src/presentation/layout_animation.rs:954-1110`).
57f44a63d99fatagen2026-10-16 05:34 UTC447
57f44a63d99fatagen2026-10-16 05:34 UTC448
Render integration reads `visual_rect` for fullscreen, container children and mono bodies (`src/renderer.rs:311-330`, `src/renderer.rs:470-505`, `src/renderer.rs:571-589`). Exit frames render above tiled or floating stacks (`src/renderer.rs:256-274`, `src/renderer.rs:737-765`). Spawns render retained content scaled from source to target size (`src/renderer.rs:767-820`, `src/renderer.rs:822-860`). Client damage follows the presented window through `visual_damage` (`src/ifs/wl_surface.rs:1735-1752`, `src/presentation/layout_animation.rs:747-764`).
57f44a63d99fatagen2026-10-16 05:34 UTC449
57f44a63d99fatagen2026-10-16 05:34 UTC450
### 5.6 Tree verify
57f44a63d99fatagen2026-10-16 05:34 UTC451
57f44a63d99fatagen2026-10-16 05:34 UTC452
`verify_tree_invariants` checks both timelines (`src/tree/verify.rs:14-22`) and runs after idle in integration tests (`src/it/testrun.rs:198-201`). It checks output identity and dummy status, active workspace membership, workspace-to-output links, toplevel parent and workspace pointers, float workspace and display stack membership, fullscreen uniqueness and placeholder linkage, scratchpad mapping and container snapshots (`src/tree/verify.rs:72-108` and following).
57f44a63d99fatagen2026-10-16 05:34 UTC453
57f44a63d99fatagen2026-10-16 05:34 UTC454
Container checks include nonempty children, cached counts, child map identity, finite nonnegative factors, factor sum tolerance, focus history and backlinks, mono child placement, no pending layout and non-mono overlap (`src/tree/verify.rs:671-853`).
57f44a63d99fatagen2026-10-16 05:34 UTC455
57f44a63d99fatagen2026-10-16 05:34 UTC456
### 5.7 Unusual choices
57f44a63d99fatagen2026-10-16 05:34 UTC457
57f44a63d99fatagen2026-10-16 05:34 UTC458
- Per-client commit queues plus per-surface timelines with explicit cross-timeline signals.
57f44a63d99fatagen2026-10-16 05:34 UTC459
- Shm upload, prime copy, dmabuf poll, fifo, commit time, restore, serial and unmap are treated uniformly as queue blockers.
57f44a63d99fatagen2026-10-16 05:34 UTC460
- The tardy path that discards blockers and relies on timeout is pragmatic.
57f44a63d99fatagen2026-10-16 05:34 UTC461
- A collision-free geometric planner with exact rational overlap checks drives window animation.
57f44a63d99fatagen2026-10-16 05:34 UTC462
- Retained textures render scaled from old source size to animated target size while clients resize.
57f44a63d99fatagen2026-10-16 05:34 UTC463
57f44a63d99fatagen2026-10-16 05:34 UTC464
## 6. Process model, config, tests, utilities
57f44a63d99fatagen2026-10-16 05:34 UTC465
57f44a63d99fatagen2026-10-16 05:34 UTC466
### 6.1 Startup
57f44a63d99fatagen2026-10-16 05:34 UTC467
57f44a63d99fatagen2026-10-16 05:34 UTC468
- `main()` only calls `cli::main()` (`src/main.rs:138-140`). CLI parsing decides run vs control commands (`src/cli.rs:312-356`).
57f44a63d99fatagen2026-10-16 05:34 UTC469
- Non-`run` commands drop all process capabilities immediately (`src/cli.rs:320-322`).
57f44a63d99fatagen2026-10-16 05:34 UTC470
- `Cmd::Run` calls `start_compositor` (`src/cli.rs:327`). It resets signal handlers (`src/compositor.rs:162-164`), makes the process a child subreaper or re-execs under one (`src/compositor.rs:164`, `src/utils/clone3.rs:87-115`), snapshots capabilities (`src/compositor.rs:165`), and keeps only `CAP_SYS_NICE` for the compositor (`src/pr_caps.rs:83-115`).
57f44a63d99fatagen2026-10-16 05:34 UTC471
- If `CAP_SYS_NICE` survived, it elevates the scheduler and moves the privileged capability onto a dedicated helper thread (`src/compositor.rs:166-172`, `src/pr_caps.rs:122-147`). The reaper child also drops caps (`src/utils/clone3.rs:116`).
57f44a63d99fatagen2026-10-16 05:34 UTC472
- The forker is created next (`src/compositor.rs:173-174`), before logging, io_uring, threads, portal, or graphics. Later startup creates threads and io_uring state that must not be forked.
57f44a63d99fatagen2026-10-16 05:34 UTC473
- Startup then spawns the portal helper, sleeper, profiler, and logger (`src/compositor.rs:174-184`), then builds the full `State` in `start_compositor2` (`src/compositor.rs:253-536`).
57f44a63d99fatagen2026-10-16 05:34 UTC474
- `start_compositor2` installs the Wayland acceptor, IPC acceptor, forker environment, portal task, and compositor task, then runs io_uring (`src/compositor.rs:495-535`).
57f44a63d99fatagen2026-10-16 05:34 UTC475
- The forker child sanitizes its environment by forcing `XDG_SESSION_TYPE=wayland` and removing `DISPLAY`/`WAYLAND_DISPLAY` (`src/forker.rs:343-348`), renames itself (`src/forker.rs:349`), takes `SIGKILL` on parent death (`src/forker.rs:350`, `src/forker.rs:584-592`), ignores `SIGCHLD` (`src/forker.rs:351-353`), and collapses its fds so only the control socket survives (`src/forker.rs:569-582`).
57f44a63d99fatagen2026-10-16 05:34 UTC476
- `start_compositor3` selects a backend, publishes sockets, loads config, creates the default seat, starts global handlers and Xwayland, then runs the backend (`src/compositor.rs:538-588`).
57f44a63d99fatagen2026-10-16 05:34 UTC477
- Backend order defaults to X11 then Metal (`src/compositor.rs:755-758`). Config is loaded after graphics/backend selection but before seats and Xwayland (`src/compositor.rs:565-581`).
57f44a63d99fatagen2026-10-16 05:34 UTC478
- `RLIMIT_NOFILE` is raised to the hard limit by default (`src/compositor.rs:797-814`).
57f44a63d99fatagen2026-10-16 05:34 UTC479
57f44a63d99fatagen2026-10-16 05:34 UTC480
### 6.2 Forker
57f44a63d99fatagen2026-10-16 05:34 UTC481
57f44a63d99fatagen2026-10-16 05:34 UTC482
- `ForkerProxy::create` makes a control socketpair and calls `double_fork` (`src/forker.rs:99-119`). The parent gets a pidfd and the child enters `Forker::handle` (`src/forker.rs:114-118`).
57f44a63d99fatagen2026-10-16 05:34 UTC483
- `double_fork` uses pidfd-carrying socketpairs so both stages reliably learn child pidfds (`src/utils/clone3.rs:24-48`, `src/utils/clone3.rs:50-85`).
57f44a63d99fatagen2026-10-16 05:34 UTC484
- The compositor never calls `fork`/`exec` directly for clients. It queues `ServerMessage::Spawn` plus separately passed fds (`src/forker.rs:206-225`, `src/forker.rs:276-290`). The forker re-forks, remaps fds with collision handling, applies env deltas, and execs (`src/forker.rs:449-546`, `src/forker.rs:594-616`).
57f44a63d99fatagen2026-10-16 05:34 UTC485
- It is forked early because only an early, single-threaded, pre-graphics process can safely `fork` again later. It also owns the child environment via `SetEnv` (`src/forker.rs:139-151`, `src/forker.rs:423-431`) and reports exec failures and pidfds back (`src/forker.rs:473-503`, `src/forker.rs:548-556`).
57f44a63d99fatagen2026-10-16 05:34 UTC486
- Xwayland is one special spawn with fixed fds stderr=2, displayfd=3, listenfd=4, wm=5, wayland=6 (`src/forker.rs:170-194`).
57f44a63d99fatagen2026-10-16 05:34 UTC487
57f44a63d99fatagen2026-10-16 05:34 UTC488
### 6.3 Config
57f44a63d99fatagen2026-10-16 05:34 UTC489
57f44a63d99fatagen2026-10-16 05:34 UTC490
- Current config is in-process and typed. `ConfigProxy::default` wires the compositor handler directly to `wry_toml_config::configure` through `wry_config::_private::client::init` (`src/config.rs:255-259`).
57f44a63d99fatagen2026-10-16 05:34 UTC491
- `init` takes a `Weak<dyn ConfigServerEndpoint>`, an `InitMessage`, and a configure function pointer (`wry-config/src/_private/client.rs:242-246`).
57f44a63d99fatagen2026-10-16 05:34 UTC492
- Traffic consists of cloned Rust enums such as `ServerMessage`, `ClientMessage`, and `Response` (`wry-config/src/_private/ipc.rs:84-150`, `src/config/handler.rs:101-117`). `ConfigProxyHandler::send` calls `client.handle(msg.clone())` with no serialization (`src/config/handler.rs:324-328`).
57f44a63d99fatagen2026-10-16 05:34 UTC493
- No `dlopen`/`libloading`/`config.so` loading remains in `src/config/handler.rs`. The public docs still describe a `cdylib` plus `config!` workflow (`wry-config/src/lib.rs:19-33`), but `wry-config/src/macros.rs:1-28` now only defines `try_get!`/`get!`, so that documentation looks stale.
57f44a63d99fatagen2026-10-16 05:34 UTC494
- The high-level `wry-config` API exposes seats, windows, workspaces, video/connectors, input, keyboard, theme, timers, tasks, exec, logging, and lifecycle calls (`wry-config/src/lib.rs:61-79`, `wry-config/src/lib.rs:107-122`).
57f44a63d99fatagen2026-10-16 05:34 UTC495
- `reload()` calls into the ambient config client (`wry-config/src/lib.rs:117-122`), becomes `ClientMessage::Reload` (`src/config/handler.rs:3714`), invokes `state.reload_config()` (`src/config/handler.rs:523-525`), and reissues `configure(true)` (`src/state.rs:2497-2502`).
57f44a63d99fatagen2026-10-16 05:34 UTC496
- Every configure sends feature negotiation then `Configure { reload }` (`src/config.rs:240-253`).
57f44a63d99fatagen2026-10-16 05:34 UTC497
- The TOML implementation preserves a `PersistentState` across reloads and clears ephemeral actions/rules/triggers/counters on unload (`toml-config/src/lib.rs:2118-2145`).
57f44a63d99fatagen2026-10-16 05:34 UTC498
- Unload clears timers, pollables, and client/window matchers (`src/config/handler.rs:307-322`), while `ConfigProxy::destroy` drops the client endpoint (`src/config.rs:48-52`) and `Clear` is available as an explicit message (`src/config.rs:128-130`).
57f44a63d99fatagen2026-10-16 05:34 UTC499
- There is a versioned `VERSION = 1` and feature list (`wry-config/src/_private.rs:21-29`, `wry-config/src/_private/ipc.rs:69-82`).
57f44a63d99fatagen2026-10-16 05:34 UTC500
57f44a63d99fatagen2026-10-16 05:34 UTC501
### 6.4 Xwayland
57f44a63d99fatagen2026-10-16 05:34 UTC502
57f44a63d99fatagen2026-10-16 05:34 UTC503
- Xwayland is started lazily. The manager allocates and listens on an X socket, exports `DISPLAY`, then waits for a readable connection attempt before launching Xwayland (`src/xwayland.rs:106-133`).
57f44a63d99fatagen2026-10-16 05:34 UTC504
- Launch uses fixed args including `-terminate`, `-rootless`, `-displayfd 3`, `-listenfd 4`, `-wm 5`, plus optional `-enable-ei-portal` after probing `Xwayland -help` (`src/xwayland.rs:231-282`).
57f44a63d99fatagen2026-10-16 05:34 UTC505
- The compositor creates a privileged Wayland client for the Xwayland process itself (`src/xwayland.rs:188-203`), waits for the displayfd signal (`src/xwayland.rs:205`), constructs the WM asynchronously (`src/xwayland.rs:214-219`), and supervises its pidfd (`src/xwayland.rs:220-225`).
57f44a63d99fatagen2026-10-16 05:34 UTC506
- Window management lives in `src/xwayland/xwm.rs:1-60` and speaks X11 through the local `xcon` parser/formatter and generated `wire_xcon` bindings (`src/xcon/parser.rs`, `src/xcon/formatter.rs`, `src/xcon/consts.rs`, `src/xwayland/xwm.rs:54-60`).
57f44a63d99fatagen2026-10-16 05:34 UTC507
- Compositor-level Xwayland supervision is one async task installed once (`src/state.rs:1630-1638`), and stopping only clears the task when the server is not running (`src/state.rs:1640-1645`).
57f44a63d99fatagen2026-10-16 05:34 UTC508
57f44a63d99fatagen2026-10-16 05:34 UTC509
### 6.5 Integration tests
57f44a63d99fatagen2026-10-16 05:34 UTC510
57f44a63d99fatagen2026-10-16 05:34 UTC511
- Tests are in-process and feature-gated (`src/compositor.rs:205-218`, `src/cli.rs:145-151`, `src/cli.rs:350-351`).
57f44a63d99fatagen2026-10-16 05:34 UTC512
- Each test boots a fresh compositor with `TestBackend` via `start_compositor_for_test` (`src/it.rs:124-186`, `src/compositor.rs:747-754`).
57f44a63d99fatagen2026-10-16 05:34 UTC513
- `TestBackend` provides an 800x600 virtual connector, keyboard, mouse, and test graphics context (`src/it/test_backend.rs:97-120`).
57f44a63d99fatagen2026-10-16 05:34 UTC514
- Virtual clients connect over a real Unix socket to the test acceptor and speak Wayland through `TestTransport` (`src/it/testrun.rs:53-107`, `src/it/test_transport.rs:35-80`).
57f44a63d99fatagen2026-10-16 05:34 UTC515
- Config is replaced by a thread-local `TestConfig` implementing the same typed config endpoint (`src/it/test_config.rs:34-113`, `src/config.rs:261-264`).
57f44a63d99fatagen2026-10-16 05:34 UTC516
- Test mode zeroes configure/transaction timeouts (`src/compositor.rs:575-578`). Each test runs as a `Phase::Present` future with a watchdog timeout (`src/it.rs:156-172`).
57f44a63d99fatagen2026-10-16 05:34 UTC517
- Tests run in parallel across worker threads, one isolated runtime dir per process (`src/it.rs:46-52`, `src/it.rs:77-103`).
57f44a63d99fatagen2026-10-16 05:34 UTC518
- There are about 73 `src/it/tests/t*.rs` cases, plus protocol-object helpers under `src/it/test_ifs/` and utilities under `src/it/test_utils/`.
57f44a63d99fatagen2026-10-16 05:34 UTC519
- Assertions cover tree geometry and focus (`src/it/tests/t0002_window.rs:9-28`), protocol behavior, session-manager state, and golden pixels. The scaled-render test renders through the real screenshot path and byte-compares QOI output (`src/it/tests/t0071_scaled_render.rs:22-60`).
57f44a63d99fatagen2026-10-16 05:34 UTC520
57f44a63d99fatagen2026-10-16 05:34 UTC521
### 6.6 `sm`
57f44a63d99fatagen2026-10-16 05:34 UTC522
57f44a63d99fatagen2026-10-16 05:34 UTC523
- `sm` is a SQLite-backed Wayland session manager (`src/sm.rs:1-56`, `src/compositor.rs:287-292`).
57f44a63d99fatagen2026-10-16 05:34 UTC524
- It models sessions, named toplevel sessions, owners, and asynchronous acquire/rename/update/disown jobs (`src/sm.rs:66-144`, `src/sm.rs:209-228`, `src/sm.rs:359-384`).
57f44a63d99fatagen2026-10-16 05:34 UTC525
- Toplevel state tracks output, workspace, floating rectangle, and fullscreen (`src/sm.rs:178-186`, `src/sm.rs:484-539`).
57f44a63d99fatagen2026-10-16 05:34 UTC526
- Persistence work is scheduled as SQLite jobs and flushed by a background task (`src/sm.rs:464-475`, `src/sm.rs:681-705`).
57f44a63d99fatagen2026-10-16 05:34 UTC527
57f44a63d99fatagen2026-10-16 05:34 UTC528
### 6.7 Keyboard and input
57f44a63d99fatagen2026-10-16 05:34 UTC529
57f44a63d99fatagen2026-10-16 05:34 UTC530
- `kbvm` is an external crates.io dependency, version 0.1.7 with `compose` (`Cargo.toml:64`).
57f44a63d99fatagen2026-10-16 05:34 UTC531
- It supplies the XKB context, RMLVO/keymap compilation, state machine, and lookup tables (`src/kbvm.rs:42-72`, `src/kbvm.rs:105-164`, `src/kbvm.rs:289-323`).
57f44a63d99fatagen2026-10-16 05:34 UTC532
- Keymaps are sealed memfds, with a separate Xwayland-compatible rendering (`src/kbvm.rs:210-231`).
57f44a63d99fatagen2026-10-16 05:34 UTC533
- `libinput` is used through unsafe FFI, with no evdev reimplementation. The code binds `libinput_path_create_context`, dispatch, event, fd, logging, and ref functions (`src/libinput.rs:15-26`), supplies restricted open/close callbacks (`src/libinput.rs:39-63`), forwards libinput logs (`src/libinput.rs:176-195`), and unrefs on drop (`src/libinput.rs:168-174`).
57f44a63d99fatagen2026-10-16 05:34 UTC534
- Local `evdev` code is only a small `EVIOCGBIT` key-capability helper (`src/evdev.rs:1-34`).
57f44a63d99fatagen2026-10-16 05:34 UTC535
57f44a63d99fatagen2026-10-16 05:34 UTC536
### 6.8 Homegrown utilities
57f44a63d99fatagen2026-10-16 05:34 UTC537
57f44a63d99fatagen2026-10-16 05:34 UTC538
- `CloneCell` (`src/utils/clonecell.rs:9-55`). `UnsafeCell` cell for cheaply cloneable `Rc`/handle types in single-threaded code.
57f44a63d99fatagen2026-10-16 05:34 UTC539
- `CopyHashMap` (`src/utils/copyhashmap.rs:21-56`). Interior-mutable hashbrown map with access counting and lockable hasher behavior.
57f44a63d99fatagen2026-10-16 05:34 UTC540
- `NumCell` (`src/utils/numcell.rs:9-30`). `Cell` numeric wrapper with fetch-add/sub and bit operations.
57f44a63d99fatagen2026-10-16 05:34 UTC541
- `AsyncQueue` (`src/utils/queue.rs:16-54`). Single-consumer async FIFO with waker support.
57f44a63d99fatagen2026-10-16 05:34 UTC542
- `SyncQueue` (`src/utils/syncqueue.rs:10-37`). Non-async interior-mutable deque.
57f44a63d99fatagen2026-10-16 05:34 UTC543
- `Stack`/`AsyncStack` (`src/utils/stack.rs:15-48`, `src/utils/stack.rs:72-99`). Interior-mutable `Vec` stacks, optionally awaitable for nonemptiness.
57f44a63d99fatagen2026-10-16 05:34 UTC544
- `SmallMap` (`src/utils/smallmap.rs:11-58`). Small inline map with interior mutability.
57f44a63d99fatagen2026-10-16 05:34 UTC545
- `LinkedList` (`src/utils/linkedlist.rs:13-60`). Intrusive-style doubly linked list with manual refcounts.
57f44a63d99fatagen2026-10-16 05:34 UTC546
- `VecSet` (`src/utils/vecset.rs:4-41`). Small vector-backed set used for pressed keys and similar sets.
57f44a63d99fatagen2026-10-16 05:34 UTC547
- `RefCounted` (`src/utils/refcounted.rs:8-40`). Manual refcount table with version bumping.
57f44a63d99fatagen2026-10-16 05:34 UTC548
- `AsyncEvent` (`src/utils/asyncevent.rs:11-42`). Counting one-shot async trigger.
57f44a63d99fatagen2026-10-16 05:34 UTC549
- `rc_eq`/`RcEq` (`src/utils/rc_eq.rs:5-45`). Pointer-identity equality for `Rc`.
57f44a63d99fatagen2026-10-16 05:34 UTC550
- `ErrorFmt` (`src/utils/errorfmt.rs:5-22`). Formats chained `Error::source` output.
57f44a63d99fatagen2026-10-16 05:34 UTC551
- `oserror` (`src/utils/oserror.rs:9-60`). Raw errno wrapper plus generated constructors/messages.
57f44a63d99fatagen2026-10-16 05:34 UTC552
- `clone3` helpers (`src/utils/clone3.rs:24-85`). pidfd-aware fork/double-fork, reaper setup, and child supervision.
57f44a63d99fatagen2026-10-16 05:34 UTC553
- The workspace also contains its own TOML parser, PHF maps, and wire-format codegen crates (`Cargo.toml:16`, `toml-config/src/toml/`, `toml-config/src/phf.rs`).
57f44a63d99fatagen2026-10-16 05:34 UTC554
57f44a63d99fatagen2026-10-16 05:34 UTC555
### 6.9 Tracy
57f44a63d99fatagen2026-10-16 05:34 UTC556
57f44a63d99fatagen2026-10-16 05:34 UTC557
- Profiling is behind the `tracy` Cargo feature (`Cargo.toml:105`).
57f44a63d99fatagen2026-10-16 05:34 UTC558
- Without it, zone/frame macros compile to no-ops (`src/tracy.rs:1-16`, `src/tracy/tracy_noop.rs:21-51`).
57f44a63d99fatagen2026-10-16 05:34 UTC559
- With it, zone names are cached in a global map and emitted through `tracy-client-sys` begin/end calls (`src/tracy/tracy_impl.rs:30-80`).
57f44a63d99fatagen2026-10-16 05:34 UTC560
- The profiler is enabled during normal startup (`src/compositor.rs:176`).
57f44a63d99fatagen2026-10-16 05:34 UTC561
57f44a63d99fatagen2026-10-16 05:34 UTC562
### 6.10 Unusual choices
57f44a63d99fatagen2026-10-16 05:34 UTC563
57f44a63d99fatagen2026-10-16 05:34 UTC564
- Nearly everything is single-threaded `Rc` plus `UnsafeCell` interior mutability, with threads isolated to CPU work, SQLite, `CAP_SYS_NICE`, and test runners.
57f44a63d99fatagen2026-10-16 05:34 UTC565
- Spawning is centralized in a pre-thread double-forked helper that passes fds over a socket and remaps colliding targets.
57f44a63d99fatagen2026-10-16 05:34 UTC566
- Config, tests, and production share the same typed config traits rather than separate serialization boundaries.
57f44a63d99fatagen2026-10-16 05:34 UTC567
- The repo vendors protocol-adjacent machinery including X11 wire parsing, Wayland buffer handling, TOML parsing, PHF maps, and XML/wire codegen.
57f44a63d99fatagen2026-10-16 05:34 UTC568
- SQLite is a core runtime dependency for session state, not merely diagnostics.
57f44a63d99fatagen2026-10-16 05:34 UTC569
57f44a63d99fatagen2026-10-16 05:34 UTC570
## 7. Smithay extension points
57f44a63d99fatagen2026-10-16 05:34 UTC571
57f44a63d99fatagen2026-10-16 05:34 UTC572
Paths in this section are relative to shallow clones of smithay (`023b78b`, 2026-10-15) and calloop (0.14.5), prefixed `smithay/` and `calloop/`.
57f44a63d99fatagen2026-10-16 05:34 UTC573
57f44a63d99fatagen2026-10-16 05:34 UTC574
### 7.1 Event loop
57f44a63d99fatagen2026-10-16 05:34 UTC575
57f44a63d99fatagen2026-10-16 05:34 UTC576
calloop 0.14.5 uses the `polling` 3.0.0 crate rather than direct epoll calls (`calloop/Cargo.toml:26`). `Poll` holds an `Arc<Poller>` (`calloop/src/sys.rs:174`) built with `Poller::new()` (`calloop/src/sys.rs:207`). Docs describe it as OS-provided polling with epoll on Linux (`calloop/src/lib.rs:99`). No `io_uring` string appears in calloop or smithay.
57f44a63d99fatagen2026-10-16 05:34 UTC577
57f44a63d99fatagen2026-10-16 05:34 UTC578
The futures executor is optional behind the `executor` feature (`calloop/Cargo.toml:41`). It is implemented as `Executor<T>` plus `Scheduler<T>` (`calloop/src/sources/futures.rs:45`), built on `async-task` runnables woken through a `PingSource`. The module docs state futures need their own wakeup means and point at `LoopHandle::adapt_io` (`calloop/src/sources/futures.rs:17`).
57f44a63d99fatagen2026-10-16 05:34 UTC579
57f44a63d99fatagen2026-10-16 05:34 UTC580
smithay does not hard-require calloop for `wayland-server::Display`. Anvil drives clients by wrapping the display in a generic fd source with `Generic::new(display, Interest::READ, Mode::Level)` then calling `dispatch_clients` and `flush_clients` (`smithay/anvil/src/state.rs:682`, `smithay/anvil/src/udev.rs:544`). The listening socket helper is itself an `EventSource` (`smithay/src/wayland/socket.rs:95`), and other helpers merely provide `EventSource` impls.
57f44a63d99fatagen2026-10-16 05:34 UTC581
57f44a63d99fatagen2026-10-16 05:34 UTC582
- `DmabufSource` (`smithay/src/backend/allocator/dmabuf.rs:631`)
57f44a63d99fatagen2026-10-16 05:34 UTC583
- `DrmDeviceNotifier` (`smithay/src/backend/drm/device/mod.rs:525`)
57f44a63d99fatagen2026-10-16 05:34 UTC584
- `UdevBackend` (`smithay/src/backend/udev.rs:130`)
57f44a63d99fatagen2026-10-16 05:34 UTC585
- `LibinputInputBackend` (`smithay/src/backend/libinput/mod.rs:707`)
57f44a63d99fatagen2026-10-16 05:34 UTC586
- `X11Backend` (`smithay/src/backend/x11/mod.rs:561`)
57f44a63d99fatagen2026-10-16 05:34 UTC587
- `WinitEventLoop` (`smithay/src/backend/winit/mod.rs:789`)
57f44a63d99fatagen2026-10-16 05:34 UTC588
- `DrmSyncPointSource` (`smithay/src/wayland/drm_syncobj/sync_point.rs:286`)
57f44a63d99fatagen2026-10-16 05:34 UTC589
- `SecurityContextListenerSource` (`smithay/src/wayland/security_context/listener_source.rs:36`)
57f44a63d99fatagen2026-10-16 05:34 UTC590
- `XWayland` (`smithay/src/xwayland/xserver.rs:279`)
57f44a63d99fatagen2026-10-16 05:34 UTC591
- `EiInput` (`smithay/src/backend/libei/mod.rs:163`)
57f44a63d99fatagen2026-10-16 05:34 UTC592
57f44a63d99fatagen2026-10-16 05:34 UTC593
A compositor could poll the display fd from another loop and call `dispatch_clients` plus `flush_clients` itself, at the cost of those ready-made sources and the `LoopHandle` insertion helpers used across backends and xwayland.
57f44a63d99fatagen2026-10-16 05:34 UTC594
57f44a63d99fatagen2026-10-16 05:34 UTC595
### 7.2 Wayland server
57f44a63d99fatagen2026-10-16 05:34 UTC596
57f44a63d99fatagen2026-10-16 05:34 UTC597
smithay uses `wayland-server` 0.31.13 and `wayland-backend` 0.3.15 as optional deps enabled by `wayland_frontend` (`smithay/Cargo.toml:64`, `smithay/Cargo.toml:66`, `smithay/Cargo.toml:115`). The default is the pure Rust backend. The libwayland system backend is only selected by `use_system_lib` through `wayland-backend/server_system` plus `wayland-sys` (`smithay/Cargo.toml:113`). That feature also gates `gbm?/import-wayland` and the `ImportEgl` path.
57f44a63d99fatagen2026-10-16 05:34 UTC598
57f44a63d99fatagen2026-10-16 05:34 UTC599
Dispatch uses `wayland-server` `Dispatch` and `GlobalDispatch`, but smithay modules expose the simpler `Dispatch2` and `GlobalDispatch2` (`smithay/src/wayland/dispatch2.rs:6`, `smithay/src/wayland/dispatch2.rs:25`), with a `delegate_dispatch2` macro (`smithay/src/wayland/dispatch2.rs:45`) that blanket-implements the upstream traits. Each protocol module documents `*State` plus `*Handler` plus `delegate_dispatch2`, for example compositor (`smithay/src/wayland/compositor/mod.rs:63`).
57f44a63d99fatagen2026-10-16 05:34 UTC600
57f44a63d99fatagen2026-10-16 05:34 UTC601
### 7.3 Renderer abstraction
57f44a63d99fatagen2026-10-16 05:34 UTC602
57f44a63d99fatagen2026-10-16 05:34 UTC603
Core traits live in `smithay/src/backend/renderer/mod.rs`.
57f44a63d99fatagen2026-10-16 05:34 UTC604
57f44a63d99fatagen2026-10-16 05:34 UTC605
- `Bind` (`:216`) has `bind` and `supported_formats`.
57f44a63d99fatagen2026-10-16 05:34 UTC606
- `Texture` (`:233`) has `size`, `width`, `height` and `format`.
57f44a63d99fatagen2026-10-16 05:34 UTC607
- `Frame` (`:270`) has `context_id`, `clear`, `draw_solid`, `render_texture_at`, `render_texture_from_to`, `transformation`, `output_size`, `wait` and `finish`.
57f44a63d99fatagen2026-10-16 05:34 UTC608
- `Renderer` plus `RendererSuper` (`:385`, `:402`) have `context_id`, `downscale_filter`, `upscale_filter`, `set_debug_flags`, `debug_flags`, `render`, `wait`, `cleanup_texture_cache` and `invalidate_caches`.
57f44a63d99fatagen2026-10-16 05:34 UTC609
- `Offscreen::create_buffer` (`:467`).
57f44a63d99fatagen2026-10-16 05:34 UTC610
- `ImportMem` (`:511`) with `import_memory`, `update_memory` and `mem_formats`. `ImportMemWl` (`:479`) with `import_shm_buffer` and `shm_formats`.
57f44a63d99fatagen2026-10-16 05:34 UTC611
- `ImportDma` (`:643`) with `dmabuf_formats`, `has_dmabuf_format` and `import_dmabuf`. `ImportDmaWl::import_dma_buffer` (`:618`). `ImportAll::import_buffer` (`:677`).
57f44a63d99fatagen2026-10-16 05:34 UTC612
- `ExportMem` (`:747`) with `copy_framebuffer`, `copy_texture`, `can_read_texture` and `map_texture`.
57f44a63d99fatagen2026-10-16 05:34 UTC613
- `Blit::blit` (`:808`) and `BlitFrame` (`:836`) with `blit_to` and `blit_from`.
57f44a63d99fatagen2026-10-16 05:34 UTC614
57f44a63d99fatagen2026-10-16 05:34 UTC615
There is no Vulkan renderer in tree. `src/backend/vulkan` only has instance and physical device helpers. Its module docs state it does not provide logical devices, rendering or memory allocation (`smithay/src/backend/vulkan/mod.rs:1`). Vulkan allocation is separate in `src/backend/allocator/vulkan`.
57f44a63d99fatagen2026-10-16 05:34 UTC616
57f44a63d99fatagen2026-10-16 05:34 UTC617
Multigpu is generic over `GraphicsApi` and `ApiDevice` (`smithay/src/backend/renderer/multigpu/mod.rs:728`, `:749`). A device exposes `renderer`, `renderer_mut`, `allocator` returning a `Dmabuf` allocator, `node`, plus cross-device import hints. Target selection needs `Bind<Dmabuf>` (`:328`), cross rendering needs target-side `ImportDma` (`:394`), and `early_import` needs `ImportMemWl` plus `ImportDmaWl` plus `ExportMem` (`:493`).
57f44a63d99fatagen2026-10-16 05:34 UTC618
57f44a63d99fatagen2026-10-16 05:34 UTC619
`OutputDamageTracker` (`smithay/src/backend/renderer/damage/mod.rs:193`) exposes `new`, `from_output`, `from_mode_source`, `mode`, `render_output`, `render_output_with_states` and `damage_output` (`:250`, `:279`, `:300`, `:317`, `:326`, `:382`, `:435`). Rendering requires `E: RenderElement<R>` and `R: Renderer`.
57f44a63d99fatagen2026-10-16 05:34 UTC620
57f44a63d99fatagen2026-10-16 05:34 UTC621
`Element` (`smithay/src/backend/renderer/element/mod.rs:518`) requires `id`, `current_commit`, `src`, `geometry` plus defaulted `location`, `transform`, `damage_since`, `opaque_regions`, `alpha`, `kind` and `is_framebuffer_effect`. `RenderElement` (`:572`) requires `draw` and optionally `underlying_storage` plus `capture_framebuffer`.
57f44a63d99fatagen2026-10-16 05:34 UTC622
57f44a63d99fatagen2026-10-16 05:34 UTC623
### 7.4 DRM
57f44a63d99fatagen2026-10-16 05:34 UTC624
57f44a63d99fatagen2026-10-16 05:34 UTC625
`DrmCompositor` docs (`smithay/src/backend/drm/compositor/mod.rs:1`) describe walking elements front to back, assigning overlays, then trying the top fitting element for cursor, and compositing the rest on primary with the supplied renderer. Overlays are atomic-only, with legacy limited to primary, plus `UnderlyingStorage` export and atomic test commits. Scanout permission is controlled by `FrameFlags` (`:1021`) with `ALLOW_PRIMARY_PLANE_SCANOUT`, `ALLOW_PRIMARY_PLANE_SCANOUT_ANY`, `ALLOW_OVERLAY_PLANE_SCANOUT`, `ALLOW_CURSOR_PLANE_SCANOUT`, `SKIP_CURSOR_ONLY_UPDATES`, `ALLOW_SCANOUT` and `DEFAULT`.
57f44a63d99fatagen2026-10-16 05:34 UTC626
57f44a63d99fatagen2026-10-16 05:34 UTC627
Frame scheduling is caller-driven. `render_frame` (`:1686`) needs `R: Renderer + Bind<Dmabuf>` and prepares planes and damage. `queue_frame` (`:2441`) queues and submits when idle. `commit_frame` (`:2487`) commits without vblank generation. `frame_submitted` (`:2618`) retires the pending frame and submits a queued one. Empty frames must be rescheduled by the caller, typically with a retrace timer.
57f44a63d99fatagen2026-10-16 05:34 UTC628
57f44a63d99fatagen2026-10-16 05:34 UTC629
VRR exists on surfaces as `vrr_supported`, `vrr_enabled` and `use_vrr` backed by `VRR_ENABLED` (`smithay/src/backend/drm/surface/atomic.rs:558`, `smithay/src/backend/drm/surface/gbm.rs:502`), with `VrrSupport` values including `RequiresModeset`. No tearing or async flip control, no gamma or CTM or color pipeline properties, and no render-as-late-as-possible deadline API were found in `src/backend/drm/compositor`.
57f44a63d99fatagen2026-10-16 05:34 UTC630
57f44a63d99fatagen2026-10-16 05:34 UTC631
### 7.5 Surface commit handling
57f44a63d99fatagen2026-10-16 05:34 UTC632
57f44a63d99fatagen2026-10-16 05:34 UTC633
Commits use double-buffered cached state plus transactions and blockers. `Blocker` and `BlockerState` with `Pending`, `Released` and `Cancelled` are in `smithay/src/wayland/compositor/transaction.rs:53`. A `Barrier` helper is at `:70`. Transactions collect surfaces plus blockers (`:111`) and support `add_blocker` (`:164`), `merge_into` (`:174`), `finalize` (`:207`), global readiness in `Transaction::state` (`:236`), application in `apply` (`:261`), and per-client ordering in `TransactionQueue` (`:280`). The header comment (`:1`) describes synchronized subsurfaces merging into the parent pending transaction and future explicit sync blockers.
57f44a63d99fatagen2026-10-16 05:34 UTC634
57f44a63d99fatagen2026-10-16 05:34 UTC635
Public hooks are `add_pre_commit_hook`, `remove_pre_commit_hook` and `add_blocker` (`smithay/src/wayland/compositor/mod.rs:454`, `:547`), backed by `PrivateSurfaceData` (`smithay/src/wayland/compositor/tree.rs:188`). `wl_surface.commit` invokes pre-commit hooks then commits (`smithay/src/wayland/compositor/handlers.rs:266`).
57f44a63d99fatagen2026-10-16 05:34 UTC636
57f44a63d99fatagen2026-10-16 05:34 UTC637
Dmabuf readiness uses `Dmabuf::generate_blocker` returning `DmabufBlocker` plus `DmabufSource` (`smithay/src/backend/allocator/dmabuf.rs:267`), with the `Blocker` impl at `:524`. Explicit sync uses acquire and release points stored in `DrmSyncobjSurfaceCachedState` (`smithay/src/wayland/drm_syncobj/mod.rs:96`), validated as pairs (`:242`), installed by pre-commit hook (`:330`), and waited on through `DrmSyncPoint::generate_blocker` plus `DrmSyncPointBlocker` (`smithay/src/wayland/drm_syncobj/sync_point.rs:240`, `:324`). Multiple surfaces can join one transaction through `PendingTransaction::merge_into` and synchronized subsurface grouping.
57f44a63d99fatagen2026-10-16 05:34 UTC638
57f44a63d99fatagen2026-10-16 05:34 UTC639
### 7.6 Presentation and timing protocols
57f44a63d99fatagen2026-10-16 05:34 UTC640
57f44a63d99fatagen2026-10-16 05:34 UTC641
`src/wayland` contains `presentation` (presentation-time), `fifo` (fifo-v1), `commit_timing` (commit-timing-v1), `drm_syncobj` (linux-drm-syncobj-v1), `content_type` (content-type-v1) and `alpha_modifier` (alpha-modifier-v1) (`smithay/src/wayland/mod.rs:50`). No `tearing_control` or `color_management` modules exist, so tearing-control-v1 and color-management-v1 have no dedicated smithay helpers in this checkout.
57f44a63d99fatagen2026-10-16 05:34 UTC642
57f44a63d99fatagen2026-10-16 05:34 UTC643
### 7.7 Allocator
57f44a63d99fatagen2026-10-16 05:34 UTC644
57f44a63d99fatagen2026-10-16 05:34 UTC645
Common docs and traits are in `smithay/src/backend/allocator/mod.rs:1`, with submodules `dmabuf`, `dumb`, `format`, `gbm`, `udmabuf`, `vulkan` and `swapchain` (`:18`), and the `Allocator` plus `Buffer` traits (`:44`, `:60`). Concrete types are `GbmAllocator` (`smithay/src/backend/allocator/gbm.rs:147`), `DumbBuffer` (`smithay/src/backend/allocator/dumb.rs:17`), `VulkanAllocator` (`smithay/src/backend/allocator/vulkan/mod.rs:123`), `VulkanImage` (`:382`), `Swapchain` (`smithay/src/backend/allocator/swapchain.rs:46`) and `Slot` (`:74`), plus `Dmabuf` in `dmabuf.rs`. The Vulkan allocator targets up to Vulkan 1.3 and requires `VK_EXT_image_drm_format_modifier`, `VK_EXT_external_memory_dmabuf` and `VK_KHR_external_memory_fd`, with optional `VK_EXT_4444_formats` (`smithay/src/backend/allocator/vulkan/mod.rs:1`).