Skip to content

Android inline-3D: rig zone and woven rect differ by a constant 168 px (56 dp) — double image #165

Description

@dfattal

Summary

On Android the inline-3D rig zone and the woven canvas rect disagree by a constant 168 device px vertically. The runtime therefore solves each eye's view for a zone ~1/2 inch higher on the panel than the pixels actually being woven, and the result on a 3D display is a double image — a disparity error, not a phase error.

168 px on the test device (480 dpi, density 3.0) is exactly 56 dp, the toolbar height. The zone appears to be reported in content-viewport coordinates while the weave rect is in window/surface coordinates that include the browser chrome.

Windows is unaffected and weaves correctly on the same pages.

Evidence

Two pages with different layouts and different scroll positions, same delta:

page zone(device px) woven rect Δy
samples/windows (multi-canvas) 60,1558 960x960 60,1726 960x467 168
samples/hello-cube (single canvas) 60,1590 960x480 60,1758 960x435 168

Log lines:

[DisplayXR] android rig locate live: 2 views | zone(device px)=60,1590 960x480
            | bound window(device px)=0,0 1080x2193 display=0 | virtualDisplayHeight=0.12m
            | fov L/R/U/D=-0.00599997/0.135171/0.155729/-0.155729
[DisplayXR] weave zero-copy failed: BeginScopedReadAccess(canvas) (rect=60,1758 960x435)
[DisplayXR] weave window bound: origin 0,0 client 1080x2193 display 0

Note the height also differs (480 vs 435), but that part is explained: 1758 + 435 = 2193 is exactly the bound window height, i.e. the rect is clipped at the viewport bottom while the zone is not. The origin delta is the defect.

The window is bound at origin 0,0 client 1080x2193 on a 1080x2400 panel. 2400 - 2193 = 207, which is not the 168 offset — so this is not simply the bound window being wrong; the two coordinate spaces are separately derived and one of them omits the toolbar.

Why this reads as "texture size wrong" rather than "phase"

Phase errors shift the interlace comb and show as a stripe/ghost that moves with head position. This instead shows a stable doubled image at every head position, because the per-eye frusta are computed for a zone whose screen rect doesn't match the pixels being woven.

Where to look

  • xrWeaveBindWindow2DXR — window geometry comes from the browser's Java UI per docs/android-port.md; likely the content view rect rather than the surface rect (or vice-versa for the zone).
  • The rig zone path that emits android rig locate live: — whichever of the two is not toolbar-adjusted.
  • Whatever the mac backend does here is the reference: the mac arm has no in-window chrome offset problem, and Windows passes an HWND whose client rect is consistently the origin for both.

Repro

  1. Runtime + vendor plug-in installed; a 3D panel at density 3.0.
  2. Launch with --enable-inline-3d --enable-blink-features=DisplayXRInline3D (via /data/local/tmp/chrome-command-line + am set-debug-app --persistent).
  3. Load displayxr-web/samples/hello-cube.
  4. adb logcat | grep -oE "zone\(device px\)=[^|]*|rect=[0-9]+,[0-9]+ [0-9]+x[0-9]+" and compare the two origins.

Eyeball: content weaves (all rects, both pages) but shows a persistent double image.

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions