Fix persistent GL_INVALID_OPERATION spam and resolution-change bugs on Android
build / build (push) Successful in 2m44s

- opengl_end_frame() bound framebuffer 0 on Android, which has no valid
  target there (real presentation goes through the OpenXR swapchain's own
  FBOs) - gl4es reported this every frame. Skip it there.
- render_hack_cameras() re-entered opengl_start_frame()/opengl_end_frame()
  for camera-monitor renders that never touch the GL screen; excluded them
  to match use_opengl()'s existing behavior. Also drains a stray error left
  by xrPollEvent().
- ChangeScreenSize() never called opengl_resize() on Android, freezing the
  3D render target at launch size after an in-game resolution change; and
  xr_get_game_resolution() used the swapchain's fixed size instead of the
  current screen resolution, misplacing the laser-pointer cursor after such
  a change.
- Removes all temporary bisection diagnostics added while tracking down the
  GL_INVALID_OPERATION source.
This commit is contained in:
ml
2026-09-04 16:34:52 +02:00
parent 504ed3e1cb
commit e0a2e1f4bf
11 changed files with 835 additions and 10 deletions
+26 -2
View File
@@ -319,6 +319,14 @@ void xr_poll_events(void) {
}
}
}
// xrPollEvent() leaves gl4es reporting a stray GL_INVALID_OPERATION on
// every call while the session is running - drain it (looped, since
// more than one can accumulate across xrPollEvent()'s possibly-multiple
// iterations above) so it doesn't surface as a false positive at the
// next unrelated glGetError() check in this app's own rendering code.
while (glGetError() != GL_NO_ERROR) {
}
}
bool xr_is_session_running(void) { return g_session_running; }
@@ -434,6 +442,7 @@ void xr_frame_end(void) {
endInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
endInfo.layerCount = layerCount;
endInfo.layers = layerCount > 0 ? layers : NULL;
xr_check(xrEndFrame(g_session, &endInfo), "xrEndFrame");
}
@@ -471,6 +480,21 @@ void xr_get_game_quad_extent(float *distance_m, float *half_width_m, float *half
}
void xr_get_game_resolution(int *width, int *height) {
*width = g_game_swapchain.width;
*height = g_game_swapchain.height;
// Not g_game_swapchain.width/height: that's the fixed physical size of
// the swapchain image the game is composited into (see xr_init()) -
// android_draw_surface_as_quad() (OpenGL.cc, engine-patches/11) always
// stretch-blits drawSurface to fill that image regardless of
// drawSurface's own pixel size, so the swapchain's size has no relation
// to the coordinate space MouseX/MouseY actually live in. gScreenWide/
// gScreenHigh (InitMac.h) is drawSurface's current size - the
// resolution the in-game options menu can change at runtime
// (ShockBitmap.c's ChangeScreenSize()) independently of the swapchain,
// which is created once at launch and never resized. Using the fixed
// swapchain size here after such a change mapped the laser pointer's
// quad-space hit into the wrong coordinate space entirely, moving
// MouseX/MouseY out of the engine's actual screen bounds - which is
// what made the cursor disappear and become unclickable.
extern int32_t gScreenWide, gScreenHigh;
*width = gScreenWide;
*height = gScreenHigh;
}
+7 -5
View File
@@ -74,11 +74,13 @@ void xr_shutdown(void);
// laser pointer always matches whatever's actually visible.
void xr_get_game_quad_extent(float *distance_m, float *half_width_m, float *half_height_m);
// Pixel resolution of the game quad's own swapchain - i.e. game_width/
// game_height as passed to xr_init() (grd_cap->w/h, see Shock.c's
// InitSDL()) - the logical coordinate space xr_input.c needs to convert a
// game-quad ray hit's normalized u,v into engine mouse coordinates (see
// xr_mouse.h).
// The engine's current screen resolution (gScreenWide/gScreenHigh,
// InitMac.h) - not the game quad's own swapchain size, which is fixed at
// launch and never changes - the logical coordinate space xr_input.c needs
// to convert a game-quad ray hit's normalized u,v into engine mouse
// coordinates (see xr_mouse.h). Can change at runtime via the in-game
// options menu (ShockBitmap.c's ChangeScreenSize()), independently of the
// swapchain.
void xr_get_game_resolution(int *width, int *height);
#ifdef __cplusplus
+1
View File
@@ -149,6 +149,7 @@ bool xr_swapchain_acquire(XrInstance instance, XrSwapchainState *state) {
// (android_draw_surface_as_quad()) land in the right place.
glBindFramebuffer(GL_FRAMEBUFFER, state->fbos[imageIndex]);
glViewport(0, 0, state->width, state->height);
return true;
}
@@ -6,8 +6,6 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
import androidx.core.app.ActivityCompat;