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:
@@ -244,16 +244,23 @@ void xr_input_sync_and_draw(XrSpace baseSpace, XrTime time, bool draw) {
|
||||
{1.0f, 0.85f, 0.1f, 1.0f}, // right: amber
|
||||
};
|
||||
|
||||
// The reticle is drawn directly into whatever framebuffer is currently
|
||||
// bound - the game quad's swapchain image (see xr_frame_end(), which
|
||||
// calls this while that image is still bound). That only makes sense
|
||||
// while aiming at the game quad; the menu quad's content comes from
|
||||
// MenuOverlay's rendered Bitmap instead (xr_menu.c), uploaded on a
|
||||
// separate swapchain, so no reticle is drawn for it here.
|
||||
// The GL reticle is drawn directly into whatever framebuffer is
|
||||
// currently bound - the game quad's swapchain image (see xr_frame_end(),
|
||||
// which calls this while that image is still bound). That only makes
|
||||
// sense while aiming at the game quad; the menu quad's own cursor is
|
||||
// drawn by MenuOverlay itself instead (see xr_menu_update_cursor()
|
||||
// below), composited into its Bitmap the same way its other content is.
|
||||
bool drawReticle = draw && !menuVisible;
|
||||
if (drawReticle)
|
||||
glUseProgram(g_reticle_program);
|
||||
|
||||
// Fed to xr_menu_update_cursor() after the loop below - whichever hand's
|
||||
// ray hits the menu quad last wins if both do, good enough for a single
|
||||
// on-quad cursor (only ever updated when hit is true, so a later hand
|
||||
// that misses doesn't hide an earlier hand's hit).
|
||||
bool menuCursorHit = false;
|
||||
float menuCursorU = 0.0f, menuCursorV = 0.0f;
|
||||
|
||||
for (int hand = 0; hand < 2; hand++) {
|
||||
XrActionStateGetInfo selectInfo = {XR_TYPE_ACTION_STATE_GET_INFO};
|
||||
selectInfo.action = g_select_click_action;
|
||||
@@ -335,6 +342,11 @@ void xr_input_sync_and_draw(XrSpace baseSpace, XrTime time, bool draw) {
|
||||
hit ? "entered" : "left", u, v);
|
||||
g_prev_hit[hand] = hit;
|
||||
}
|
||||
if (hit) {
|
||||
menuCursorHit = true;
|
||||
menuCursorU = u;
|
||||
menuCursorV = v;
|
||||
}
|
||||
if (selectDownEdge && hit) {
|
||||
xr_menu_touch(u, v, true);
|
||||
g_menu_touch_active[hand] = true;
|
||||
@@ -364,6 +376,9 @@ void xr_input_sync_and_draw(XrSpace baseSpace, XrTime time, bool draw) {
|
||||
glDrawArrays(GL_LINES, 0, 4);
|
||||
glDisableVertexAttribArray(RETICLE_POSITION_LOC);
|
||||
}
|
||||
|
||||
if (menuVisible)
|
||||
xr_menu_update_cursor(menuCursorU, menuCursorV, menuCursorHit);
|
||||
}
|
||||
|
||||
void xr_input_shutdown(void) {
|
||||
|
||||
Reference in New Issue
Block a user