Fixed bug 1565 - some small GL context creation enhancements
authorSam Lantinga <slouken@libsdl.org>
Sun, 12 Aug 2012 11:16:24 -0700
changeset 6393 a773384edf20
parent 6392 fa7eb111f994
child 6394 9612bcd79130
Fixed bug 1565 - some small GL context creation enhancements Matthias Bentrup 2012-08-09 12:53:17 PDT With OpenGL 4.3 the ARB added a new context flag for context reset isolation and renamed the existing ES2 profile bit to ES profile bit, as it can be used to request GLES 3 compatible contexts, too. This patch adds these changes to SDL on Linux and Windows. Also SDL lacks the ability to create shared contexts. This patch also adds a new GL attribute to enable context sharing. As casting a GL context to int is not portable, I added only a boolean attribute SDL_GL_SHARE_WITH_CURRENT_CONTEXT, which makes the new context share resources with the context current on the creating thread.
include/SDL_video.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/windows/SDL_windowsopengl.c
src/video/windows/SDL_windowsopengl.h
src/video/x11/SDL_x11opengl.c
--- a/include/SDL_video.h	Sat Aug 11 10:15:59 2012 -0700
+++ b/include/SDL_video.h	Sun Aug 12 11:16:24 2012 -0700
@@ -185,13 +185,15 @@
     SDL_GL_CONTEXT_MINOR_VERSION,
     SDL_GL_CONTEXT_EGL,
     SDL_GL_CONTEXT_FLAGS,
-    SDL_GL_CONTEXT_PROFILE_MASK
+    SDL_GL_CONTEXT_PROFILE_MASK,
+    SDL_GL_SHARE_WITH_CURRENT_CONTEXT
 } SDL_GLattr;
 
 typedef enum
 {
     SDL_GL_CONTEXT_PROFILE_CORE           = 0x0001,
     SDL_GL_CONTEXT_PROFILE_COMPATIBILITY  = 0x0002,
+    SDL_GL_CONTEXT_PROFILE_ES             = 0x0004,
     SDL_GL_CONTEXT_PROFILE_ES2            = 0x0004
 } SDL_GLprofile;
 
@@ -199,7 +201,8 @@
 {
     SDL_GL_CONTEXT_DEBUG_FLAG              = 0x0001,
     SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
-    SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG      = 0x0004
+    SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG      = 0x0004,
+    SDL_GL_CONTEXT_RESET_ISOLATION_FLAG    = 0x0008
 } SDL_GLcontextFlag;
 
 
--- a/src/video/SDL_sysvideo.h	Sat Aug 11 10:15:59 2012 -0700
+++ b/src/video/SDL_sysvideo.h	Sun Aug 12 11:16:24 2012 -0700
@@ -280,6 +280,7 @@
         int flags;
         int profile_mask;
         int use_egl;
+        int share_with_current_context;
         int retained_backing;
         int driver_loaded;
         char driver_path[256];
--- a/src/video/SDL_video.c	Sat Aug 11 10:15:59 2012 -0700
+++ b/src/video/SDL_video.c	Sun Aug 12 11:16:24 2012 -0700
@@ -505,6 +505,7 @@
 #endif
     _this->gl_config.flags = 0;
     _this->gl_config.profile_mask = 0;
+    _this->gl_config.share_with_current_context = 0;
 
     /* Initialize the video subsystem */
     if (_this->VideoInit(_this) < 0) {
@@ -2309,11 +2310,30 @@
         _this->gl_config.use_egl = value;
         break;
     case SDL_GL_CONTEXT_FLAGS:
+        if( value & ~(SDL_GL_CONTEXT_DEBUG_FLAG |
+		      SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG |
+		      SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG |
+		      SDL_GL_CONTEXT_RESET_ISOLATION_FLAG) ) {
+	    SDL_SetError("Unknown OpenGL context flag %d", value);
+	    retval = -1;
+	    break;
+	}
         _this->gl_config.flags = value;
         break;
     case SDL_GL_CONTEXT_PROFILE_MASK:
+        if( value != 0 &&
+	    value != SDL_GL_CONTEXT_PROFILE_CORE &&
+	    value != SDL_GL_CONTEXT_PROFILE_COMPATIBILITY &&
+	    value != SDL_GL_CONTEXT_PROFILE_ES ) {
+	    SDL_SetError("Unknown OpenGL context profile %d", value);
+	    retval = -1;
+	    break;
+	}
         _this->gl_config.profile_mask = value;
         break;
+    case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
+        _this->gl_config.share_with_current_context = value;
+	break;
     default:
         SDL_SetError("Unknown OpenGL attribute");
         retval = -1;
@@ -2475,6 +2495,11 @@
             *value = _this->gl_config.profile_mask;
             return 0;
         }
+    case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
+        {
+            *value = _this->gl_config.share_with_current_context;
+            return 0;
+        }
     default:
         SDL_SetError("Unknown OpenGL attribute");
         return -1;
--- a/src/video/windows/SDL_windowsopengl.c	Sat Aug 11 10:15:59 2012 -0700
+++ b/src/video/windows/SDL_windowsopengl.c	Sun Aug 12 11:16:24 2012 -0700
@@ -61,6 +61,11 @@
 #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT           0x00000004
 #endif
 
+#ifndef WGL_EXT_create_context_es_profile
+#define WGL_EXT_create_context_es_profile
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT            0x00000004
+#endif
+
 typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
                                                             HGLRC
                                                             hShareContext,
@@ -112,6 +117,8 @@
         GetProcAddress(handle, "wglDeleteContext");
     _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
         GetProcAddress(handle, "wglMakeCurrent");
+    _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
+        GetProcAddress(handle, "wglShareLists");
 
     if (!_this->gl_data->wglGetProcAddress ||
         !_this->gl_data->wglCreateContext ||
@@ -519,10 +526,22 @@
 WIN_GL_CreateContext(_THIS, SDL_Window * window)
 {
     HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
-    HGLRC context;
+    HGLRC context, share_context;
+
+    if (_this->gl_config.share_with_current_context) {
+        share_context = (HGLRC)(_this->current_glctx);
+    } else {
+        share_context = 0;
+    }
 
-    if (_this->gl_config.major_version < 3) {
+    if (_this->gl_config.major_version < 3 &&
+	_this->gl_config.profile_mask == 0 &&
+	_this->gl_config.flags == 0) {
+        /* Create legacy context */
         context = _this->gl_data->wglCreateContext(hdc);
+	if( share_context != 0 ) {
+            _this->gl_data->wglShareLists(share_context, hdc);
+	}
     } else {
         PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
         HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
@@ -567,7 +586,7 @@
 	    attribs[iattr++] = 0;
 
             /* Create the GL 3.x context */
-            context = wglCreateContextAttribsARB(hdc, 0, attribs);
+            context = wglCreateContextAttribsARB(hdc, share_context, attribs);
             /* Delete the GL 2.x context */
             _this->gl_data->wglDeleteContext(temp_context);
         }
--- a/src/video/windows/SDL_windowsopengl.h	Sat Aug 11 10:15:59 2012 -0700
+++ b/src/video/windows/SDL_windowsopengl.h	Sun Aug 12 11:16:24 2012 -0700
@@ -34,6 +34,7 @@
       HGLRC(WINAPI * wglCreateContext) (HDC hdc);
       BOOL(WINAPI * wglDeleteContext) (HGLRC hglrc);
       BOOL(WINAPI * wglMakeCurrent) (HDC hdc, HGLRC hglrc);
+      BOOL(WINAPI * wglShareLists) (HGLRC hglrc1, HGLRC hglrc2);
       BOOL(WINAPI * wglChoosePixelFormatARB) (HDC hdc,
                                               const int *piAttribIList,
                                               const FLOAT * pfAttribFList,
--- a/src/video/x11/SDL_x11opengl.c	Sat Aug 11 10:15:59 2012 -0700
+++ b/src/video/x11/SDL_x11opengl.c	Sun Aug 12 11:16:24 2012 -0700
@@ -484,7 +484,13 @@
     XWindowAttributes xattr;
     XVisualInfo v, *vinfo;
     int n;
-    GLXContext context = NULL;
+    GLXContext context = NULL, share_context;
+
+    if (_this->gl_config.share_with_current_context) {
+        share_context = (GLXContext)(_this->current_glctx);
+    } else {
+        share_context = NULL;
+    }
 
     /* We do this to create a clean separation between X and GLX errors. */
     XSync(display, False);
@@ -493,9 +499,12 @@
     v.visualid = XVisualIDFromVisual(xattr.visual);
     vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
     if (vinfo) {
-        if (_this->gl_config.major_version < 3) {
+        if (_this->gl_config.major_version < 3 &&
+            _this->gl_config.profile_mask == 0 &&
+            _this->gl_config.flags == 0) {
+            /* Create legacy context */
             context =
-                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
+                _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
         } else {
             /* If we want a GL 3.0 context or later we need to get a temporary
                context to grab the new context creation function */
@@ -505,7 +514,7 @@
                 SDL_SetError("Could not create GL context");
                 return NULL;
             } else {
-	        /* max 8 attributes plus terminator */
+                /* max 8 attributes plus terminator */
                 int attribs[9] = {
                     GLX_CONTEXT_MAJOR_VERSION_ARB,
                     _this->gl_config.major_version,
@@ -513,21 +522,21 @@
                     _this->gl_config.minor_version,
                     0
                 };
-		int iattr = 4;
+                int iattr = 4;
 
-		/* SDL profile bits match GLX profile bits */
-		if( _this->gl_config.profile_mask != 0 ) {
-		    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
-		    attribs[iattr++] = _this->gl_config.profile_mask;
-		}
+                /* SDL profile bits match GLX profile bits */
+                if( _this->gl_config.profile_mask != 0 ) {
+                    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+                    attribs[iattr++] = _this->gl_config.profile_mask;
+                }
 
-		/* SDL flags match GLX flags */
-		if( _this->gl_config.flags != 0 ) {
-		    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
-		    attribs[iattr++] = _this->gl_config.flags;
-		}
+                /* SDL flags match GLX flags */
+                if( _this->gl_config.flags != 0 ) {
+                    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
+                    attribs[iattr++] = _this->gl_config.flags;
+                }
 
-		attribs[iattr++] = 0;
+                attribs[iattr++] = 0;
 
                 /* Get a pointer to the context creation function for GL 3.0 */
                 PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
@@ -568,7 +577,7 @@
                         context =
                             glXCreateContextAttribs(display,
                                                     framebuffer_config[0],
-                                                    NULL, True, attribs);
+                                                    share_context, True, attribs);
                         _this->gl_data->glXDestroyContext(display,
                                                           temp_context);
                     }