fix(multi/linux): route a present-owner's hardware 2D/3D request to the weave engine's DP (#1774) - #1775
Conversation
…he weave engine's DP (#1774) On the desktop-Linux service an XR_DXR_weave present-owner (the DisplayXR browser) has no window, so session_render is never initialised and multi_compositor_request_display_mode returned false at its first gate. Every xrRequestDisplayModeDXR from the browser's tab policy (browser#55) was dropped silently, and no hardware-state event was ever sent. The weave engine's own DP (mc->weave.dp), the only DP in the service and the one holding the vendor lens, never heard about it, so the panel stayed lensed over a 2D tab. - comp_multi_compositor.c: under COMP_MULTI_HAVE_WEAVE && XRT_OS_LINUX_DESKTOP, a client without per-session render goes to the weave engine. - comp_multi_weave_linux.c: comp_multi_weave_linux_request_display_mode applies the request inline on the IPC thread under weave.mutex, as the D3D11 service's #815 does: a present-owner asking for 2D has stopped submitting, so a frame-gated apply would never run. Before the engine exists the wish is recorded and applied at engine bring-up. The hardware-state event is sent to the session only once the DP confirmed a change (#961; a DP with no slot is mode-neutral and counts as accepted). There is one WARN per transition, with the DP's get_hardware_3d_state read-back. - sim_display (Vulkan DP): SIM_DISPLAY_FAKE_LENS=1 fills request_display_mode and get_hardware_3d_state with a recording fake lens (one WARN per transition). It is off by default, so default behaviour is unchanged. - weave_present_vk_linux --test-display-mode (headless) requests 2D before the first submit, then 3D, then 2D, and requires exactly the events 2D, 3D, 2D, each one before the next request. Windows, macOS and Android are untouched: the new branch is compiled only on desktop Linux with the weave service. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cover stale/fast switches (#1774) Review refinements on top of the present-owner display-mode routing: - The hardware-state event carries the REQUESTED state once the DP accepted it (#961), never a read-back. A vendor lens may switch asynchronously (Leia SR flips it via LENS_ON/OFF events), so an immediate get_hardware_3d_state can still show the old state. The read-back is now logged as information only: "DP readback: 3D (may lag — the lens switches asynchronously)". - The DP call runs on the IPC thread under weave.mutex, so it is timed with os_monotonic_get_ns and the duration goes into the per-transition (and rejection) WARN, "in N ms", with "(slow)" past 50 ms. No behaviour change. - A 3D request before the engine exists withdraws a recorded 2D (one WARN), so bring-up applies nothing stale. - weave_present_vk_linux --test-display-mode is now table-driven: - stale (default): 2D,3D before the first submit (no event at bring-up), then 2D, the fast triple 3D,2D,3D in one frame, a no-op 3D (no duplicate event) and 2D. It expects the events 2D,3D,2D,3D,2D in order. - =deferred: the original pre-submit 2D applied at bring-up. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
950bfae to
981ea6e
Compare
|
Hardware check passed (pre-merge, 2026-10-02) on a Leia 3D display, GNOME 50 Wayland: this branch's hybrid build as the service + a locally built Leia Linux plug-in (real srSDK backend) + the released browser v1.0.10 pointed at it. Switching from an inline-3D tab to a 2D tab turned the lens off, and back on when returning — confirmed by eye. Service log: the plug-in's |
Fixes #1774. On desktop Linux, switching the DisplayXR browser from an inline-3D tab to a 2D tab left the panel's lens on.
Call chains
Windows (reference): browser tab policy →
xrRequestDisplayModeDXR→oxr_session_request_display_mode(IPC branch) →ipc_handle_compositor_request_display_mode→compositor_request_display_mode(comp_d3d11_service.cpp) →service_apply_pending_mode(applied immediately on the IPC thread, #815) →apply_mode_transition→ the DP'srequest_display_mode→broadcast_hardware_state(only after the DP accepts, #961).Linux before this PR: … →
ipc_handle_compositor_request_display_mode→multi_compositor_request_display_mode, which returnsfalsewhen!mc->session_render.initialized. A present-owner has no window, so that condition is always true for it.Drop point: the weave engine's DP (
mc->weave.dp, created inweave_ensure_engine) is never called, and noHARDWARE_DISPLAY_STATE_CHANGEevent is sent anywhere on the Linux service path.Change
comp_multi_compositor.c: on desktop Linux with the weave service, a client that has no per-session render is routed to the weave engine.comp_multi_weave_linux.c:comp_multi_weave_linux_request_display_modeapplies the request immediately, underweave.mutex, the same lock order every submit uses.request_display_modeslot counts as accepted, the same rule asdp_request_display_mode_confirmed. A request for the state the panel is already in sends no event.get_hardware_3d_stateright after the request can still show the old state.weave(#1699): hardware 3D -> 2D (xrRequestDisplayModeDXR) on the weave engine's display processor (request_display_mode accepted) in N ms[ (slow)]; DP readback: 2D (may lag — the lens switches asynchronously).(slow)is added above 50 ms.SIM_DISPLAY_FAKE_LENS=1turns on a fake lens that records each request, so a headless run can see where the request lands. It is off by default, so default behaviour does not change.weave_present_vk_linux --headless N --test-display-mode[=stale|deferred]: sends batches of requests and requires the matching events, in order, with each batch's events present before the next batch.stale(default): 2D then 3D before the first submit (no event at start-up), then 2D, a fast 3D, 2D, 3D within one frame, a repeated 3D (must send no duplicate event), and 2D. Expected events: 2D, 3D, 2D, 3D, 2D.deferred: 2D before the first submit (applied at start-up), then 3D, then 2D. Expected events: 2D, 3D, 2D.Windows, macOS and Android are unchanged: the new branch only compiles under
COMP_MULTI_HAVE_WEAVE && XRT_OS_LINUX_DESKTOP.Verification (headless, sim_display)
The dev service ran in a private
XDG_RUNTIME_DIRwithDXR_PLUGIN_EXCLUSIVE=sim-display(log showsactive plug-in: id=sim-display), and the client used the same env.stalewithSIM_DISPLAY_FAKE_LENS=1: PASS.deferredwithSIM_DISPLAY_FAKE_LENS=1: PASS.stalewith no fake lens (the DP has no mode slot, so it counts as accepted): PASS.--expect-anaglyphself-check passes, and fd counts stay flat.ctest: 73/75 pass. The two failures (tests_rig_composer,tests_oxr_view_space) also fail on an unmodifiedorigin/mainbuild on this box.Not yet verified on hardware. sim_display only shows the request reaches the right DP and the events follow. A run on the Leia panel still has to confirm the lens actually drops on a 2D tab and comes back on an inline-3D tab. On the switch, the service journal should show the plug-in's
lens OFF (request_display_mode(2D))line and the newweave(#1699): hardware 3D -> 2D … in N msWARN. The browser log should showdisplay-mode event: panel hardware is now 2D.Known scope limit: the event goes only to the session that asked. The Linux service has no arbiter for which session controls the panel, and the Leia lens state is shared across the whole service process, so with two present-owners the last request wins.
🤖 Generated with Claude Code