# OVRAS for the Steam Frame: start here This fork ports **OpenVR Advanced Settings (OVRAS)** so that it runs **natively on the Steam Frame** (SteamOS, aarch64, standalone) as a SteamVR dashboard tab. This file is the entry point for continuing the work on any computer. | Document | Content | |---|---| | [REQUIREMENTS.md](REQUIREMENTS.md) | Goal, decisions (with dates), requirements per iteration, feature classification | | [DESIGN.md](DESIGN.md) | Design of iteration 1 (approved): what changes where, and why | | [PROGRESS.md](PROGRESS.md) | What was done per step, test results, **test checklist for the Frame** | | [OVRAS-FEATURES.md](OVRAS-FEATURES.md) | OVRAS's features and how they are implemented; issues found while reading | | [`/CLAUDE.md`](../../CLAUDE.md) | Working rules and conventions (for people and for Claude Code) | ## Status (2026-10-07) - **Iteration 1 ("native start on the Frame"): implemented, not yet tested on the Frame.** - Tested without a headset: - Linux x86_64 build. - aarch64 cross build: no private Qt API except `QVulkan*`, Qt 6.8, GLIBC ≤ 2.38. - Render tests with OpenGL and Vulkan; Vulkan with validation layers and no messages. - Release package (1.6 MB). - **Next step:** test checklist T1–T11 on the Frame ([PROGRESS.md](PROGRESS.md)), record the results there, then assessment. - **After that:** iteration 2. R5 hides the features that are native in SteamVR or don't work on the Frame. Then the remaining features are checked one by one. ## Background in brief - **Proton:** The Windows build of OVRAS runs on the Frame through Proton. Its laser y-axis is mirrored there, which makes it unusable, and it is inefficient (x86 emulation + Wine). - **Basis:** the fork is based on upstream's **`qt6` branch**, the maintainer's Qt 6.8 / CMake port, still in progress. `master` is fully merged into `qt6`. - **Goal: a minimal change set against `qt6`**, so changes can later go upstream as pull requests. - **Template:** the platform knowledge comes from the author's **vrdashboard template**, verified on the Frame. Its baseline is commit `4a5b090` in `git@git.matzman.net:SteamFrame/FrameAssistant.git`; its `docs/STEAM-FRAME.md` and `CLAUDE.md` describe the Frame. From it come the render backends (`src/render/`) and the build/package scripts (`build_scripts/steamframe/`). - **Hard rule: only public Qt API.** The binary must run on the Frame's system Qt (6.8.0). QRhi (private) was therefore replaced and QML is compiled to bytecode only. ## Repository, branches, remotes | Branch | Meaning | |---|---| | `steamframe` | **The work branch.** Based on `qt6` (`2d4db7e`). | | `qt6` | Mirror of upstream's `qt6` at `2d4db7e` (reference / diff base) | | `master` | Mirror of upstream's `master` at `31df8b4` (5.8.17) | Commits on `steamframe` (one per step; use for later pull requests): ``` aac3edf Steam Frame port: requirements and design of iteration 1 266a2f9 Fix the Linux build of the qt6 branch, compile QML to bytecode only 423ea57 Add a Steam Frame build option; no chaperone commit at start; timer-based tick 4826686 Render through public Qt API: OpenGL and Vulkan backends, --graphics-api b22c35a Manifest for Linux; connect as Background app where Utility is refused bde675f Steam Frame build, packaging and deployment scripts; render test 3ed686d Read the version from build_scripts/compile_version_string.txt ``` Then the handover documentation (this file, `CLAUDE.md`, `OVRAS-FEATURES.md`). Fork-only files that don't belong in an upstream pull request: `docs/steamframe/`, `CLAUDE.md`. ## Setting up on another computer ```sh git clone -b steamframe git@git.matzman.net:SteamFrame/OpenVR-AdvancedSettings-frame.git cd OpenVR-AdvancedSettings-frame git remote add upstream https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings.git git fetch upstream # to see whether upstream's qt6 has moved on ``` **Requirements:** - **For the Frame build and the tests:** Docker or Podman (containers based on Debian trixie; they bring Qt 6.8 and everything else). - **For a local Linux build (optional):** - CMake ≥ 3.20, Ninja, GCC/Clang (C++20). - Qt ≥ 6.8 with Quick, QuickControls2, QuickDialogs2, Multimedia, WebSockets, Svg, DBus; `Test` for the tests. - Vulkan headers. - libpulse, libX11, libXt, libXtst. - Tested on Arch with Qt 6.11. - **For deployment:** SSH access to the Frame, `rsync`. ## Commands ```sh # Local build (x86_64), optionally with tests cmake -S . -B build/x86 -G Ninja -DCMAKE_BUILD_TYPE=Debug -DOVRAS_BUILD_TESTS=ON cmake --build build/x86 ctest --test-dir build/x86 # render tests: OpenGL and Vulkan # -DOVRAS_STEAM_FRAME=ON: Frame capabilities/defaults (src/utils/platform_capabilities.h) # Frame (aarch64) build in the container → build/steamframe-cross/Release/ build_scripts/steamframe/container-build.sh cross build_scripts/steamframe/container-build.sh cross shell # shell in the container # Tests in the container, Vulkan with validation layers (must print "No Vulkan validation messages") build_scripts/steamframe/container-test.sh VK_DRIVER=lvp build_scripts/steamframe/container-test.sh # software Vulkan # Package → dist/AdvancedSettings--linux-arm64(.tar.gz) build_scripts/steamframe/package-release.sh # builds first; --no-build packages only # Copy to the Frame and install (SteamVR must be running there) build_scripts/steamframe/deploy-to-frame.sh @ ``` **Check for private Qt API** (R1). Only `QVulkan*` may appear: ```sh docker run --rm -v "$PWD:$PWD" -w "$PWD" ovras-steamframe-cross-arm64 \ aarch64-linux-gnu-objdump -T build/steamframe-cross/Release/AdvancedSettings_app \ | grep Qt_6_PRIVATE_API | grep -v QVulkan ``` **On the Frame** (in `~/AdvancedSettings/`): | Command | Effect | |---|---| | `./install.sh` | Registers with SteamVR (auto-start) and starts | | `./run.sh opengl\|vulkan [options]` | Restarts with that graphics API; further options go to the program | | `./uninstall.sh` | Unregisters | | `AdvancedSettings.log` | Log (in the working directory, i.e. this folder) | Program options (new): `--graphics-api opengl|vulkan` (default `opengl`); `--snapshot ` (diagnosis: writes the rendered overlay as PNG at most once per second while visible). Existing ones include `--force-install-manifest` and `--force-remove-manifest`; see `--help`. ## Steam Frame facts the code relies on Verified with the template on SteamOS holo 0.4.3; details in FrameAssistant's `docs/STEAM-FRAME.md`. - **Runtime:** - The system Qt is 6.8.0, with Multimedia, WebSockets, DBus, Svg and Widgets. - libpulse is present. - GLIBC is 2.39. - **Manifest and SteamVR:** - The manifest needs `binary_path_linux_arm`; entries without it are skipped silently. - SteamVR refuses `VRApplication_Utility`. Manifest commands therefore fall back to `Background`, which needs a running SteamVR. - `VR_Shutdown` must run before the graphics device is destroyed (crash with Vulkan otherwise). - **Rendering and input:** - OpenGL runs through zink (no native GL driver); Vulkan is about 1.9× faster per frame. - SteamVR reports overlay mouse coordinates with y from the bottom. - **Processes and display:** - Over SSH there is no display: set `DISPLAY=:0` (the scripts do). - Process names are cut to 15 characters: find instances by command line. - An executable must not be named like a SteamVR process (e.g. `vrdashboard`). - **Private package repositories:** the Frame's `/etc/pacman.conf` points to private Valve repositories marked "DO_NOT_SHARE". Never put those URLs into the repository. ## Known open points and risks - **SteamVR keyboard:** text fields may not get focus. The template had to send the offscreen window an explicit `FocusIn`; `qt6` doesn't (T5). - **Unverified on the Frame:** - QML modules: Controls/Material, Layouts, Dialogs, Multimedia. - libXt/libXtst present? libstdc++ ≥ GLIBCXX_3.4.32? - **Remaining play-area commit:** "auto-apply chaperone" (opt-in, default off) still commits at start-up; this belongs to R5. - **Windows:** the Windows build is broken on `steamframe`. There is no D3D11 render path anymore (decision D1: evaluated later, together with upstream). - **Version:** OVRAS's version comes from `build_scripts/compile_version_string.txt`.