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).
parent
86f87bf755
commit
ece8d2bb05
|
@ -373,6 +373,16 @@ X11_GL_InitExtensions(_THIS)
|
||||||
(int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
|
(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 */
|
/* Check for GLX_EXT_visual_rating */
|
||||||
if (HasExtension("GLX_EXT_visual_rating", extensions)) {
|
if (HasExtension("GLX_EXT_visual_rating", extensions)) {
|
||||||
_this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
|
_this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
|
||||||
|
@ -576,7 +586,6 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
XVisualInfo v, *vinfo;
|
XVisualInfo v, *vinfo;
|
||||||
int n;
|
int n;
|
||||||
GLXContext context = NULL, share_context;
|
GLXContext context = NULL, share_context;
|
||||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL;
|
|
||||||
|
|
||||||
if (_this->gl_config.share_with_current_context) {
|
if (_this->gl_config.share_with_current_context) {
|
||||||
share_context = (GLXContext)SDL_GL_GetCurrentContext();
|
share_context = (GLXContext)SDL_GL_GetCurrentContext();
|
||||||
|
@ -601,78 +610,52 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
context =
|
context =
|
||||||
_this->gl_data->glXCreateContext(display, vinfo, share_context, True);
|
_this->gl_data->glXCreateContext(display, vinfo, share_context, True);
|
||||||
} else {
|
} else {
|
||||||
/* If we want a GL 3.0 context or later we need to get a temporary
|
/* max 8 attributes plus terminator */
|
||||||
context to grab the new context creation function */
|
int attribs[9] = {
|
||||||
GLXContext temp_context =
|
GLX_CONTEXT_MAJOR_VERSION_ARB,
|
||||||
_this->gl_data->glXCreateContext(display, vinfo, NULL, True);
|
_this->gl_config.major_version,
|
||||||
if (temp_context) {
|
GLX_CONTEXT_MINOR_VERSION_ARB,
|
||||||
/* max 8 attributes plus terminator */
|
_this->gl_config.minor_version,
|
||||||
int attribs[9] = {
|
0
|
||||||
GLX_CONTEXT_MAJOR_VERSION_ARB,
|
};
|
||||||
_this->gl_config.major_version,
|
int iattr = 4;
|
||||||
GLX_CONTEXT_MINOR_VERSION_ARB,
|
|
||||||
_this->gl_config.minor_version,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
int iattr = 4;
|
|
||||||
|
|
||||||
/* SDL profile bits match GLX profile bits */
|
/* SDL profile bits match GLX profile bits */
|
||||||
if( _this->gl_config.profile_mask != 0 ) {
|
if( _this->gl_config.profile_mask != 0 ) {
|
||||||
attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
|
attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
|
||||||
attribs[iattr++] = _this->gl_config.profile_mask;
|
attribs[iattr++] = _this->gl_config.profile_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SDL flags match GLX flags */
|
/* SDL flags match GLX flags */
|
||||||
if( _this->gl_config.flags != 0 ) {
|
if( _this->gl_config.flags != 0 ) {
|
||||||
attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
|
attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
|
||||||
attribs[iattr++] = _this->gl_config.flags;
|
attribs[iattr++] = _this->gl_config.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
attribs[iattr++] = 0;
|
attribs[iattr++] = 0;
|
||||||
|
|
||||||
/* Get a pointer to the context creation function for GL 3.0 */
|
/* Get a pointer to the context creation function for GL 3.0 */
|
||||||
glXCreateContextAttribs =
|
if (!_this->gl_data->glXCreateContextAttribsARB) {
|
||||||
(PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
|
SDL_SetError("OpenGL 3.0 and later are not supported by this system");
|
||||||
glXGetProcAddress((GLubyte *)
|
} else {
|
||||||
"glXCreateContextAttribsARB");
|
int glxAttribs[64];
|
||||||
if (!glXCreateContextAttribs) {
|
|
||||||
SDL_SetError("GL 3.x is not supported");
|
/* Create a GL 3.x context */
|
||||||
context = temp_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 {
|
} else {
|
||||||
int glxAttribs[64];
|
context = _this->gl_data->glXCreateContextAttribsARB(display,
|
||||||
|
|
||||||
/* 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,
|
|
||||||
framebuffer_config[0],
|
framebuffer_config[0],
|
||||||
share_context, True, attribs);
|
share_context, True, attribs);
|
||||||
_this->gl_data->glXDestroyContext(display,
|
|
||||||
temp_context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ struct SDL_GLDriverData
|
||||||
void *(*glXGetProcAddress) (const GLubyte*);
|
void *(*glXGetProcAddress) (const GLubyte*);
|
||||||
XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
|
XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
|
||||||
GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
|
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);
|
void (*glXDestroyContext) (Display*, GLXContext);
|
||||||
Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
|
Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
|
||||||
void (*glXSwapBuffers) (Display*, GLXDrawable);
|
void (*glXSwapBuffers) (Display*, GLXDrawable);
|
||||||
|
|
Loading…
Reference in New Issue