Fixed bug 4890 - Add hint for SDL that the graphics context is externally managed
authorSam Lantinga <slouken@libsdl.org>
Sun, 08 Dec 2019 11:33:06 -0800
changeset 13320881796f84081
parent 13319 580cc3860ac3
child 13321 37350f1e7902
Fixed bug 4890 - Add hint for SDL that the graphics context is externally managed

Aaron Barany

Add SDL_HINT_VIDEO_EXTERNAL_CONTEXT hint to notify SDL that the graphics context is external. This disables the automatic context save/restore behavior on Android and avoids using OpenGL by default when SDL_WINDOW_VUKLAN isn't set.

When the application wishes to manage the OpenGL contexts on Android, this avoids cases where SDL unbinds the context and creates new contexts, which can interfere with the application's operation.

When using Vulkan and Metal renderer implementations, this avoids SDL forcing OpenGL to be enabled on certain platforms. While using the SDL_WINDOW_VULKAN flag can be used to achieve the same thing, it also causes Vulkan to be loaded. If the application uses Vulkan directly, this is not necessary, and fails window creation when using Metal due to Vulkan not being present. (assuming MoltenVK isn't installed)
include/SDL_hints.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/android/SDL_androidevents.c
src/video/android/SDL_androidwindow.c
     1.1 --- a/include/SDL_hints.h	Fri Dec 06 13:48:13 2019 -0800
     1.2 +++ b/include/SDL_hints.h	Sun Dec 08 11:33:06 2019 -0800
     1.3 @@ -165,6 +165,21 @@
     1.4  #define SDL_HINT_VIDEO_ALLOW_SCREENSAVER    "SDL_VIDEO_ALLOW_SCREENSAVER"
     1.5  
     1.6  /**
     1.7 + * \brief A variable controlling whether the graphics context is externally managed.
     1.8 + *
     1.9 + * This variable can be set to the following values:
    1.10 + *  "0"         - SDL will manage graphics contexts that are attached to windows.
    1.11 + *  "1"         - Disable graphics context management on windows.
    1.12 + *
    1.13 + * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the
    1.14 + * context will be automatically saved and restored when pausing the application. Additionally, some
    1.15 + * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this
    1.16 + * behavior, which is desireable when the application manages the graphics context, such as
    1.17 + * an externally managed OpenGL context or attaching a Vulkan surface to the window.
    1.18 + */
    1.19 +#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT    "SDL_VIDEO_EXTERNAL_CONTEXT"
    1.20 +
    1.21 +/**
    1.22   *  \brief  A variable controlling whether the X11 VidMode extension should be used.
    1.23   *
    1.24   *  This variable can be set to the following values:
     2.1 --- a/src/video/SDL_sysvideo.h	Fri Dec 06 13:48:13 2019 -0800
     2.2 +++ b/src/video/SDL_sysvideo.h	Sun Dec 08 11:33:06 2019 -0800
     2.3 @@ -439,6 +439,7 @@
     2.4  extern SDL_VideoDisplay *SDL_GetDisplay(int displayIndex);
     2.5  extern SDL_VideoDisplay *SDL_GetDisplayForWindow(SDL_Window *window);
     2.6  extern void *SDL_GetDisplayDriverData( int displayIndex );
     2.7 +extern SDL_bool SDL_IsVideoContextExternal(void);
     2.8  
     2.9  extern void SDL_GL_DeduceMaxSupportedESProfile(int* major, int* minor);
    2.10  
     3.1 --- a/src/video/SDL_video.c	Fri Dec 06 13:48:13 2019 -0800
     3.2 +++ b/src/video/SDL_video.c	Sun Dec 08 11:33:06 2019 -0800
     3.3 @@ -664,6 +664,12 @@
     3.4      return _this->displays[displayIndex].driverdata;
     3.5  }
     3.6  
     3.7 +SDL_bool
     3.8 +SDL_IsVideoContextExternal(void)
     3.9 +{
    3.10 +    return SDL_GetHintBoolean(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, SDL_FALSE);
    3.11 +}
    3.12 +
    3.13  const char *
    3.14  SDL_GetDisplayName(int displayIndex)
    3.15  {
    3.16 @@ -1437,7 +1443,7 @@
    3.17  
    3.18      /* Some platforms have OpenGL enabled by default */
    3.19  #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
    3.20 -    if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN)) {
    3.21 +    if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !SDL_IsVideoContextExternal()) {
    3.22          flags |= SDL_WINDOW_OPENGL;
    3.23      }
    3.24  #endif
     4.1 --- a/src/video/android/SDL_androidevents.c	Fri Dec 06 13:48:13 2019 -0800
     4.2 +++ b/src/video/android/SDL_androidevents.c	Sun Dec 08 11:33:06 2019 -0800
     4.3 @@ -26,6 +26,7 @@
     4.4  #include "SDL_events.h"
     4.5  #include "SDL_androidkeyboard.h"
     4.6  #include "SDL_androidwindow.h"
     4.7 +#include "../SDL_sysvideo.h"
     4.8  
     4.9  /* Can't include sysaudio "../../audio/android/SDL_androidaudio.h"
    4.10   * because of THIS redefinition */
    4.11 @@ -95,11 +96,14 @@
    4.12      SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
    4.13  
    4.14      if (videodata->isPaused) {
    4.15 +        SDL_bool isContextExternal = SDL_IsVideoContextExternal();
    4.16  
    4.17          /* Make sure this is the last thing we do before pausing */
    4.18 -        SDL_LockMutex(Android_ActivityMutex);
    4.19 -        android_egl_context_backup(Android_Window);
    4.20 -        SDL_UnlockMutex(Android_ActivityMutex);
    4.21 +        if (!isContextExternal) {
    4.22 +            SDL_LockMutex(Android_ActivityMutex);
    4.23 +            android_egl_context_backup(Android_Window);
    4.24 +            SDL_UnlockMutex(Android_ActivityMutex);
    4.25 +        }
    4.26  
    4.27          ANDROIDAUDIO_PauseDevices();
    4.28          openslES_PauseDevices();
    4.29 @@ -112,7 +116,7 @@
    4.30              openslES_ResumeDevices();
    4.31  
    4.32              /* Restore the GL Context from here, as this operation is thread dependent */
    4.33 -            if (!SDL_HasEvent(SDL_QUIT)) {
    4.34 +            if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
    4.35                  SDL_LockMutex(Android_ActivityMutex);
    4.36                  android_egl_context_restore(Android_Window);
    4.37                  SDL_UnlockMutex(Android_ActivityMutex);
    4.38 @@ -146,11 +150,14 @@
    4.39  
    4.40      if (videodata->isPaused) {
    4.41  
    4.42 +        SDL_bool isContextExternal = SDL_IsVideoContextExternal();
    4.43          if (backup_context) {
    4.44  
    4.45 -            SDL_LockMutex(Android_ActivityMutex);
    4.46 -            android_egl_context_backup(Android_Window);
    4.47 -            SDL_UnlockMutex(Android_ActivityMutex);
    4.48 +            if (!isContextExternal) {
    4.49 +                SDL_LockMutex(Android_ActivityMutex);
    4.50 +                android_egl_context_backup(Android_Window);
    4.51 +                SDL_UnlockMutex(Android_ActivityMutex);
    4.52 +            }
    4.53  
    4.54              ANDROIDAUDIO_PauseDevices();
    4.55              openslES_PauseDevices();
    4.56 @@ -167,7 +174,7 @@
    4.57              openslES_ResumeDevices();
    4.58  
    4.59              /* Restore the GL Context from here, as this operation is thread dependent */
    4.60 -            if (!SDL_HasEvent(SDL_QUIT)) {
    4.61 +            if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
    4.62                  SDL_LockMutex(Android_ActivityMutex);
    4.63                  android_egl_context_restore(Android_Window);
    4.64                  SDL_UnlockMutex(Android_ActivityMutex);
     5.1 --- a/src/video/android/SDL_androidwindow.c	Fri Dec 06 13:48:13 2019 -0800
     5.2 +++ b/src/video/android/SDL_androidwindow.c	Sun Dec 08 11:33:06 2019 -0800
     5.3 @@ -82,7 +82,7 @@
     5.4  
     5.5      /* Do not create EGLSurface for Vulkan window since it will then make the window
     5.6         incompatible with vkCreateAndroidSurfaceKHR */
     5.7 -    if ((window->flags & SDL_WINDOW_VULKAN) == 0) {
     5.8 +    if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
     5.9          data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
    5.10  
    5.11          if (data->egl_surface == EGL_NO_SURFACE) {