From 22a2decf64e6a162e374aeb634fbcb21550c43a0 Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Fri, 28 Jun 2019 16:38:42 +0200 Subject: [PATCH] Android: concurrency issues, make sure Activity is in running State when calling functions like SDL_CreateWindow, SDL_CreateRenderer, Android_GLES_CreateContext Bugs 4694, 4681, 4142 --- src/core/android/SDL_android.c | 20 ++++++++++++++++++++ src/core/android/SDL_android.h | 1 + src/render/SDL_render.c | 14 ++++++++++++++ src/video/android/SDL_androidgl.c | 10 +++++++++- src/video/android/SDL_androidwindow.c | 2 +- 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index b0a2be397..918df7bcf 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -24,6 +24,7 @@ #include "SDL_hints.h" #include "SDL_log.h" #include "SDL_main.h" +#include "SDL_timer.h" #ifdef __ANDROID__ @@ -720,6 +721,25 @@ void Android_ActivityMutex_Unlock() { SDL_UnlockMutex(Android_ActivityMutex); } +/* Lock the Mutex when the Activity is in its 'Running' state */ +void Android_ActivityMutex_Lock_Running() { + int pauseSignaled = 0; + int resumeSignaled = 0; + +retry: + + SDL_LockMutex(Android_ActivityMutex); + + pauseSignaled = SDL_SemValue(Android_PauseSem); + resumeSignaled = SDL_SemValue(Android_ResumeSem); + + if (pauseSignaled > resumeSignaled) { + SDL_UnlockMutex(Android_ActivityMutex); + SDL_Delay(50); + goto retry; + } +} + /* Set screen resolution */ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetScreenResolution)( JNIEnv *env, jclass jcls, diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index b345b05ce..480d57ca0 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -133,6 +133,7 @@ SDL_bool SDL_IsDeXMode(void); void Android_ActivityMutex_Lock(void); void Android_ActivityMutex_Unlock(void); +void Android_ActivityMutex_Lock_Running(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index abdca68df..5b0c1bf30 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -29,6 +29,9 @@ #include "SDL_sysrender.h" #include "software/SDL_render_sw_c.h" +#if defined(__ANDROID__) +# include "../core/android/SDL_android.h" +#endif #define SDL_WINDOWRENDERDATA "_SDL_WindowRenderData" @@ -837,6 +840,10 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags) SDL_bool batching = SDL_TRUE; const char *hint; +#if defined(__ANDROID__) + Android_ActivityMutex_Lock_Running(); +#endif + if (!window) { SDL_SetError("Invalid window"); goto error; @@ -951,9 +958,16 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags) SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Created renderer: %s", renderer->info.name); +#if defined(__ANDROID__) + Android_ActivityMutex_Unlock(); +#endif return renderer; error: + +#if defined(__ANDROID__) + Android_ActivityMutex_Unlock(); +#endif return NULL; #else diff --git a/src/video/android/SDL_androidgl.c b/src/video/android/SDL_androidgl.c index d71cd9b33..4dd982b97 100644 --- a/src/video/android/SDL_androidgl.c +++ b/src/video/android/SDL_androidgl.c @@ -49,7 +49,15 @@ Android_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) SDL_GLContext Android_GLES_CreateContext(_THIS, SDL_Window * window) { - return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface); + SDL_GLContext ret; + + Android_ActivityMutex_Lock_Running(); + + ret = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface); + + SDL_UnlockMutex(Android_ActivityMutex); + + return ret; } int diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 96a94e178..64eff5203 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -42,7 +42,7 @@ Android_CreateWindow(_THIS, SDL_Window * window) SDL_WindowData *data; int retval = 0; - SDL_LockMutex(Android_ActivityMutex); + Android_ActivityMutex_Lock_Running(); if (Android_Window) { retval = SDL_SetError("Android only supports one window");