Android: prevents rare crashes when app goes to background or ends.
Make sure the thread is actually paused, and context backep-up, before SurfaceView is destroyed (eg surfaceDestroyed() actually returns). Add a timeout when surfaceDestroyed() is called, and check 'backup_done' variable. It prevents crashes like: #00 pc 000000000000c0d0 /system/lib64/libutils.so (android::RefBase::incStrong(void const*) const+8) #01 pc 000000000000c7f4 /vendor/lib64/egl/eglSubDriverAndroid.so (EglAndroidWindowSurface::UpdateBufferList(ANativeWindowBuffer*)+284) #02 pc 000000000000c390 /vendor/lib64/egl/eglSubDriverAndroid.so (EglAndroidWindowSurface::DequeueBuffer()+240) #03 pc 000000000000bb10 /vendor/lib64/egl/eglSubDriverAndroid.so (EglAndroidWindowSurface::GetBuffer(EglSubResource*, EglMemoryDesc*)+64) #04 pc 000000000032732c /vendor/lib64/egl/libGLESv2_adreno.so (EglWindowSurface::UpdateResource(EsxContext*)+116) #05 pc 0000000000326dd0 /vendor/lib64/egl/libGLESv2_adreno.so (EglWindowSurface::GetResource(EsxContext*, EsxResource**, EsxResource**, int)+56) #06 pc 00000000002ae484 /vendor/lib64/egl/libGLESv2_adreno.so (EsxContext::AcquireBackBuffer(int)+364) #07 pc 0000000000249680 /vendor/lib64/egl/libGLESv2_adreno.so (EsxContext::Clear(unsigned int, unsigned int, unsigned int, EsxClearValues*)+1800) #08 pc 00000000002cb52c /vendor/lib64/egl/libGLESv2_adreno.so (EsxGlApiParamValidate::GlClear(EsxDispatch*, unsigned int)+132)
parent
d52ba78b29
commit
005e2dff21
|
@ -472,7 +472,7 @@ Android_JNI_CreateKey_once(void)
|
|||
}
|
||||
|
||||
static void
|
||||
register_methods(JNIEnv *env, const char *classname, JNINativeMethod *methods, int nb)
|
||||
register_methods(JNIEnv *env, const char *classname, JNINativeMethod *methods, int nb)
|
||||
{
|
||||
jclass clazz = (*env)->FindClass(env, classname);
|
||||
if (clazz == NULL || (*env)->RegisterNatives(env, clazz, methods, nb) < 0) {
|
||||
|
@ -492,7 +492,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
|
|||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
register_methods(env, "org/libsdl/app/SDLActivity", SDLActivity_tab, SDL_arraysize(SDLActivity_tab));
|
||||
register_methods(env, "org/libsdl/app/SDLActivity", SDLActivity_tab, SDL_arraysize(SDLActivity_tab));
|
||||
register_methods(env, "org/libsdl/app/SDLInputConnection", SDLInputConnection_tab, SDL_arraysize(SDLInputConnection_tab));
|
||||
register_methods(env, "org/libsdl/app/SDLAudioManager", SDLAudioManager_tab, SDL_arraysize(SDLAudioManager_tab));
|
||||
register_methods(env, "org/libsdl/app/SDLControllerManager", SDLControllerManager_tab, SDL_arraysize(SDLControllerManager_tab));
|
||||
|
@ -994,6 +994,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, j
|
|||
/* Called from surfaceDestroyed() */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env, jclass jcls)
|
||||
{
|
||||
int nb_attempt = 50;
|
||||
|
||||
retry:
|
||||
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
if (Android_Window)
|
||||
|
@ -1001,21 +1005,27 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env,
|
|||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
SDL_WindowData *data = (SDL_WindowData *) Android_Window->driverdata;
|
||||
|
||||
/* We have to clear the current context and destroy the egl surface here
|
||||
* Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
|
||||
* Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
|
||||
*/
|
||||
/* Wait for Main thread being paused and context un-activated to release 'egl_surface' */
|
||||
if (! data->backup_done) {
|
||||
nb_attempt -= 1;
|
||||
if (nb_attempt == 0) {
|
||||
SDL_SetError("Try to release egl_surface with context probably still active");
|
||||
} else {
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
SDL_Delay(10);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->egl_surface != EGL_NO_SURFACE) {
|
||||
SDL_EGL_MakeCurrent(_this, NULL, NULL);
|
||||
SDL_EGL_DestroySurface(_this, data->egl_surface);
|
||||
data->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (data->native_window) {
|
||||
ANativeWindow_release(data->native_window);
|
||||
data->native_window = NULL;
|
||||
}
|
||||
data->native_window = NULL;
|
||||
|
||||
/* GL Context handling is done in the event loop because this function is run from the Java thread */
|
||||
}
|
||||
|
@ -1190,7 +1200,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeFocusChanged)(
|
|||
if (Android_Window) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeFocusChanged()");
|
||||
SDL_SendWindowEvent(Android_Window, (hasFocus ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ android_egl_context_restore(SDL_Window *window)
|
|||
event.type = SDL_RENDER_DEVICE_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
data->backup_done = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +81,7 @@ android_egl_context_backup(SDL_Window *window)
|
|||
data->egl_context = SDL_GL_GetCurrentContext();
|
||||
/* We need to do this so the EGLSurface can be freed */
|
||||
SDL_GL_MakeCurrent(window, NULL);
|
||||
data->backup_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef struct
|
|||
{
|
||||
EGLSurface egl_surface;
|
||||
EGLContext egl_context; /* We use this to preserve the context when losing focus */
|
||||
SDL_bool backup_done;
|
||||
ANativeWindow *native_window;
|
||||
|
||||
} SDL_WindowData;
|
||||
|
|
Loading…
Reference in New Issue