Conversation
Contributor
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| alsa-lib | wasm32 | built | 76a1d382 |
| libcurl | wasm32 | built | 4f9b5a1f |
| libcxx | wasm32 | built | ec27aa51 |
| libcxx | wasm64 | built | 8f4ee8d0 |
| libdrm | wasm32 | built | 1d5db816 |
| libevdev | wasm32 | built | 9333885b |
| libffi | wasm32 | built | e3940282 |
| libinput-lite | wasm32 | built | 1c625bbd |
| libinput | wasm32 | built | a60361d6 |
| libpng | wasm32 | built | 9689c61e |
| libudev | wasm32 | built | 30ef5cef |
| libwayland | wasm32 | built | 6f1dfcf1 |
| libxkbcommon | wasm32 | built | f2d812a7 |
| libxml2 | wasm32 | built | e75d97c9 |
| libxml2 | wasm64 | built | 32bd5ba0 |
| mtdev | wasm32 | built | 5abcd835 |
| openssl | wasm32 | built | 04ac59f8 |
| openssl | wasm64 | built | 049550f6 |
| sdl2 | wasm32 | built | 90b6724c |
| sqlite | wasm32 | built | 68933c56 |
| sqlite | wasm64 | built | 88bbf041 |
| zlib | wasm32 | built | 073eb2db |
| zlib | wasm64 | built | 0d12bab1 |
| bc | wasm32 | built | 324366af |
| bzip2 | wasm32 | built | 1eed3d03 |
| coreutils | wasm32 | built | 72e54e1f |
| curl | wasm32 | built | bdcbcc48 |
| dash | wasm32 | built | 46e890ed |
| diffutils | wasm32 | built | 08846c06 |
| dinit | wasm32 | built | c6b49d0d |
| fbdoom | wasm32 | built | f29b87e9 |
| file | wasm32 | built | e75acd51 |
| findutils | wasm32 | built | 2359e785 |
| gawk | wasm32 | built | a1f49aa3 |
| git | wasm32 | built | 0be6d225 |
| grep | wasm32 | built | ee2307ef |
| gzip | wasm32 | built | d87a65c0 |
| kandelo-sdk | wasm32 | built | 327eb2ca |
| kernel | wasm32 | built | a25b079e |
| less | wasm32 | built | 2707cc56 |
| lsof | wasm32 | built | 85b55778 |
| m4 | wasm32 | built | 1cade1f2 |
| make | wasm32 | built | bd353850 |
| mariadb | wasm32 | built | d485f8ad |
| mariadb | wasm64 | built | 79043662 |
| msmtpd | wasm32 | built | 8876faf5 |
| nano | wasm32 | built | 6d2d0e7f |
| ncurses | wasm32 | built | dcd4f1be |
| netcat | wasm32 | built | 38dfa0f9 |
| nginx | wasm32 | built | 8165bdc3 |
| php | wasm32 | built | ef94bc44 |
| posix-utils-lite | wasm32 | built | 7f8aa0f1 |
| sed | wasm32 | built | d39bedcf |
| spidermonkey | wasm32 | built | e3c4dd41 |
| tar | wasm32 | built | df3a2b98 |
| tcl | wasm32 | built | 26cd0438 |
| unzip | wasm32 | built | 69dc6810 |
| userspace | wasm32 | built | 758ef3be |
| vim | wasm32 | built | 8cab3cab |
| wget | wasm32 | built | ac5f4481 |
| xz | wasm32 | built | f371fe0e |
| zip | wasm32 | built | d0a493c6 |
| zstd | wasm32 | built | 97996306 |
| bash | wasm32 | built | 66c00206 |
| mariadb-test | wasm32 | built | 1651df80 |
| mariadb-vfs | wasm32 | built | 1f6769f5 |
| mariadb-vfs | wasm64 | built | 575a5172 |
| nethack | wasm32 | built | 99bf9067 |
| node | wasm32 | built | dbee0563 |
| spidermonkey-node | wasm32 | built | 659020ab |
| vim-browser-bundle | wasm32 | built | e51bb29e |
| nethack-browser-bundle | wasm32 | built | 9a7373e0 |
| rootfs | wasm32 | built | 470d7e0a |
| shell | wasm32 | built | e5ef64d2 |
| lamp | wasm32 | built | bcf07ede |
| node-vfs | wasm32 | built | 2ceb0b40 |
| wordpress | wasm32 | built | 1a3268f3 |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
mho22
force-pushed
the
explore-dri-wayland
branch
2 times, most recently
from
July 16, 2026 11:34
4440a9d to
e9ca2d3
Compare
mho22
marked this pull request as ready for review
July 17, 2026 08:40
mho22
force-pushed
the
explore-dri-sdl2
branch
from
August 21, 2026 10:02
d2f79e1 to
a97a334
Compare
mho22
force-pushed
the
explore-dri-wayland
branch
from
August 21, 2026 10:02
e9ca2d3 to
1d4b00b
Compare
mho22
force-pushed
the
explore-dri-sdl2
branch
from
August 24, 2026 19:08
a97a334 to
52ad9c6
Compare
mho22
force-pushed
the
explore-dri-wayland
branch
from
August 24, 2026 19:08
1d4b00b to
a3ccc13
Compare
mho22
force-pushed
the
explore-dri-sdl2
branch
from
August 26, 2026 14:37
52ad9c6 to
d194992
Compare
mho22
force-pushed
the
explore-dri-wayland
branch
from
August 26, 2026 14:37
a3ccc13 to
af3e6c7
Compare
This was referenced Aug 26, 2026
mho22
force-pushed
the
explore-dri-wayland
branch
from
August 28, 2026 20:14
af3e6c7 to
539230f
Compare
mho22
force-pushed
the
explore-dri-sdl2
branch
2 times, most recently
from
August 28, 2026 20:47
d194992 to
42e3a4a
Compare
libwayland dispatches every protocol message through a libffi call, so the port needs closures that can be built at runtime. This shim covers the calling conventions the Wayland stack actually uses rather than the whole libffi surface, which keeps the generated call_indirect dispatch small enough to audit.
wayland-scanner generates the client and server glue from protocol XML, and it runs on the build host rather than the target — a wasm binary cannot generate its own bindings. Vendoring the protocol XML alongside it pins what every client in this stack is compiled against, so a compositor and its clients cannot disagree about a protocol version.
Upstream libwayland builds unmodified once the kernel answers the parts it depends on: a unix socket per connection, SCM_RIGHTS to pass buffer and dmabuf descriptors between processes, and shared memory the two sides map at different addresses. The port is the point where a real Wayland client can connect to a real Wayland server inside the kernel, so the protocol work above it is upstream code rather than an imitation.
A Wayland compositor sends a keymap, not keysyms: the client compiles it and does its own translation. libxkbcommon is what compiles it, so without the port every client sees raw keycodes and no client can produce text.
libinput is what a compositor uses to turn evdev records into pointer, keyboard and touch events, and it will not open a device it cannot identify. That pulls in libevdev to describe the device, mtdev to normalise multitouch, and enough of libudev to enumerate and tag one. The libudev piece is a shim over the kernel's device nodes rather than a port: there is no udev daemon here, and libinput only needs the enumeration and the input-id properties that tagging produces.
The compositor runs as an ordinary process against the same kernel its clients use. It serves wl_shm, xdg_shell, wl_seat and wl_output — the minimum a stock client needs to map a surface, receive input and learn the output geometry it is drawing for.
libkwl is the client-side half a Wayland program needs before it can draw anything: connect, bind globals, take a role, handle the configure handshake, compile the keymap. wpkdraw is the software rasteriser above it — rectangles, text and antialiased edges into a wl_shm buffer. wlterm is the first real client built on both: a VT100 terminal that runs a shell. It is what makes the compositor demonstrably useful rather than a surface that renders a test pattern.
Three clients on one compositor is where the software blit stops being enough. The compositor now hands each client's buffer to the host as a foreign texture and composites on the GPU, and a WebGL2 presenter scans the result out to the canvas. The kernel and host fixes here are the ones three concurrent clients exposed: page-rounding on munmap unbind, an implicit pointer grab so a drag does not change surface mid-gesture, a use-after-free when a client disconnects while its buffer is still referenced, and a present path that degrades to the software blit instead of failing when a GL context is lost.
Records what the compositor still lacks against a real tiling compositor — layer shell, a bar, a launcher, theming — and the order that work is expected to land in.
The local source-build set asserts its exact roster, so each new library has to be placed: they are platform packages, since the sysroot exposes them to any client rather than shipping them as a product. `fetch-binaries` also has to skip `kind=source` packages under `--fetch-only`: they have no published archive to fetch, so treating a missing one as a failure made the fetch step report errors for packages that were never meant to be fetched.
wlterm folded both waitpid outcomes into one line:
int exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : 0;
printf("WLTERM_EXIT code=%d\n", exit_code);
WEXITSTATUS is undefined unless WIFEXITED, so a shell killed by a
signal reported `code=0` — the same text a clean exit prints. A crashed
shell was indistinguishable from a finished one in the marker stream
the smokes and the browser specs read.
Report the signal on its own marker, `WLTERM_EXIT signal=<n>`, and keep
`code=` for the WIFEXITED case. The smoke gains a second case: a dash
that sends itself SIGKILL must produce `signal=9` and no `code=` line.
943cb1f raised `ABI_VERSION` to 44 and left three hand-written test fixtures at 43: (func (export "__abi_version") (result i32) i32.const 43) Each one is compiled and run as a guest program, so the kernel refused it before execution: pid=100: refusing unsafe program artifact before execution: ABI 43, expected 44 That failed three cases across `catch-ref-fresh-worker.test.ts` and `gc-reference-state-fresh-worker.test.ts`. The tier rebuild never cleared them because the suite builds these artifacts itself. `gc-reference-state-fresh-worker` runs the checked byte fixture rather than the `.wat`, since WABT cannot parse the typed-reference syntax. Its bytes are regenerated with the Rust `wat` crate from the corrected source and differ from the old ones in exactly one byte — offset 208, `0x2b` to `0x2c`. `apps/browser-demos/test/fork-continuation.spec.ts` imports the same constant, so both hosts move together.
`scripts/ci-vitest-evidence-classes.tsv` must exactly cover the live Vitest file inventory, so `ci-run-test-suite.sh vitest exact-abi-source` refuses to enumerate while the two drift. This branch raises ABI_VERSION, which is exactly when that group runs. Classify the test files this branch adds, and drop the rows for files it no longer carries. A file is `source-only` only when its whole import closure stays clear of the binary resolver; the runner enforces that separately from the cover check. The smokes exec staged wasm, so they are `prepared-product`; the remaining unit tests import only `host/src/`.
mho22
force-pushed
the
explore-dri-sdl2
branch
from
August 30, 2026 09:10
42e3a4a to
81c667e
Compare
mho22
force-pushed
the
explore-dri-wayland
branch
from
August 30, 2026 09:10
539230f to
b5d3c7a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Kandelo could scan out pixels and read input, but had no display server. This PR ports the Wayland libraries to the wasm32 sysroot and builds
wlcompositor, a PID-2 Wayland server that composites real clients onto the KMS surface.Third layer of the six-PR DRI stack (#698 → #709 → #948 → #976 → #1318 → #1241). It stacks on
explore-dri-sdl2.What changed
The Wayland library stack
libwayland's dispatch, ahead of the full libffi port that lands in Toolkit on Kandelo — the C/C++ library stack behind foot, Waybar and mako #1318.wayland-scannerand thewayland-protocolsXML./dev/inputdevices Evdev on Kandelo - /dev/input keyboard and pointer, plus an espeak-ng speech demo #698 added.The compositor and its clients
wlcompositor, a PID-2 Wayland server:wl_compositor,wl_shm,xdg-shell,wl_seat, and CPU or GPU compositing onto/dev/dri/card0.wpkdraw,libkwland thewltermterminal.The fixes a running desktop exposed
Driving the desktop as a real user surfaced defects that marker-based gates passed straight over:
sys_munmapran its fb0/DRI coverage sweeps against the raw length whileMemoryManager::munmaprounds to the 64 K page, so amap(aligned)/unmap(raw bo size)pair freed pages the host kept mirroring. The length is now rounded up front, withchecked_addclosing the overflow edge.eglSwapBuffersdegrades to CPU compositing instead of freezing the canvas.detachKernel()never cleared the per-CRTC display-size map, and the pane'sResizeObserverkept feeding the dead kernel, so a second boot in the same tab letterboxed at 1920×1080. The map is cleared on detach and the stale observer disconnects.Host-side robustness that rides along: the imported-bo coherence copy moves out of the blocked-poll retry path, inherited GL state is sanitized before a presenter rebuild, the presenter rebuilds when a remounted pane brings a new canvas, the guest's
UNPACK_ROW_LENGTHis restored, a binding's foreign textures are deleted on unbind, and the scanout shader is raised tohighpfor modes above 2048 px.Docs
docs/plans/2026-07-14-build-hyprland-class-compositor-plan.md— the roadmap #976 stacks on.Both hosts
The kernel and
host/src/{kernel-worker,webgl/*}.tschanges are shared code and take effect on Node and the browser together. The browser-only surface is thekandelo-sessionreboot fix and the Playwright GPU-compositing gate; the GPU path exists only in the browser, and the Node smokes assert the inverse (WLC_RENDERER cpu). Coverage lands on the side it exercises:wldesktop-smoke(Node) gains toolbar-routing and two off-window grab-release gates,kandelo-wayland.spec(Chromium) asserts the GPU-pathglReadPixelsCOMPOSITE_SAMPLEis present and non-black, andkandelo-sessiongets two unit tests for the detach/reboot display-size lifecycle. The kernel changes carry two unit tests.Deliberately left as is
With reasons in the commit bodies: the guest sees
EIOfor all host bind-foreign-texture failures; select/pselect completions have no import-coherence sync, since there is no in-tree consumer; and the single-sample bilinear degrade is kept pending a follow-up consecutive-overrun counter.Rebased and rebuilt
This branch sits on
explore-dri-sdl2at42e3a4abc. The history was rebuilt from 15 commits to 11; two test commits added since bring it to 13.Against the previous tip, the only files that differ outside those
mainitself moved are 17, and every change in them is a comment — including one incrates/kernel/src/syscalls.rs, where a test comment cited a plan label (the PR6 crash) that no longer resolves. No code changed.The earlier description of this PR covered only its tip commit and was marked draft pending the series merge order. That order is now settled: #1318 sits between #976 and #1241.
Verification
Run at the pre-rebase stack tip
ab7ab2b63, which contained the 11 commits here at the time:cargo test -p kandelo --target aarch64-apple-darwin --lib→ 1665 passed, 0 failedbash scripts/check-abi-version.sh→ exit 0scripts/run-libc-tests.sh→ 302 passed, 20 XFAIL, 0 build failures, and 1 unexpected failure:regression/raise-race. That test forks 100 children inside a signal handler; 5 waits returnECHILD, reproducibly.scripts/run-libc-tests.sh:163skips it wheneverCI=true, so it does not gate this PR, and whether it regressed or predates the stack is not yet established.scripts/run-posix-tests.sh→ 174 passed, 0 FAIL, 3 XFAIL, 2 SKIPBoth suites need
WASM_POSIX_RESOLUTION_POLICY=source-only-v1andWASM_POSIX_SOURCE_ONLY_BINARY_ROOT=<repo>/local-binaries/source-only-v1.binaries-abi-v44/index.tomldoes not exist until the toolkit tier merges, so thebinaries/provenance tier cannot be materialized locally. The full host vitest suite needs both provenance tiers resolvable at once, which only CI's prepared workspace provides — it is the gate for that suite and for the browser demos.The stack has since been rebased onto
mainat888e628d5. Two gates were re-run at the new stack tipccc7c6214(explore-dri-omarchy):bash scripts/check-abi-version.sh→ exit 0, snapshot in sync and the 43 → 44 bump consistent;scripts/ci-run-test-suite.sh vitest exact-abi-source→ 3049 passed, 0 failed, with two files failing to collect on paths #1321 moved tocrates/runtime-core/. That collection failure is amaindefect and #1337 fixes it.