Android: native_window validity is guaranteed between surfaceCreated and Destroyed
authorSylvain Becker <sylvain.becker@gmail.com>
Wed, 09 Jan 2019 22:41:52 +0100
changeset 12513efddb8c5e161
parent 12512 afc8e5d1d992
child 12514 8034efde00c5
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()
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
src/core/android/SDL_android.c
     1.1 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Wed Jan 09 15:18:41 2019 +0100
     1.2 +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Wed Jan 09 22:41:52 2019 +0100
     1.3 @@ -737,6 +737,7 @@
     1.4                                              float y, float p);
     1.5      public static native void onNativeAccel(float x, float y, float z);
     1.6      public static native void onNativeClipboardChanged();
     1.7 +    public static native void onNativeSurfaceCreated();
     1.8      public static native void onNativeSurfaceChanged();
     1.9      public static native void onNativeSurfaceDestroyed();
    1.10      public static native String nativeGetHint(String name);
    1.11 @@ -1574,6 +1575,7 @@
    1.12      @Override
    1.13      public void surfaceCreated(SurfaceHolder holder) {
    1.14          Log.v("SDL", "surfaceCreated()");
    1.15 +        SDLActivity.onNativeSurfaceCreated();
    1.16      }
    1.17  
    1.18      // Called when we lose the surface
     2.1 --- a/src/core/android/SDL_android.c	Wed Jan 09 15:18:41 2019 +0100
     2.2 +++ b/src/core/android/SDL_android.c	Wed Jan 09 22:41:52 2019 +0100
     2.3 @@ -83,6 +83,9 @@
     2.4          jint surfaceWidth, jint surfaceHeight,
     2.5          jint deviceWidth, jint deviceHeight, jint format, jfloat rate);
     2.6  
     2.7 +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceCreated)(
     2.8 +        JNIEnv *env, jclass jcls);
     2.9 +
    2.10  JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
    2.11          JNIEnv *env, jclass jcls);
    2.12  
    2.13 @@ -661,8 +664,25 @@
    2.14      return Android_RemoveHaptic(device_id);
    2.15  }
    2.16  
    2.17 -
    2.18 -/* Surface Created */
    2.19 +/* Called from surfaceCreated() */
    2.20 +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceCreated)(JNIEnv *env, jclass jcls)
    2.21 +{
    2.22 +    SDL_LockMutex(Android_ActivityMutex);
    2.23 +
    2.24 +    if (Android_Window && Android_Window->driverdata)
    2.25 +    {
    2.26 +        SDL_WindowData *data = (SDL_WindowData *) Android_Window->driverdata;
    2.27 +
    2.28 +        data->native_window = Android_JNI_GetNativeWindow();
    2.29 +        if (data->native_window == NULL) {
    2.30 +            SDL_SetError("Could not fetch native window from UI thread");
    2.31 +        }
    2.32 +    }
    2.33 +
    2.34 +    SDL_UnlockMutex(Android_ActivityMutex);
    2.35 +}
    2.36 +
    2.37 +/* Called from surfaceChanged() */
    2.38  JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, jclass jcls)
    2.39  {
    2.40      SDL_LockMutex(Android_ActivityMutex);
    2.41 @@ -674,10 +694,6 @@
    2.42  
    2.43          /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
    2.44          if (data->egl_surface == EGL_NO_SURFACE) {
    2.45 -            if (data->native_window) {
    2.46 -                ANativeWindow_release(data->native_window);
    2.47 -            }
    2.48 -            data->native_window = Android_JNI_GetNativeWindow();
    2.49              data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
    2.50          }
    2.51  
    2.52 @@ -687,7 +703,7 @@
    2.53      SDL_UnlockMutex(Android_ActivityMutex);
    2.54  }
    2.55  
    2.56 -/* Surface Destroyed */
    2.57 +/* Called from surfaceDestroyed() */
    2.58  JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env, jclass jcls)
    2.59  {
    2.60      SDL_LockMutex(Android_ActivityMutex);
    2.61 @@ -708,6 +724,11 @@
    2.62              data->egl_surface = EGL_NO_SURFACE;
    2.63          }
    2.64  
    2.65 +        if (data->native_window) {
    2.66 +            ANativeWindow_release(data->native_window);
    2.67 +        }
    2.68 +        data->native_window = NULL;
    2.69 +
    2.70          /* GL Context handling is done in the event loop because this function is run from the Java thread */
    2.71      }
    2.72