Split the menu quad back onto its own independent OpenXR swapchain
build / build (push) Successful in 1m43s
build / build (push) Successful in 1m43s
Replaces the single shared, side-by-side swapchain (game + menu content packed into one image, needing viewport/scissor juggling to keep the menu's own glClear from bleeding into the game's region) with two fully independent XrSwapchainState instances, each sized to exactly its own content and acquired/released on its own within the same xrBeginFrame/xrEndFrame pair - an ordinary multi-layer OpenXR setup. The shared-swapchain design was originally adopted to work around what looked like a Horizon OS compositor limitation with independent swapchains, but that was diagnosed before the real root cause of the "menu shows the game's content" bug was found (gl4es's fpe.c unconditionally substituting its own shader onto the menu's draw call - see README's Debugging notes). Since the actual fix routes the menu's blit through a real, non-gl4es glBlitFramebuffer() call - orthogonal to how many swapchains exist - splitting back onto two swapchains works fine and removes the GL_SCISSOR_TEST workaround and sub-rectangle offset math entirely. Confirmed on-device: both quads render correctly, hit-testing and 90 FPS unaffected. Also adds a visible cursor to the menu quad itself: xr_input.c now tracks whichever hand's aim ray hits the menu each frame and forwards it to a new MenuOverlay.nativeUpdateCursor(), which draws a small dot at that position (composited through the same Bitmap the menu's own content already goes through) - previously there was no visual feedback at all showing where you were pointing before pulling the trigger.
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
// Minimal OpenXR bring-up for questshock's immersive Quest build. Keeps the
|
||||
// game's own rendering untouched (see android/engine-patches/
|
||||
// 11-android-openxr-present.patch) - this module only owns the OpenXR
|
||||
// instance/session/swapchain and the final "submit a quad layer instead of
|
||||
// presenting to a window" step. No stereo rendering, no controller input
|
||||
// yet (see the plan's steps B/C/D for those) - the game composite is shown
|
||||
// as a single flat quad floating in front of the viewer.
|
||||
// instance/session/swapchains and the final "submit quad layers instead of
|
||||
// presenting to a window" step. No stereo rendering - the game composite is
|
||||
// shown as a single flat quad floating in front of the viewer.
|
||||
#ifndef QUESTSHOCK_XR_SESSION_H
|
||||
#define QUESTSHOCK_XR_SESSION_H
|
||||
|
||||
@@ -16,11 +15,13 @@ extern "C" {
|
||||
|
||||
// Call once, right after init_opengl() (OpenGL.cc) has created and made
|
||||
// current the GL context SDL/gl4es already use - creates the OpenXR
|
||||
// instance/session sharing that same EGL display/context, plus one
|
||||
// swapchain sized to the game's logical resolution (game_width/height, i.e.
|
||||
// grd_cap->w/h - see Shock.c's InitSDL()). Returns false if OpenXR bring-up
|
||||
// failed (e.g. no runtime installed) - callers should fall back to the
|
||||
// existing window-present path in that case.
|
||||
// instance/session sharing that same EGL display/context, plus the game
|
||||
// quad's own swapchain, sized to the game's logical resolution
|
||||
// (game_width/height, i.e. grd_cap->w/h - see Shock.c's InitSDL()). The
|
||||
// menu quad's own, independently-sized swapchain (see xr_menu.h) is created
|
||||
// alongside it. Returns false if OpenXR bring-up failed (e.g. no runtime
|
||||
// installed) - callers should fall back to the existing window-present path
|
||||
// in that case.
|
||||
bool xr_init(int game_width, int game_height);
|
||||
|
||||
// Pumps XR session-state events. Call once per frame, before
|
||||
@@ -34,17 +35,19 @@ void xr_poll_events(void);
|
||||
bool xr_is_session_running(void);
|
||||
|
||||
// Begins the XR frame (xrWaitFrame/xrBeginFrame) and, if the runtime wants
|
||||
// this frame rendered, acquires the next swapchain image and binds its
|
||||
// framebuffer as the current render target - ready for the caller to draw
|
||||
// into exactly as it would have drawn to the default framebuffer. Returns
|
||||
// true if the caller should draw this frame; xr_frame_end() must be called
|
||||
// unconditionally afterward either way (a begun XR frame must always be
|
||||
// ended, rendered or not).
|
||||
// this frame rendered, acquires the game quad's next swapchain image and
|
||||
// binds its framebuffer as the current render target - ready for the
|
||||
// caller to draw into exactly as it would have drawn to the default
|
||||
// framebuffer. Returns true if the caller should draw this frame;
|
||||
// xr_frame_end() must be called unconditionally afterward either way (a
|
||||
// begun XR frame must always be ended, rendered or not).
|
||||
bool xr_frame_begin(void);
|
||||
|
||||
// Releases the swapchain image (if one was acquired this frame) and
|
||||
// submits it as a single XrCompositionLayerQuad positioned in front of the
|
||||
// local reference space's origin, then ends the XR frame.
|
||||
// Releases the game quad's swapchain image (if one was acquired this
|
||||
// frame), acquires/renders/releases the menu quad's own swapchain image if
|
||||
// it's currently visible (see xr_menu.h), submits whichever of the two
|
||||
// quads actually rendered this frame as composition layers positioned in
|
||||
// front of the local reference space's origin, then ends the XR frame.
|
||||
void xr_frame_end(void);
|
||||
|
||||
void xr_shutdown(void);
|
||||
|
||||
Reference in New Issue
Block a user