Android: native_window validity is guaranteed between surfaceCreated and Destroyed It's currently still available after surfaceDestroyed(). And available (but invalid) between surfaceCreated() and surfaceChanged(). Which means ANativewindow_getWidth/Height/Format() fail in those cases. https://developer.android.com/reference/android/view/SurfaceHolder.html#getSurface()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
index ac8515d..09cafc5 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
@@ -737,6 +737,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
float y, float p);
public static native void onNativeAccel(float x, float y, float z);
public static native void onNativeClipboardChanged();
+ public static native void onNativeSurfaceCreated();
public static native void onNativeSurfaceChanged();
public static native void onNativeSurfaceDestroyed();
public static native String nativeGetHint(String name);
@@ -1574,6 +1575,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
+ SDLActivity.onNativeSurfaceCreated();
}
// Called when we lose the surface
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 7de6b4b..8613d45 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -83,6 +83,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
jint surfaceWidth, jint surfaceHeight,
jint deviceWidth, jint deviceHeight, jint format, jfloat rate);
+JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceCreated)(
+ JNIEnv *env, jclass jcls);
+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
JNIEnv *env, jclass jcls);
@@ -661,8 +664,25 @@ JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
return Android_RemoveHaptic(device_id);
}
+/* Called from surfaceCreated() */
+JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceCreated)(JNIEnv *env, jclass jcls)
+{
+ SDL_LockMutex(Android_ActivityMutex);
+
+ if (Android_Window && Android_Window->driverdata)
+ {
+ SDL_WindowData *data = (SDL_WindowData *) Android_Window->driverdata;
+
+ data->native_window = Android_JNI_GetNativeWindow();
+ if (data->native_window == NULL) {
+ SDL_SetError("Could not fetch native window from UI thread");
+ }
+ }
+
+ SDL_UnlockMutex(Android_ActivityMutex);
+}
-/* Surface Created */
+/* Called from surfaceChanged() */
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, jclass jcls)
{
SDL_LockMutex(Android_ActivityMutex);
@@ -674,10 +694,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, j
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
if (data->egl_surface == EGL_NO_SURFACE) {
- if (data->native_window) {
- ANativeWindow_release(data->native_window);
- }
- data->native_window = Android_JNI_GetNativeWindow();
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
}
@@ -687,7 +703,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, j
SDL_UnlockMutex(Android_ActivityMutex);
}
-/* Surface Destroyed */
+/* Called from surfaceDestroyed() */
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env, jclass jcls)
{
SDL_LockMutex(Android_ActivityMutex);
@@ -708,6 +724,11 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env,
data->egl_surface = EGL_NO_SURFACE;
}
+ if (data->native_window) {
+ ANativeWindow_release(data->native_window);
+ }
+ data->native_window = NULL;
+
/* GL Context handling is done in the event loop because this function is run from the Java thread */
}