diff --git a/mpcore/src/main/cpp/emu/gles_shim.cpp b/mpcore/src/main/cpp/emu/gles_shim.cpp index 13de449..bc884cd 100644 --- a/mpcore/src/main/cpp/emu/gles_shim.cpp +++ b/mpcore/src/main/cpp/emu/gles_shim.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,10 @@ uint32_t GuestCallerLR(GuestEngine& eng) { // eglSwapBuffers - see Shim_glClear's own comment for why presenting a // back buffer that received none of them is what made the screen cycle // between stale, black and real frames. +// Task #52 probe switch - see Shim_glViewport. Opt-in per this +// project's standing rule that diagnostics default to off. +constexpr bool kLogViewportChanges = false; + std::atomic g_drawsSinceSwap{0}; // Shadowed GL state (2026-09-19). These exist so the per-draw code paths @@ -1722,7 +1727,36 @@ uint32_t Shim_glVertexAttribPointer(GuestEngine& eng, uint32_t r0, uint32_t r1, } uint32_t Shim_glViewport(GuestEngine& eng, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3, uint32_t sp) { - glViewport((GLint)eng.ReadIncomingArg(0, r0, r1, r2, r3, sp), (GLint)eng.ReadIncomingArg(1, r0, r1, r2, r3, sp), (GLsizei)eng.ReadIncomingArg(2, r0, r1, r2, r3, sp), (GLsizei)eng.ReadIncomingArg(3, r0, r1, r2, r3, sp)); + GLint vx = (GLint)eng.ReadIncomingArg(0, r0, r1, r2, r3, sp); + GLint vy = (GLint)eng.ReadIncomingArg(1, r0, r1, r2, r3, sp); + GLsizei vw = (GLsizei)eng.ReadIncomingArg(2, r0, r1, r2, r3, sp); + GLsizei vh = (GLsizei)eng.ReadIncomingArg(3, r0, r1, r2, r3, sp); + // Task #52 probe (2026-09-19, temporary). A Xiaomi 14 capture showed the + // game rendering into viewport=[0,0,2136,960] while the surface was + // 2670x1200 - i.e. a reduced internal resolution being upscaled. Whether + // that is the game's own choice or a wrong size we fed it is unknown, and + // the project already has form here: task #39 was exactly this shape (the + // UI projection used 2000x1000 instead of the real 2400x1080 because a + // JNI float argument was arriving as zero). Logging each DISTINCT + // viewport against the real EGL surface size, so the comparison is a fact + // rather than an inference. + if (kLogViewportChanges) { + static std::mutex mu; + static std::set> seen; + std::lock_guard lock(mu); + if (seen.insert({vx, vy, vw, vh}).second && seen.size() <= 24) { + EGLint sw = -1, sh = -1; + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLSurface surf = eglGetCurrentSurface(EGL_DRAW); + eglQuerySurface(dpy, surf, EGL_WIDTH, &sw); + eglQuerySurface(dpy, surf, EGL_HEIGHT, &sh); + GLint fb = g_shadowBoundFramebuffer.load(std::memory_order_relaxed); + Log("gles_shim: VIEWPORT [%d,%d %dx%d] fb=%d | EGL surface %dx%d%s", + vx, vy, vw, vh, fb, sw, sh, + (fb == 0 && (vw != sw || vh != sh)) ? " <<< SMALLER THAN THE SCREEN >>>" : ""); + } + } + glViewport(vx, vy, vw, vh); return 0; }