Skip to content

fix(scene): browser sources paint on the GPU under X11 on Mesa - #73

Merged
kixelated merged 5 commits into
mainfrom
quest/m0/cef-headless
Nov 7, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest/m0/cef-headless

Conversation

@kixelated

@kixelated kixelated commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Problem

quest/m0/cef-headless.md asked whether browser sources paint on the GPU path under a real Mesa desktop session, since its first trial used a headless sway. nixos2 (Intel UHD 630, Mesa 26.2.4, plus an RTX 2070) now logs into GNOME on the Intel GPU, but with no monitor attached.

What the trial found on nixos2:

  • Wayland, any GPU: GNOME with no monitor advertises no wl_output. Chromium's WaylandConnection::Initialize keeps round-tripping until one appears, so CEF's initialize never returns (gdb: wl_display_roundtrip_queue under WaylandConnection::Initialize, wayland_connection.cc:297). No GPU process ever starts, and every page stays Starting. The same happens with the studio on the RTX 2070. So the Wayland path paints only with a display connected, and the Mesa question needs an HDMI dummy plug (see the quest's ## Waiting).
  • X11 (GNOME's XWayland), Intel: CEF delivers shared textures, but they come back blank. The GPU process loads libGLX_mesa: ANGLE draws through GLX, so nothing lands in the DMA-BUF shared image. This is the "textures import but come back empty" result from the sway trial too. A 500 ms delay before import did not change it, so it is not a sync race.

Approach

  • The X11 GPU path passes --use-angle=gl-egl, so ANGLE draws through EGL, as it already does on Wayland. With it, Intel under XWayland paints Paint::Gpu (Intel X-tiled modifier, imported by ANV).
  • The quest is rewritten to what remains, not finished. That is the Wayland trial on Mesa, which waits on a display, and the loud failure. The rewrite records the no-output hang and where Chromium's allocation-failure signal is lost: the capturer's Stop() calls OnStopped(), and CEF's CefVideoConsumerOSR leaves OnStopped and OnLog empty.
  • quest/m0/cef-x11-nvidia.md gets a lead: rerun nixos with gl-egl. On nixos2's XWayland, CEF also allocated on the Intel GPU that runs the X server, even with the studio on the RTX 2070.

Impact

  • On X11 or XWayland, browser sources on Mesa GPUs now paint on the GPU path instead of showing blank pages.
  • NVIDIA under X11 still hits cef-x11-nvidia. Without this change it did not paint either.
  • Public API: none. Wire: none.

Choices made without asking

  • No workaround for the missing display. Per the brief, the trial did not add a GNOME virtual monitor or a headless compositor. It asks for the dummy plug instead.
  • The no-wl_output hang is left in the quest, not fixed here. A setup probe could pick X11 or the CPU path when the Wayland display has no output. That needs a Wayland client in moq-scene, and fixing it now would change what the pending Mesa trial sees. Recommended: do it in the quest's next PR, alongside the allocation-failure signal.
  • gl-egl only on X11. Wayland already uses EGL.

Alternatives

  • --use-angle=vulkan: not tried. gl-egl keeps the GL path Wayland uses and was enough.
  • Relaying shared textures through the CPU on X11: drops the GPU path that now works.

Validation

Every run was on nixos2 over ssh, in GNOME's session (XDG_RUNTIME_DIR=/run/user/1000), with VK_DRIVER_FILES set to Mesa's intel_icd. Each page's paint was printed by a temporary eprintln! that is not committed.

Session Path Result
GNOME Wayland, no monitor, Intel GPU, Wayland hangs in CEF initialize; 0 paints
GNOME Wayland, no monitor, RTX 2070 GPU, Wayland same hang
XWayland (DISPLAY=:0), Intel, before GPU, X11 1 shared texture, blank; 0/1
XWayland, Intel, at 6172f71 GPU, X11 7/9, every paint on_accelerated_paint (16)
no display, Intel, at 6172f71 CPU 8/9, every paint on_paint (19)

The X11 run has two failures:

  • copy_and_cut_reach_the_clipboard: the X11 path keeps CEF's native copy (#59), which goes to the X clipboard, but the test reads only the studio's relay (Helper::copied()). Before this PR the X11 path never painted, so the test never reached that point.
  • cookies_survive_a_restart: also fails on the CPU path, and on a clean checkout of main (claim commit 07415d9, CPU path). The page's request reaches the test's loopback server twice, but CEF never paints. Pre-existing.

Other checks:

  • nix develop --command quest gate just ci on nixos2 (Linux) at 6172f71: passes, 276 tests.
  • nix develop --command quest gate just ci on nixos2 (Linux) at 9b77257 (main at 299a97a merged in, including the moq pin bump from moq-dev/studio#69): passes, 278 tests. quest check passes on macOS. Nothing ran locally on macOS (disk space). Later commits change only quest files and merge main (a quest-only change).
  • The nightly just render-sw job already fails on main, with helpers exiting on SIGTRAP: run 42235026329.

Follow-ups

  • Worth a quest: the helper outlives a studio that dies or is killed. The helper leads its own process group and, while stuck in initialize, never reads the socket's end. Three test runs that hit their timeout left helpers spinning against GNOME until they were killed by hand. Suggested fix: PR_SET_PDEATHSIG on the helper.
  • Worth a quest: cookies_survive_a_restart fails on nixos2 on every path, and the nightly render-sw fails on SIGTRAP.
  • Worth a quest: copy_and_cut_reach_the_clipboard cannot pass on the X11 path. Either read the X clipboard there, or say the suite runs only on Wayland and with no display.

Review

  • Reviewer: Codex (quest review), gpt-6.1-sol, medium effort.
  • Round 2 of the branch's session, at 9de4d36: no findings.
  • Reviewed head: 9de4d36.
  • 9b77257 only merges origin/main (299a97a) without conflicts, so this record still counts for it.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

Quest-Claim: 5fea8ca4b0bed1e9
@pullfrog

pullfrog Bot commented Nov 7, 2026

Copy link
Copy Markdown

Pullfrog  | Review this ➔

@kixelated kixelated changed the title Browser sources on the GPU under Mesa fix(scene): browser sources paint on the GPU under X11 on Mesa Nov 7, 2026
@kixelated
kixelated marked this pull request as ready for review November 7, 2026 02:23
@coderabbitai

coderabbitai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 6 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e9a52ee9-33d2-4a6b-9bdc-fd7b0a18c0ba
Commits

Reviewing files that changed from the base of the PR and between 299a97a and 9b77257.

Files selected for processing: 3

  • quest/m0/cef-headless.md
  • quest/m0/cef-x11-nvidia.md
  • rs/moq-scene/src/browser/host.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@kixelated kixelated left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed head 9de4d36 against base c929c40.

No actionable findings. The ANGLE override is confined to Raster::Gpu with Display::X11, after selecting X11 Ozone. The existing Wayland selection, software/headless fallback, render-node override and shared-texture handoff remain unchanged. Selecting the EGL backend is a focused correction rather than adding CPU copies or a timing workaround.

Direction: keep this scoped X11 fix. The retained quests correctly leave Mesa Wayland validation, the no-output initialization hang, allocation-failure reporting and NVIDIA X11 unresolved; this change should not be treated as completing those paths.

Verification limits: GitHub-only static review of all three changed files and surrounding display selection/CEF initialization and paint handling. I did not run quest context, builds, browser tests or hardware trials, independently verify the reported GPU paints, or measure frame time, GPU copies or encoder load. The reported clipboard/cookie failures and headless hangs are not validated or fixed by this review.

(Written by review (OpenAI))

@kixelated
kixelated enabled auto-merge (squash) November 7, 2026 03:41
@kixelated
kixelated merged commit 306e114 into main Nov 7, 2026
3 checks passed
@kixelated
kixelated deleted the quest/m0/cef-headless branch November 7, 2026 03:56
kixelated added a commit that referenced this pull request Nov 7, 2026
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Nov 7, 2026
Under X11, CEF allocates shared textures on the device the X server hands
out over DRI3, whatever --render-node-override says. With the studio on
another GPU, that GPU's tiling came out scrambled while the source still
read as copied on the GPU. The studio now asks the X server for its DRI3
device at setup and takes the CPU path, saying why, when it is not the
studio's GPU.

A page painting into memory now carries why, which the Sources panel shows
on hover and Health lists while the program shows the source.

On NVIDIA under XWayland, the GPU path already paints since --use-angle=gl-egl
(#73), which finishes quest/m0/cef-x11-nvidia.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant