mirror of
https://github.com/daniel-lynch/ovrplugin-openxr-shim.git
synced 2026-10-04 22:00:05 +02:00
docs+build: hygiene pass — close leak risk, de-drift docs, fix build prereqs
Repo hygiene round following a full review. No shim behaviour changes. Leak risk: - .gitignore: ignore CLAUDE.md (personal assistant-lane config, was one `git add -A` away from a public commit) and scratch_obj/. Docs vs. reality: - shim/README.md: rewritten. It described a pre-implementation skeleton with "core fns are TODO stubs returning -1005", three mutually inconsistent stub counts, and four completed milestones listed as open. Now carries the verified breakdown: 438/438 exports = 371 generated stubs + 46 core + 7 layers + 2 Vulkan queries + 12 passthru trampolines. - TESTING.md: dropped the self-contradicting "NOT yet" block (5 of 6 items were done or misstated, and contradicted the same file 45 lines above). Path B now points at tools/desktop-harness, which exists, instead of the orphaned shim/tests/harness.c. Path A prereqs marked as the record they are. - HOST.md: corrected the runtime assumption. The OpenXR runtime inside Lepton is SteamVR (vendor/etc/openxr/1/active_runtime.json -> vrclient.so), not Monado. Favourable: SteamVR emulates Oculus Touch by default and advertises the XR_FB_foveation family, so the existing input and foveation paths should carry over. The old "remaining unknowns" are resolved by Lepton's published source and replaced with the items to check before a first Frame boot. - README.md: same runtime correction. - docs/research/RECON.md: the four passages prescribing an entitlement NOP/stub/bypass are corrected in place rather than merely disclaimed by the top banner, which they contradicted. Build correctness: - shim/build_android.sh: missing patchelf is now fatal. It warned and exited 0, producing a .so that cannot resolve the OpenXR loader at runtime. - scripts/fetch_deps.sh + packaging/build_openxr_loader.sh: pin the OpenXR and Vulkan header versions (were tracking `main`), overridable via OPENXR_TAG / VULKAN_HEADERS_TAG; require cmake for the loader build. - packaging/steamframe_patches.sh: use the apktool.jar that fetch_deps.sh downloads. Its prereq check demanded an `apktool` binary on PATH that the documented setup never provides, so it could not run after a clean setup. - shim/gen_stubs.sh: it reads all_exports.txt, not shim_surface.txt; comment and emitted banner corrected. stubs.c regenerated (banner line only). - shim/src/core.c: split seven `if (out) ...; return ...;` one-liners. Host build now compiles with zero warnings, down from seven. Verified: host build 0 warnings; gen_stubs.sh output identical on regeneration; bash -n clean on all edited scripts; pinned header/tarball URLs return 200 and the tag tarball extracts to the expected directory name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
574f41a0e4
commit
1f3dc40c07
13 files changed
+304
-161
No files matched your search
@@ -34,3 +34,7 @@ packaging/libs/
|
||||
*.zip
|
||||
*.tar.gz
|
||||
save_backup/
|
||||
|
||||
# Session/lane scratch (personal assistant-lane config — never public)
|
||||
CLAUDE.md
|
||||
scratch_obj/
|
||||
@@ -1,7 +1,15 @@
|
||||
# Target host platform — Steam Frame
|
||||
|
||||
Researched 2026-06-23. Answers "can the dumped APK run on Steam Frame, and do we
|
||||
need Android given SteamOS is Linux?"
|
||||
Researched 2026-06-23; **corrected 2026-09-18 against the shipped hardware and Lepton's
|
||||
published source.** Answers "can the dumped APK run on Steam Frame, and do we need Android
|
||||
given SteamOS is Linux?"
|
||||
|
||||
> **Correction (2026-09-18):** the 2026-06 research assumed the OpenXR runtime inside Lepton
|
||||
> would be **Monado**. It is **SteamVR**. Lepton ships
|
||||
> `vendor/etc/openxr/1/active_runtime.json` naming runtime `steamvr`
|
||||
> (`VALVE_runtime_is_steamvr: true`) and pointing at a host-mounted
|
||||
> `/data/steamvr/runtime/bin/androidarm64/vrclient.so`. Sections below are updated; treat any
|
||||
> remaining "Monado" reference in older docs as superseded.
|
||||
|
||||
## Do we need the Android side? YES.
|
||||
The game is an **Android binary**, not a Linux one — ARM64==ARM64 does NOT bridge:
|
||||
@@ -18,34 +26,64 @@ The game is an **Android binary**, not a Linux one — ARM64==ARM64 does NOT bri
|
||||
run **native ARM64, no emulation** (the "Waydroid needs x86" caveat is about
|
||||
Waydroid on x86 PCs; Frame is ARM so it doesn't apply). Walkabout Mini Golf
|
||||
(Quest title) already cited running on it.
|
||||
- **Monado** = open OpenXR runtime, runs on **Linux AND Android**, Vulkan
|
||||
compositor using VK_KHR_external_memory_fd / external_semaphore_fd (matches our
|
||||
Vulkan-renderer finding).
|
||||
- **SteamVR** is the OpenXR runtime apps see inside Lepton, bind-mounted in from the host
|
||||
(not Monado — see the correction above). It advertises the `XR_FB_foveation` family,
|
||||
`XR_FB_swapchain_update_state`, `XR_META_foveation_eye_tracked` and
|
||||
`XR_EXT_eye_gaze_interaction`, and it presents Frame controllers as **emulating Oculus
|
||||
Touch** by default (falling back Frame profile -> generic -> Touch). Both facts are
|
||||
favourable: our Touch bindings and our FB-foveation path should work unchanged.
|
||||
- Lepton also mounts the host's graphics stack into the container (mesa/turnip/zink, gralloc
|
||||
`minigbm_msm`) plus host Vulkan layers including a foveated-rendering injector and a
|
||||
renderpass optimizer.
|
||||
|
||||
## Architecture
|
||||
```
|
||||
Steam Frame (SteamOS / Arch Linux, ARM64)
|
||||
└─ Lepton (AOSP/Waydroid container, native ARM64)
|
||||
└─ RE4 VR APK (unmodified bionic Android binary)
|
||||
├─ libUE4.so → [SHIM libOVRPlugin] → OpenXR → Monado → Frame compositor (Vulkan)
|
||||
├─ libUE4.so → [SHIM libOVRPlugin] → OpenXR → SteamVR (vrclient.so) → Frame compositor
|
||||
└─ ovr_* Platform SDK → out of scope (no entitlement code ships in this repo —
|
||||
a valid entitlement is the user's responsibility; see README "Legal / scope")
|
||||
```
|
||||
|
||||
## Why the shim IS the project
|
||||
Meta ended VrApi support 2022-08-31; OpenXR is the only supported Quest API and
|
||||
Valve's whole stack is OpenXR (Monado). So:
|
||||
- OpenXR Quest games -> Lepton+Monado likely run them with little/no work.
|
||||
Valve's whole stack is OpenXR (SteamVR on Frame). So:
|
||||
- OpenXR Quest games -> Lepton+SteamVR likely run them with little/no work.
|
||||
- VrApi games (RE4 VR) -> won't: Lepton/AOSP will never ship Meta's proprietary
|
||||
libvrapi.so, so the unmodified game finds no VR runtime. The OVRPlugin->OpenXR
|
||||
shim is exactly what bridges a dead-API VrApi game to Frame's OpenXR stack.
|
||||
|
||||
## Remaining real unknowns (gated on Frame shipping ~summer 2026)
|
||||
1. Does Lepton expose an OpenXR loader+runtime to apps INSIDE the container?
|
||||
(Almost certainly yes for the OpenXR-Quest-game use case; ride on it.)
|
||||
2. Can a SIDELOADED app reach the runtime + compositor (perms across the Waydroid
|
||||
boundary)?
|
||||
3. **Likely the real technical crux:** sharing Vulkan swapchain images from inside
|
||||
the Lepton container out to the host Monado/Frame compositor
|
||||
(VK_KHR_external_memory_fd across the container GPU boundary). May be moot if
|
||||
Monado's compositor runs inside the container.
|
||||
## Status of the old unknowns (resolved 2026-09-18)
|
||||
|
||||
Steam Frame shipped **2026-09-14** and Lepton is open source (MIT for the tool), so the three
|
||||
2026-06 unknowns are answered:
|
||||
|
||||
1. **Does Lepton expose an OpenXR runtime to apps inside the container?** Yes — SteamVR, via
|
||||
the bind-mounted `active_runtime.json` and `vrclient.so` described above.
|
||||
2. **Can a sideloaded app reach the runtime + compositor?** Yes. Lepton documents adb
|
||||
sideloading (`lepton install_app`, or `adb install` against the container), and its own
|
||||
installer pushes an adjacent `obb/` directory into the app's data — which matters for us,
|
||||
since RE4 VR ships its assets as OBBs.
|
||||
3. **Vulkan swapchain sharing across the container GPU boundary** — a non-issue by design:
|
||||
Lepton mounts the host graphics drivers into the container rather than proxying them.
|
||||
|
||||
### New items to check before a first boot attempt
|
||||
|
||||
- **Page alignment (check this first).** Our shim's ELF LOAD segments align at 4 KB and
|
||||
`repack.sh` runs `zipalign -p 4`. Valve's Unreal docs reference a 16 KB page-alignment
|
||||
requirement on this platform. If the Frame kernel uses 16 KB pages, the library will not
|
||||
load, and it would present as an unexplained launch failure. Fix is
|
||||
`-Wl,-z,max-page-size=16384` at link time plus `zipalign -P 16`.
|
||||
- **The Build spoof in `packaging/steamframe_patches.sh` is confirmed necessary.** Lepton sets
|
||||
`ro.product.manufacturer=Valve` and `ro.product.model=Lepton`, so UE's Oculus-HMD gate is
|
||||
false without it and our shim is never called.
|
||||
- **Swapchain usage flags.** `setup_layer` requests only COLOR_ATTACHMENT and SAMPLED. Meta
|
||||
over-provisions; a spec-following runtime does not.
|
||||
- **Refresh rate.** 72 Hz is hardcoded in two places; Frame runs 72/90/120/144.
|
||||
- **`UECommandLine.txt`.** Lepton's installer pushes one into `/data/steam_app`, which may be
|
||||
a route for the UE streaming CVars that the baked-commandline dead end blocked on Quest.
|
||||
Unverified, but cheap to try.
|
||||
- **App SDK level.** RE4 VR is `minSdkVersion 25` / `targetSdkVersion 29`, arm64-v8a only.
|
||||
Lepton rejects APKs whose SDK level is *higher* than the container's, so a low target should
|
||||
be fine — but it is untested.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
A from-scratch reimplementation of Meta's `libOVRPlugin.so` on top of **OpenXR**,
|
||||
so legacy VrApi/OVRPlugin-based Meta Quest titles can run on standard OpenXR
|
||||
runtimes (Monado, and eventually Valve's **Steam Frame** under Lepton).
|
||||
runtimes — Valve's **Steam Frame** (SteamVR inside Lepton), Monado, and others.
|
||||
|
||||
**Status:** *Resident Evil 4 VR* boots and is playable on a Quest 2 through this
|
||||
shim — stereo rendering, head + controller tracking, buttons, grips, haptics, and
|
||||
@@ -12,12 +12,12 @@ save loading all work. (Developed as a preservation / interoperability experimen
|
||||
|
||||
Quest's `libOVRPlugin.so` is the C shim Unreal/Unity games call to talk to Meta's
|
||||
VR runtime. Meta deprecated the underlying VrApi in 2022 and the whole modern stack
|
||||
(incl. Steam Frame's Monado) is OpenXR-only, so VrApi-era titles have no runtime on
|
||||
(incl. Steam Frame's SteamVR) is OpenXR-only, so VrApi-era titles have no runtime on
|
||||
non-Meta OpenXR platforms. This project re-exports the `ovrp_*` C API backed by
|
||||
OpenXR instead, as a **drop-in replacement** `libOVRPlugin.so`:
|
||||
|
||||
```
|
||||
game (libUE4.so) ──ovrp_* C API──> [THIS SHIM] ──OpenXR──> runtime (Monado / Meta / …)
|
||||
game (libUE4.so) ──ovrp_* C API──> [THIS SHIM] ──OpenXR──> runtime (SteamVR / Meta / Monado / …)
|
||||
```
|
||||
|
||||
It implements the OpenXR instance/session lifecycle, the Vulkan graphics binding,
|
||||
@@ -44,11 +44,15 @@ of it to the `ovrp_*` ABI the game expects.
|
||||
## Build
|
||||
|
||||
```sh
|
||||
scripts/fetch_deps.sh # OpenXR + Vulkan headers (Apache-2.0), Android NDK
|
||||
shim/build_android.sh # -> shim/build/arm64/libOVRPlugin.so
|
||||
scripts/fetch_deps.sh # OpenXR + Vulkan headers (Apache-2.0), NDK, JDK, build-tools
|
||||
shim/build_android.sh # -> shim/build/arm64/libOVRPlugin.so
|
||||
packaging/build_openxr_loader.sh # -> packaging/libs/arm64/libopenxr_loader.so
|
||||
```
|
||||
Needs: Android NDK (r27c), a JDK, and the OpenXR/Vulkan headers (the fetch script
|
||||
gets them). A host x86-64 build is also supported for compile-validation.
|
||||
`fetch_deps.sh` pins the header versions; override with `OPENXR_TAG` / `VULKAN_HEADERS_TAG`.
|
||||
|
||||
From your distro you also need **`patchelf`** (the Android build fails without it — the shim
|
||||
cannot resolve the OpenXR loader) and **`cmake`** (for the loader build). A host x86-64 build
|
||||
is also supported for compile-validation and the desktop harness: `shim/build_host.sh`.
|
||||
|
||||
## Use (with your own dumped game)
|
||||
|
||||
|
||||
+88
-47
@@ -25,7 +25,7 @@ Idea: build the shim as an Android arm64 `.so`, drop it into the RE4 APK in plac
|
||||
of the real `libOVRPlugin.so`, sideload, run. Our shim calls the Quest's own
|
||||
`libopenxr_loader` -> Meta's OpenXR runtime.
|
||||
|
||||
Prereqs to do first (these are the currently-open work items):
|
||||
Prereqs (all done — kept as the record of what Path A needed):
|
||||
1. **NDK arm64 build** of the shim — DONE. `shim/build_android.sh` -> NDK r27c ->
|
||||
build/arm64/libOVRPlugin.so (aarch64, 438/438 drop-in, NEEDED libopenxr_loader).
|
||||
2. **Instance handshake** — DONE. src/android_init.c: JNI_OnLoad captures the JavaVM;
|
||||
@@ -34,9 +34,9 @@ Prereqs to do first (these are the currently-open work items):
|
||||
Application-context reflection fallback. [VERIFY-ON-HW] whether Meta's runtime
|
||||
accepts the Application context vs requiring the real Activity, and the
|
||||
PreInitialize3-creates-instance-before-activity ordering.
|
||||
3. **Manifest** — add the OpenXR usage declarations Meta's runtime expects
|
||||
(`<uses-feature android:name="android.hardware.vr.headtracking">` already there;
|
||||
add OpenXR `<meta-data>`/intent bits per Meta's OpenXR mobile docs).
|
||||
3. **Manifest** — no change needed in the end. RE4 VR is already a shipping Quest VR app
|
||||
and declares `<uses-feature android:name="android.hardware.vr.headtracking">`;
|
||||
`packaging/inspect_manifest.sh` reports any gaps.
|
||||
4. **Entitlement** — on Quest you OWN RE4 and the Quest has the real Meta Horizon
|
||||
platform service, so leave the ORIGINAL libovrplatformloader.so untouched and only
|
||||
swap libOVRPlugin.so. Logged into the owning account, the real ovr_Entitlement check
|
||||
@@ -55,61 +55,102 @@ cp shim/build/arm64/libOVRPlugin.so apk/lib/arm64-v8a/libOVRPlugin.so
|
||||
adb install -r re4vr-shim.apk # or push OBB + sideload
|
||||
adb logcat | grep -iE 'xrr|OVRPlugin|openxr' # watch the [xrr] logs
|
||||
```
|
||||
Expected first-run signal: instance/session create succeed in logcat; if the frame
|
||||
loop spins and the projection layer submits, you get an image (even if poses/input
|
||||
are rough). Known rough edges on first run: depth (Unsupported), input (controllers
|
||||
return NotYetImplemented), the [VERIFY-ON-HW] swapchain index lockstep.
|
||||
`packaging/repack.sh` now does the repack, align and re-sign in one step; the manual
|
||||
sequence above is kept only to show what it does.
|
||||
|
||||
## Path B — Monado simulated (fast iteration, works on the Mac)
|
||||
First-run signal to look for: instance and session create succeeding in logcat, then the
|
||||
frame loop spinning and the projection layer submitting. (Historically the rough edges on a
|
||||
first run were depth, input and the swapchain index lockstep; input and rendering are now
|
||||
working — see "Current state" below.)
|
||||
|
||||
Monado has a simulated/headless HMD driver — no real headset. Run it in a Linux
|
||||
arm64 VM (UTM/QEMU on Apple Silicon), point an OpenXR loader at it, and run the
|
||||
harness (tests/harness.c) which drives the ovrp_* sequence:
|
||||
## Path B — desktop OpenXR harness (fast iteration) — BUILT
|
||||
|
||||
`tools/desktop-harness/` drives the `ovrp_*` sequence against a real OpenXR runtime with no
|
||||
headset and no RE4:
|
||||
PreInitialize3 -> Initialize5 -> SetupLayer -> [WaitToBeginFrame -> BeginFrame4 ->
|
||||
GetNodePoseState3 -> EndFrame4] xN -> Shutdown2
|
||||
and asserts each returns ovrpSuccess. This exercises the real OpenXR calls without
|
||||
RE4 or hardware. Build:
|
||||
asserting each returns `ovrpSuccess`. Build and run:
|
||||
```
|
||||
# inside the Linux arm64 env, with Monado + openxr loader installed:
|
||||
cc -std=c11 -Iinclude -Ithird_party/openxr tests/harness.c \
|
||||
src/*.c -lopenxr_loader -lvulkan -o harness # needs a Vulkan device/headless
|
||||
XR_RUNTIME_JSON=/path/to/monado/openxr_monado-dev.json ./harness
|
||||
shim/build_host.sh # -> build/host/{libOVRPlugin.so,harness}
|
||||
tools/desktop-harness/run.sh # headless against monado-service
|
||||
```
|
||||
Note: Initialize5 needs real Vulkan handles; for a pure-logic smoke test the harness
|
||||
can pass a headless VkInstance/Device (or we add a "no-gfx" build flag that skips
|
||||
xrCreateSession to test the non-rendering calls first).
|
||||
Needs libvulkan and an OpenXR loader (Debian: `libvulkan-dev libopenxr-loader1
|
||||
libopenxr-dev`); without the loader `build_host.sh` compiles the objects and stops.
|
||||
|
||||
Worth adding when chasing a portability bug: run it with `VK_LAYER_KHRONOS_validation` and
|
||||
the OpenXR core-validation API layer enabled. The harness currently passes without them, so
|
||||
it does not yet catch usage-flag or queue-family mistakes that a strict runtime would reject.
|
||||
|
||||
Note: `shim/tests/harness.c` is the original superseded smoke test; its build line is stale
|
||||
and no script references it.
|
||||
|
||||
## Path C — Steam Frame (the target)
|
||||
|
||||
Same arm64 shim `.so`, but the APK runs under **Lepton** (Valve's Waydroid/AOSP) and
|
||||
the OpenXR runtime is **Monado**. Once Frame ships: NDK build -> repack -> sideload
|
||||
into Lepton -> the open question is whether Lepton exposes the OpenXR loader +
|
||||
Vulkan swapchain sharing across the container (see HOST.md unknowns). Path A having
|
||||
worked makes this mostly a packaging/runtime-plumbing exercise.
|
||||
Same arm64 shim `.so`, but the APK runs under **Lepton** (Valve's Waydroid fork, now open
|
||||
source) and the OpenXR runtime inside the container is **SteamVR** — Lepton's
|
||||
`vendor/etc/openxr/1/active_runtime.json` names `steamvr` and points at a host-mounted
|
||||
`vrclient.so`. (Earlier notes here and in `HOST.md` assumed Monado; that was wrong.)
|
||||
|
||||
What that buys us: SteamVR presents Frame controllers as emulating Oculus Touch by default,
|
||||
so the shim's Touch bindings should bind; and it advertises the `XR_FB_foveation` family plus
|
||||
`XR_META_foveation_eye_tracked`, so the existing foveation path survives. Lepton also mounts
|
||||
the host's mesa/turnip/zink and gralloc into the container, which answers the old
|
||||
`HOST.md` unknown about sharing swapchain images across the container boundary.
|
||||
|
||||
Steam Frame shipped 2026-09-14. Flow: NDK build -> `repack.sh` -> `steamframe_patches.sh`
|
||||
(the Build spoof is required — Lepton reports `ro.product.manufacturer=Valve`) -> sideload
|
||||
via adb into a Lepton container. Path A having worked makes this mostly packaging and
|
||||
runtime-plumbing, but see `HOST.md` for the specific items to check first.
|
||||
|
||||
---
|
||||
|
||||
## Current state (what's ready to test vs not)
|
||||
## Current state
|
||||
|
||||
WIRED & building (host x86-64, validation only):
|
||||
- Session lifecycle: instance/system/session create, event-driven state machine.
|
||||
- Frame loop: xrWaitFrame/Begin/EndFrame, predicted display time.
|
||||
- Poses: xrLocateViews (eyes) + xrLocateSpace (head).
|
||||
- Swapchains: xrCreateSwapchain from ovrpLayerDesc, enumerate VkImages, per-frame
|
||||
acquire/wait/release, real XrCompositionLayerProjection submit.
|
||||
- 20 OpenXR functions; 239/239 ovrp_ symbols.
|
||||
**Path A is done and field-verified.** RE4 VR boots and is playable on a Quest 2 through the
|
||||
shim on Meta's OpenXR runtime: stereo rendering, head and controller tracking, buttons,
|
||||
grips, haptics, save loading. The frame-pacing "ghost" that dominated development is fixed
|
||||
(game-thread pacing; see `docs/research/ghost-fix-2026-06-27.md`). Shipped and verified:
|
||||
|
||||
NOT yet (the to-do list before a meaningful Quest run):
|
||||
- arm64/Android NDK build (host build only so far).
|
||||
- [ANDROID-TODO] JavaVM/activity -> XrInstanceCreateInfoAndroidKHR + xrInitializeLoaderKHR.
|
||||
- Input: controller/hand action sets (GetControllerState4 returns NotYetImplemented).
|
||||
- Depth layer (SetupLayerDepth -> Unsupported).
|
||||
- Map ovrp_GetInstance/DeviceExtensionsVk -> xrGetVulkan*ExtensionsKHR (so the app
|
||||
creates its VkInstance/Device with the runtime's required extensions).
|
||||
- [VERIFY-ON-HW] swapchain index lockstep assumption.
|
||||
- Session lifecycle, event-driven state machine, Android instance handshake
|
||||
(`src/android_init.c`).
|
||||
- Frame loop with `xrWaitFrame` on the game thread and a FIFO frameState handoff to the
|
||||
render thread.
|
||||
- Poses via `xrLocateViews` and `xrLocateSpace`; `LOCAL_FLOOR` when the game asks for floor
|
||||
level.
|
||||
- Swapchains from `ovrpLayerDesc`, per-frame acquire/wait/release, real projection-layer
|
||||
submit, layer z-order fix so splash quads composite above the eye layer.
|
||||
- Input action sets for Touch controllers plus haptics (`src/xr_input.c`).
|
||||
- Vulkan extension queries mapped to `xrGetVulkan*ExtensionsKHR` (`src/vk_session.c`).
|
||||
- CPU/GPU perf levels forwarded via `XR_EXT_performance_settings`; game-driven foveation.
|
||||
- 438/438 `ovrp_` symbols; around 48 OpenXR entry points.
|
||||
|
||||
## Pick-up-tomorrow shortlist
|
||||
1. Install Android NDK; cross-build the shim to arm64 (proves it builds for target).
|
||||
2. Stand up the Monado-sim Linux arm64 VM on the Mac + run tests/harness.c (Path B
|
||||
smoke test of the non-gfx calls).
|
||||
3. Then start the [ANDROID-TODO] instance handshake (gates the real Quest run).
|
||||
**Open / known gaps:**
|
||||
- Depth layer submission is built but gated off (`debug.re4vr.depth`); Meta's runtime accepts
|
||||
but does not use plain KHR depth for reprojection.
|
||||
- Swapchain index lockstep with UE's own `TextureStage` is assumed, not enforced — a
|
||||
mismatch is logged but not corrected.
|
||||
- Residual `XR_FRAME_DISCARDED` hiccups from the frameState ring dropping its oldest entry
|
||||
under overflow instead of applying back-pressure.
|
||||
- In-game black near load zones is a level-streaming / memory stall, mitigated rather than
|
||||
fixed. See `docs/handoffs/HANDOFF-2026-06-27.md`.
|
||||
- Several `debug.re4vr.*` paths are documented dead ends kept for reference.
|
||||
|
||||
## Next: Path C (Steam Frame)
|
||||
|
||||
Frame shipped 2026-09-14, so this is the live front. Highest-value items before a first boot
|
||||
attempt, in order:
|
||||
1. **Page alignment.** The shim's ELF segments and the repacked APK are 4 KB-aligned
|
||||
(`zipalign -p 4`); Valve's Unreal docs reference a 16 KB page-alignment requirement. If
|
||||
the Frame kernel uses 16 KB pages the library will not load. Check first: it is a
|
||||
`-Wl,-z,max-page-size=16384` plus `zipalign -P 16` fix, but it would present as a
|
||||
mystery launch failure.
|
||||
2. **Swapchain usage flags.** `setup_layer` requests only COLOR_ATTACHMENT and SAMPLED.
|
||||
Meta over-provisions mutable, broadly-usable images; a spec-following runtime gives you
|
||||
exactly what you asked for, and UE 4.25 needs a mutable format for its linear UNORM view.
|
||||
3. **Refresh rate.** 72 Hz is hardcoded in `ovrp_GetSystemDisplayFrequency2` and in the
|
||||
frame-budget constant. Frame runs 72/90/120/144. Derive it from
|
||||
`predictedDisplayPeriod`.
|
||||
4. **Session events.** Only READY and STOPPING are handled, so focus loss and quit from the
|
||||
Steam overlay never reach the game.
|
||||
5. **The per-frame GPU flush-wait.** It exists because Meta's compositor does not sync
|
||||
against our submit. A/B it on Frame with `debug.re4vr.noflushwait`.
|
||||
+15
-11
@@ -10,11 +10,12 @@ Legal posture: dump-your-own only. We extract from hardware *you own* running a
|
||||
copy *you own*. **Nothing here gets redistributed** — only patches/shims you
|
||||
author, applied by people who dump their own copy. Same model as ReXGlue.
|
||||
|
||||
> **Editor's note (2026-06):** this is a historical recon document. It explores an
|
||||
> entitlement-**stub** approach in a few places (§4, the wiring summary, the decision tree)
|
||||
> that was **not** carried into the project — entitlement handling is out of scope and the
|
||||
> shim ships **no circumvention code** (see the README's scope section). Those passages are
|
||||
> kept as a record of the original investigation, not as instructions.
|
||||
> **Editor's note (2026-06, revised 2026-09):** this is a historical recon document. Its
|
||||
> original text proposed an entitlement-stub approach in a few places (§4, the wiring
|
||||
> summary, the decision tree). That was **not** carried into the project: entitlement
|
||||
> handling is out of scope and the shim ships **no circumvention code** (see the README's
|
||||
> scope section). Those passages have since been **corrected in place** so the document no
|
||||
> longer reads as instructions; the correction is noted inline where it applies.
|
||||
|
||||
---
|
||||
|
||||
@@ -98,7 +99,7 @@ Interpret the result:
|
||||
|-----------------------------------|-----------------------------------------------------|------------|
|
||||
| `libopenxr_loader.so` | ✅ Standard OpenXR — Steam Frame provides a runtime; you translate vendor extensions. | Tractable |
|
||||
| `libvrapi.so` | ⚠️ Proprietary Meta VrApi — must reimplement/shim the runtime. | Hard |
|
||||
| `libovrplatformloader.so` | Present either way — this is the **entitlement check** to NOP/stub. | Required patch |
|
||||
| `libovrplatformloader.so` | Present either way — the platform/entitlement library. **Left untouched** by this project (out of scope). | Not patched |
|
||||
| `libUE4.so` (or split into modules)| The Unreal runtime itself — the host you'll be hooking. | n/a |
|
||||
|
||||
- [x] **RESULT — runtime is:** ☑ **VrApi** (legacy OVRPlugin path). Confirmed
|
||||
@@ -117,8 +118,10 @@ libUE4.so --(NEEDED + ovr_* Platform SDK, 132 refs)--> libovrplatformloader.so
|
||||
- => **PORT SEAM = reimplement libOVRPlugin.so (ovrp_* on OpenXR), drop libvrapi.**
|
||||
ovrp_* is the documented Unity-shared API (OVR_Plugin.h); modern Meta OVRPlugin
|
||||
has an OpenXR backend = reference impl / prior art.
|
||||
- => **Stub the ovr_* Platform SDK** (libovrplatformloader.so) — entitlement/account,
|
||||
just return OK; don't reimplement.
|
||||
- => **Leave the ovr_* Platform SDK alone** (`libovrplatformloader.so`). Entitlement and
|
||||
account handling are **out of scope**: the original library is kept and its real check
|
||||
runs unchanged. (The original recon note here proposed stubbing it; that was *not*
|
||||
carried into the project — see the README's scope section.)
|
||||
|
||||
> If you want to double-check beyond filename presence, extract and inspect
|
||||
> imports of `libUE4.so` (it may dynamically link the runtime):
|
||||
@@ -187,12 +190,13 @@ device: Quest 2 serial <redacted-serial> (codename hollywood)
|
||||
|
||||
**Decision tree:**
|
||||
- **OpenXR** → next phase: map which Meta OpenXR vendor extensions the binary
|
||||
requests, plan the OpenXR→Steam-Frame-runtime shim + entitlement stub.
|
||||
requests, plan the OpenXR→Steam-Frame-runtime shim.
|
||||
This is the "weekend-of-shimming" branch.
|
||||
- **VrApi** → next phase: scope a VrApi reimplementation/translation shim
|
||||
(much larger). Reassess whether the project is worth it vs. waiting/UEVR.
|
||||
- **Either way** → `libovrplatformloader.so` entitlement bypass is a required
|
||||
Ghidra patch (legal for your own copy).
|
||||
- **Either way** → `libovrplatformloader.so` is left as shipped. Entitlement handling is
|
||||
out of scope for this project and no bypass is part of it; on Quest the platform's real
|
||||
check runs unchanged. (The original recon note assumed a patch here; superseded.)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,14 +4,18 @@
|
||||
set -euo pipefail
|
||||
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_env.sh"
|
||||
[ -n "${NDK:-}" ] && [ -d "$NDK" ] || { echo "NDK not found. Set \$ANDROID_NDK or run scripts/fetch_deps.sh"; exit 1; }
|
||||
command -v cmake >/dev/null || { echo "cmake not found — install it (and optionally ninja) to build the loader"; exit 1; }
|
||||
# Keep this in step with OPENXR_TAG in scripts/fetch_deps.sh so the loader and the headers
|
||||
# the shim compiles against are the same OpenXR version.
|
||||
OPENXR_TAG="${OPENXR_TAG:-release-1.1.50}"
|
||||
SRC="$ROOT/tools/OpenXR-SDK"
|
||||
|
||||
if [ ! -d "$SRC" ]; then
|
||||
echo "downloading OpenXR-SDK source..."
|
||||
curl -fsSL -o "$ROOT/tools/oxrsdk.tgz" \
|
||||
"https://github.com/KhronosGroup/OpenXR-SDK/archive/refs/heads/main.tar.gz"
|
||||
"https://github.com/KhronosGroup/OpenXR-SDK/archive/refs/tags/${OPENXR_TAG}.tar.gz"
|
||||
tar xzf "$ROOT/tools/oxrsdk.tgz" -C "$ROOT/tools"
|
||||
mv "$ROOT/tools/OpenXR-SDK-main" "$SRC"
|
||||
mv "$ROOT/tools/OpenXR-SDK-${OPENXR_TAG}" "$SRC"
|
||||
fi
|
||||
|
||||
GEN="Unix Makefiles"; command -v ninja >/dev/null && GEN="Ninja"
|
||||
|
||||
@@ -16,12 +16,22 @@
|
||||
# in.apk : shim-repacked APK (default: out/re4vr-shim.apk)
|
||||
# out.apk : patched output (default: out/re4vr-steamframe.apk)
|
||||
#
|
||||
# Prereqs: apktool (https://apktool.org), plus the Android build-tools used by repack.sh.
|
||||
# Prereqs: tools/apktool.jar (scripts/fetch_deps.sh) or apktool on PATH, plus a JDK and
|
||||
# the Android build-tools used by repack.sh.
|
||||
# NOTE: prepared for the non-Quest bring-up; not yet validated on Steam Frame hardware.
|
||||
set -euo pipefail
|
||||
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_env.sh"
|
||||
[ -n "${BT:-}" ] && [ -d "$BT" ] || { echo "Android build-tools not found. Run scripts/fetch_deps.sh"; exit 1; }
|
||||
command -v apktool >/dev/null || { echo "apktool not found — install it (https://apktool.org) to run the smali/manifest patches"; exit 1; }
|
||||
# Prefer the apktool.jar that scripts/fetch_deps.sh downloads (same as inspect_manifest.sh);
|
||||
# fall back to an `apktool` wrapper on PATH.
|
||||
if [ -f "${APKTOOL_JAR:-}" ]; then
|
||||
APKTOOL=("${JAVA_HOME:+$JAVA_HOME/bin/}java" -jar "$APKTOOL_JAR")
|
||||
elif command -v apktool >/dev/null; then
|
||||
APKTOOL=(apktool)
|
||||
else
|
||||
echo "apktool not found — run scripts/fetch_deps.sh (fetches tools/apktool.jar) or install"
|
||||
echo "apktool on PATH (https://apktool.org) to run the smali/manifest patches"; exit 1
|
||||
fi
|
||||
|
||||
IN="${1:-$PKG/out/re4vr-shim.apk}"
|
||||
OUT="${2:-$PKG/out/re4vr-steamframe.apk}"
|
||||
@@ -54,7 +64,7 @@ rm -rf "$WORK"; mkdir -p "$WORK"
|
||||
DEC="$WORK/dec"
|
||||
|
||||
echo "== apktool decode =="
|
||||
apktool d -f -o "$DEC" "$IN" >/dev/null
|
||||
"${APKTOOL[@]}" d -f -o "$DEC" "$IN" >/dev/null
|
||||
|
||||
# Locate UE's GameActivity smali (ue4 or unreal namespace, across smali_classesN dirs).
|
||||
mapfile -t GA < <(find "$DEC" -path '*/com/epicgames/ue4/GameActivity.smali' \
|
||||
@@ -90,7 +100,7 @@ if [ -f "$MAN" ]; then
|
||||
fi
|
||||
|
||||
echo "== apktool build =="
|
||||
apktool b -o "$WORK/unsigned.apk" "$DEC" >/dev/null
|
||||
"${APKTOOL[@]}" b -o "$WORK/unsigned.apk" "$DEC" >/dev/null
|
||||
|
||||
echo "== align + sign =="
|
||||
"$BT/zipalign" -f -p 4 "$WORK/unsigned.apk" "$WORK/aligned.apk"
|
||||
|
||||
+15
-6
@@ -3,22 +3,27 @@
|
||||
# the Android NDK). Run once after cloning.
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
# Pinned upstream versions. Bump deliberately, not implicitly: tracking `main` means a
|
||||
# clone six months from now builds against different headers than the one that was tested.
|
||||
OPENXR_TAG="${OPENXR_TAG:-release-1.1.50}"
|
||||
VULKAN_HEADERS_TAG="${VULKAN_HEADERS_TAG:-v1.4.321}"
|
||||
OXR="$ROOT/shim/third_party/openxr/openxr"
|
||||
VK="$ROOT/shim/third_party/vulkan/vulkan"
|
||||
|
||||
echo "== OpenXR headers (Apache-2.0) =="
|
||||
echo "== OpenXR headers (Apache-2.0, $OPENXR_TAG) =="
|
||||
mkdir -p "$OXR"
|
||||
OXRBASE="https://raw.githubusercontent.com/KhronosGroup/OpenXR-SDK/main/include/openxr"
|
||||
OXRBASE="https://raw.githubusercontent.com/KhronosGroup/OpenXR-SDK/$OPENXR_TAG/include/openxr"
|
||||
for h in openxr.h openxr_platform.h openxr_platform_defines.h; do
|
||||
curl -fsSL "$OXRBASE/$h" -o "$OXR/$h"
|
||||
done
|
||||
|
||||
echo "== Vulkan headers (Apache-2.0) =="
|
||||
echo "== Vulkan headers (Apache-2.0, $VULKAN_HEADERS_TAG) =="
|
||||
mkdir -p "$VK/vk_video"
|
||||
VKBASE="https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan"
|
||||
VKBASE="https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/$VULKAN_HEADERS_TAG/include/vulkan"
|
||||
for h in vulkan_core.h vk_platform.h; do curl -fsSL "$VKBASE/$h" -o "$VK/$h"; done
|
||||
printf '#ifndef VULKAN_H_\n#define VULKAN_H_\n#include "vk_platform.h"\n#include "vulkan_core.h"\n#endif\n' > "$VK/vulkan.h"
|
||||
VVBASE="https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video"
|
||||
VVBASE="https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/$VULKAN_HEADERS_TAG/include/vk_video"
|
||||
for f in $(grep -oE 'vk_video/[a-zA-Z0-9_]+\.h' "$VK/vulkan_core.h" | sed 's|vk_video/||' | sort -u); do
|
||||
curl -fsSL "$VVBASE/$f" -o "$VK/vk_video/$f"
|
||||
done
|
||||
@@ -44,5 +49,9 @@ echo "== apktool (manifest tooling) =="
|
||||
[ -f "$ROOT/tools/apktool.jar" ] || curl -fsSL -o apktool.jar \
|
||||
"https://github.com/iBotPeaches/Apktool/releases/download/v2.10.0/apktool_2.10.0.jar"
|
||||
|
||||
echo "done. Now: shim/build_android.sh (and packaging/repack.sh for an installable APK)."
|
||||
echo
|
||||
echo "Also needed, not fetched here: patchelf (build_android.sh) and cmake"
|
||||
echo "(packaging/build_openxr_loader.sh). Install them from your distro."
|
||||
echo "done. Now: shim/build_android.sh, packaging/build_openxr_loader.sh,"
|
||||
echo "then packaging/repack.sh for an installable APK."
|
||||
echo "NOTE: URLs are Linux-x86_64; on macOS swap the NDK/JDK/build-tools archives."
|
||||
+72
-51
@@ -1,61 +1,82 @@
|
||||
# libOVRPlugin.so shim (OVRPlugin v1.51 -> OpenXR)
|
||||
# libOVRPlugin.so shim (OVRPlugin v1.51 ABI -> OpenXR)
|
||||
|
||||
Drop-in replacement for RE4 VR's libOVRPlugin.so that re-exports the ovrp_* symbols
|
||||
backed by OpenXR (Monado) instead of Meta's libvrapi.so. See ../HOST.md, ../SHIM-SCOPE.md.
|
||||
Drop-in replacement for RE4 VR's `libOVRPlugin.so`. It re-exports the `ovrp_*` C ABI the
|
||||
game calls and implements it on **OpenXR + Vulkan** instead of Meta's `libvrapi.so`.
|
||||
|
||||
**Status: working.** RE4 VR boots and is playable on a Quest 2 through this shim on Meta's
|
||||
OpenXR runtime — stereo rendering, head and controller tracking, buttons, grips, haptics,
|
||||
and save loading. Steam Frame is the next target; see `../HOST.md`.
|
||||
|
||||
## Export surface
|
||||
|
||||
The artifact exports **438/438** `ovrp_*` symbols, matching `../analysis/all_exports.txt`
|
||||
exactly (0 missing, 0 extra), so any `dlsym` of any `ovrp_` resolves even for the ~199
|
||||
entry points RE4 never references.
|
||||
|
||||
| Source | Exports | What |
|
||||
|---|---|---|
|
||||
| `src/stubs.c` (generated) | 371 | 103 Unsupported (-1004), 67 no-op Success (0), 201 NotYetImplemented (-1005) |
|
||||
| `src/core.c` | 46 | lifecycle, frame loop, poses, controller, system info |
|
||||
| `src/layers.c` | 7 | `SetupLayer` / `GetLayerTexture2` / stage count / eye layer desc |
|
||||
| `src/vk_session.c` | 2 | the Vulkan instance/device extension queries |
|
||||
| `src/passthru.c` | 12 | trampolines for calls the game makes that need no real impl |
|
||||
|
||||
`gen_stubs.sh` regenerates `src/stubs.c` from `../analysis/all_exports.txt`; functions
|
||||
prototyped in the header are skipped there (67 of them) and implemented in `core.c`.
|
||||
Regeneration is deterministic — re-running it on a clean tree produces no diff.
|
||||
|
||||
## Layout
|
||||
- include/ovrplugin_shim.h — OVRPlugin v1.51 C ABI (types + core protos; self-checking
|
||||
_Static_asserts on binary-verified struct sizes).
|
||||
- gen_stubs.sh — generates src/stubs.c from ../analysis/shim_surface.txt.
|
||||
- src/stubs.c (generated) — 224 stubs: 101 Unsupported(-1004), 32 no-op Success(0),
|
||||
91 NotYetImplemented(-1005).
|
||||
- src/core.c — the 15 header-prototyped core fns (frame loop/init/poses/
|
||||
controller/system), currently TODO stubs returning -1005 with outputs zeroed.
|
||||
|
||||
## Build (host, for validation)
|
||||
```
|
||||
cc -std=c11 -Wall -shared -fPIC -fvisibility=hidden -Iinclude src/stubs.c src/core.c \
|
||||
-o build/libOVRPlugin.so
|
||||
```
|
||||
Status: builds; exports exactly 239 ovrp_ symbols (1:1 with shim_surface.txt, 0
|
||||
missing/extra); dlopen+dlsym verified. This is the SKELETON — it loads and resolves,
|
||||
it does not yet drive VR (core fns are TODO).
|
||||
- `include/ovrplugin_shim.h` — the `ovrp_*` C ABI: types, structs, core prototypes.
|
||||
Independently written against the observed ABI, with `_Static_assert`s pinning the
|
||||
binary-verified struct sizes so a layout mistake fails the build rather than the device.
|
||||
- `src/xr_runtime.{c,h}` — the OpenXR engine: instance/session lifecycle, the frame loop,
|
||||
swapchains, layer composition, foveation, perf levels.
|
||||
- `src/vk_session.c` — Vulkan graphics binding, image enumeration, the tile-memory flush.
|
||||
- `src/layers.c` — layer setup and eye layer geometry.
|
||||
- `src/xr_input.c` — action sets and controller/haptics mapping.
|
||||
- `src/android_init.c` — JavaVM/activity capture, `xrInitializeLoaderKHR`, Android instance
|
||||
create-info chaining.
|
||||
- `src/passthru.c` — the author-only A/B diagnostic (see below).
|
||||
- `src/stubs.c` — generated.
|
||||
|
||||
## Real target build (deployable) — TODO
|
||||
Must be aarch64 / Android (bionic) since it runs inside Lepton. Use the Android NDK:
|
||||
```
|
||||
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang \
|
||||
-std=c11 -shared -fPIC -fvisibility=hidden -Iinclude src/stubs.c src/core.c \
|
||||
-o build/arm64/libOVRPlugin.so
|
||||
```
|
||||
(host build only proves the C + symbol coverage; NDK build is the artifact that
|
||||
replaces the real lib in the APK.)
|
||||
Roughly 48 distinct OpenXR entry points are used.
|
||||
|
||||
## Modules (current)
|
||||
- include/ovrplugin_shim.h — OVRPlugin v1.51 ABI (types, structs, core protos).
|
||||
- src/stubs.c (generated) — 221 stubs (unsupported/no-op/TODO).
|
||||
- src/core.c — lifecycle + frame loop + poses (-> xr_runtime).
|
||||
- src/xr_runtime.{h,c} — OpenXR engine: session, frame loop, swapchains.
|
||||
- src/vk_session.c — Vulkan-typed: xrCreateSession binding + image enum.
|
||||
- src/layers.c — ovrp_SetupLayer / GetLayerTexture2 / StageCount.
|
||||
- tests/harness.c — Path B smoke test (see ../TESTING.md).
|
||||
Build adds: -Ithird_party/openxr -Ithird_party/vulkan, and src/{core,xr_runtime,
|
||||
vk_session,layers,stubs}.c. 20 OpenXR fns used; 239/239 ovrp_ exported.
|
||||
## Build
|
||||
|
||||
## Done so far
|
||||
Session lifecycle, frame loop (xrWaitFrame/Begin/EndFrame), poses (xrLocateViews/
|
||||
Space), swapchains (xrCreateSwapchain from ovrpLayerDesc, acquire/wait/release,
|
||||
XrCompositionLayerProjection submit). Vulkan binding from Initialize5 args [VERIFIED].
|
||||
**The deployable artifact** is Android arm64 — the game runs inside Horizon OS or Lepton:
|
||||
|
||||
```sh
|
||||
../scripts/fetch_deps.sh # OpenXR + Vulkan headers, NDK, JDK, build-tools
|
||||
./build_android.sh # -> build/arm64/libOVRPlugin.so
|
||||
```
|
||||
Needs the NDK (r27c) and `patchelf` (to add `NEEDED libopenxr_loader.so`). Then
|
||||
`../packaging/repack.sh` swaps it into your own dumped APK.
|
||||
|
||||
**Host build** is compile-validation plus the desktop OpenXR harness, not a shipping
|
||||
artifact:
|
||||
|
||||
```sh
|
||||
./build_host.sh # -> ../build/host/{libOVRPlugin.so,harness}
|
||||
../tools/desktop-harness/run.sh
|
||||
```
|
||||
Needs libvulkan and an OpenXR loader; without the loader it builds the objects and stops.
|
||||
|
||||
## Debug: passthru forwarding (author-only diagnostic)
|
||||
`debug.re4vr.passthru=1` makes the shim hand the whole OVRPlugin session to a real,
|
||||
SONAME-patched `libOVRPlugin_real.so` if one is present in the APK — an A/B harness for
|
||||
diffing native runtime behavior against the shim. **No such binary is included or
|
||||
distributed by this repo**; you would have to place one from your own device dump, and
|
||||
without it the flag is inert. All other `debug.re4vr.*` props are likewise diagnostics.
|
||||
|
||||
## Next (see ../TESTING.md for the test plan)
|
||||
1. NDK arm64 build (host build is validation only).
|
||||
2. [ANDROID-TODO] JavaVM/activity -> XrInstanceCreateInfoAndroidKHR + xrInitializeLoaderKHR.
|
||||
3. Input action sets (controllers/hands); depth layer; GetVulkan*ExtensionsKHR mapping.
|
||||
4. Repack APK (real entitlement — you own it); test on Quest 2.
|
||||
`debug.re4vr.passthru=1` hands the whole OVRPlugin session to a real, SONAME-patched
|
||||
`libOVRPlugin_real.so` if one is present in the APK — an A/B harness for diffing native
|
||||
runtime behaviour against the shim. **No such binary is included or distributed by this
|
||||
repo**; you would have to place one from your own device dump, and without it the flag is
|
||||
inert. All other `debug.re4vr.*` props are likewise diagnostics.
|
||||
|
||||
## Known gaps
|
||||
|
||||
- Depth layer submission is gated behind `debug.re4vr.depth` and off by default; Meta's
|
||||
runtime accepts but does not use plain KHR depth for reprojection.
|
||||
- Input binds `/interaction_profiles/oculus/touch_controller` only.
|
||||
- Several `debug.re4vr.*` paths are documented dead ends kept for reference (copy-ring,
|
||||
render-ahead, submithook); see `../docs/research/` for what each one ruled out.
|
||||
|
||||
See `../docs/research/SHIM-SCOPE.md` for how the surface was scoped, `../TESTING.md` for the
|
||||
test plan, and `../docs/README.md` for the research trail.
|
||||
@@ -27,11 +27,12 @@ mkdir -p "$SHIM/build/arm64"
|
||||
|
||||
# the xr* symbols resolve against libopenxr_loader.so at runtime; declare the dep so
|
||||
# the dynamic linker loads it (bundle libopenxr_loader.so in the APK lib/arm64-v8a/).
|
||||
# Without this the shim's xr* symbols never resolve at runtime, so a build that skipped it
|
||||
# is unusable — fail loudly rather than emitting a broken .so.
|
||||
PATCHELF="$(command -v patchelf || true)"
|
||||
if [ -n "$PATCHELF" ]; then
|
||||
"$PATCHELF" --add-needed libopenxr_loader.so "$SHIM/build/arm64/libOVRPlugin.so"
|
||||
echo "added NEEDED libopenxr_loader.so"
|
||||
else
|
||||
echo "WARN: patchelf not found — add 'libopenxr_loader.so' as NEEDED before packaging"
|
||||
fi
|
||||
[ -n "$PATCHELF" ] || { echo "ERROR: patchelf not found. It is required to add"; \
|
||||
echo " 'libopenxr_loader.so' as NEEDED; without it the shim cannot resolve the"; \
|
||||
echo " OpenXR loader at runtime. Install patchelf and re-run."; exit 1; }
|
||||
"$PATCHELF" --add-needed libopenxr_loader.so "$SHIM/build/arm64/libOVRPlugin.so"
|
||||
echo "added NEEDED libopenxr_loader.so"
|
||||
echo "built: $SHIM/build/arm64/libOVRPlugin.so"
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Generate shim/src/stubs.c from analysis/shim_surface.txt.
|
||||
# Generate shim/src/stubs.c from analysis/all_exports.txt (the FULL 438-export set).
|
||||
# Each ovrp_ function gets a stub returning a sensible ovrpResult, classified by
|
||||
# name per SHIM-SCOPE.md buckets. Functions prototyped in the header (real sigs)
|
||||
# are SKIPPED here and live in core.c instead.
|
||||
@@ -36,7 +36,7 @@ ovrp_GetLayerTextureFoveation ovrp_GetControllerHapticsDesc2 "
|
||||
# original return constant when passthru is off, and tail-call the real lib when it's on.
|
||||
|
||||
{
|
||||
echo '/* AUTO-GENERATED by gen_stubs.sh from analysis/shim_surface.txt. Do not edit by hand. */'
|
||||
echo '/* AUTO-GENERATED by gen_stubs.sh from analysis/all_exports.txt. Do not edit by hand. */'
|
||||
echo '#include "ovrplugin_shim.h"'
|
||||
echo '#include "log.h"'
|
||||
echo
|
||||
|
||||
+14
-7
@@ -211,31 +211,38 @@ OVRP_EXPORT ovrpResult ovrp_GetSystemDisplayFrequency2(float *outFreq) {
|
||||
/* per-frame app-state getters the loading loop polls (all (ovrpBool* out)->result) */
|
||||
OVRP_EXPORT ovrpResult ovrp_GetAppHasVrFocus2(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetAppHasVrFocus2, out);
|
||||
if (out) *out = ovrpBool_True; return ovrpSuccess; /* we have focus */
|
||||
if (out) *out = ovrpBool_True;
|
||||
return ovrpSuccess; /* we have focus */
|
||||
}
|
||||
OVRP_EXPORT ovrpResult ovrp_GetAppShouldQuit2(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetAppShouldQuit2, out);
|
||||
if (out) *out = ovrpBool_False; return ovrpSuccess;
|
||||
if (out) *out = ovrpBool_False;
|
||||
return ovrpSuccess;
|
||||
}
|
||||
OVRP_EXPORT ovrpResult ovrp_GetUserPresent2(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetUserPresent2, out);
|
||||
if (out) *out = ovrpBool_True; return ovrpSuccess; /* headset worn */
|
||||
if (out) *out = ovrpBool_True;
|
||||
return ovrpSuccess; /* headset worn */
|
||||
}
|
||||
OVRP_EXPORT ovrpResult ovrp_GetAppShouldRecenter2(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetAppShouldRecenter2, out);
|
||||
if (out) *out = ovrpBool_False; return ovrpSuccess;
|
||||
if (out) *out = ovrpBool_False;
|
||||
return ovrpSuccess;
|
||||
}
|
||||
OVRP_EXPORT ovrpResult ovrp_GetAppShouldRecreateDistortionWindow2(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetAppShouldRecreateDistortionWindow2, out);
|
||||
if (out) *out = ovrpBool_False; return ovrpSuccess;
|
||||
if (out) *out = ovrpBool_False;
|
||||
return ovrpSuccess;
|
||||
}
|
||||
OVRP_EXPORT ovrpResult ovrp_GetSystemMultiViewSupported2(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetSystemMultiViewSupported2, out);
|
||||
if (out) *out = ovrpBool_True; return ovrpSuccess; /* Quest supports multiview */
|
||||
if (out) *out = ovrpBool_True;
|
||||
return ovrpSuccess; /* Quest supports multiview */
|
||||
}
|
||||
OVRP_EXPORT ovrpResult ovrp_GetAppHasInputFocus(ovrpBool *out) {
|
||||
PT_FWD(ovrp_GetAppHasInputFocus, out);
|
||||
if (out) *out = ovrpBool_True; return ovrpSuccess;
|
||||
if (out) *out = ovrpBool_True;
|
||||
return ovrpSuccess;
|
||||
}
|
||||
/* the OpenXR session IS our display; nothing extra to set up */
|
||||
OVRP_EXPORT ovrpResult ovrp_SetupDistortionWindow3(unsigned int flags) {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* AUTO-GENERATED by gen_stubs.sh from analysis/shim_surface.txt. Do not edit by hand. */
|
||||
/* AUTO-GENERATED by gen_stubs.sh from analysis/all_exports.txt. Do not edit by hand. */
|
||||
#include "ovrplugin_shim.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
Reference in new issue
Block a user