Skip to content
Permalink
Browse files

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).
  • Loading branch information
icculus committed Feb 2, 2015
1 parent 86f87bf commit ece8d2bb056aad9f6937509abae636effb053fc0
Showing with 52 additions and 67 deletions.
  1. +50 −67 src/video/x11/SDL_x11opengl.c
  2. +2 −0 src/video/x11/SDL_x11opengl.h
@@ -373,6 +373,16 @@ X11_GL_InitExtensions(_THIS)
(int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
}

/* Check for GLX_ARB_create_context */
if (HasExtension("GLX_ARB_create_context", extensions)) {
_this->gl_data->glXCreateContextAttribsARB =
(GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
_this->gl_data->glXChooseFBConfig =
(GLXFBConfig *(*)(Display *, int, const int *, int *))
X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
}

/* Check for GLX_EXT_visual_rating */
if (HasExtension("GLX_EXT_visual_rating", extensions)) {
_this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
@@ -576,7 +586,6 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
XVisualInfo v, *vinfo;
int n;
GLXContext context = NULL, share_context;
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL;

if (_this->gl_config.share_with_current_context) {
share_context = (GLXContext)SDL_GL_GetCurrentContext();
@@ -601,78 +610,52 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
context =
_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 */
GLXContext temp_context =
_this->gl_data->glXCreateContext(display, vinfo, NULL, True);
if (temp_context) {
/* max 8 attributes plus terminator */
int attribs[9] = {
GLX_CONTEXT_MAJOR_VERSION_ARB,
_this->gl_config.major_version,
GLX_CONTEXT_MINOR_VERSION_ARB,
_this->gl_config.minor_version,
0
};
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;
}
/* max 8 attributes plus terminator */
int attribs[9] = {
GLX_CONTEXT_MAJOR_VERSION_ARB,
_this->gl_config.major_version,
GLX_CONTEXT_MINOR_VERSION_ARB,
_this->gl_config.minor_version,
0
};
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 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;

/* Get a pointer to the context creation function for GL 3.0 */
if (!_this->gl_data->glXCreateContextAttribsARB) {
SDL_SetError("OpenGL 3.0 and later are not supported by this system");
} else {
int glxAttribs[64];

/* Create a GL 3.x context */
GLXFBConfig *framebuffer_config = NULL;
int fbcount = 0;

attribs[iattr++] = 0;
X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);

/* Get a pointer to the context creation function for GL 3.0 */
glXCreateContextAttribs =
(PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
glXGetProcAddress((GLubyte *)
"glXCreateContextAttribsARB");
if (!glXCreateContextAttribs) {
SDL_SetError("GL 3.x is not supported");
context = temp_context;
if (!_this->gl_data->glXChooseFBConfig
|| !(framebuffer_config =
_this->gl_data->glXChooseFBConfig(display,
DefaultScreen(display), glxAttribs,
&fbcount))) {
SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
} else {
int glxAttribs[64];

/* Create a GL 3.x context */
GLXFBConfig *framebuffer_config = NULL;
int fbcount = 0;
GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
int screen,
const int *attrib_list,
int *nelements);

glXChooseFBConfig =
(GLXFBConfig *
(*)(Display *, int, const int *,
int *)) _this->gl_data->
glXGetProcAddress((GLubyte *) "glXChooseFBConfig");

X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);

if (!glXChooseFBConfig
|| !(framebuffer_config =
glXChooseFBConfig(display,
DefaultScreen(display), glxAttribs,
&fbcount))) {
SDL_SetError
("No good framebuffers found. GL 3.x disabled");
context = temp_context;
} else {
context =
glXCreateContextAttribs(display,
context = _this->gl_data->glXCreateContextAttribsARB(display,
framebuffer_config[0],
share_context, True, attribs);
_this->gl_data->glXDestroyContext(display,
temp_context);
}
}
}
}
@@ -40,6 +40,8 @@ struct SDL_GLDriverData
void *(*glXGetProcAddress) (const GLubyte*);
XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *);
GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *);
void (*glXDestroyContext) (Display*, GLXContext);
Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
void (*glXSwapBuffers) (Display*, GLXDrawable);

0 comments on commit ece8d2b

Please sign in to comment.