diff --git a/README.md b/README.md index 6dd32be..018cfed 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,11 @@ SSH, SFTP, Steam Link, remote desktop, volume, sleep, restart and shut down. -Nothing is installed on the Frame for any of this: the app uses what SteamOS -already ships (sideloading a game copies Valve's own devkit scripts to -`~/devkit-utils`, as Valve's Devkit Client does). [How each feature works](docs/frame-control.md). +The app uses what SteamOS already ships. Sideloading copies Valve's devkit +scripts to `~/devkit-utils`, as Valve's Devkit Client does; the optional +[performance HUD](docs/vr-utilities.md) copies our own Python helpers into +`~/.local/share/frame-control/vr/`. Neither needs a third-party app. +[How each feature works](docs/frame-control.md). ## Install @@ -200,7 +202,7 @@ Frame's software fits together, all checked against a real headset and labelled | [Android apps (Lepton)](docs/apks.md) | Sideloading, the rated F-Droid catalogue, per-app instances | | [Sideloading Linux and Windows games](docs/sideloading.md) | A .zip, folder or .exe as a Steam Devkit Game, runtime detection | | [Install links for websites](docs/web-install.md) | `frame-control://install` links and manifests, the rules, a button to paste | -| [Steam games](docs/steam-games.md) · [VR video](docs/vr-video.md) · [WebXR in Chromium](docs/webxr-chromium.md) | Installing and buying, watching VR180/360, the Chromium build | +| [VR comfort and HUD](docs/vr-utilities.md) · [Steam games](docs/steam-games.md) · [VR video](docs/vr-video.md) · [WebXR in Chromium](docs/webxr-chromium.md) | Installing and buying, watching VR180/360, the Chromium build | | [SSH](docs/ssh.md) · [Streaming](docs/streaming.md) · [Files](docs/file-transfer.md) · [Panels](docs/panels.md) · [Tailscale](docs/tailscale.md) | Topic notes | | [Frame Control for iPhone](docs/iphone.md) | The iPhone and iPad app, how it runs the server on the Frame, pairing | | [Recovery and OS images](docs/recovery-and-images.md) | Where to download the Frame's OS, what's inside, testing without the headset | diff --git a/docs/evidence/vr-utilities/device.json b/docs/evidence/vr-utilities/device.json new file mode 100644 index 0000000..a604007 --- /dev/null +++ b/docs/evidence/vr-utilities/device.json @@ -0,0 +1,53 @@ +{ + "date": "2026-09-28", + "os": { + "version": "0.4.1", + "build": "20260925.6191901", + "variant": "vr" + }, + "performance": { + "compositorFps": 72.0, + "frameMs": 13.89, + "appFps": null, + "gpuMs": 3.07, + "compositorCpuMs": 0.61, + "cpuPercent": 40.6, + "gpuMHz": 903.0 + }, + "batteryPercent": 16, + "maxTempC": 73.5, + "ownership": [ + { + "id": 1009850, + "owned": false, + "installed": false, + "frame": 0 + }, + { + "id": 1173510, + "owned": false, + "installed": false, + "frame": 0 + }, + { + "id": 1068820, + "owned": false, + "installed": false, + "frame": 0 + }, + { + "id": 908520, + "owned": false, + "installed": false, + "frame": 0 + }, + { + "id": 1494460, + "owned": false, + "installed": false, + "frame": 0 + } + ], + "hudLifecycle": "open, duplicate-open, close passed before control-test pause; overlay probe removal verified", + "comfort": "Initial 1cm seated probe restored exactly. Later commits/readback disagreed while Frame in use; Alex paused control tests. No controls shipped." +} diff --git a/docs/evidence/vr-utilities/hud-card.png b/docs/evidence/vr-utilities/hud-card.png new file mode 100644 index 0000000..d12d009 Binary files /dev/null and b/docs/evidence/vr-utilities/hud-card.png differ diff --git a/docs/panels.md b/docs/panels.md index b08720b..4f160db 100644 --- a/docs/panels.md +++ b/docs/panels.md @@ -121,5 +121,10 @@ a limit on the number of floating panels. script needed. - **Inside the desktop panel**: KWin tiling (Meta+arrow keys with a Bluetooth keyboard) or virtual desktops arrange windows within the 1280×800 rectangle. -- **Windows-only overlay tools** (Desktop+, OVR Toolkit, OVRdrop) do this for a - PC's desktop in SteamVR. They don't run on the Frame's standalone Linux. +- **Optional overlay tools:** Desktop+, OVR Toolkit and similar software are + separate from Frame Control. Public reports describe some Proton support; + Windows-only does not by itself prove a Frame app cannot run. Local status + and sources are in [VR utilities](vr-utilities.md). +- **Our performance HUD:** Home → VR comfort and performance → Open HUD in + headset creates its own gamescope panel using built-in tools. It needs no + third-party overlay app. [Metrics and verification](vr-utilities.md). diff --git a/docs/steam-games.md b/docs/steam-games.md index 0d2e192..48734cb 100644 --- a/docs/steam-games.md +++ b/docs/steam-games.md @@ -106,3 +106,11 @@ returns nothing without `cc`, so Frame Control takes the country from - Installing when there's more than one library folder, such as a microSD card. - Uninstalling. `steam://uninstall/` should open a confirmation in the headset. + +## Optional VR software + +The [VR utilities list](vr-utilities.md#optional-software) is separate from our +controls and HUD. It checks software ownership as well as games; paid utilities +are installable only when already in the loaded Frame account library. No +purchase flow is added. Public reports, local results and ownership are shown +separately, and untested tools remain untested. diff --git a/docs/vr-utilities.md b/docs/vr-utilities.md new file mode 100644 index 0000000..1cde0f8 --- /dev/null +++ b/docs/vr-utilities.md @@ -0,0 +1,132 @@ +# VR comfort and performance + +Frame Control owns its HUD and telemetry. They use SteamVR/OpenVR, gamescope, +Python and xterm already on the Frame, plus the Frame's sensors. No feature +requires fpsVR, OVR Advanced Settings, XSOverlay or another third-party app. +The software list is a separate, optional convenience. + +This is **part of [#25](https://github.com/saphid/frame-control/issues/25)**, +not completion of the issue. Playspace controls remain blocked on the device +checks below. The PR stays draft. + +## Our performance HUD + +On **Home → VR comfort and performance**, the app shows a timestamped sample +with each status refresh (30 seconds, or Refresh). **Open HUD in headset** +starts our text HUD as a gamescope panel, refreshed every two seconds. In the +SteamVR dashboard, select **Frame Control HUD**, then Float in World or dock +it to a controller. **Close HUD**, or closing its terminal, ends it. Opening +it twice reuses the existing process. + +| Value | Meaning and source | +|---|---| +| Compositor FPS / period | Differences between two `IVRCompositor_029::GetFrameTiming` frame indices and monotonic compositor timestamps, sampled 200 ms apart. Output cadence, not game FPS or a long-term average. | +| Application FPS | Reciprocal of OpenVR's client frame interval. Unavailable if there is no positive interval; not inferred from refresh rate. | +| Render GPU time | OpenVR total render GPU milliseconds, not GPU utilisation. | +| Compositor CPU | OpenVR compositor render CPU milliseconds, not game CPU time. | +| System CPU | `/proc/stat` busy-time delta across the sample, with guest time counted once and iowait treated as idle. | +| GPU clock | `3d00000.gpu/cur_freq`, converted from Hz to MHz; frequency is not load. | +| Hottest sensor / battery | Existing thermal-zone and battery sysfs reads from `frame_status.py`. | + +OpenVR uses background application mode, which does not start SteamVR or keep +it running. This mode also returned live timing in a read-only device probe. + +Missing sensors, a stopped or incompatible SteamVR runtime, and non-advancing +frame indices display **Unavailable**, never invented zero FPS. Failed status +refreshes clear the HUD card rather than keeping a stale live-looking sample. +The HUD itself adds CPU/GPU work; it is a diagnostic, not a zero-overhead benchmark. + +**Verified 2026-09-28**, SteamOS 0.4.1, build `20260925.6191901`, SteamVR +2.18.1: the exact OpenVR interface and 192-byte timing layout returned advancing +frame indices and live GPU/CPU timing. Sensor reads, creation of overlay +`valve.steam.desktopgame.2000250025`, duplicate-open handling, and closing the +HUD passed. The temporary probe overlay disappeared after its process closed. +[Sanitized device sample](evidence/vr-utilities/device.json). + +**Unverified:** visual placement while wearing the headset, controller docking, +and overhead during gameplay. The companion card was checked in the attached +preview using live Frame data. Creating an overlay does not establish that it +was visible to the wearer. + +The optional HUD copies only `frame_status.py` and `frame_vr.py` into +`~/.local/share/frame-control/vr/`. It tags only the window whose X11 PID matches +its own xterm, avoiding other threads' windows. Stop checks both PID and Linux +process start time before sending SIGTERM. It does not stop Steam or SteamVR, +edit their settings, install a service, or need sudo. + +## Playspace, seated height and recenter: paused + +**Verified 2026-09-28:** SteamVR exposes `IVRChaperoneSetup_006` and +`IVRChaperone_004`. An initial 1 cm seated zero-pose translation committed, +read back and restored numerically. A later trial, while the shared Frame was +in use, changed universe IDs after commits and returned transforms that did +not match the requested write or restore. Journal entries reported +`CommitWorkingCopy`, `VREvent_ChaperoneUniverseHasChanged` and +`VREvent_ChaperoneRoomSetupCommitted`. The collision-bound arrays and play-area +size matched in the saved before/after records, but the origin matrices did not. + +Alex confirmed the headset was in use and asked to pause control tests. No +further playspace writes were made. The exploratory control implementation was +removed from the shipping API; `recenter`, `adjust` and `restore` are rejected. +This is an **unresolved feasibility check**, not evidence that OpenVR controls +cannot work. Concurrent use and the Frame driver's coordinate-system handling +still need to be separated. + +The probe's original and last-read poses remain in the Frame's +`~/.local/share/frame-control/vr/comfort.json` for investigation. This draft +neither reads nor applies that baseline. Do not blindly replay it into a room +that may have changed. No recenter test was reached in the later trial. + +Before adding controls, on an idle Frame: + +1. Establish current room and tracking state, and inspect the retained probe + evidence before considering any restoration. +2. Prove seated and standing height/move operations in the Frame driver's + current coordinates, including delayed readback, coordinate rebasing and + recovery. Show that the physical safety boundary stays correct. +3. Verify recenter independently, and test a full apply/restore cycle plus a + concurrent room-change refusal. Add a fake OpenVR test for those contracts. +4. Check the apparent result in a seated and a standing app before exposing UI. + +**Documented:** seated and standing are tracking origins selected by an app; +changing a seated origin cannot force every game to support seated play. + +**Inferred from the installed SteamVR defaults:** there is no generic snap-turn +or locomotion-vignette setting. `dashboard.verticalOffsetCm_2` and +`steamvr.panelMaskVignette` affect panels, not the player's height or game +locomotion. The app gives game-setting hints for snap-turn, teleport movement +and movement vignette instead of writing these unrelated settings. + +## Optional software + +**Verified 2026-09-28 (same build):** a read-only query of Steam's loaded +`appStore.allApps` found none of these five apps on the Frame account. The query +includes software, which the existing games-only library filter excludes. +Steam's public app-details API listed only Desktop+ as free. No software was +purchased, installed or launched during these ownership checks. + +| Utility | Local Frame status | Public evidence / optional source | +|---|---|---| +| OVR Advanced Settings (1009850) | **Untested**, not owned | Steam edition is paid. Developer's [free source and releases](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings). No verified Frame result in this work. | +| XSOverlay (1173510) | **Untested**, not owned | Supplied research attributes Proton support with tweaks to [Road to VR](https://www.roadtovr.com/valve-steam-frame-review/). This is a public report, not our verification. | +| OVR Toolkit (1068820) | **Untested**, not owned | Same [public Frame report](https://www.roadtovr.com/valve-steam-frame-review/); no local verification. | +| fpsVR (908520) | **Untested**, not owned | [Steam listing](https://store.steampowered.com/app/908520/). No Frame-specific result established in the supplied research. General PC VR reviews do not verify Frame support. | +| Desktop+ (1494460) | **Untested**, free | [Developer source](https://github.com/elvissteinjr/DesktopPlus). No verified Frame result in this work. | + +**Documented (supplied research):** the XSOverlay/OVR Toolkit claims are kept as +attributed leads. **Verified source check 2026-09-28:** fetching the linked +review returned HTTP 200 and the expected review title, but neither utility name +appeared in the fetched HTML or extracted text. The claims could not be +corroborated from that page; this is not proof of incompatibility. They do not make those apps dependencies or mark them +locally verified. No paid utility is auto-acquired. A server-side check blocks +installation through the Steam endpoint if the paid utility is absent from the +loaded Frame library; an empty/unavailable library fails closed. Desktop+ uses +the existing free Steam install flow, which may need a license confirmation in +the headset. None is advertised as known-good without local evidence. + +Compatibility reports reuse the existing `compat-db` storage and validation +with `package: "steam:"`, rather than colliding with Android package IDs. +The optional list shows the latest `works`, `issues` or `broken` report with its +date, build and notes, separately from public sources and ownership. With no +report the status stays **untested**. No shared database schema change or +production deployment is needed; no reports were published by this work.