X11: Fixes for OpenGL 3.0 and later context creation.
authorRyan C. Gordon <icculus@icculus.org>
Mon, 02 Feb 2015 01:05:41 -0500
changeset 933026eb20aad02f
parent 9329 64bb8e49c6a6
child 9331 bb0b744fd1a6
X11: Fixes for OpenGL 3.0 and later context creation.

- Don't create a temporary context first; this was probably due to Windows
needing one to get the address of wglCreateContextAttribsARB(), but that's
a unique quirk of WGL, and doesn't apply to glX. The glX spec explicitly says
you have to get a function pointer that works with any context from
glXGetProcAddress(), including when no context exists.

- Properly check for the GLX_ARB_create_context instead of just looking for a
non-NULL glXCreateContextAttribsARB()...some implementations, like Mesa,
never return NULL for function lookups (Mesa returns pointers into a jump
table that is filled out when the GL is initialized; since you can look up
functions before you have a valid context, it can't definitely say a function
isn't valid at that point).
src/video/x11/SDL_x11opengl.c
src/video/x11/SDL_x11opengl.h
     1.1 --- a/src/video/x11/SDL_x11opengl.c	Sat Jan 31 22:45:54 2015 +0100
     1.2 +++ b/src/video/x11/SDL_x11opengl.c	Mon Feb 02 01:05:41 2015 -0500
     1.3 @@ -373,6 +373,16 @@
     1.4              (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
     1.5      }
     1.6  
     1.7 +    /* Check for GLX_ARB_create_context */
     1.8 +    if (HasExtension("GLX_ARB_create_context", extensions)) {
     1.9 +        _this->gl_data->glXCreateContextAttribsARB =
    1.10 +            (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
    1.11 +                X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
    1.12 +        _this->gl_data->glXChooseFBConfig =
    1.13 +            (GLXFBConfig *(*)(Display *, int, const int *, int *))
    1.14 +                X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
    1.15 +    }
    1.16 +
    1.17      /* Check for GLX_EXT_visual_rating */
    1.18      if (HasExtension("GLX_EXT_visual_rating", extensions)) {
    1.19          _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
    1.20 @@ -576,7 +586,6 @@
    1.21      XVisualInfo v, *vinfo;
    1.22      int n;
    1.23      GLXContext context = NULL, share_context;
    1.24 -    PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL;
    1.25  
    1.26      if (_this->gl_config.share_with_current_context) {
    1.27          share_context = (GLXContext)SDL_GL_GetCurrentContext();
    1.28 @@ -601,78 +610,52 @@
    1.29              context =
    1.30                  _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
    1.31          } else {
    1.32 -            /* If we want a GL 3.0 context or later we need to get a temporary
    1.33 -               context to grab the new context creation function */
    1.34 -            GLXContext temp_context =
    1.35 -                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
    1.36 -            if (temp_context) {
    1.37 -                /* max 8 attributes plus terminator */
    1.38 -                int attribs[9] = {
    1.39 -                    GLX_CONTEXT_MAJOR_VERSION_ARB,
    1.40 -                    _this->gl_config.major_version,
    1.41 -                    GLX_CONTEXT_MINOR_VERSION_ARB,
    1.42 -                    _this->gl_config.minor_version,
    1.43 -                    0
    1.44 -                };
    1.45 -                int iattr = 4;
    1.46 +            /* max 8 attributes plus terminator */
    1.47 +            int attribs[9] = {
    1.48 +                GLX_CONTEXT_MAJOR_VERSION_ARB,
    1.49 +                _this->gl_config.major_version,
    1.50 +                GLX_CONTEXT_MINOR_VERSION_ARB,
    1.51 +                _this->gl_config.minor_version,
    1.52 +                0
    1.53 +            };
    1.54 +            int iattr = 4;
    1.55  
    1.56 -                /* SDL profile bits match GLX profile bits */
    1.57 -                if( _this->gl_config.profile_mask != 0 ) {
    1.58 -                    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
    1.59 -                    attribs[iattr++] = _this->gl_config.profile_mask;
    1.60 -                }
    1.61 +            /* SDL profile bits match GLX profile bits */
    1.62 +            if( _this->gl_config.profile_mask != 0 ) {
    1.63 +                attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
    1.64 +                attribs[iattr++] = _this->gl_config.profile_mask;
    1.65 +            }
    1.66  
    1.67 -                /* SDL flags match GLX flags */
    1.68 -                if( _this->gl_config.flags != 0 ) {
    1.69 -                    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
    1.70 -                    attribs[iattr++] = _this->gl_config.flags;
    1.71 -                }
    1.72 +            /* SDL flags match GLX flags */
    1.73 +            if( _this->gl_config.flags != 0 ) {
    1.74 +                attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
    1.75 +                attribs[iattr++] = _this->gl_config.flags;
    1.76 +            }
    1.77  
    1.78 -                attribs[iattr++] = 0;
    1.79 +            attribs[iattr++] = 0;
    1.80  
    1.81 -                /* Get a pointer to the context creation function for GL 3.0 */
    1.82 -                glXCreateContextAttribs =
    1.83 -                    (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
    1.84 -                    glXGetProcAddress((GLubyte *)
    1.85 -                                      "glXCreateContextAttribsARB");
    1.86 -                if (!glXCreateContextAttribs) {
    1.87 -                    SDL_SetError("GL 3.x is not supported");
    1.88 -                    context = temp_context;
    1.89 +            /* Get a pointer to the context creation function for GL 3.0 */
    1.90 +            if (!_this->gl_data->glXCreateContextAttribsARB) {
    1.91 +                SDL_SetError("OpenGL 3.0 and later are not supported by this system");
    1.92 +            } else {
    1.93 +                int glxAttribs[64];
    1.94 +
    1.95 +                /* Create a GL 3.x context */
    1.96 +                GLXFBConfig *framebuffer_config = NULL;
    1.97 +                int fbcount = 0;
    1.98 +
    1.99 +                X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
   1.100 +
   1.101 +                if (!_this->gl_data->glXChooseFBConfig
   1.102 +                    || !(framebuffer_config =
   1.103 +                        _this->gl_data->glXChooseFBConfig(display,
   1.104 +                                          DefaultScreen(display), glxAttribs,
   1.105 +                                          &fbcount))) {
   1.106 +                    SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
   1.107                  } else {
   1.108 -                    int glxAttribs[64];
   1.109 -
   1.110 -                    /* Create a GL 3.x context */
   1.111 -                    GLXFBConfig *framebuffer_config = NULL;
   1.112 -                    int fbcount = 0;
   1.113 -                    GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
   1.114 -                                                       int screen,
   1.115 -                                                       const int *attrib_list,
   1.116 -                                                       int *nelements);
   1.117 -
   1.118 -                    glXChooseFBConfig =
   1.119 -                        (GLXFBConfig *
   1.120 -                         (*)(Display *, int, const int *,
   1.121 -                             int *)) _this->gl_data->
   1.122 -                        glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
   1.123 -
   1.124 -                    X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
   1.125 -
   1.126 -                    if (!glXChooseFBConfig
   1.127 -                        || !(framebuffer_config =
   1.128 -                             glXChooseFBConfig(display,
   1.129 -                                               DefaultScreen(display), glxAttribs,
   1.130 -                                               &fbcount))) {
   1.131 -                        SDL_SetError
   1.132 -                            ("No good framebuffers found. GL 3.x disabled");
   1.133 -                        context = temp_context;
   1.134 -                    } else {
   1.135 -                        context =
   1.136 -                            glXCreateContextAttribs(display,
   1.137 +                    context = _this->gl_data->glXCreateContextAttribsARB(display,
   1.138                                                      framebuffer_config[0],
   1.139                                                      share_context, True, attribs);
   1.140 -                        _this->gl_data->glXDestroyContext(display,
   1.141 -                                                          temp_context);
   1.142 -                    }
   1.143                  }
   1.144              }
   1.145          }
     2.1 --- a/src/video/x11/SDL_x11opengl.h	Sat Jan 31 22:45:54 2015 +0100
     2.2 +++ b/src/video/x11/SDL_x11opengl.h	Mon Feb 02 01:05:41 2015 -0500
     2.3 @@ -40,6 +40,8 @@
     2.4      void *(*glXGetProcAddress) (const GLubyte*);
     2.5      XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
     2.6      GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
     2.7 +    GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *);
     2.8 +    GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *);
     2.9      void (*glXDestroyContext) (Display*, GLXContext);
    2.10      Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
    2.11      void (*glXSwapBuffers) (Display*, GLXDrawable);