Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 45 additions & 32 deletions quest/m0/cef-headless.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,53 @@ GPU path cannot paint fails its source saying why instead of staying
[moq-dev/studio#59](https://github.com/moq-dev/studio/pull/59) picks the
display at setup: Chromium's Wayland Ozone platform when `$WAYLAND_DISPLAY` is
set, X11 when only `$DISPLAY` is, and the CPU path with neither. It passes the
browser suite on the GPU path on NVIDIA (RTX 3070 Ti, GNOME on Wayland), and
on the CPU path with no display on NVIDIA and Intel.

Mesa did not paint in its only trial, on nixos2 (Intel UHD 630, Mesa 26.2.4,
beside an RTX 2070), under a headless sway on the Intel render node, since no
desktop session was logged in:

- Wayland: CEF's GPU process starts on Mesa's EGL, but the first shared image
fails to allocate ("Unable to allocate frame for first frame capture:
OOM?") and the page never paints. The same happens with glvnd pinned to
Mesa (`__EGL_VENDOR_LIBRARY_FILENAMES`) and with `--disable-gpu-sandbox`.
Release CEF strips the allocation's own log (a `DLOG` in
`media/gfx/renderable_mappable_shared_image_video_frame_pool.cc`).
- X11, under that sway's XWayland: shared textures import, but come back
empty (transparent pages, black WebGL).
- The same headless sway on the NVIDIA render node paints shared textures, so
the harness itself works.

First check whether a real Mesa desktop session paints; the headless sway on
a hybrid host may be the cause. If it does not, find which allocation fails
(a debug CEF build, or `chrome://gpu` in a CEF client on the same host).

When the capturer cannot allocate, CEF never paints and never says so. Fail
the page loudly instead, from a signal CEF or Chromium gives (no first-paint
timeout).
browser suite on the GPU path on NVIDIA (RTX 3070 Ti, GNOME on Wayland).

Found on nixos2 (Intel UHD 630, Mesa 26.2.4, beside an RTX 2070):

- X11 on Mesa paints since
[moq-dev/studio#73](https://github.com/moq-dev/studio/pull/73). ANGLE drew
through GLX there, which left every shared texture blank; the X11 path now
passes `--use-angle=gl-egl`.
- Wayland is still unknown on Mesa. Under a headless sway on the Intel render
node, the first shared image fails to allocate ("Unable to allocate frame
for first frame capture: OOM?") and the page never paints. That headless
sway on the NVIDIA node paints, so the harness works.
- GNOME with no monitor attached cannot run the Wayland path on any GPU. It
advertises no `wl_output`, and Chromium's `WaylandConnection::Initialize`
round-trips until one appears, so CEF's `initialize` never returns. The
helper hangs before reading a command and every page stays `Starting`.
Meanwhile `gnome-shell` uses a full core.

Remaining:

- Rerun `binary(browser)` on Wayland on the Intel GPU in GNOME with a display
connected, over ssh with `WAYLAND_DISPLAY=wayland-0`,
`XDG_RUNTIME_DIR=/run/user/1000`, and `VK_DRIVER_FILES` pointing at Mesa's
`intel_icd`. If it still fails to allocate, find which allocation fails (a
debug CEF build, or `chrome://gpu` in a CEF client on the same host).
- Fail a page loudly when the GPU path cannot paint, from a signal CEF or
Chromium gives (no first-paint timeout):
- On allocation failure, Chromium's frame sink video capturer logs the OOM
line and calls `Stop()`, which calls the consumer's `OnStopped()`. CEF's
`CefVideoConsumerOSR` drops `OnStopped` and `OnLog` (empty bodies in
`libcef/browser/osr/video_consumer_osr.h`), so no client callback fires.
Surfacing it likely needs a CEF change upstream.
- When `$WAYLAND_DISPLAY` has no `wl_output`, decide that at setup rather
than hang in `initialize`: for example, check for an output in `raster()`
and fall to X11 or the CPU path.

Decided 2026-11-06 (maintainer, /quest-unblock): this trial runs before
nixos2 switches to Windows ([windows-host](/quest/m0/windows-host.md)), which
then leaves no Mesa machine on NixOS.

Since 2026-11-06 ([kixelated/nixos#31](https://github.com/kixelated/nixos/pull/31)),
GDM logs `kixelated` into GNOME at boot on nixos2. Its GNOME Shell runs on
the Intel GPU (`card1`, `renderD128`) with no monitor attached, so an agent
runs `binary(browser)` there over ssh with `WAYLAND_DISPLAY=wayland-0` and
`XDG_RUNTIME_DIR=/run/user/1000`. If a page paints only with a display
connected, say so and ask the maintainer for an HDMI dummy plug on the
motherboard's port.
## Waiting

- Maintainer: connect an HDMI dummy plug (or a monitor) to nixos2's
motherboard HDMI port, which the Intel GPU drives, since GNOME offers
Chromium no Wayland output without one. An agent cannot plug hardware, and
a virtual monitor would test a different setup from a real desktop. Check
that `cat /sys/class/drm/card1-HDMI-A-*/status` shows `connected` and that
`wayland-info` on `wayland-0` lists a `wl_output`. Alternative: skip the
Wayland trial on Mesa and let nixos2 switch to Windows, leaving the Wayland
result unknown. Recommended: the dummy plug.
5 changes: 5 additions & 0 deletions quest/m0/cef-x11-nvidia.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ From [moq-dev/studio#59](https://github.com/moq-dev/studio/pull/59), picked
- On nixos (RTX 3070 Ti, NVIDIA 580), the GPU path under X11 never paints:
CEF's GPU process logs "Can't create buffer -- gbm device is missing".
Wayland sessions avoid it since #59, but X11-only sessions still hit it.
- Since [moq-dev/studio#73](https://github.com/moq-dev/studio/pull/73) the X11
path passes `--use-angle=gl-egl`, which made it paint on Mesa; rerun nixos
with it first. On nixos2 under GNOME's XWayland, with the studio on the RTX
2070, CEF still allocated on the Intel GPU that runs the X server (Intel
X-tiled modifier) despite `--render-node-override`.
- First find why. Likely suspects: the NVIDIA GBM backend
(`nvidia-drm_gbm.so`) is not on CEF's search path (`GBM_BACKENDS_PATH`), or
`nvidia-drm` modeset is off. Fix it if the studio can, for example by
Expand Down
5 changes: 5 additions & 0 deletions rs/moq-scene/src/browser/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,11 @@ wrap_app! {
Display::X11 => "x11",
};
command_line.append_switch_with_value(Some(&"ozone-platform".into()), Some(&platform.into()));
// On X11, ANGLE otherwise draws through GLX, which on Mesa
// leaves shared textures blank. Wayland is always EGL.
if *display == Display::X11 {
command_line.append_switch_with_value(Some(&"use-angle".into()), Some(&"gl-egl".into()));
}
// Paint on the studio's GPU, which is the only one it
// imports from.
if let Some(node) = render_node {
Expand Down