diff --git a/include/SDL_hints.h b/include/SDL_hints.h index b8da07732..b90c9dce6 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -164,6 +164,21 @@ extern "C" { */ #define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" +/** + * \brief A variable controlling whether the graphics context is externally managed. + * + * This variable can be set to the following values: + * "0" - SDL will manage graphics contexts that are attached to windows. + * "1" - Disable graphics context management on windows. + * + * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the + * context will be automatically saved and restored when pausing the application. Additionally, some + * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this + * behavior, which is desireable when the application manages the graphics context, such as + * an externally managed OpenGL context or attaching a Vulkan surface to the window. + */ +#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT" + /** * \brief A variable controlling whether the X11 VidMode extension should be used. * diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 372cb6c07..07bbc3f36 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -439,6 +439,7 @@ extern int SDL_GetIndexOfDisplay(SDL_VideoDisplay *display); extern SDL_VideoDisplay *SDL_GetDisplay(int displayIndex); extern SDL_VideoDisplay *SDL_GetDisplayForWindow(SDL_Window *window); extern void *SDL_GetDisplayDriverData( int displayIndex ); +extern SDL_bool SDL_IsVideoContextExternal(void); extern void SDL_GL_DeduceMaxSupportedESProfile(int* major, int* minor); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 7cabee30a..f675e28fd 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -664,6 +664,12 @@ SDL_GetDisplayDriverData(int displayIndex) return _this->displays[displayIndex].driverdata; } +SDL_bool +SDL_IsVideoContextExternal(void) +{ + return SDL_GetHintBoolean(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, SDL_FALSE); +} + const char * SDL_GetDisplayName(int displayIndex) { @@ -1437,7 +1443,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) /* Some platforms have OpenGL enabled by default */ #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__ - if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN)) { + if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !SDL_IsVideoContextExternal()) { flags |= SDL_WINDOW_OPENGL; } #endif diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index de560c96a..87ad12fef 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -26,6 +26,7 @@ #include "SDL_events.h" #include "SDL_androidkeyboard.h" #include "SDL_androidwindow.h" +#include "../SDL_sysvideo.h" /* Can't include sysaudio "../../audio/android/SDL_androidaudio.h" * because of THIS redefinition */ @@ -95,11 +96,14 @@ Android_PumpEvents_Blocking(_THIS) SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; if (videodata->isPaused) { + SDL_bool isContextExternal = SDL_IsVideoContextExternal(); /* Make sure this is the last thing we do before pausing */ - SDL_LockMutex(Android_ActivityMutex); - android_egl_context_backup(Android_Window); - SDL_UnlockMutex(Android_ActivityMutex); + if (!isContextExternal) { + SDL_LockMutex(Android_ActivityMutex); + android_egl_context_backup(Android_Window); + SDL_UnlockMutex(Android_ActivityMutex); + } ANDROIDAUDIO_PauseDevices(); openslES_PauseDevices(); @@ -112,7 +116,7 @@ Android_PumpEvents_Blocking(_THIS) openslES_ResumeDevices(); /* Restore the GL Context from here, as this operation is thread dependent */ - if (!SDL_HasEvent(SDL_QUIT)) { + if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) { SDL_LockMutex(Android_ActivityMutex); android_egl_context_restore(Android_Window); SDL_UnlockMutex(Android_ActivityMutex); @@ -146,11 +150,14 @@ Android_PumpEvents_NonBlocking(_THIS) if (videodata->isPaused) { + SDL_bool isContextExternal = SDL_IsVideoContextExternal(); if (backup_context) { - SDL_LockMutex(Android_ActivityMutex); - android_egl_context_backup(Android_Window); - SDL_UnlockMutex(Android_ActivityMutex); + if (!isContextExternal) { + SDL_LockMutex(Android_ActivityMutex); + android_egl_context_backup(Android_Window); + SDL_UnlockMutex(Android_ActivityMutex); + } ANDROIDAUDIO_PauseDevices(); openslES_PauseDevices(); @@ -167,7 +174,7 @@ Android_PumpEvents_NonBlocking(_THIS) openslES_ResumeDevices(); /* Restore the GL Context from here, as this operation is thread dependent */ - if (!SDL_HasEvent(SDL_QUIT)) { + if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) { SDL_LockMutex(Android_ActivityMutex); android_egl_context_restore(Android_Window); SDL_UnlockMutex(Android_ActivityMutex); diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 64eff5203..53cb6b939 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -82,7 +82,7 @@ Android_CreateWindow(_THIS, SDL_Window * window) /* Do not create EGLSurface for Vulkan window since it will then make the window incompatible with vkCreateAndroidSurfaceKHR */ - if ((window->flags & SDL_WINDOW_VULKAN) == 0) { + if ((window->flags & SDL_WINDOW_OPENGL) != 0) { data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window); if (data->egl_surface == EGL_NO_SURFACE) {