Files
OpenVR-AdvancedSettings-frame/docs/steamframe/PROGRESS.md
T
matzmanandClaude Opus 5.5 ec82b5fead Register the manifest when Steam already lists the app key
Steam writes every VR app the user owns into its generated
steamapps.vrmanifest, installed or not. Whoever owns OVRAS on Steam
therefore always has steam.overlay.1009850 registered, as a steam:// URL
without a working directory, and --force-install-manifest failed with
"Could not find working directory of already installed application:
VRApplicationError_PropertyNotSet" (found on the Steam Frame).

Such an entry has no manifest file to remove, so OVRAS now leaves it
alone and adds its own manifest. Whether SteamVR accepts a second
manifest for the key, and which entry it then uses, is not documented:
logApplicationEntry() logs what SteamVR reports for the key after
installing, so a test on the Frame shows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:25:57 +02:00

263 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)
**Changes:**
- **`CMakeLists.txt`:**
- `Core5Compat` removed (unused, not on the Frame).
- `GuiPrivate` requested explicitly. This is temporary, until step 3 replaces QRhi.
- `QT_QMLCACHEGEN_ARGUMENTS --only-bytecode`.
- OpenVR library directory per architecture (`linux64` / `linuxarm64` / `win64`), for
linking and for the copy next to the binary.
- `RPATH $ORIGIN`.
- `libXtst` linked.
- **`overlaycontroller.cpp`:** `d3d11.h` and `case QRhi::D3D11` only under `_WIN32`.
- **Logging:** 8 active easylogging `LOG(INFO)` calls became `qInfo()`
(`overlaycontroller.cpp` 6, `ChaperoneTabController.cpp` 1,
`MoveCenterTabController.cpp` 1). Commented-out `LOG` lines are left unchanged.
- Only changed lines are formatted (`git clang-format`).
**Results (x86_64, Arch, Qt 6.11.1, GCC):**
- The build succeeds, with 1463 compiler warnings, as in `qt6`.
- `objdump -T`: 7 `Qt_6_PRIVATE_API` symbols, all `QRhi…` (step 3). The
`QQmlPrivate::AOTCompiledContext` symbols are gone (bytecode-only QML).
- `libopenvr_api.so` is resolved from the binary's directory (`ldd`).
- Not started: without a running SteamVR the start hangs in OpenVR init (expected; tested
on the Frame in step 5).
### Step 2: platform option, R7, tick (2026-10-07)
**Changes:**
- **Platform option:**
- CMake option `OVRAS_STEAM_FRAME` (default OFF) sets the compile definition
`OVRAS_STEAM_FRAME=1`.
- New `src/utils/platform_capabilities.h` evaluates it as the only place. It holds
`k_chaperoneCommitSupported`, `k_defaultVsyncDisabled` and `k_defaultCustomTickRateMs`.
- **Tick (R6):**
- In "vsync disabled" mode, `m_pumpEventsTimer` runs directly at `customTickRateMs`
(`applyTickInterval()`, `Qt::PreciseTimer`); the 1 ms counting is gone.
- Changing the setting restarts the timer.
- Setting defaults in `settings_controller.h` come from the constants: Frame `true`/11 ms,
otherwise unchanged `false`/20 ms.
- **R7:** with `!k_chaperoneCommitSupported`:
- `updateChaperoneResetData()` and `applyChaperoneResetData()` skip
`CommitWorkingCopy`/`RevertWorkingCopy`. Each logs once per function.
- The init autosave profile is skipped.
**Results:**
- Both variants (default and `-DOVRAS_STEAM_FRAME=ON`) build on x86_64. The definition is
only set in the Frame variant (`compile_commands.json`).
- Not tested at runtime yet (Frame, step 5).
**Notes:**
- Another commit at start-up remains, but only on opt-in. `SetWidget()` applies a chaperone
profile and commits when "auto-apply chaperone" (`autoApplyChaperoneToggle`, default
`false`) is on. That's a chaperone-profile feature, so it belongs to R5 (iteration 2).
- clang-format reflows comment blocks next to new comments. Separate new comments from
existing commented-out code with a blank line, otherwise the diff grows.
### Step 3: rendering through public API, `--graphics-api`, mouse y, shutdown order (2026-10-07)
**Changes:**
- **`src/render/`** (new): `RenderBackend`, `OpenGLRenderBackend`, `VulkanRenderBackend` from
the template (`4a5b090`).
- Changes to the template code: `VRDASH_*` → `OVRAS_*` names, origin note in the file
header, references to `OverlayController`.
- Formatted completely in OVRAS style.
- One comment in `VulkanRenderBackend.h` was wrapped by hand, because the automatic
wrapping had broken its column layout.
- **`OverlayController`:**
- QRhi block replaced by `configureWindow` → `renderControl.initialize` →
`attachWindow` → `createRenderTarget`.
- `renderOverlay()` wraps the frame in `beginFrame`/`finishFrame`. It submits
`vrTextureBounds` + `vrTexture` while the context is current.
- `SetOverlayFromQRhiTexture`, the QRhi members and `QVulkanInstance` are removed.
- Render delay 5 → 16 ms (about 60 fps).
- **Shutdown:** `Shutdown()` runs only once. It calls `VR_Shutdown()`, then frees the
backend's render target (`releaseRenderTarget`, `detachWindow`).
- **Mouse y:** always flipped; the Linux un-flip and its TODO are removed.
- **`openvr_init::renderInterop()`:** Vulkan extensions and HMD GPU from SteamVR.
- **`main.cpp`:** parses `--graphics-api`, then `createRenderBackend` → `initialize` →
`QQuickWindow::setGraphicsApi` → `OverlayController`.
- **`setup.*`:** `--graphics-api opengl|vulkan` (default `opengl`). Unknown or not built in
→ error, exit code `GENERAL_FAILURE`.
- **CMake:**
- `GuiPrivate` is gone.
- The Vulkan backend is built when `QT_FEATURE_vulkan` is set (`OVRAS_HAS_VULKAN`).
**Results (x86_64, Qt 6.11.1):**
- The build succeeds. The Vulkan backend is built in.
- `objdump -T`: only `QVulkanDeviceFunctions::*` / `QVulkanFunctions::*` remain as
`Qt_6_PRIVATE_API`. Acceptance criterion R1 (symbols) is met.
- Warnings 1463 → 1630. The new code itself has none; the additional ones come from
`openvr.h` in the three new translation units.
- **Not tested yet:**
- running both backends, Vulkan validation, the snapshot test (step 5, with the
containers)
- mouse direction (Frame)
**Risk:**
- `MyTextField` opens the SteamVR keyboard on `activeFocus`. The template had to send the
offscreen window an explicit `FocusIn`, otherwise `activeFocusItem` stayed null. The `qt6`
branch doesn't send it. If text fields don't respond on the Frame, that is the cause (R4).
### Step 4: manifest and installation (2026-10-07)
**Changes:**
- **`manifest.vrmanifest`:** `binary_path_linux` and `binary_path_linux_arm` →
`AdvancedSettings_app`.
- **`manifest::handleManifests`:**
- `VR_Init(Utility)`; on `VRInitError_Init_NotAvailableToUtilityApps`,
`VR_Init(Background)`.
- Other errors: message and exit code `OPENVR_INIT_ERROR`, instead of
`initializeOpenVR`'s retry loop.
- **`main.cpp`:** `--graphics-api` is checked before connecting to OpenVR. A wrong value
used to fail only after `initializeOpenVR`'s retry loop.
**Results (x86_64, without SteamVR):**
- `--force-install-manifest` exits right away with `OPENVR_INIT_ERROR` (−2).
- `--graphics-api foo` exits right away with `GENERAL_FAILURE` (−1).
- The build tree contains the binary, `libopenvr_api.so`, both manifests,
`default_action_manifests/` and `res/`.
- Not tested yet: `Background` on the Frame (step 5).
### Step 5: Frame build, package, tests (2026-10-07)
**Changes:**
- **`build_scripts/steamframe/`** (new, see DESIGN.md section 9): containers, toolchain, build,
test, package and deploy scripts.
- **`test/render/`** (new): render test for both backends (`OVRAS_BUILD_TESTS=ON`).
- **`CMakeLists.txt`:**
- option `OVRAS_BUILD_TESTS`
- RPATH only `$ORIGIN` (`BUILD_WITH_INSTALL_RPATH`). Before, the cross binary also had the
host's absolute link directory in its RUNPATH.
- **`.gitignore`:** `dist/`.
**Results:**
- **Render tests:**
- locally (Arch, Qt 6.11, Intel Iris Xe): OpenGL and Vulkan, 4/4 passed each
- in the container (Debian trixie, Qt 6.8, same GPU via `/dev/dri`): 2/2 passed,
**no Vulkan validation messages**
- Proof that the layer was active: `VK_LOADER_DEBUG=layer` shows
"Inserted device layer VK_LAYER_KHRONOS_validation".
- **Cross build (aarch64, Qt 6.8 Debian):** succeeds once the container has `libxt-dev`
(`input_sender_X11.cpp` includes `X11/Intrinsic.h`).
- `Qt_6_PRIVATE_API` without `QVulkan*`: 0 → **R1 symbols met**.
- Qt version tag: `Qt_6.8` (fits the Frame's 6.8.0).
- GLIBC ≤ 2.38 (the Frame has 2.39); GLIBCXX ≤ 3.4.32 (not checked against the Frame).
- NEEDED: Qt6 Core/Gui/Qml/Quick/Widgets/Network/DBus/Multimedia/WebSockets, libX11,
libXtst, libpulse, libopenvr_api, libstdc++/libc.
- **Package** `dist/AdvancedSettings-5.7.4-linux-arm64.tar.gz`: 3.0 MB (9.1 MB unpacked); since the version fix below `…-5.8.17-…`.
The version 5.7.4 comes from `qt6`'s `project()` (master is at 5.8.17).
**Open (needs the Frame):**
- Are the QML modules OVRAS imports present in the Frame's system Qt? QtQuick.Controls
(Material), Layouts, Dialogs, Multimedia.
- Do libXt/libXtst exist on SteamOS? Is libstdc++ new enough?
### Version from `compile_version_string.txt` (2026-10-07)
- **Problem:** `qt6`'s `CMakeLists.txt` had the version hard-coded as 5.7.4. The qmake build
read it from `build_scripts/compile_version_string.txt` (`5.8.17-release`). `master` is
fully merged into `qt6`, so only the number was stale. Consequence: the version check
(comparison with `ver/versioncheck.json`, 5.8.17) would have reported an update.
- **Fix:** CMake reads the file.
- `APPLICATION_VERSION` = full string, as in qmake.
- `project(VERSION)` = numeric part.
- **Result:** `APPLICATION_VERSION="5.8.17-release"`, `CMAKE_PROJECT_VERSION=5.8.17`, package
`dist/AdvancedSettings-5.8.17-linux-arm64.tar.gz` (3.0 MB).
### Fix: manifest commands without a display (2026-10-07)
- **Problem (first deploy to the Frame):** `install.sh` aborted with a core dump in
`./AdvancedSettings_app --force-install-manifest`. Log: "could not connect to display",
then "no Qt platform plugin could be initialized" (fatal).
- **Cause:** `main.cpp` creates the `QApplication` before it handles the manifest options.
Qt's default platform plugin (`xcb`) aborts without a display, and over SSH there is
none. `install.sh` set `DISPLAY=:0` only for the start, not for registering.
`uninstall.sh` (`--force-remove-manifest`) had the same problem.
- **Fix (`package-release.sh`, generated scripts only):** both manifest calls run with
`QT_QPA_PLATFORM=offscreen`. Registering draws nothing, so it needs no display at all.
The normal start keeps `DISPLAY=:0` (`xcb`), because rendering needs a real OpenGL/Vulkan
context. No change to the program.
- **Result:** package rebuilt (`--no-build`), generated scripts checked with `sh -n`.
- **Not tested yet:** the fix itself on the Frame (T1, T11). No local x86 build was at hand
for a test without a display.
### Fix: OpenVR library for aarch64 (2026-10-07)
- **Problem (second deploy):** with the display fix, `--force-install-manifest` got as far
as `VR_Init` and failed there: "Installation path could not be located (110)", and on
stderr "Unable to read VR Path Registry from /data/work/openvrpaths.vrpath".
`~/.config/openvr/openvrpaths.vrpath` on the Frame is correct (runtime `/opt/steamvr`).
- **Cause:** the package shipped `third-party/openvr/lib/linuxarm64/libopenvr_api.so`. It is
byte-identical to the OpenVR SDK 2.15.6's `lib/linuxarm64` and looks for the path registry
in the fixed path `/data/work/openvrpaths.vrpath`. The SDK's `bin/linuxarm64` library
(used by the template, verified on the Frame) and SteamVR's own one in
`/opt/steamvr/bin/linuxarm64` don't contain that path. OVRAS's `third-party/openvr` had no
`bin/linuxarm64`.
- **Fix:**
- New file `third-party/openvr/bin/linuxarm64/libopenvr_api.so` from the SDK v2.15.6
(`raw.githubusercontent.com/ValveSoftware/openvr/v2.15.6/bin/linuxarm64/…`, SHA-256
`cc3671d2…47e9`).
- `CMakeLists.txt`: `OPENVR_LIB_DIR` = `bin/linuxarm64` for aarch64 only. x86_64 and
Windows are unchanged.
- Rejected: setting `VR_PATHREG_OVERRIDE` in the scripts. It wouldn't help when SteamVR
autostarts OVRAS.
- **Result:** cross build and package succeed. The package contains the new library (no
`/data/work`), `Qt_6_PRIVATE_API` without `QVulkan*`: 0, RUNPATH `$ORIGIN`. Package
1.6 MB (was 3.0 MB, the old library was 5.4 MB).
- **Not tested yet:** on the Frame (T1).
### Finding: app key already registered by Steam (2026-10-07)
- **Third try of T1** (by hand on the Frame, with the two fixes above): `VR_Init` works, as
`Utility` (vrserver.txt: "New Connect message … (VRApplication_Utility)"; SteamVR did
**not** refuse Utility this time, unlike with the template). Then: "Manifest Previously
Installed", "Could not find working directory of already installed application:
VRApplicationError_PropertyNotSet".
- **Cause:** Steam's generated `steamapps.vrmanifest` lists every owned VR app, including
OVRAS (`steam.overlay.1009850`, launch via `steam://` URL), although the Steam version is
uninstalled. Not a leftover of the uninstallation; it can't be removed permanently.
- **Next:** design DESIGN.md section 2a (approved 2026-10-07).
- **Implementation (`setup.cpp`, `setup.h`):** as designed: key without working directory →
nothing removed, `AddApplicationManifest` directly (error name on refusal);
`logApplicationEntry()` after "Manifest reinstalled." logs source, launch type, working
directory, binary, URL and auto-launch for the key.
- **Result:** cross build and package succeed, `Qt_6_PRIVATE_API` without `QVulkan*`: 0.
- **Not tested yet:** on the Frame. The log decides: `AppKeyAlreadyExists` or Steam's entry
(`steam://` URL) → own app key needed (option 2); our working directory and binary →
enough.
### Test checklist on the Frame (step 5)
Deploy: `build_scripts/steamframe/deploy-to-frame.sh <user>@<frame>` (SteamVR running).
| # | Check | Criterion | Result |
|---|---|---|---|
| T1 | `install.sh`: registration works (log: "Manifest reinstalled", via Background) | R2 | first try failed: abort without a display (fixed, see above); retest open |
| T2 | Tab appears in the dashboard, UI correct (OpenGL) | R2, R3 | open |
| T3 | `./run.sh vulkan`: UI correct | R3 | open |
| T4 | Laser right way up, click, scrolling on several pages (both APIs) | R4 | open |
| T5 | Text field (e.g. new profile name): SteamVR keyboard opens, input arrives | R4 | open |
| T6 | An OVRAS action arrives (e.g. push-to-talk, log/notification) | R4 | open |
| T7 | Play area before/after start unchanged; log: "CommitWorkingCopy skipped" | R7 | open |
| T8 | Quit app (OVRAS "Exit" and Quit in the SteamVR dashboard): no crash (both APIs) | R2 | open |
| 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).