Commit 01e0d8fc855dd2c0e412c55633aacf5cf72e593a

Ryan C. Gordon 2017-08-19T15:02:03

opengl: Add support for [GLX|WGL]_ARB_create_context_robustness. This patch was originally written by Marc Di Luzio for glX and enhanced by Maximilian Malek for WGL, etc. Thanks to both of you! Fixes Bugzilla #3643. Fixes Bugzilla #3735.

diff --git a/include/SDL_video.h b/include/SDL_video.h
index 21a1424..0700023 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -201,7 +201,8 @@ typedef enum
     SDL_GL_CONTEXT_PROFILE_MASK,
     SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
     SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
-    SDL_GL_CONTEXT_RELEASE_BEHAVIOR
+    SDL_GL_CONTEXT_RELEASE_BEHAVIOR,
+    SDL_GL_CONTEXT_RESET_NOTIFICATION
 } SDL_GLattr;
 
 typedef enum
@@ -225,6 +226,12 @@ typedef enum
     SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH  = 0x0001
 } SDL_GLcontextReleaseFlag;
 
+typedef enum
+{
+    SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000,
+    SDL_GL_CONTEXT_RESET_LOSE_CONTEXT    = 0x0001
+} SDL_GLContextResetNotification;
+
 
 /* Function prototypes */
 
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 8aaf9d2..ff0d222 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -329,6 +329,7 @@ struct SDL_VideoDevice
         int profile_mask;
         int share_with_current_context;
         int release_behavior;
+        int reset_notification;
         int framebuffer_srgb_capable;
         int retained_backing;
         int driver_loaded;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 8253558..7debc48 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -2990,6 +2990,7 @@ SDL_GL_ResetAttributes()
     _this->gl_config.flags = 0;
     _this->gl_config.framebuffer_srgb_capable = 0;
     _this->gl_config.release_behavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH;
+    _this->gl_config.reset_notification = SDL_GL_CONTEXT_RESET_NO_NOTIFICATION;
 
     _this->gl_config.share_with_current_context = 0;
 }
@@ -3099,6 +3100,9 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value)
     case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
         _this->gl_config.release_behavior = value;
         break;
+    case SDL_GL_CONTEXT_RESET_NOTIFICATION:
+        _this->gl_config.reset_notification = value;
+        break;
     default:
         retval = SDL_SetError("Unknown OpenGL attribute");
         break;
diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c
index ffa6c2b..d91ca5b 100644
--- a/src/video/windows/SDL_windowsopengl.c
+++ b/src/video/windows/SDL_windowsopengl.c
@@ -453,11 +453,16 @@ WIN_GL_InitExtensions(_THIS)
         );
     }
 
-    /* Check for GLX_ARB_context_flush_control */
+    /* Check for WGL_ARB_context_flush_control */
     if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
         _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
     }
 
+    /* Check for WGL_ARB_create_context_robustness */
+    if (HasExtension("WGL_ARB_create_context_robustness", extensions)) {
+        _this->gl_data->HAS_WGL_ARB_create_context_robustness = SDL_TRUE;
+    }
+
     _this->gl_data->wglMakeCurrent(hdc, NULL);
     _this->gl_data->wglDeleteContext(hglrc);
     ReleaseDC(hwnd, hdc);
@@ -713,8 +718,8 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window)
             SDL_SetError("GL 3.x is not supported");
             context = temp_context;
         } else {
-        /* max 10 attributes plus terminator */
-            int attribs[11] = {
+        /* max 12 attributes plus terminator */
+            int attribs[13] = {
                 WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
                 WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
                 0
@@ -741,6 +746,14 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window)
                                     WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
             }
 
+            /* only set if wgl extension is available */
+            if (_this->gl_data->HAS_WGL_ARB_create_context_robustness) {
+                attribs[iattr++] = WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
+                attribs[iattr++] = _this->gl_config.reset_notification ?
+                                    WGL_LOSE_CONTEXT_ON_RESET_ARB :
+                                    WGL_NO_RESET_NOTIFICATION_ARB;
+            }
+
             attribs[iattr++] = 0;
 
             /* Create the GL 3.x context */
diff --git a/src/video/windows/SDL_windowsopengl.h b/src/video/windows/SDL_windowsopengl.h
index de0a1c7..87e4689 100644
--- a/src/video/windows/SDL_windowsopengl.h
+++ b/src/video/windows/SDL_windowsopengl.h
@@ -30,6 +30,7 @@ struct SDL_GLDriverData
     SDL_bool HAS_WGL_ARB_pixel_format;
     SDL_bool HAS_WGL_EXT_swap_control_tear;
     SDL_bool HAS_WGL_ARB_context_flush_control;
+    SDL_bool HAS_WGL_ARB_create_context_robustness;
 
 	/* Max version of OpenGL ES context that can be created if the
 	   implementation supports WGL_EXT_create_context_es2_profile.
diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c
index 0756484..8a658df 100644
--- a/src/video/x11/SDL_x11opengl.c
+++ b/src/video/x11/SDL_x11opengl.c
@@ -394,6 +394,11 @@ X11_GL_InitExtensions(_THIS)
     if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
         _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
     }
+
+    /* Check for GLX_ARB_create_context_robustness */
+    if (HasExtension("GLX_ARB_create_context_robustness", extensions)) {
+        _this->gl_data->HAS_GLX_ARB_create_context_robustness = SDL_TRUE;
+    }
 }
 
 /* glXChooseVisual and glXChooseFBConfig have some small differences in
@@ -621,8 +626,8 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
             context =
                 _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
         } else {
-            /* max 10 attributes plus terminator */
-            int attribs[11] = {
+            /* max 12 attributes plus terminator */
+            int attribs[13] = {
                 GLX_CONTEXT_MAJOR_VERSION_ARB,
                 _this->gl_config.major_version,
                 GLX_CONTEXT_MINOR_VERSION_ARB,
@@ -652,6 +657,15 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
                     GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
             }
 
+            /* only set if glx extension is available */
+            if( _this->gl_data->HAS_GLX_ARB_create_context_robustness ) {
+                attribs[iattr++] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
+                attribs[iattr++] =
+                    _this->gl_config.reset_notification ?
+                    GLX_LOSE_CONTEXT_ON_RESET_ARB :
+                    GLX_NO_RESET_NOTIFICATION_ARB;
+            }
+
             attribs[iattr++] = 0;
 
             /* Get a pointer to the context creation function for GL 3.0 */
diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h
index 7e5654d..dd3c7e5 100644
--- a/src/video/x11/SDL_x11opengl.h
+++ b/src/video/x11/SDL_x11opengl.h
@@ -35,6 +35,7 @@ struct SDL_GLDriverData
     SDL_bool HAS_GLX_EXT_visual_info;
     SDL_bool HAS_GLX_EXT_swap_control_tear;
     SDL_bool HAS_GLX_ARB_context_flush_control;
+    SDL_bool HAS_GLX_ARB_create_context_robustness;
 
 	/* Max version of OpenGL ES context that can be created if the
 	   implementation supports GLX_EXT_create_context_es2_profile.