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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c
index 1e94b04..c46710f 100644
--- a/src/video/x11/SDL_x11opengl.c
+++ b/src/video/x11/SDL_x11opengl.c
@@ -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);
- }
}
}
}
diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h
index ed7f292..b3410fd 100644
--- a/src/video/x11/SDL_x11opengl.h
+++ b/src/video/x11/SDL_x11opengl.h
@@ -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);