Skip to content

feat(linux): populate the per-monitor display registry (multi-screen M0) - #1851

Merged
dfattal merged 8 commits into
mainfrom
feat/multi-screen-m0-screen-registry
Oct 7, 2026
Merged

dfattal merged 8 commits into
mainfrom
feat/multi-screen-m0-screen-registry

Conversation

@dfattal

@dfattal dfattal commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1850. Refs #69 and #1849 (the plan + ADR-047). Multi-screen plan M0 (docs/roadmap/multi-screen.md).

What and why

The per-monitor DP registry (ADR-015) was empty on Linux. os_display_edid_enumerate was a stub off Windows, so build_dp_registry() did nothing, and POSIX asked only the active plug-in for claims. M0 makes the registry a real screen registry on desktop Linux.

  1. Linux monitor enumeration (os_display_edid_linux.c, desktop Linux only; Android and macOS keep the stub). Each RandR monitor from os_display_desktop_enumerate (placement rect, primary flag) is tied to one connected DRM connector in /sys/class/drm/card*-* (EDID, status, enabled, modes). The first rule that fires wins:

    • name: HDMI-A-1 → HDMI-1.
    • mm: exactly one connector whose EDID size is within 10 mm of the RandR size.
    • mode: exactly one connector that has the monitor's pixel mode.

    An ambiguous monitor is listed without EDID identity, never guessed. A connector is used at most once. With no X server, every connected and enabled connector becomes a DRM-only record flagged origin_unknown. The EDID parser reads the manufacturer and product id (bytes 8-11), the serial (12-15), the size in cm (21/22), and the first detailed timing's pixels, mm and refresh. The loader logs the join method per monitor once at INFO.

  2. Claims from every plug-in on POSIX. A new POSIX collect_display_sources_platform mirrors the Windows one. It uses the same manifest roots and order as discovery, honours DXR_PLUGIN_EXCLUSIVE, and reuses the active plug-in instead of loading it twice. try_load_one is split into load_and_probe_one plus the active-plug-in wrapper, as on Windows. The other plug-ins are claim sources only: no device is created from them, and active selection is unchanged.

  3. The registry is populated at instance create. displayxr-cli displays and displays --claims list both monitors with geometry, mm, EDID ids, serial, connector, the resolved plug-in and its confidence.

A decision the plan did not cover: where the back-compat claim lands

A plug-in without probe_displays gets a synthesized EDID claim on the primary monitor. On this box the primary monitor is eDP-1, and the active plug-in wins every monitor it claims (#1521). The registry would therefore have sent eDP-1 to leia-sr and HDMI-1 to sim-display, which is backwards.

Off-Windows, the active plug-in's synthesized claim now lands on the monitor its panel matches. The panel comes from the plug-in's own get_display_info, which the builder and the display-info apply path record with target_plugin_note_active_panel. The match reuses the ADR-033 rules: non-zero origin, then connector mode, then pixel size, with ties broken on physical size (os_display_desktop_select_by_size). Windows keeps the primary-monitor claim unchanged. A plug-in that implements probe_displays never takes the synthesized path, so the Leia plug-in's real claim decides as soon as that plug-in PR lands. displays --claims brings the system up headlessly first, so it reports the same placement as the runtime.

Other notes

  • No plug-in ABI change. xrt_display_descriptor is untouched. Connector, mm, device mode and the join method live in os_display_edid_monitor, which is runtime-internal, and in a loader side table keyed by monitor_id.
  • monitor_id change on Linux. The id now also hashes the connector name when the platform has one, so DRM-only records at (0, 0) stay distinct. Windows has no connector, so its ids are unchanged.
  • No compositor or oxr change. On Linux nothing reads the registry yet: the Vulkan compositor uses the scalar dp_factory_*, and the registry-routed consumers (in-process GL, the D3D11 service) are Windows-only. Weaving is unchanged.
  • New behaviour carried over from Windows. With XRT_PREFERRED_PLUGIN_ID=sim-display, an installed vendor plug-in is now loaded and probed for its claims. DXR_PLUGIN_EXCLUSIVE still keeps it out of the process.

displayxr-cli displays --claims on ds1-linux

Laptop eDP-1 plus an Acer DS1 on HDMI, GNOME Wayland with XWayland, installed leia-sr 2.10.0 active, dev sim-display:

 :: Connected displays (EDID)
	[0] SDC 423F  3456x2160 @ 0Hz  pos (0,0)  [primary]
	    serial=0x0000003F  300x190 mm  native 2880x1800  output='eDP-1' connector='eDP-1' join=name
	[1] ACR 0001  3840x2160 @ 60Hz  pos (3456,0)
	    serial=0x322EF05E  344x193 mm  native 3840x2160  output='HDMI-1' connector='HDMI-A-1' join=name
 :: Per-display DP claims (resolved registry, #69)
	monitor 0x03fdab50663276e4  3456x2160 @ (0,0)
	    SDC 423F serial=0x0000003F  300x190 mm  output=eDP-1  connector=eDP-1  [primary]
	    plug-in='sim-display'  confidence=FALLBACK  apis=vk|gl
	monitor 0x886e4475353b22b9  3840x2160 @ (3456,0)
	    ACR 0001 serial=0x322EF05E  344x193 mm  output=HDMI-1  connector=HDMI-A-1
	    plug-in='leia-sr'  confidence=EDID  apis=(none)

Log line: 'leia-sr' has no probe_displays — back-compat claim placed on its panel (monitor 0x886e…, 3840x2160 at (3456,0)) instead of the primary monitor.

apis=(none) on leia-sr is not caused by this PR. The installed plug-in (2.10.0) fails the existing #1243 vk_bundle ABI guard against this runtime (sizeof 2168 vs 2176 in Release), and the scalar path refuses the same factory today. A matching plug-in build shows vk.

With DISPLAY unset (no X server), the same box lists two DRM-only records, HDMI-A-1 and eDP-1, each with join=drm-only and (origin unknown).

Tests

  • New tests_aux_display_edid_linux (desktop Linux only, hardware-free):
    • EDID parse of the real DS1 base block (ACR, serial, DTD 3840x2160@60, 344x193 mm).
    • eDP with no serial and no DTD, falling back to cm.
    • Aspect-ratio encoding in bytes 21/22 is not treated as a size.
    • Short and headerless blobs are rejected.
    • Joins by name, by mm and by mode.
    • Identical panels stay unjoined.
    • A connector is used at most once.
    • DRM-only records when there is no X server.
    • The sysfs reader against a temp-dir fixture.
  • ./scripts/build_linux.sh and its selftest pass, in both Debug and Release.
  • ctest: the new test plus tests_aux_display_desktop_select pass. tests_rig_composer and tests_oxr_view_space* fail on this box with or without this branch. The same failure counts appear on a Sep-30 main build; they depend on the live Leia panel.
  • build-mingw-check.sh aux_os passes. MinGW cannot compile target_plugin_loader.c (<Windows.h> case), so the Windows side of the loader change relies on CI.

🤖 Generated with Claude Code

@dfattal
dfattal requested a review from a team as a code owner October 7, 2026 17:40
dfattal added a commit that referenced this pull request Oct 7, 2026
…ed names, card prefix)

Review of #1851, finding 1. A bare name match could tie a monitor to the
wrong connector. The NVIDIA X driver numbers outputs from 0 (DP-0, DP-1) while
nvidia-drm connectors start at 1, and two GPUs can each have an HDMI-A-1.

- New first rule (randr-edid): when the X server publishes the output's own
  EDID property (native X; XWayland does not), that is the identity. The
  connector is the one enabled connector with the same vendor/product/serial,
  or, among identical ones, the one whose name agrees.
  os_display_x11_read_monitor_edids reads it, with Xrandr still dlopen'd and
  the new entry points optional.
- A name match now counts only when the connector agrees physically: its
  modes hold the monitor's device mode, or its EDID mm is within tolerance.
  The device mode is the compositor's (Mutter) mode, else the RandR rect,
  never the DRM-derived mode, which was itself found by name. Same-named
  connectors on two cards are both considered.
- The connector name keeps its card prefix ("card1-HDMI-A-1"), and so does the
  monitor_id hash.
- DRM connectors are sorted by name, so DRM-only order is stable across boots.
- Connected-but-disabled connectors are excluded from the mm and mode joins.

Tests: NVIDIA off-by-one naming, the same name on two cards, a disabled twin
of the panel, X server EDID with and without identical connectors, and the
sorted sysfs read. plugin-discovery.md §3.4 updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal added a commit that referenced this pull request Oct 7, 2026
… release them with the instance

Review of #1851, finding 2. On POSIX, every installed plug-in was loaded and
probed as a claim source even when the outcome was already settled. With
XRT_PREFERRED_PLUGIN_ID=sim-display, every in-process app dlopened the Leia
plug-in and ran its SR probe against the shared DS1, and that claim-only
instance was never released.

- The active plug-in wins every monitor it claims (#1521), and only a
  different pinned plug-in outranks it. When the active plug-in claims every
  monitor and no other plug-in is preferred, the POSIX source set is now the
  active plug-in alone, so nothing else is dlopened or probed. The check is
  repeated on each resolve (a later descriptor set may hold a monitor it does
  not claim). This covers XRT_PREFERRED_PLUGIN_ID=sim-display and a
  sim-display-only box.
- New target_plugin_release_claim_sources(), called from t_instance_destroy.
  It calls destroy() on every claim-only instance (never the active one),
  pairing with the probe() that made it, and drops the cache so the next
  resolve re-collects. dlopen handles stay loaded, as for every plug-in.

Windows keeps its existing behaviour (all registered plug-ins are claim
sources for the process lifetime); Android has no claim-only sources.

Verified on ds1-linux: XRT_PREFERRED_PLUGIN_ID=sim-display `displays --claims`
never loads leia-sr; the default run still resolves eDP-1 -> sim-display and
HDMI-1 -> leia-sr, and selftest logs the release of sim-display at teardown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal added a commit that referenced this pull request Oct 7, 2026
Review of #1851, finding 3. The placement of the back-compat claim (for a
plug-in without probe_displays) now comes from a pure, exported policy,
target_plugin_backcompat_claim_index(). synth_primary_edid_claim feeds it the
active plug-in's noted panel and the side-table records, so the loader and the
tests run the same code.

New tests_target_backcompat_claim (links target_lists, like
tests_input_host_geometry):
- no panel known gives the primary (or descriptor 0, or a primary that is
  not first);
- the DS1 panel lands on the HDMI monitor, not the eDP primary, by connector
  device mode, and by pixel size when no device mode is known;
- a plug-in origin inside a known monitor is trusted first and settles two
  same-size monitors;
- an origin is never matched against DRM-only records (origin unknown);
- a panel that matches nothing, or has no pixel size, falls back to the
  primary.

The join cases from the same review item (NVIDIA off-by-one naming, identical
panels, disabled connector) landed with the join fix in the previous commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal added a commit that referenced this pull request Oct 7, 2026
Review of #1851, finding 4. Refresh came only from the EDID's first detailed
timing, and only when that timing matched the mode in use. eDP panels often
carry no detailed timing in the base block, so eDP-1 printed 0Hz.

Mutter's DisplayConfig already returns each connector's current mode with its
refresh. os_display_connector_annotate now keeps it
(os_display_desktop_info::native_refresh_mhz, compositor source only; DRM
sysfs has no refresh). The join prefers it over the EDID guess. ds1-linux now
reports eDP-1 @ 60Hz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dfattal

dfattal commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

Review fixes pushed: one commit per finding.

# Finding Commit
1 RandR↔DRM join hardening ff03b5a50
2 Claim sources loaded only when they can matter, and released with the instance 36ee14709
3 Tests for where the stand-in claim lands 6cdab1dc0
4 Refresh rate from the compositor's current mode 010da945c

1. Join hardening (ff03b5a50)

  • When the X server publishes an output's own EDID property (native X does; XWayland does not), that is now the first rule and the monitor's identity.
  • A name match counts only when the connector also agrees physically: its modes include the monitor's device mode, or its EDID size is within tolerance. The device mode is Mutter's, else the RandR rect, never the mode read from DRM.
  • The connector name keeps its card prefix (card1-HDMI-A-1).
  • Connectors are sorted by name, so DRM-only order is stable across boots.
  • Disabled connectors are excluded from the mm and mode rules.
  • New tests cover NVIDIA's off-by-one names, the same name on two cards, a disabled twin, and the X server's EDID.

2. Claim sources (36ee14709)

  • On POSIX, other plug-ins are no longer loaded when the active plug-in claims every monitor and no other plug-in is preferred, because they could not change the result.
  • XRT_PREFERRED_PLUGIN_ID=sim-display therefore never loads leia-sr. I checked this on ds1-linux.
  • Plug-ins loaded only as claim sources are released at t_instance_destroy.
  • Windows behaviour is unchanged.

3. Placement tests (6cdab1dc0)

  • The rule for where the stand-in claim lands is now a pure exported function, target_plugin_backcompat_claim_index.
  • New tests_target_backcompat_claim pins it: the claim lands on the panel's monitor, not the primary.

4. Refresh (010da945c)

  • Refresh now comes from Mutter's current mode, so eDP-1 reports 60Hz instead of 0Hz.

Updated displayxr-cli displays --claims on ds1-linux. The monitor ids change because the connector key now includes the card prefix.

	monitor 0x355a98151b71a984  3456x2160 @ (0,0)
	    SDC 423F serial=0x0000003F  300x190 mm  output=eDP-1  connector=card1-eDP-1  [primary]
	    plug-in='sim-display'  confidence=FALLBACK  apis=vk|gl
	monitor 0x0b4e5796bb9ae0d9  3840x2160 @ (3456,0)
	    ACR 0001 serial=0x322EF05E  344x193 mm  output=HDMI-1  connector=card1-HDMI-A-1
	    plug-in='leia-sr'  confidence=EDID  apis=(none)

Checks: build_linux.sh and its selftest pass, the new tests pass, and build-mingw-check.sh aux_os passes. The same 5 tests fail on this box as before (tests_rig_composer and tests_oxr_view_space*); they depend on the live panel.

Not verified on hardware: the X-server EDID rule (this box runs XWayland, which publishes no EDID) and NVIDIA naming. Unit tests cover both.

🤖 Generated with Claude Code

dfattal and others added 8 commits October 7, 2026 13:58
…RM sysfs)

os_display_edid_enumerate was a stub off Windows, so the per-monitor DP
registry (#69 / ADR-015) stayed empty on Linux. The new desktop-Linux
enumerator ties each RandR monitor (placement rect, primary) to one DRM
connector from /sys/class/drm (EDID, connector name, modes): by output
name, else a unique physical-size match, else a unique pixel-mode match.
It never guesses: an ambiguous monitor is listed without EDID identity.
With no X server every connected, enabled connector becomes a DRM-only
record flagged origin_unknown.

The EDID parser reads the manufacturer/product ids (bytes 8-11), the serial
(12-15), the cm size (21/22) and the first detailed timing's pixels, mm and
refresh. os_display_edid_monitor gains runtime-private fields (serial, mm,
device mode, connector, RandR name, join method, origin_unknown); the
plug-in-facing xrt_display_descriptor is unchanged. aux_os stays free of
logging and new link dependencies.

Multi-screen plan M0, part of #1850.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k-compat claim on the panel

POSIX ensure_display_sources consulted only the active plug-in. It now loads
every manifest plug-in as a claim source through a POSIX
collect_display_sources_platform, the twin of the Windows one: same roots and
order as discovery, DXR_PLUGIN_EXCLUSIVE honoured, the active plug-in reused.
try_load_one is split into load_and_probe_one + the active-plug-in wrapper,
as on Windows. Non-active plug-ins are claim sources only; active selection is
unchanged. Android keeps the single active source.

A plug-in without probe_displays gets a synthesized EDID claim on the primary
monitor. With the registry now populated on Linux, that put the vendor's claim
on the laptop screen, and because the active plug-in wins every monitor it
claims (#1521) the laptop would route to the vendor DP and the 3D panel to
sim-display. Off-Windows the ACTIVE plug-in's synthesized claim now lands on
the monitor its panel matches (ADR-033 rules: origin, connector mode, pixel
size). The match uses the get_display_info noted by the builder and the
display-info apply path (target_plugin_note_active_panel). Windows is
unchanged, and a real probe_displays always decides.

monitor_id also hashes the connector name when there is one (unchanged on
Windows). The loader logs each monitor's join method once at INFO.
`displayxr-cli displays` prints serial, mm, device mode, output, connector and
join. `displays --claims` brings the system up headlessly first, so its
placement matches the runtime's.

Multi-screen plan M0, part of #1850.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hardware-free tests for multi-screen M0. The fixtures are the DS1's real EDID
base block (ACR 0001, serial 0x322EF05E, DTD 3840x2160@60, 344x193 mm) and an
eDP block with no serial and no detailed timing (cm fallback). Cases: name, mm
and mode joins; identical panels left unjoined; one connector per monitor;
DRM-only records with an unknown origin when no X server is reachable; the
sysfs reader against a temp-dir fixture (connected/disconnected, enabled,
edid, modes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lug-in claims

New §3.4 covers the RandR<->DRM join rules, the DRM-only fallback, the
runtime-private extras and monitor_id, POSIX claim collection from every
plug-in (and the XRT_PREFERRED_PLUGIN_ID consequence), and the active
plug-in's back-compat claim following its panel off-Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed names, card prefix)

Review of #1851, finding 1. A bare name match could tie a monitor to the
wrong connector. The NVIDIA X driver numbers outputs from 0 (DP-0, DP-1) while
nvidia-drm connectors start at 1, and two GPUs can each have an HDMI-A-1.

- New first rule (randr-edid): when the X server publishes the output's own
  EDID property (native X; XWayland does not), that is the identity. The
  connector is the one enabled connector with the same vendor/product/serial,
  or, among identical ones, the one whose name agrees.
  os_display_x11_read_monitor_edids reads it, with Xrandr still dlopen'd and
  the new entry points optional.
- A name match now counts only when the connector agrees physically: its
  modes hold the monitor's device mode, or its EDID mm is within tolerance.
  The device mode is the compositor's (Mutter) mode, else the RandR rect,
  never the DRM-derived mode, which was itself found by name. Same-named
  connectors on two cards are both considered.
- The connector name keeps its card prefix ("card1-HDMI-A-1"), and so does the
  monitor_id hash.
- DRM connectors are sorted by name, so DRM-only order is stable across boots.
- Connected-but-disabled connectors are excluded from the mm and mode joins.

Tests: NVIDIA off-by-one naming, the same name on two cards, a disabled twin
of the panel, X server EDID with and without identical connectors, and the
sorted sysfs read. plugin-discovery.md §3.4 updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… release them with the instance

Review of #1851, finding 2. On POSIX, every installed plug-in was loaded and
probed as a claim source even when the outcome was already settled. With
XRT_PREFERRED_PLUGIN_ID=sim-display, every in-process app dlopened the Leia
plug-in and ran its SR probe against the shared DS1, and that claim-only
instance was never released.

- The active plug-in wins every monitor it claims (#1521), and only a
  different pinned plug-in outranks it. When the active plug-in claims every
  monitor and no other plug-in is preferred, the POSIX source set is now the
  active plug-in alone, so nothing else is dlopened or probed. The check is
  repeated on each resolve (a later descriptor set may hold a monitor it does
  not claim). This covers XRT_PREFERRED_PLUGIN_ID=sim-display and a
  sim-display-only box.
- New target_plugin_release_claim_sources(), called from t_instance_destroy.
  It calls destroy() on every claim-only instance (never the active one),
  pairing with the probe() that made it, and drops the cache so the next
  resolve re-collects. dlopen handles stay loaded, as for every plug-in.

Windows keeps its existing behaviour (all registered plug-ins are claim
sources for the process lifetime); Android has no claim-only sources.

Verified on ds1-linux: XRT_PREFERRED_PLUGIN_ID=sim-display `displays --claims`
never loads leia-sr; the default run still resolves eDP-1 -> sim-display and
HDMI-1 -> leia-sr, and selftest logs the release of sim-display at teardown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #1851, finding 3. The placement of the back-compat claim (for a
plug-in without probe_displays) now comes from a pure, exported policy,
target_plugin_backcompat_claim_index(). synth_primary_edid_claim feeds it the
active plug-in's noted panel and the side-table records, so the loader and the
tests run the same code.

New tests_target_backcompat_claim (links target_lists, like
tests_input_host_geometry):
- no panel known gives the primary (or descriptor 0, or a primary that is
  not first);
- the DS1 panel lands on the HDMI monitor, not the eDP primary, by connector
  device mode, and by pixel size when no device mode is known;
- a plug-in origin inside a known monitor is trusted first and settles two
  same-size monitors;
- an origin is never matched against DRM-only records (origin unknown);
- a panel that matches nothing, or has no pixel size, falls back to the
  primary.

The join cases from the same review item (NVIDIA off-by-one naming, identical
panels, disabled connector) landed with the join fix in the previous commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #1851, finding 4. Refresh came only from the EDID's first detailed
timing, and only when that timing matched the mode in use. eDP panels often
carry no detailed timing in the base block, so eDP-1 printed 0Hz.

Mutter's DisplayConfig already returns each connector's current mode with its
refresh. os_display_connector_annotate now keeps it
(os_display_desktop_info::native_refresh_mhz, compositor source only; DRM
sysfs has no refresh). The join prefers it over the EDID guess. ds1-linux now
reports eDP-1 @ 60Hz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dfattal
dfattal force-pushed the feat/multi-screen-m0-screen-registry branch from 010da94 to be5490f Compare October 7, 2026 20:59
@dfattal
dfattal merged commit 959be0b into main Oct 7, 2026
40 checks passed
dfattal added a commit that referenced this pull request Oct 7, 2026
…ed names, card prefix)

Review of #1851, finding 1. A bare name match could tie a monitor to the
wrong connector. The NVIDIA X driver numbers outputs from 0 (DP-0, DP-1) while
nvidia-drm connectors start at 1, and two GPUs can each have an HDMI-A-1.

- New first rule (randr-edid): when the X server publishes the output's own
  EDID property (native X; XWayland does not), that is the identity. The
  connector is the one enabled connector with the same vendor/product/serial,
  or, among identical ones, the one whose name agrees.
  os_display_x11_read_monitor_edids reads it, with Xrandr still dlopen'd and
  the new entry points optional.
- A name match now counts only when the connector agrees physically: its
  modes hold the monitor's device mode, or its EDID mm is within tolerance.
  The device mode is the compositor's (Mutter) mode, else the RandR rect,
  never the DRM-derived mode, which was itself found by name. Same-named
  connectors on two cards are both considered.
- The connector name keeps its card prefix ("card1-HDMI-A-1"), and so does the
  monitor_id hash.
- DRM connectors are sorted by name, so DRM-only order is stable across boots.
- Connected-but-disabled connectors are excluded from the mm and mode joins.

Tests: NVIDIA off-by-one naming, the same name on two cards, a disabled twin
of the panel, X server EDID with and without identical connectors, and the
sorted sysfs read. plugin-discovery.md §3.4 updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal added a commit that referenced this pull request Oct 7, 2026
… release them with the instance

Review of #1851, finding 2. On POSIX, every installed plug-in was loaded and
probed as a claim source even when the outcome was already settled. With
XRT_PREFERRED_PLUGIN_ID=sim-display, every in-process app dlopened the Leia
plug-in and ran its SR probe against the shared DS1, and that claim-only
instance was never released.

- The active plug-in wins every monitor it claims (#1521), and only a
  different pinned plug-in outranks it. When the active plug-in claims every
  monitor and no other plug-in is preferred, the POSIX source set is now the
  active plug-in alone, so nothing else is dlopened or probed. The check is
  repeated on each resolve (a later descriptor set may hold a monitor it does
  not claim). This covers XRT_PREFERRED_PLUGIN_ID=sim-display and a
  sim-display-only box.
- New target_plugin_release_claim_sources(), called from t_instance_destroy.
  It calls destroy() on every claim-only instance (never the active one),
  pairing with the probe() that made it, and drops the cache so the next
  resolve re-collects. dlopen handles stay loaded, as for every plug-in.

Windows keeps its existing behaviour (all registered plug-ins are claim
sources for the process lifetime); Android has no claim-only sources.

Verified on ds1-linux: XRT_PREFERRED_PLUGIN_ID=sim-display `displays --claims`
never loads leia-sr; the default run still resolves eDP-1 -> sim-display and
HDMI-1 -> leia-sr, and selftest logs the release of sim-display at teardown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal added a commit that referenced this pull request Oct 7, 2026
Review of #1851, finding 3. The placement of the back-compat claim (for a
plug-in without probe_displays) now comes from a pure, exported policy,
target_plugin_backcompat_claim_index(). synth_primary_edid_claim feeds it the
active plug-in's noted panel and the side-table records, so the loader and the
tests run the same code.

New tests_target_backcompat_claim (links target_lists, like
tests_input_host_geometry):
- no panel known gives the primary (or descriptor 0, or a primary that is
  not first);
- the DS1 panel lands on the HDMI monitor, not the eDP primary, by connector
  device mode, and by pixel size when no device mode is known;
- a plug-in origin inside a known monitor is trusted first and settles two
  same-size monitors;
- an origin is never matched against DRM-only records (origin unknown);
- a panel that matches nothing, or has no pixel size, falls back to the
  primary.

The join cases from the same review item (NVIDIA off-by-one naming, identical
panels, disabled connector) landed with the join fix in the previous commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dfattal
dfattal deleted the feat/multi-screen-m0-screen-registry branch October 7, 2026 21:38
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.

Multi-screen M0: populate the per-monitor display registry on Linux (every plug-in's claims, displayxr-cli displays)

1 participant