Skip to content

feat(multi-screen): per-part views for a straddling zone (XrDisplayZonePartsDXR, display_zones v4) + one majority rule - #2011

Draft
dfattal wants to merge 4 commits into
mainfrom
feat/zone-locate-per-screen
Draft

dfattal wants to merge 4 commits into
mainfrom
feat/zone-locate-per-screen

Conversation

@dfattal

@dfattal dfattal commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Runtime side of DisplayXR/displayxr-browser-pvt#272. Stacked follow-up: #2018 (present-owners + the painted-partition weave crop).

(A) A zone is framed from its own screen on every segmenting session (ADR-047 Amendment 9)

oxr_session_locate_views never splits a zone-scoped locate, and its one view set was framed from the window's majority screen. On sessions whose own compositor segments the window (in-process D3D11 / D3D12 / GL / Vulkan / Metal, or a direct client of the D3D11 service), a zone wholly on the other screen of a straddling window was rendered from the wrong viewer. It is now framed from the zone's screen: that screen's eyes and nominal viewer, the whole window relative to it, then the zone rebase. The present-owner path already did this (#1927).

(B) Per-part views for a straddling zone: XrDisplayZonePartsDXR (XR_DXR_display_zones v4, ADR-047 Amendment 10)

David's § 8.3 decisions are recorded in docs/roadmap/multi-screen.md § 8 (now "Decided").

  • New output struct, chained on XrViewState of a zone-scoped locate: XrDisplayZonePartsDXR / XrDisplayZonePartDXR, type 1004999155 (registry row updated). SPEC_VERSION 3 → 4. Spec: XR_DXR_display_zones.md § 3.3.2. index.json note updated; gen_extensions_index.py --check is green.
  • The runtime returns the parts (decision 1). Each part is located like a window segment over the parts' own table (u_weave_zone_part_table → oxr_segment_views_zone_parts). That screen's eyes are carried into the frame of the zone's majority screen, the part is the Kooima canvas on its own screen, and a display rig gets one m2v for the whole zone (vdh_scale and the rig offset with "window" read as "zone"), so the parts meet at the seam. This also holds across panels of different pitch.
  • XrView[] keeps the one set, so an app that does not chain the struct is unchanged. Two-call idiom, never an error.
  • PRIMARY_MULTIVIEW_DXR gets per-part zone views through the struct only (decision 6). Camera-centric locates are never split.
  • Seam: two viewers, no blending (decision 4).
  • Budget (decision 5): at most DXR_ZONE_PARTS_MAX (default 4, 0 = never, max 16) zones per display time are split, first located first served. Registered in the control-panel-performance-settings.md census.
  • Where it runs in this PR: in-process segmenting compositors and direct D3D11-service clients. Their parts are located client-side from the segment table, so there is no wire change. Present-owners are in the stacked PR.

(C) ⚠ Behaviour change: the majority rule now applies everywhere (decision 2)

A straddling zone's one view set is now framed from the screen holding most of the zone (u_weave_rect_majority_segment; ties go to the primary, then the leftmost) on every path:

  • This changes the browser / present-owner path (u_weave_zone_screen_segment, ipc_try_get_sr_view_poses). A straddling inline-3D element was framed from the primary screen. It is now framed from its majority screen, so an element mostly on screen 2 is rendered from screen 2's viewer and geometry. The browser needs no change to get this.
  • In-process and direct-IPC sessions used the window's majority. They now use the zone's.

Tests

tests/tests_weave_segments.cpp covers the majority rule (ties, slivers, off-window, and a sweep that asserts the server and client rules agree), the part table (cut, zone-relative rects, the same cut as the weave's rect parts), the part framing (own-screen canvas, eye-relative centre, one m2v, abutting virtual canvases, different pitch), and the per-frame budget. I built it standalone with MSVC and ran it: 24 cases, 2619 assertions, all pass. tests_oxr_segment_views (17 cases) also passes. oxr_session.c and ipc_server_handler.c compile locally with MSVC; CI does the rest. There was no hardware run: the panels were in use on the shared box.

🤖 Generated with Claude Code

dfattal and others added 4 commits October 12, 2026 14:58
…reen

oxr_session_locate_views never splits a zone-scoped locate, and its one
view set was framed from the screen holding most of the window. A zone
wholly on the other screen of a straddling window (an XR_DXR_display_zones
app on an in-process D3D11/D3D12/GL/Vulkan/Metal compositor, or a direct
client of the D3D11 service) was therefore rendered from the wrong viewer
and framed against the wrong panel, though that screen's DP wove it.

Now oxr_segment_views_zone_segment picks the segment holding the whole
zone, and the locate frames that screen's whole-window metrics with its
eyes and nominal viewer before the usual zone rebase. A zone on the
primary takes the single-screen path. A straddling zone keeps the
majority's set, as before. This is the in-process / direct-IPC twin of
the present-owner rule (ADR-047 Amendment 4 addendum,
u_weave_zone_screen_segment), and it picks the same screen wherever that
rule re-frames (swept in tests_weave_segments).

ADR-047 Amendment 9; XR_DXR_display_zones multi-screen note updated. No
extension revision: the locate API is unchanged.

Refs DisplayXR/displayxr-browser-pvt#272

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Design for the full fix of displayxr-browser-pvt#272: a zone-scoped
locate returns per-part view sets (XrDisplayZonePartsDXR, one m2v per
zone), the weave crops at the painted partition, and the browser exposes
each part as a view pair with a sub-viewport. Proposal only, with the
open questions that need David's sign-off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…isplayZonePartsDXR, spec v4)

A zone-scoped xrLocateViews of a zone that straddles the seam between two
screens can now return one view set per part, chained on XrViewState
(XR_DXR_display_zones v4, type 1004999155). Each part is located like a
window segment over the parts' own table (u_weave_zone_part_table ->
oxr_segment_views_zone_parts): that screen's eyes carried into the frame
of the zone's majority screen, the part as the Kooima canvas on its own
screen, and one m2v for the whole zone under a display rig, so the parts
meet at the seam. XrView[] keeps the zone's one set.

The one set of a straddling zone is framed from the screen holding most of
the ZONE on every path (u_weave_rect_majority_segment): the present-owner
rule (u_weave_zone_screen_segment) used the primary, every other session
the window's majority.

At most DXR_ZONE_PARTS_MAX (default 4) zones per display time are split,
first located first served. Camera-centric locates are never split;
PRIMARY_MULTIVIEW_DXR gets per-part zone views through the struct only.

In-process segmenting compositors and direct D3D11-service clients locate
the parts client-side from the segment table (no wire change). Present-owner
parts (server-side) and the painted-partition weave crop are a follow-up.

ADR-047 Amendment 10; XR_DXR_display_zones.md 3.3.2; census entry for
DXR_ZONE_PARTS_MAX; type-value registry row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Per-part views via XrDisplayZonePartsDXR (runtime returns the parts),
majority framing for unaware callers everywhere, extra XRViews with a
sub-viewport on the web (DisplayXR-only), seam accepted, a per-frame cap
of split zones, PRIMARY_MULTIVIEW_DXR via the struct only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dfattal
dfattal force-pushed the feat/zone-locate-per-screen branch from 8edf458 to ae65363 Compare October 12, 2026 21:58
@dfattal dfattal changed the title feat(multi-screen): frame a zone-scoped locate from the zone's own screen (+ per-part views proposal) feat(multi-screen): per-part views for a straddling zone (XrDisplayZonePartsDXR, display_zones v4) + one majority rule Oct 12, 2026
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