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).
Ryan C. Gordon 2015-02-02 01:05:41 -05:00
parent 86f87bf755
commit ece8d2bb05
2 changed files with 51 additions and 66 deletions

View File

@ -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;
/* 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 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 */
glXCreateContextAttribs =
(PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
glXGetProcAddress((GLubyte *)
"glXCreateContextAttribsARB");
if (!glXCreateContextAttribs) {
SDL_SetError("GL 3.x is not supported");
context = temp_context;
/* 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;
X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
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);
}
}
}
}

View File

@ -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);