# What monolith should take from jay/wry

Companion to `wry-reports.md`, which holds the raw findings and citations.

## The async runtime

Don't port it. Port the phase discipline.

Why it doesn't pay off inside a smithay compositor.

- Most of jay's I/O is client sockets. In smithay those belong to wayland-backend, which reads and writes through its own readiness loop in `dispatch_clients`/`flush_clients`. Moving to io_uring would leave only DRM events, udev, libinput and timers on the ring, a handful of completions per frame.
- Even inside jay the raw speed win is small. A frame costs on the order of tens to low hundreds of syscalls, well under 1% of a 6.9 ms frame at 144 Hz. Input-to-photon latency is decided by when you render, not by how cheaply you wake up.
- Tasks can't hold `&mut State`, so jay runs on `Rc<State>` with `Cell`/`CloneCell`/`CopyHashMap` everywhere. Smithay's handler traits hand you `&mut D`. Running both models means fighting every delegate.
- There is no fallback when io_uring is unavailable (`kernel.io_uring_disabled`, hardened kernels, some sandboxes). Jay exits.
- Every smithay helper that is a calloop `EventSource` (`DrmDeviceNotifier`, `LibinputInputBackend`, `XWayland`, `DrmSyncPointSource`, `DmabufSource`, the socket listener) would need rewrapping.

What it does well, and the calloop equivalent.

| jay feature | real benefit | in monolith |
|---|---|---|
| Four ordered phases fed by dirty queues | N events collapse into one layout and one render per pass, with deterministic ordering | Fixed stages in the post-dispatch closure (layout, derived state, animation tick, render, flush), each with a dirty set and a scheduled flag |
| `now()` frozen per pass | Every animation computed in a pass sees one timestamp | Store an `Instant` in `State` at the top of the post-dispatch closure |
| Async fns for sequential flows (present loop, xwm, dbus, pipewire) | Readable state machines | Explicit enum for the present loop, calloop's executor for portal and screencast flows, and x11rb/zbus/pipewire-rs for the protocols |
| Cancel-on-drop tasks | Structured lifetimes | `async_task::Task` also cancels on drop |
| Linked timeouts on client `sendmsg` | A stuck client can't stall the compositor | wayland-backend flushes nonblocking already |

## Worth taking, ranked

### 1. Deadline frame scheduler

`src/backends/metal/present.rs`, flip handling in `src/backends/metal/video.rs`.

Biggest latency payoff, and it slots straight into smithay because `DrmCompositor` leaves timing to the caller. Sleep until `next_vblank - pre_margin - post_margin`, then latch, render and commit.

- `pre_margin` is a decaying per-second max of measured wakeup-to-latch CPU time.
- `post_margin` grows 500 µs per second that saw a missed flip and decays toward the device minimum otherwise.
- Vblank timestamps come from queued `CRTC_SEQUENCE` events, with emulation when the driver returns `EOPNOTSUPP`.

This is an algorithm port, a few hundred lines. With a Vulkan renderer, GPU time needs to be covered too, either through `post_margin` misses as jay does or with timestamp queries.

### 2. Async shm upload pipeline

`src/cpu_worker.rs`, `src/gfx_apis/vulkan/transfer.rs`, `src/clientmem.rs`.

Smithay's GLES renderer uploads shm synchronously inside `import_shm_buffer` on the main thread. Jay keeps the commit blocked while a worker thread memcpys only damaged rows into a staging buffer, and the GPU finishes the copy on the transfer queue. Sealed memfds (`F_SEAL_SHRINK` plus a large enough size) let the worker read client memory without the thread-local SIGBUS dance. foot, software-rendered toolkits and Xwayland without glamor all take this path. Build it into monolith's `ImportMemWl` as a smithay `Blocker`.

### 3. Vulkan renderer internals as a reference

Smithay has no Vulkan renderer, so monolith writes one either way. Jay's ~10k lines are coupled to `cmm`, `theme`, `State`, the ring and the cpu worker, so lift modules and ideas rather than the crate.

- fp16 linear blend buffer with a resolve pass. Blending is correct and HDR-ready, and color transforms happen in one place.
- Op list sorted and batched by pipeline key, one `queue_submit2` per frame.
- Vertex data via buffer device address in push constants, instanced draws.
- Specialization constants for EOTF, matrix and alpha mode instead of runtime branches.
- Descriptor heap, then descriptor buffer, then push descriptor tiers.
- Timeline semaphores mapped to DRM syncobj points, sync_file import/export for implicit sync.
- Global-priority graphics and transfer queues (`src/gfx_apis/vulkan/device.rs:448-528`).
- Offline shaderc compilation with hash tracking.

Implement smithay's `Renderer`, `Frame`, `Bind<Dmabuf>`, `Offscreen`, `ImportDma`, `ImportMemWl` and `ExportMem` so that `DrmCompositor`, `OutputDamageTracker` and the element system work unmodified. `Frame` calls append to the op list and `finish` records and submits. Jay stops at rounded rects, so blur and shadows are new work. They would be extra op kinds or custom `RenderElement`s.

### 4. Commit blocker taxonomy

Smithay already has per-client transaction queues and `Blocker`. Jay's contribution is the list of things a commit waits on, all treated uniformly.

- implicit dmabuf fences
- syncobj acquire points
- shm upload completion
- prime copy completion
- fifo-v1 barrier
- commit-timing-v1 deadline, released by the scheduler's before-latch hook
- layout transaction serial

Each becomes a smithay `Blocker` or pre-commit hook. The commit-timing integration with the deadline scheduler is the subtle one.

### 5. Two-timeline tree, transactions, multiphase animations

`SplitView`/`TreeLink`, `LiveTL`/`RenderTL`, `src/transactions.rs` and `src/tree_serial_groups.rs` are upstream jay. `src/presentation/` is yours.

`LiveTL` is what clients have been configured to and `RenderTL` is what is on screen. `RenderTL` advances only when every affected client has acked and committed, or after a 50 ms timeout. Animations are transaction effects that diff the pre and post trees at publication time. Tags are a natural fit. A tag switch changes the visibility and size of many windows at once, which is exactly the case transactions exist for.

- `multiphase.rs` is near-pure geometry with 1.7k lines of tests. Lift it almost verbatim.
- Retained snapshots from `layout_animation.rs`, where the old texture is scaled to the animated rect while the client catches up, port as a concept onto smithay elements.
- Reimplement transactions and configure serial groups against smithay's xdg-shell configure/ack and `Blocker`s.

### 6. Integration test harness

`src/it/`.

An in-process compositor on a headless backend, real-socket clients, zeroed timeouts, tree-invariant verification after every idle point, and golden-pixel QOI comparisons. Use wayland-client or smithay-client-toolkit in place of jay's `wl_usr`. An animation-heavy compositor needs this from the start.

### 7. Small items

- `SCHED_RR` with `SCHED_RESET_ON_FORK`, with `CAP_SYS_NICE` parked on a helper thread (`src/utils/nice.rs`, `src/pr_caps.rs`).
- Tracy zones named per task.
- KMS hygiene. Reset unknown properties to defaults at init, retry device init with features disabled, `TEST_ONLY` before modesets, roll back on failure.
- VRR cursor throttling (`src/output_schedule.rs`), so cursor motion doesn't pin VRR at max refresh.
- Lazy Xwayland startup on the first X connection.

## Skip

- Bespoke wire protocol, codegen and `wl_usr`. Smithay owns this layer.
- Homegrown xcon, dbus and pipewire stacks. Use x11rb via smithay's `X11Wm`, zbus and pipewire-rs.
- Forker process. `std::process::Command` uses `posix_spawn` and is safe from a threaded process. Set env, rlimits and sched policy on the `Command`.
- The `Rc` plus cell utility collection, which only exists because of jay's executor.
- Jay's plane assignment, which never uses overlays. `DrmCompositor` already assigns overlays.
- `metal_cm` KMS color pipelines for now. It is large and driver-quirky. Keep the renderer's color math shaped so it can slot in later.
- SQLite session manager, unless session restore becomes a goal.

## Gaps smithay leaves

- No tearing/async page flip control in `DrmCompositor`. Needs an upstream patch or a custom commit path.
- No KMS color pipeline, CTM/gamma or HDR metadata handling.
- No tearing-control-v1 or color-management-v1 protocol helpers.

## License

jay and wry are `GPL-3.0-only`. Copying code from them makes monolith GPL-3.0. Smithay is MIT, which is compatible with that. `src/presentation/` is your own new code and can be relicensed freely. Jay-authored code (scheduler, shaders, transfer path) can only be reimplemented from the design if monolith is meant to be permissive.
