2300d081c3
build / build (push) Successful in 2m12s
- New android/app/src/main/cpp/xr_session.c (+.h): owns the OpenXR
instance/session/local-space/swapchain and the per-frame
xrWaitFrame/xrBeginFrame/xrEndFrame loop, submitting the game's
existing flat render as a single head-tracked XrCompositionLayerQuad.
No stereo rendering or controller input yet - that's steps B/C/D of
the plan.
- 11-android-openxr-cmake.patch: links the OpenXR loader as a build
dependency, staged into jniLibs the same way as gl4es/SDL2.
build-image/Dockerfile and prepare-android-project.sh build and stage
it.
- 12-android-openxr-present.patch: redirects OpenGL.cc's final present
step (opengl_swap_and_restore / SDLDraw's software path) into the XR
swapchain FBO instead of the window, on Android only. Two real gl4es
bugs had to be worked around to get pixels on screen at all:
- gl4es's own glBindFramebuffer errors on an FBO id it didn't create
itself, even though the real driver-level bind succeeds - fixed by
creating the swapchain FBO container via gl4es's own
glGenFramebuffers/glBindFramebuffer, and only using the real
(dlsym'd) driver call for attaching OpenXR's foreign swapchain
texture, which gl4es's own attach can't handle.
- gl4es's glBegin/glVertexAttrib/glVertex3f immediate-mode emulation
only captures a fresh per-vertex value for attribute 0 (position,
driven directly by glVertex3f) - custom attributes like this
shader's texcoords/light are GLES2's *constant*-attribute API and
applied once for the whole draw, not per vertex, silently
collapsing the UI-overlay quad to a single sampled texel. Fixed by
switching that one draw call to real vertex arrays
(glVertexAttribPointer/glDrawArrays).
Also flips the V texcoord to match SDL's top-down row order against
GL's texture convention, and reuses a persistent texture object
instead of a fresh gen/upload/delete every frame.
- AndroidManifest.xml: declares the immersive-HMD intent category and
focus-aware metadata, drops the 2D-panel layout hint.
- README: documents the new OpenXR immersive mode.
70 lines
3.7 KiB
XML
70 lines
3.7 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
android:installLocation="auto">
|
|
|
|
<!-- OpenGL ES 2.0 -->
|
|
<uses-feature android:glEsVersion="0x00020000" />
|
|
|
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
|
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
|
|
<uses-feature android:name="android.hardware.gamepad" android:required="false" />
|
|
<uses-feature android:name="android.hardware.usb.host" android:required="false" />
|
|
<!-- External mouse input events -->
|
|
<uses-feature android:name="android.hardware.type.pc" android:required="false" />
|
|
|
|
<!-- Immersive OpenXR app now (see android/app/src/main/cpp/xr_session.c),
|
|
not a 2D Home panel - vr.headtracking is what actually declares that
|
|
to Horizon OS. -->
|
|
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
|
|
|
|
<!-- Plain, unrestricted /sdcard access for the res/data,res/sound the
|
|
user drops in and the shaders/soundfont this app extracts there on
|
|
first run - see res/GET_ASSETS_QUEST.txt and QuestShockActivity.
|
|
requestLegacyExternalStorage below (paired with targetSdkVersion 29
|
|
in build.gradle) is what keeps this working instead of Android 11+
|
|
scoped storage. -->
|
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
|
|
<application android:label="@string/app_name"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:allowBackup="true"
|
|
android:requestLegacyExternalStorage="true"
|
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
|
android:hardwareAccelerated="true" >
|
|
|
|
<!-- Tells Horizon OS this activity wants the compositor for itself
|
|
(immersive VR), not the Home 2D-panel path - required for an
|
|
OpenXR session to actually start. -->
|
|
<meta-data android:name="com.oculus.vr.focusaware" android:value="true" />
|
|
|
|
<activity android:name="de.ladkau.questshock.QuestShockActivity"
|
|
android:label="@string/app_name"
|
|
android:alwaysRetainTaskState="true"
|
|
android:launchMode="singleInstance"
|
|
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
|
android:preferMinimalPostProcessing="true"
|
|
android:screenOrientation="landscape"
|
|
android:exported="true"
|
|
>
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
<!-- The vendor-neutral, Khronos-defined way to declare an
|
|
immersive OpenXR entry point (vs. e.g. Meta's own
|
|
com.oculus.intent.category.VR) - see this project's
|
|
"favor OpenXR" rule in the README. If Horizon OS still
|
|
launches this as a flat panel on-device, the next thing
|
|
to try is adding a com.oculus.supportedDevices meta-data
|
|
listing the target Quest models - not confirmed
|
|
necessary from static analysis alone. -->
|
|
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
|
|
</intent-filter>
|
|
<intent-filter>
|
|
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
|
</intent-filter>
|
|
</activity>
|
|
</application>
|
|
|
|
</manifest>
|