Files
DroidDeck/docs/quest-presentation-test.md
Jagger15andxXJsonDeruloXx a692436f67 fix(quest): correct desktop and Steam display corruption across sessions (#733)
fix(quest): stabilize desktop and Steam layer presentation

Keep Quest SDR scenes and the black backdrop off the Android Vulkan swapchain regardless of session order or HDR preferences. Only report the first frame after client content is submitted.

Add backdrop lifecycle and first-frame regression coverage. Record the user's successful Quest 3 Test 2 result.

Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
2026-10-15 09:51:02 -04:00

127 lines
7.1 KiB
Markdown

# Quest presentation candidate Test 2 — 2026-10-13
Base: `main` at `a394dfd31b2102e20dd99c6f51b4873bbdedab05`.
Reference APK: `DroidDeck-PR669-A6xx-Test2(1).apk`, SHA-256
`95ffb5ea6ae61d6a92c4ce9ad46f329d77a0f113ebbaabc6da30d6c8bd951154`.
Its embedded source revision is `d3f3439bbc45ca67de86d0093356a449c2c74600`.
## Evidence and scope
Reported symptoms: Desktop shows vertical corruption; Steam has green marks in
its black borders; starting Desktop first also corrupts subsequent Steam, and
closing Steam can expose corruption when returning to the menu. The supplied
modified PR669 APK reportedly avoids the transition problem.
Source inspection confirms that the compositor outlives sessions. The old
Quest workaround enables only `hdr.steam`, and the initial HDR-gated layer
selection happens only at compositor startup. Whole desktops and black borders
can still use the Android Vulkan swapchain even when a fullscreen game uses a
SurfaceControl layer. This is consistent with the reported symptoms, but is not
an on-device reproduction or proof of the exact driver defect.
The supplied APK has the same Steam-only preference initialization and the
same bundled Quest 3 Turnip binary as main (SHA-256
`af0d6bb38756eace17b43311c5c61a7ef3dc6e83d5cb8a63577d6a1d10c0aed0`).
It additionally supports a Quest 2 driver. Therefore the APK comparison does
not establish a new Quest 3 driver regression. Device, installed driver,
persistent preferences and session logs still matter.
## Test 1 startup regression and Test 2 correction
The Test 1 user confirmed a Quest 3 and a black window after runtime setup.
The supplied state report identifies `0.4.0-questdisplay-test1`, runtime `r9`
installed, an active guest, `installing=null`, no recorded failure, and saved
session artifacts. The session was suspended at capture. Suspension alone does
not establish the cause of the original black window. The retained main log
starts after the test window was closed, so the startup diagnostics are absent.
Source review found a Test 1 bug: `vkp_render` unconditionally signaled the first
frame after successfully showing the black backdrop, even with no client draws.
The Android listener then hid the loading UI and marked Steam's window as shown.
This also happened when the content-layer operation returned a successful no-op
(no visible geometry or no available pool slot). Consequently `firstFrame=true`
in Test 1 is not reliable evidence that Steam had displayed a frame.
Test 2 removes the backdrop notification. The existing content-layer presenter
owns the notification after submitting client content. A host regression test
compiles the production `vkp_render` entrypoint with controlled layer outcomes;
it failed on Test 1's empty scene and passes with this change. It also covers
successful no-ops, content presentation, errors and the existing non-Quest,
frame-generation and Cardboard routes. All seven focused host tests pass.
On 2026-10-13, the user tested Test 2 on Quest 3 and confirmed that it was
functioning as intended. This is a user-reported hardware result; a separate
pass/fail record for each checklist item below was not supplied. Broader headset,
game, colour and performance coverage remains outstanding. The user's separate
Quest 2 success report concerns the Adreno 6xx compatibility PR, not this build.
## Candidate change
- Recognize Quest 2/3/3S for presentation independently of HDR and session order.
This does not install an A6xx driver or expand main's Quest 2 driver support.
- Enable the layer protocol before the first client connects.
- Compose complete SDR scenes into the existing GPU-rendered gralloc layer,
including Desktop's multiple windows. Keep the existing path for a fullscreen
AHB that cannot be imported into the compositor.
- Present the black backdrop as an opaque SurfaceControl layer, initialized
once through a CPU-mapped 16-by-16 buffer. Game/desktop rendering stays on
the GPU. The backdrop does not use a Turnip Android swapchain.
- Use actual native-window dimensions for layer geometry without creating a
Vulkan swapchain solely for sizing.
- Retire the backdrop on detach/rebind and hide it before a real swapchain
frame. Reject a black buffer whose CPU lock/unlock failed.
Other devices retain their normal presentation paths. Frame generation and
Cardboard still use the original swapchain path and are outside this test's
coverage; leave them off for the first test. HDR negotiation itself is unchanged.
## Validation
The full ARM64 native compositor, including the existing frame-generation
engines, is compiled from this checkout with Android NDK r27d, API 26 and 16 KB
ELF alignment. Host tests exercise the actual backdrop implementation with
mock Android APIs: initialized pixels and padded rows, immutable reuse,
resize, hide/show, retirement/recreation, absent windows, allocation/lock/
unlock/transaction failure recovery, and the Quest device gate. These checks
cannot validate Horizon's compositor, colours, latency or graphics output.
Run the focused host tests (LeakSanitizer may need `ASAN_OPTIONS=detect_leaks=0`
when the test runner itself operates under ptrace):
```sh
python3 -m unittest tools.tests.test_quest_presentation tools.tests.test_quest_kgsl -v
```
The test APK uses the verified official CI APK for this exact base commit,
with only `lib/arm64-v8a/libdroiddeckwayland.so` rebuilt and replaced, an added
`assets/quest-presentation-test.json` provenance record, and a new APK signature.
DEX, other native libraries and runtime assets stay unchanged. The manifest is
repackaged with the repository's variant helper as `com.droiddeck.questdisplaytest`
so it can install beside the normal app and the supplied APK, whose signing key
is different. Provider authorities and the signature permission are renamed too.
It uses separate app data and needs its own initial setup. It is not a complete
Gradle rebuild. The displayed version is `0.4.0-questdisplay-test2`. It is signed
using the repository's public AOSP test key. The launcher label remains DroidDeck;
check the version in app info to distinguish the test installation.
Test 2 retains Test 1's package, version code and signing certificate. Install it
over Test 1 without uninstalling or clearing data; its installed runtime and
session logs are retained. The original main application remains separate.
## Headset test
Fully close DroidDeck before starting. Keep the same driver and resolution
settings that produced the problem; turn off frame generation and Cardboard.
1. Cold launch Desktop. Check the desktop, windows and black borders.
2. Switch Desktop to Steam without restarting the app.
3. Close Steam and return to the DroidDeck menu.
4. Fully close the app, then launch Steam first; inspect the top/bottom borders.
5. Switch to Desktop and repeat both transitions several times.
6. Resize the Quest panel and suspend/resume the app once.
Record the headset model and whether each step is fixed. If it fails, export
that session's logs, including `wayland.log` and device information. Look for
`Quest presentation: display layers for Steam and desktop` to confirm this
renderer was loaded. Test 2's reported Quest 3 result is recorded above.