- AndroidManifest.xml: add android:screenOrientation="landscape" and a
build / build (push) Successful in 2m15s
build / build (push) Successful in 2m15s
<layout> defaultWidth/defaultHeight/minWidth/minHeight/gravity hint - Quest's Home shell otherwise defaults a freshly-launched 2D panel to a portrait shape, cropping the game's 4:3 640x480 content down to a sliver. - The actual root cause of the remaining crop (game rendering into one corner of an otherwise correctly-sized panel), found via on-device logcat and the new diagnostics below rather than guesswork: ChangeScreenSize() (engine/src/MacSrc/ShockBitmap.c) calls SDL_SetWindowSize() whenever the game sets its video mode. That's a desktop-only operation in effect - Android has no SetWindowSize driver hook, so SDL's generic layer instead overwrites its own cached window size to the game's internal resolution (640x480) and synthesizes a resize event from that, desyncing SDL's notion of the window size from the real, unchanged Android surface (e.g. 1600x1200). Both SDL's own renderer viewport and the engine's custom GL viewport then scale against that corrupted cached size. 10-android-no-window-resize.patch skips the desktop-only SDL_SetWindowFullscreen/SetWindowSize/ SetWindowPosition calls on Android, keeping the legitimate SDL_RenderSetLogicalSize/offscreen-bitmap setup. - 06-android-resize-event.patch: also react to SDL_WINDOWEVENT_RESIZED in the engine's event loop, not just SIZE_CHANGED - Android's SDL video backend never sends SIZE_CHANGED for surface-driven resizes, only RESIZED, an independent gap worth closing regardless of the bug above. - 08/09-android-logcat-*.patch: route the engine's existing log.c output (previously plain fprintf(stderr,...), never actually captured by logcat on this build) through __android_log_vprint instead, so every existing INFO/DEBUG/WARN/ERROR call site becomes visible for on-device debugging. This is what made the diagnostic below (and everything since) observable at all. - 07-android-size-diagnostics.patch: one-time startup log comparing SDL_GetWindowSize/SDL_GL_GetDrawableSize/SDL_GetRendererOutputSize - the evidence that actually pinned down the SDL_SetWindowSize bug above. - QuestShockActivity.java: add a diagnostic onSizeChanged() log on GameSurface, used to rule out a later Android-side panel relayout as the cause before finding the real one.
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
android:launchMode="singleInstance"
|
||||
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||
android:preferMinimalPostProcessing="true"
|
||||
android:screenOrientation="landscape"
|
||||
android:exported="true"
|
||||
>
|
||||
<intent-filter>
|
||||
@@ -43,6 +44,19 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
<!-- Without this, Quest's Home shell picks its own default 2D
|
||||
panel shape for this activity - a tall portrait rectangle,
|
||||
which crops a 4:3 landscape game like System Shock's classic
|
||||
640x480 down to a sliver. defaultWidth/defaultHeight (the
|
||||
standard Android multi-window sizing hint, which Quest's
|
||||
panel system honors for 2D apps) requests a properly
|
||||
landscape, 4:3-ish panel instead; minWidth/minHeight keep it
|
||||
from being resized below the game's native resolution. -->
|
||||
<layout android:defaultWidth="1280dp"
|
||||
android:defaultHeight="960dp"
|
||||
android:minWidth="640dp"
|
||||
android:minHeight="480dp"
|
||||
android:gravity="center" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ 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;
|
||||
@@ -89,6 +91,20 @@ public class QuestShockActivity extends SDLActivity {
|
||||
}
|
||||
super.surfaceChanged(holder, format, width, height);
|
||||
}
|
||||
|
||||
// Diagnostic only (see OpenGL.cc's matching log) - Android's real,
|
||||
// legitimate signal for "this View's laid-out size actually
|
||||
// changed" is onSizeChanged(), fired by the framework itself, not
|
||||
// something we have to poll or guess about. If Quest's Home shell
|
||||
// settles a freshly-launched panel into its final <layout> size via
|
||||
// a genuine later layout pass, this is where that would show up -
|
||||
// confirming whether a real event exists to hook, before writing
|
||||
// any fix around it.
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
Log.i(TAG, "GameSurface.onSizeChanged() " + oldw + "x" + oldh + " -> " + w + "x" + h);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
--- a/src/Libraries/INPUT/Source/sdl_events.c
|
||||
+++ b/src/Libraries/INPUT/Source/sdl_events.c
|
||||
@@ -737,7 +737,24 @@
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
+ break;
|
||||
+
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
+#ifdef __ANDROID__
|
||||
+ // Android's SDL video backend (Android_SendResize() in
|
||||
+ // src/video/android/SDL_androidvideo.c) only ever sends
|
||||
+ // RESIZED for surface-driven resizes - e.g. the Quest Home
|
||||
+ // shell settling the 2D panel into its requested <layout>
|
||||
+ // defaultWidth/defaultHeight after activity launch - never
|
||||
+ // SIZE_CHANGED (unlike desktop platforms, where an
|
||||
+ // app-driven SDL_SetWindowSize() triggers both, handled
|
||||
+ // above). Without this, opengl_resize() never re-runs after
|
||||
+ // that late resize, leaving the GL viewport stuck at
|
||||
+ // whatever (smaller) size the window first reported,
|
||||
+ // rendered into one corner of the now-larger surface.
|
||||
+ if (can_use_opengl())
|
||||
+ opengl_resize(ev.window.data1, ev.window.data2);
|
||||
+#endif
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
@@ -0,0 +1,24 @@
|
||||
--- a/src/MacSrc/OpenGL.cc
|
||||
+++ b/src/MacSrc/OpenGL.cc
|
||||
@@ -332,6 +332,21 @@
|
||||
|
||||
int width, height;
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
+#ifdef __ANDROID__
|
||||
+ // Temporary diagnostic: the reported panel/surface size is correct
|
||||
+ // (confirmed via SDLSurface's own "Window size" log and a Java-side
|
||||
+ // onSizeChanged() probe showing no later relayout), but the rendered
|
||||
+ // content still only fills a small corner of it. That means the
|
||||
+ // divergence is somewhere below the Java/Activity layer - between what
|
||||
+ // SDL_GetWindowSize() (the value used for opengl_resize() below) reports
|
||||
+ // and what SDL/EGL/gl4es actually believe the live drawable size is.
|
||||
+ // Compare all three directly instead of guessing further.
|
||||
+ int drawable_w, drawable_h, output_w, output_h;
|
||||
+ SDL_GL_GetDrawableSize(window, &drawable_w, &drawable_h);
|
||||
+ SDL_GetRendererOutputSize(renderer, &output_w, &output_h);
|
||||
+ INFO("Android size diag: SDL_GetWindowSize=%dx%d SDL_GL_GetDrawableSize=%dx%d SDL_GetRendererOutputSize=%dx%d",
|
||||
+ width, height, drawable_w, drawable_h, output_w, output_h);
|
||||
+#endif
|
||||
opengl_resize(width, height);
|
||||
|
||||
// Now make the palettes
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -440,6 +440,7 @@
|
||||
${FLUIDSYNTH_LIBRARIES}
|
||||
${OPENGL_LIBRARIES}
|
||||
${ALSA_LIBRARIES}
|
||||
+ $<$<BOOL:${ANDROID}>:log>
|
||||
)
|
||||
|
||||
# Turn on address sanitizing if wanted (desktop only - not meaningful for
|
||||
@@ -0,0 +1,45 @@
|
||||
--- a/src/Libraries/LG/Source/LOG/src/log.c
|
||||
+++ b/src/Libraries/LG/Source/LOG/src/log.c
|
||||
@@ -28,6 +28,10 @@
|
||||
|
||||
#include "log.h"
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+#include <android/log.h>
|
||||
+#endif
|
||||
+
|
||||
static struct {
|
||||
void *udata;
|
||||
log_LockFn lock;
|
||||
@@ -99,6 +103,23 @@
|
||||
time_t t = time(NULL);
|
||||
struct tm *lt = localtime(&t);
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ /* Plain stdout/stderr isn't captured by logcat on this platform (unlike
|
||||
+ e.g. gl4es's own "LIBGL"-tagged logging, which goes through this same
|
||||
+ API directly) - route there instead so every existing INFO/DEBUG/WARN/
|
||||
+ ERROR call site in the engine becomes visible for on-device debugging,
|
||||
+ with no changes needed at those call sites. */
|
||||
+ if (!L.quiet) {
|
||||
+ static const int android_priority[] = {
|
||||
+ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
|
||||
+ ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
|
||||
+ };
|
||||
+ va_list args;
|
||||
+ va_start(args, fmt);
|
||||
+ __android_log_vprint(android_priority[level], "QuestShock", fmt, args);
|
||||
+ va_end(args);
|
||||
+ }
|
||||
+#else
|
||||
/* Log to stderr */
|
||||
if (!L.quiet) {
|
||||
va_list args;
|
||||
@@ -116,6 +137,7 @@
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
+#endif
|
||||
|
||||
/* Log to file */
|
||||
if (L.fp) {
|
||||
@@ -0,0 +1,31 @@
|
||||
--- a/src/MacSrc/ShockBitmap.c
|
||||
+++ b/src/MacSrc/ShockBitmap.c
|
||||
@@ -42,11 +42,28 @@
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
+#ifndef __ANDROID__
|
||||
+ // On Android there's exactly one OS-controlled-size surface - no
|
||||
+ // desktop-style window to resize, move, or toggle fullscreen on.
|
||||
+ // SDL_SetWindowSize() still "succeeds" there (Android has no
|
||||
+ // SetWindowSize driver hook, so SDL's generic layer just overwrites its
|
||||
+ // own cached window->w/h to the requested game resolution, e.g.
|
||||
+ // 640x480, and synthesizes a resize event from that) - which desyncs
|
||||
+ // SDL's own notion of the window size from the real, unchanged Android
|
||||
+ // surface size (e.g. 1600x1200), and that desync is exactly what then
|
||||
+ // makes both SDL's internal renderer viewport and this engine's own
|
||||
+ // custom GL viewport (OpenGL.cc's opengl_resize(), driven by that same
|
||||
+ // now-wrong cached size) shrink to the game's resolution instead of
|
||||
+ // filling the real surface - confirmed on-device via added logcat
|
||||
+ // diagnostics (see android/engine-patches/07-09) showing the correct
|
||||
+ // 1600x1200 size at startup, then this exact call sequence collapsing
|
||||
+ // it to 640x480 the moment the splash screen sets its video mode.
|
||||
extern bool fullscreenActive;
|
||||
SDL_SetWindowFullscreen(window, fullscreenActive ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
|
||||
SDL_SetWindowSize(window, width, height);
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
+#endif
|
||||
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
|
||||
Reference in New Issue
Block a user