Add OpenGL 3.X context creation support
authorSam Lantinga <slouken@libsdl.org>
Mon, 20 Feb 2012 23:37:57 -0500
changeset 6296b42657486c0d
parent 6295 a2c60beb6115
child 6298 9110462bfc57
Add OpenGL 3.X context creation support

Matthias Bentrup 2011-10-30 03:58:24 PDT

I've updated the context creation patch to include the bugfixes by Martin
Schreiber and also included a profile bit to request a ES2 compatible profile.

The wgl context creation may use 2 call to wglChoosePixelFormat if no
acceleration attribute is selected, this should work around a bug with buggy
AMD drivers (see #1254).
include/SDL_video.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/windows/SDL_windowsopengl.c
src/video/x11/SDL_x11opengl.c
     1.1 --- a/include/SDL_video.h	Mon Feb 20 20:56:52 2012 -0500
     1.2 +++ b/include/SDL_video.h	Mon Feb 20 23:37:57 2012 -0500
     1.3 @@ -182,9 +182,25 @@
     1.4      SDL_GL_ACCELERATED_VISUAL,
     1.5      SDL_GL_RETAINED_BACKING,
     1.6      SDL_GL_CONTEXT_MAJOR_VERSION,
     1.7 -    SDL_GL_CONTEXT_MINOR_VERSION
     1.8 +    SDL_GL_CONTEXT_MINOR_VERSION,
     1.9 +    SDL_GL_CONTEXT_FLAGS,
    1.10 +    SDL_GL_CONTEXT_PROFILE_MASK
    1.11  } SDL_GLattr;
    1.12  
    1.13 +typedef enum
    1.14 +{
    1.15 +    SDL_GL_CONTEXT_PROFILE_CORE           = 0x0001,
    1.16 +    SDL_GL_CONTEXT_PROFILE_COMPATIBILITY  = 0x0002,
    1.17 +    SDL_GL_CONTEXT_PROFILE_ES2            = 0x0004
    1.18 +} SDL_GLprofile;
    1.19 +
    1.20 +typedef enum
    1.21 +{
    1.22 +    SDL_GL_CONTEXT_DEBUG_FLAG              = 0x0001,
    1.23 +    SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
    1.24 +    SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG      = 0x0004
    1.25 +} SDL_GLcontextFlag;
    1.26 +
    1.27  
    1.28  /* Function prototypes */
    1.29  
     2.1 --- a/src/video/SDL_sysvideo.h	Mon Feb 20 20:56:52 2012 -0500
     2.2 +++ b/src/video/SDL_sysvideo.h	Mon Feb 20 23:37:57 2012 -0500
     2.3 @@ -270,6 +270,8 @@
     2.4          int accelerated;
     2.5          int major_version;
     2.6          int minor_version;
     2.7 +        int flags;
     2.8 +        int profile_mask;
     2.9          int retained_backing;
    2.10          int driver_loaded;
    2.11          char driver_path[256];
     3.1 --- a/src/video/SDL_video.c	Mon Feb 20 20:56:52 2012 -0500
     3.2 +++ b/src/video/SDL_video.c	Mon Feb 20 23:37:57 2012 -0500
     3.3 @@ -500,6 +500,8 @@
     3.4      _this->gl_config.major_version = 2;
     3.5      _this->gl_config.minor_version = 0;
     3.6  #endif
     3.7 +    _this->gl_config.flags = 0;
     3.8 +    _this->gl_config.profile_mask = 0;
     3.9  
    3.10      /* Initialize the video subsystem */
    3.11      if (_this->VideoInit(_this) < 0) {
    3.12 @@ -2300,6 +2302,12 @@
    3.13      case SDL_GL_CONTEXT_MINOR_VERSION:
    3.14          _this->gl_config.minor_version = value;
    3.15          break;
    3.16 +    case SDL_GL_CONTEXT_FLAGS:
    3.17 +        _this->gl_config.flags = value;
    3.18 +        break;
    3.19 +    case SDL_GL_CONTEXT_PROFILE_MASK:
    3.20 +        _this->gl_config.profile_mask = value;
    3.21 +        break;
    3.22      default:
    3.23          SDL_SetError("Unknown OpenGL attribute");
    3.24          retval = -1;
    3.25 @@ -2446,6 +2454,16 @@
    3.26              *value = _this->gl_config.minor_version;
    3.27              return 0;
    3.28          }
    3.29 +    case SDL_GL_CONTEXT_FLAGS:
    3.30 +        {
    3.31 +            *value = _this->gl_config.flags;
    3.32 +            return 0;
    3.33 +        }
    3.34 +    case SDL_GL_CONTEXT_PROFILE_MASK:
    3.35 +        {
    3.36 +            *value = _this->gl_config.profile_mask;
    3.37 +            return 0;
    3.38 +        }
    3.39      default:
    3.40          SDL_SetError("Unknown OpenGL attribute");
    3.41          return -1;
     4.1 --- a/src/video/windows/SDL_windowsopengl.c	Mon Feb 20 20:56:52 2012 -0500
     4.2 +++ b/src/video/windows/SDL_windowsopengl.c	Mon Feb 20 23:37:57 2012 -0500
     4.3 @@ -39,6 +39,26 @@
     4.4  #define WGL_CONTEXT_FLAGS_ARB           0x2093
     4.5  #define WGL_CONTEXT_DEBUG_BIT_ARB       0x0001
     4.6  #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
     4.7 +
     4.8 +#ifndef WGL_ARB_create_context_profile
     4.9 +#define WGL_ARB_create_context_profile
    4.10 +#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
    4.11 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
    4.12 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
    4.13 +#endif
    4.14 +
    4.15 +#ifndef WGL_ARB_create_context_robustness
    4.16 +#define WGL_ARB_create_context_robustness
    4.17 +#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB         0x00000004
    4.18 +#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB     0x8256
    4.19 +#define WGL_NO_RESET_NOTIFICATION_ARB                   0x8261
    4.20 +#define WGL_LOSE_CONTEXT_ON_RESET_ARB                   0x8252
    4.21 +#endif
    4.22 +#endif
    4.23 +
    4.24 +#ifndef WGL_EXT_create_context_es2_profile
    4.25 +#define WGL_EXT_create_context_es2_profile
    4.26 +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT           0x00000004
    4.27  #endif
    4.28  
    4.29  typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
    4.30 @@ -398,7 +418,7 @@
    4.31  {
    4.32      HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
    4.33      PIXELFORMATDESCRIPTOR pfd;
    4.34 -    int pixel_format;
    4.35 +    int pixel_format = 0;
    4.36      int iAttribs[64];
    4.37      int *iAttr;
    4.38      float fAttribs[1] = { 0 };
    4.39 @@ -468,16 +488,19 @@
    4.40          *iAttr++ = _this->gl_config.multisamplesamples;
    4.41      }
    4.42  
    4.43 -    if (_this->gl_config.accelerated >= 0) {
    4.44 -        *iAttr++ = WGL_ACCELERATION_ARB;
    4.45 -        *iAttr++ = (_this->gl_config.accelerated ? WGL_FULL_ACCELERATION_ARB :
    4.46 -                                                   WGL_NO_ACCELERATION_ARB);
    4.47 -    }
    4.48 +    *iAttr++ = WGL_ACCELERATION_ARB;
    4.49 +    *iAttr++ = WGL_FULL_ACCELERATION_ARB;
    4.50  
    4.51      *iAttr = 0;
    4.52  
    4.53      /* Choose and set the closest available pixel format */
    4.54 -    pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
    4.55 +    if (_this->gl_config.accelerated != 0) {
    4.56 +        pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
    4.57 +    }
    4.58 +    if (!pixel_format && _this->gl_config.accelerated != 1) {
    4.59 +        iAttr[-1] = WGL_NO_ACCELERATION_ARB;
    4.60 +	pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
    4.61 +    }
    4.62      if (!pixel_format) {
    4.63          pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
    4.64      }
    4.65 @@ -521,11 +544,28 @@
    4.66              SDL_SetError("GL 3.x is not supported");
    4.67              context = temp_context;
    4.68          } else {
    4.69 -            int attribs[] = {
    4.70 +	    /* max 8 attributes plus terminator */
    4.71 +            int attribs[9] = {
    4.72                  WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
    4.73                  WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
    4.74                  0
    4.75              };
    4.76 +	    int iattr = 4;
    4.77 +
    4.78 +	    /* SDL profile bits match WGL profile bits */
    4.79 +	    if( _this->gl_config.profile_mask != 0 ) {
    4.80 +	        attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
    4.81 +		attribs[iattr++] = _this->gl_config.profile_mask;
    4.82 +	    }
    4.83 +
    4.84 +	    /* SDL flags match WGL flags */
    4.85 +	    if( _this->gl_config.flags != 0 ) {
    4.86 +	        attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
    4.87 +		attribs[iattr++] = _this->gl_config.flags;
    4.88 +	    }
    4.89 +
    4.90 +	    attribs[iattr++] = 0;
    4.91 +
    4.92              /* Create the GL 3.x context */
    4.93              context = wglCreateContextAttribsARB(hdc, 0, attribs);
    4.94              /* Delete the GL 2.x context */
     5.1 --- a/src/video/x11/SDL_x11opengl.c	Mon Feb 20 20:56:52 2012 -0500
     5.2 +++ b/src/video/x11/SDL_x11opengl.c	Mon Feb 20 23:37:57 2012 -0500
     5.3 @@ -67,11 +67,6 @@
     5.4  #define GLX_CONTEXT_DEBUG_BIT_ARB          0x0001
     5.5  #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
     5.6  
     5.7 -#ifndef GLX_EXT_swap_control
     5.8 -#define GLX_SWAP_INTERVAL_EXT              0x20F1
     5.9 -#define GLX_MAX_SWAP_INTERVAL_EXT          0x20F2
    5.10 -#endif
    5.11 -
    5.12  /* Typedef for the GL 3.0 context creation function */
    5.13  typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
    5.14                                                          GLXFBConfig config,
    5.15 @@ -80,6 +75,31 @@
    5.16                                                          Bool direct,
    5.17                                                          const int
    5.18                                                          *attrib_list);
    5.19 +
    5.20 +#ifndef GLX_ARB_create_context_profile
    5.21 +#define GLX_ARB_create_context_profile
    5.22 +#define GLX_CONTEXT_PROFILE_MASK_ARB       0x9126
    5.23 +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB   0x00000001
    5.24 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
    5.25 +#endif
    5.26 +
    5.27 +#ifndef GLX_ARB_create_context_robustness
    5.28 +#define GLX_ARB_create_context_robustness
    5.29 +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB  0x00000004
    5.30 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB     0x8256
    5.31 +#define GLX_NO_RESET_NOTIFICATION_ARB                   0x8261
    5.32 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB                   0x8252
    5.33 +#endif
    5.34 +#endif
    5.35 +
    5.36 +#ifndef GLX_EXT_create_context_es2_profile
    5.37 +#define GLX_EXT_create_context_es2_profile
    5.38 +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT    0x00000002
    5.39 +#endif
    5.40 +
    5.41 +#ifndef GLX_EXT_swap_control
    5.42 +#define GLX_SWAP_INTERVAL_EXT              0x20F1
    5.43 +#define GLX_MAX_SWAP_INTERVAL_EXT          0x20F2
    5.44  #endif
    5.45  
    5.46  #define OPENGL_REQUIRES_DLOPEN
    5.47 @@ -305,8 +325,11 @@
    5.48      X11_PumpEvents(_this);
    5.49  }
    5.50  
    5.51 +/* glXChooseVisual and glXChooseFBConfig have some small differences in
    5.52 + * the attribute encoding, it can be chosen with the for_FBConfig parameter. 
    5.53 + */
    5.54  int 
    5.55 -X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size)
    5.56 +X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
    5.57  {
    5.58      int i = 0;
    5.59  
    5.60 @@ -314,7 +337,12 @@
    5.61      SDL_assert(size >= 32);
    5.62  
    5.63      /* Setup our GLX attributes according to the gl_config. */
    5.64 -    attribs[i++] = GLX_RGBA;
    5.65 +    if( for_FBConfig ) {
    5.66 +        attribs[i++] = GLX_RENDER_TYPE;
    5.67 +	attribs[i++] = GLX_RGBA_BIT;
    5.68 +    } else {
    5.69 +        attribs[i++] = GLX_RGBA;
    5.70 +    }
    5.71      attribs[i++] = GLX_RED_SIZE;
    5.72      attribs[i++] = _this->gl_config.red_size;
    5.73      attribs[i++] = GLX_GREEN_SIZE;
    5.74 @@ -329,6 +357,8 @@
    5.75  
    5.76      if (_this->gl_config.double_buffer) {
    5.77          attribs[i++] = GLX_DOUBLEBUFFER;
    5.78 +	if( for_FBConfig )
    5.79 +	    attribs[i++] = True;
    5.80      }
    5.81  
    5.82      attribs[i++] = GLX_DEPTH_SIZE;
    5.83 @@ -361,6 +391,8 @@
    5.84  
    5.85      if (_this->gl_config.stereo) {
    5.86          attribs[i++] = GLX_STEREO;
    5.87 +	if( for_FBConfig )
    5.88 +	    attribs[i++] = True;
    5.89      }
    5.90  
    5.91      if (_this->gl_config.multisamplebuffers) {
    5.92 @@ -391,10 +423,8 @@
    5.93      XVisualInfo *vinfo;
    5.94  
    5.95      /* 64 seems nice. */
    5.96 -    const int max_attrs = 64;
    5.97 -    int attribs[max_attrs];
    5.98 -    const int i = X11_GL_GetAttributes(_this,display,screen,attribs,max_attrs);
    5.99 -    SDL_assert(i <= max_attrs);
   5.100 +    int attribs[64];
   5.101 +    int i = X11_GL_GetAttributes(_this,display,screen,attribs,64,SDL_FALSE);
   5.102  
   5.103      if (!_this->gl_data) {
   5.104          /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
   5.105 @@ -439,13 +469,29 @@
   5.106                  SDL_SetError("Could not create GL context");
   5.107                  return NULL;
   5.108              } else {
   5.109 -                int attribs[] = {
   5.110 +	        /* max 8 attributes plus terminator */
   5.111 +                int attribs[9] = {
   5.112                      GLX_CONTEXT_MAJOR_VERSION_ARB,
   5.113                      _this->gl_config.major_version,
   5.114                      GLX_CONTEXT_MINOR_VERSION_ARB,
   5.115                      _this->gl_config.minor_version,
   5.116                      0
   5.117                  };
   5.118 +		int iattr = 4;
   5.119 +
   5.120 +		/* SDL profile bits match GLX profile bits */
   5.121 +		if( _this->gl_config.profile_mask != 0 ) {
   5.122 +		    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
   5.123 +		    attribs[iattr++] = _this->gl_config.profile_mask;
   5.124 +		}
   5.125 +
   5.126 +		/* SDL flags match GLX flags */
   5.127 +		if( _this->gl_config.flags != 0 ) {
   5.128 +		    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
   5.129 +		    attribs[iattr++] = _this->gl_config.flags;
   5.130 +		}
   5.131 +
   5.132 +		attribs[iattr++] = 0;
   5.133  
   5.134                  /* Get a pointer to the context creation function for GL 3.0 */
   5.135                  PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
   5.136 @@ -472,7 +518,7 @@
   5.137                               int *)) _this->gl_data->
   5.138                          glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
   5.139  
   5.140 -                    X11_GL_GetAttributes(_this,display,screen,glxAttribs,64);
   5.141 +                    X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
   5.142  
   5.143                      if (!glXChooseFBConfig
   5.144                          || !(framebuffer_config =