Handover documentation for continuing on another computer
- docs/steamframe/README.md: entry point with status, branches/remotes, setup, commands, Steam Frame facts, open points. - CLAUDE.md: working rules and code conventions (fork-only). - docs/steamframe/OVRAS-FEATURES.md: OVRAS's features, how they are implemented, issues found while reading. - PROGRESS.md: status and wrap-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3ed686dec5
commit
7c5a9a7a1e
@@ -0,0 +1,96 @@
|
||||
# CLAUDE.md
|
||||
|
||||
Guidance for Claude Code (and humans) working in this fork. Fork-only file: not part of
|
||||
upstream pull requests.
|
||||
|
||||
**Start with [docs/steamframe/README.md](docs/steamframe/README.md):** goal, status, setup,
|
||||
commands, Steam Frame facts. Then [REQUIREMENTS.md](docs/steamframe/REQUIREMENTS.md)
|
||||
(decisions), [DESIGN.md](docs/steamframe/DESIGN.md) and
|
||||
[PROGRESS.md](docs/steamframe/PROGRESS.md) (status, Frame test checklist).
|
||||
|
||||
## Working rules (agreed with the user, always apply)
|
||||
|
||||
- **Proper software engineering:** follow established procedures and processes, not ad-hoc
|
||||
hacking.
|
||||
- **Nothing without explicit permission.**
|
||||
- Propose first, then act only on the user's go-ahead.
|
||||
- Permission covers only what was asked. No extra changes, renames, rewrites or "while I'm
|
||||
at it" fixes: suggest those instead.
|
||||
- **Ask, don't assume.** When a requirement, decision or detail is unclear, ask. Give a
|
||||
recommendation with the question.
|
||||
- **Iterations in phases.** Each phase ends with the user's OK (informal is enough):
|
||||
1. requirements
|
||||
2. design
|
||||
3. implementation
|
||||
4. tests
|
||||
5. assessment
|
||||
- Keep iterations small.
|
||||
- **Document everything** in `docs/steamframe/`: requirements, decisions (with date), design,
|
||||
progress, test results. Report results faithfully, including what was *not* tested. Keep
|
||||
the docs in sync with every change.
|
||||
- **Communication:** the user writes German or English; answer in the user's language. Docs
|
||||
and code comments are in English.
|
||||
|
||||
## Goal and constraints (details: REQUIREMENTS.md)
|
||||
|
||||
- OVRAS runs natively on the Steam Frame (SteamOS, aarch64). Windows is out of scope for now.
|
||||
- **Minimal change set against upstream's `qt6` branch**, because changes are meant to go
|
||||
upstream later.
|
||||
- Change existing code only where needed.
|
||||
- Bring new parts in as self-contained files.
|
||||
- **Only public Qt API.** No `GuiPrivate`/QRhi, and QML is compiled to bytecode only.
|
||||
`objdump -T … | grep Qt_6_PRIVATE_API` may only show `QVulkan*`.
|
||||
- **Frame differences:**
|
||||
- Switched by the CMake option `OVRAS_STEAM_FRAME`.
|
||||
- It is evaluated **only** in `src/utils/platform_capabilities.h`, which turns it into
|
||||
capability constants named by capability (e.g. `k_chaperoneCommitSupported`).
|
||||
- The code asks for capabilities, never for the platform.
|
||||
|
||||
## Code conventions
|
||||
|
||||
- **Comments:** every change gets comments that explain it fully (what and why, e.g. which
|
||||
Frame or SteamVR fact). Keep them direct and concise. Trivial mechanical changes such as
|
||||
`LOG(INFO)` → `qInfo()` are explained in the commit message instead.
|
||||
- **Style:**
|
||||
- OVRAS style (`.clang-format`, since 2018) everywhere, including code taken over from the
|
||||
template.
|
||||
- **Format only changed lines:** `git add …; git clang-format; git add …`. Never
|
||||
reformat whole existing files, because a dozen files already deviate.
|
||||
- New files are formatted completely (`clang-format -i`).
|
||||
- Separate new comments from existing commented-out code with a blank line. Otherwise
|
||||
clang-format reflows the old block and the diff grows.
|
||||
- **Commits:**
|
||||
- One commit per step / topic, with a message that explains the why.
|
||||
- End every commit message with `Co-Authored-By: Claude …`.
|
||||
- Push to `origin` (the fork); `upstream` is the GitHub OVRAS repository.
|
||||
- **Template code** (`src/render/`, `build_scripts/steamframe/`) carries a note about its
|
||||
origin (vrdashboard template, FrameAssistant `4a5b090`).
|
||||
|
||||
## Architecture notes (what is easy to break)
|
||||
|
||||
- **`main.cpp` order:**
|
||||
1. parse the command line
|
||||
2. choose the render backend (`--graphics-api`)
|
||||
3. `initializeOpenVR(Overlay)`
|
||||
4. `backend->initialize(openvr_init::renderInterop())`
|
||||
5. `QQuickWindow::setGraphicsApi()`
|
||||
6. `OverlayController`
|
||||
|
||||
`setGraphicsApi` must come before any `QQuickWindow` exists, and `OverlayController` owns
|
||||
one.
|
||||
- **`OverlayController`:**
|
||||
- Owns `m_renderBackend`, declared *before* `m_renderControl` / `m_window`: Qt's device
|
||||
comes from the backend.
|
||||
- `SetWidget()` and `renderOverlay()` follow the call order in `src/render/RenderBackend.h`.
|
||||
- **Shutdown:**
|
||||
- OVRAS ends with `exit()`.
|
||||
- `Shutdown()` (once only) calls `vr::VR_Shutdown()` *before* `releaseRenderTarget()` /
|
||||
`detachWindow()`.
|
||||
- **Tick:**
|
||||
- `m_pumpEventsTimer`: 1 ms polling in "vsync" mode; in "vsync disabled" mode it runs
|
||||
directly at `customTickRateMs` (`applyTickInterval()`).
|
||||
- Frame defaults: vsync disabled, 11 ms.
|
||||
- **Mouse:** SteamVR reports y from the bottom, so it is flipped on every platform.
|
||||
- **Logging:** OVRAS writes `AdvancedSettings.log` into the working directory.
|
||||
- **SteamVR Input:** `action_manifest.json` and `default_action_manifests/` (incl.
|
||||
`…_default_frame.json` for `frame_controller`) lie next to the binary.
|
||||
@@ -0,0 +1,197 @@
|
||||
# OVRAS: features and how they are implemented
|
||||
|
||||
Analysis of 2026-10-07, based on upstream `master` (`31df8b4`, 5.8.17). Line numbers refer to
|
||||
that state. `qt6` has the same features, so the numbers are close. Paths are relative to
|
||||
`src/`. Which of these features SteamVR now offers itself is in
|
||||
[REQUIREMENTS.md](REQUIREMENTS.md), "Feature classification".
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Dashboard overlay:**
|
||||
- `VR_Init(VRApplication_Overlay)`, app key `steam.overlay.1009850`.
|
||||
- QML UI (1200×800) rendered off-screen via `QQuickRenderControl`.
|
||||
- The texture goes to `SetOverlayTexture`. On `steamframe` the render backends in `render/`
|
||||
do this; before, it was an OpenGL FBO, and on `qt6` QRhi.
|
||||
- **Input:** SteamVR mouse/scroll events are turned into Qt events (`overlaycontroller.cpp`,
|
||||
`mainEventLoop()`).
|
||||
- **Main loop (`OnTimeoutPumpEvents` → `mainEventLoop()`):**
|
||||
- Timer; "vsync" mode once per compositor frame (`GetTimeSinceLastVsync`).
|
||||
- Per tick:
|
||||
1. input actions
|
||||
2. VR events
|
||||
3. poses
|
||||
4. `eventLoopTick` of the tab controllers (always)
|
||||
5. `dashboardLoopTick` (only while the dashboard is visible)
|
||||
- **SteamVR Input:** `package_files/action_manifest.json`, 5 action sets:
|
||||
- `motion`: space drag/turn, gravity, snap/smooth turn, height toggle, offsets, auto-turn
|
||||
- `music`: media keys
|
||||
- `misc`: axis locks, chaperone toggle, keyboard shortcuts
|
||||
- `system`: push-to-talk, exclusive input, haptic clicks
|
||||
- `haptic`: vibration, proximity sensor
|
||||
|
||||
Default bindings exist for Vive, Index, WMR, HP, Touch, generic HMD and Frame controllers.
|
||||
- **Persistence:**
|
||||
- App settings in a `QSettings` INI file (`settings/`). Profiles are stored as arrays
|
||||
(`ISettingsObject`).
|
||||
- SteamVR's own settings go directly through `vr::VRSettings()` (`openvr/ovr_settings_wrapper`).
|
||||
- **Platform:**
|
||||
- Windows: WASAPI / `IPolicyConfig`, `SendInput`.
|
||||
- Linux: PulseAudio, X11 XTest, D-Bus MPRIS.
|
||||
- Elsewhere: dummies.
|
||||
|
||||
## Features
|
||||
|
||||
### Playspace movement (`tabcontrollers/MoveCenterTabController.cpp`)
|
||||
|
||||
Almost everything shifts or rotates the **working standing zero pose** through
|
||||
`IVRChaperoneSetup` and shows it live with `ShowWorkingSetPreview()`. Nothing is committed
|
||||
per frame. This mechanism does **not work on the Frame** (inside-out tracking).
|
||||
|
||||
- **Core, `updateSpace()` (:2497–2721):**
|
||||
- Offsets X/Y/Z and the rotation (centidegrees) are multiplied with the stored basis.
|
||||
- The result goes to `SetWorkingStandingZeroPoseToRawTrackingPose`, in seated mode
|
||||
additionally to the seated pose.
|
||||
- Safety limit: about 40 km.
|
||||
- **Space drag:**
|
||||
- The controller's position delta, multiplied by `dragMult`, is added to the offsets.
|
||||
- Axis locks; the speed is kept for fling.
|
||||
- Comfort mode skips frames.
|
||||
- **Space turn:** the change of the yaw angle via quaternions
|
||||
(`q·conj(q_last)`, `quaternion/quaternion.h`). Rotation pivots on the HMD by default.
|
||||
- **Snap/smooth turn:** fixed angle per press resp. per tick, so smooth turn depends on the
|
||||
frame rate.
|
||||
- **Gravity/momentum:** Euler integration with friction, terminal velocity 50 m/s, landing on
|
||||
the floor, reversible.
|
||||
- **Height toggle:** Y offset plus a new gravity floor.
|
||||
- **Offset profiles, apply/reset:**
|
||||
- "Apply" commits with `CommitWorkingCopy(Live)` (limit 990 m).
|
||||
- `zeroOffsets()` / `updateChaperoneResetData()` also commit at start-up. On the Frame
|
||||
this shifts the play area, hence R7.
|
||||
|
||||
### Rotation (`tabcontrollers/RotationTabController.cpp`, via `setRotation`)
|
||||
|
||||
- **Auto-turn:**
|
||||
- Rotates the space when the user gets near a wall, either as a snap or smoothly.
|
||||
- Direction: from the corner shared with the last wall, otherwise cord untangling (HMD
|
||||
total rotation count).
|
||||
- **Vestibular motion:** rotation as if walking on a circle of radius r
|
||||
(`2·asin(d/2r)`).
|
||||
- **View ratchetting:** amplifies head turns away from the wall.
|
||||
|
||||
### Fix floor / recenter (`tabcontrollers/FixFloorTabController.cpp`)
|
||||
|
||||
- **Fix floor:**
|
||||
- Measures the lower controller over 25 frames.
|
||||
- Subtracts the controller thickness per model and orientation (Vive / Knuckles).
|
||||
- Commits the result as a Y offset; undo is possible.
|
||||
- **Recenter:** `VRChaperone()->ResetZeroPose(...)`.
|
||||
|
||||
### Chaperone (`tabcontrollers/ChaperoneTabController.cpp`)
|
||||
|
||||
- **Settings:**
|
||||
- Visibility, color, fade distance, wall height, center marker, floor bounds and style.
|
||||
- These are keys in `k_pch_CollisionBounds_Section`.
|
||||
- "Disable" sets the fade distance to 0 and remembers the old value.
|
||||
- **Own center marker overlay:** shows the rotation count (cord).
|
||||
- **Dim when crouching:** below a height, the fade distance goes to 0 over 10 s.
|
||||
- **Proximity warnings:**
|
||||
- Distance of HMD and controllers to the walls (`utils/ChaperoneUtils.cpp`: projection onto
|
||||
each wall segment).
|
||||
- Reactions: switch to the beginner style, vibration (own thread,
|
||||
`TriggerHapticVibrationAction`), alarm sound with distance-dependent volume, open the
|
||||
dashboard.
|
||||
- **Chaperone profiles:**
|
||||
- Save the geometry (`GetLiveCollisionBoundsInfo`, zero pose, size) and the settings.
|
||||
- Apply them with `SetWorking…` + `CommitWorkingCopy`.
|
||||
- Autosave profile.
|
||||
|
||||
### Video (`tabcontrollers/VideoTabController.cpp`)
|
||||
|
||||
- **Brightness:** a black overlay right in front of the HMD. Its alpha `(1−x)^(1/3)`
|
||||
compensates for perception.
|
||||
- **Color tint:**
|
||||
- either a colored overlay (`SetOverlayColor`)
|
||||
- or SteamVR's `HmdDisplayColorGainR/G/B`
|
||||
- **SteamVR keys:** supersampling (incl. manual override), motion smoothing, supersample
|
||||
filtering.
|
||||
- **Video profiles.**
|
||||
|
||||
### Audio (`tabcontrollers/AudioTabController.cpp`, `audiomanager/`)
|
||||
|
||||
- **Interface:** `AudioManager` with a Windows, a PulseAudio and a dummy implementation.
|
||||
- **Windows:**
|
||||
- WASAPI/MMDevice, `IAudioEndpointVolume`.
|
||||
- The default device is set via the undocumented `IPolicyConfig`.
|
||||
- External changes come in via `IMMNotificationClient`.
|
||||
- **Linux:**
|
||||
- PulseAudio: `pa_context_set_default_sink/source`; existing source outputs are moved to
|
||||
the new source.
|
||||
- The original state is restored at exit.
|
||||
- **No mirror device.**
|
||||
- **Mirror device and device override:** these are SteamVR keys (`k_pch_audio_*`), not
|
||||
OVRAS's own routing.
|
||||
- **Push-to-talk / -mute:** SteamVR Input action → mic mute + notification overlay on the
|
||||
HMD.
|
||||
- **Mute the mic when the HMD is taken off:** proximity sensor action.
|
||||
- **Audio profiles.**
|
||||
|
||||
### SteamVR tab (`tabcontrollers/SteamVRTabController.cpp`)
|
||||
|
||||
- **Toggles:** each is a SteamVR setting.
|
||||
- performance graph, multiple drivers, do not disturb, no-HMD mode
|
||||
- camera options
|
||||
- system button to all apps, don't fade to grid, controller power auto-launch
|
||||
- **Restart SteamVR:** Windows only, via `.bat`.
|
||||
- **Per-game controller bindings:**
|
||||
- Use SteamVR's web server `localhost:27062`, with a spoofed `Referer`.
|
||||
- Saved as JSON and applied when the scene app changes.
|
||||
- **Receiver/tracker pairing:** WebSocket to the lighthouse web interface (`start_pairing`).
|
||||
- **`openvr/lh_console_util.cpp`** (`lighthouse_console`) is compiled but **not used**.
|
||||
- There is no base-station power management.
|
||||
|
||||
### Utilities (`tabcontrollers/UtilitiesTabController.cpp`, `keyboard_input/`, `media_keys/`, `alarm_clock/`)
|
||||
|
||||
- **Keyboard:**
|
||||
- Buttons (Enter, Alt-Tab, Ctrl-C/V, …) and 3 freely defined shortcuts.
|
||||
- A parser for the syntax `^`=Ctrl, `*`=Alt, `>`=Shift, `#`=Super.
|
||||
- Sent via Windows `SendInput` or X11 XTest. On the Frame (gamescope) the X11 path probably
|
||||
doesn't reach games.
|
||||
- **Media keys:**
|
||||
- Windows: `VK_MEDIA_*`.
|
||||
- Linux: D-Bus to every `org.mpris.MediaPlayer2.*`.
|
||||
- **Tracker battery:** icon overlay on each tracker (`Prop_DeviceBatteryPercentage_Float`),
|
||||
only while the dashboard is visible.
|
||||
- **Alarm clock:** HMD overlay at a set time, shown for 3 s.
|
||||
|
||||
### Statistics (`tabcontrollers/StatisticsTabController.cpp`)
|
||||
|
||||
- **Frame counters:** `VRCompositor()->GetCumulativeStats()` gives presented, dropped,
|
||||
reprojected and timed-out frames. "Reset" only stores an offset.
|
||||
- **Distance traveled:** horizontal HMD movement, every 11th tick, steps ≥ 1 cm.
|
||||
- **Rotation count, maximum controller speed.**
|
||||
|
||||
### Settings tab (`tabcontrollers/SettingsTabController.cpp`)
|
||||
|
||||
Autostart (`SetApplicationAutoLaunch`), native chaperone import, block Oculus SDK, desktop
|
||||
mode, tick rate (vsync / custom tick rate).
|
||||
|
||||
## Issues found while reading (not verified)
|
||||
|
||||
| Place (master) | Issue |
|
||||
|---|---|
|
||||
| `MoveCenterTabController.cpp:1198` | `updateChaperoneResetData()` allocates `new vr::HmdQuad_t[]` on every call and never frees the old array (memory leak) |
|
||||
| `MoveCenterTabController.cpp:2512` | `if ( m_chaperoneHasCommit ) { m_chaperoneHasCommit = true; … }` looks like a slip |
|
||||
| `MoveCenterTabController.cpp:1332` | `leftHandSpaceDrag`: the final `else` overwrites the swap/override choice |
|
||||
| `MoveCenterTabController` | Rotation is wrapped inconsistently (snap/smooth/auto-turn 0–36000 vs. ±18000 elsewhere) |
|
||||
| `VideoTabController.cpp:114` | Sets the sort order of the brightness overlay instead of the color overlay |
|
||||
| `ChaperoneTabController.cpp:903` | Floor bounds are read as Bool but written as Int32 |
|
||||
| `MoveCenterTabController::zeroOffsets` | If `GetCalibrationState() == 200`, init never completes and the commit repeats every tick (with commits enabled) |
|
||||
| `utils/FrameRateUtils.cpp`, `openvr/lh_console_util.cpp` | Compiled but unused |
|
||||
|
||||
Found on the `qt6` branch and fixed on `steamframe` (see PROGRESS.md):
|
||||
- the build fails on Linux
|
||||
- QRhi Vulkan path: wrong `m_nFormat` (Qt enum instead of `VkFormat`); no layout transition,
|
||||
no SteamVR extensions, no choice of the HMD's GPU
|
||||
- mouse y not flipped on Linux
|
||||
- no `VR_Shutdown`
|
||||
- hard-coded version 5.7.4
|
||||
@@ -1,5 +1,8 @@
|
||||
# Steam Frame port: progress
|
||||
|
||||
**Status (2026-10-07): iteration 1 implemented. Next: test checklist T1–T11 on the Frame
|
||||
(at the end of this file), then assessment. Getting started: [README.md](README.md).**
|
||||
|
||||
## Iteration 1
|
||||
|
||||
### Step 1: build fixes, bytecode-only QML (2026-10-07)
|
||||
@@ -186,3 +189,12 @@ Deploy: `build_scripts/steamframe/deploy-to-frame.sh <user>@<frame>` (SteamVR ru
|
||||
| T9 | Auto-start after a SteamVR restart / reboot | R2 | open |
|
||||
| T10 | `pidstat -p $(pgrep -f AdvancedSettings_app) 10 6`: dashboard closed / OVRAS visible / other tab visible | R6 | open |
|
||||
| T11 | `uninstall.sh` unregisters it | R2 | open |
|
||||
|
||||
### Wrap-up (2026-10-07)
|
||||
|
||||
- **Remotes:** `origin` = `git@git.matzman.net:SteamFrame/OpenVR-AdvancedSettings-frame.git`
|
||||
(branches `steamframe`, `qt6`, `master`); `upstream` = GitHub OVRAS.
|
||||
- **Handover documentation:** `docs/steamframe/README.md` (entry point), `CLAUDE.md`
|
||||
(working rules, conventions), `docs/steamframe/OVRAS-FEATURES.md` (feature analysis).
|
||||
- **Still open in iteration 1:** phase 4 (tests on the Frame, T1–T11) and phase 5
|
||||
(assessment).
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
# 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 (3.0 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-<version>-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 <user>@<frame>
|
||||
```
|
||||
|
||||
**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` | Restarts with that graphics API |
|
||||
| `./uninstall.sh` | Unregisters |
|
||||
| `AdvancedSettings.log` | Log (in the working directory, i.e. this folder) |
|
||||
|
||||
Program options (new): `--graphics-api opengl|vulkan` (default `opengl`). 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`.
|
||||
Reference in New Issue
Block a user