diff --git a/include/SDL_video.h b/include/SDL_video.h index 7a034a48b..4e83fa32f 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -270,7 +270,9 @@ typedef enum SDL_GL_MULTISAMPLEBUFFERS, SDL_GL_MULTISAMPLESAMPLES, SDL_GL_ACCELERATED_VISUAL, - SDL_GL_RETAINED_BACKING + SDL_GL_RETAINED_BACKING, + SDL_GL_CONTEXT_MAJOR_VERSION, + SDL_GL_CONTEXT_MINOR_VERSION } SDL_GLattr; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 9c781b340..1b54ed347 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -305,6 +305,8 @@ struct SDL_VideoDevice int multisamplebuffers; int multisamplesamples; int accelerated; + int major_version; + int minor_version; int retained_backing; int driver_loaded; char driver_path[256]; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index f2b259ac0..e23ae2e59 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -257,6 +257,8 @@ SDL_VideoInit(const char *driver_name, Uint32 flags) _this->gl_config.multisamplesamples = 0; _this->gl_config.retained_backing = 1; _this->gl_config.accelerated = -1; /* not known, don't set */ + _this->gl_config.major_version = 2; + _this->gl_config.minor_version = 1; /* Initialize the video subsystem */ if (_this->VideoInit(_this) < 0) { @@ -2694,6 +2696,12 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value) case SDL_GL_RETAINED_BACKING: _this->gl_config.retained_backing = value; break; + case SDL_GL_CONTEXT_MAJOR_VERSION: + _this->gl_config.major_version = value; + break; + case SDL_GL_CONTEXT_MINOR_VERSION: + _this->gl_config.minor_version = value; + break; default: SDL_SetError("Unknown OpenGL attribute"); retval = -1; diff --git a/src/video/win32/SDL_win32opengl.c b/src/video/win32/SDL_win32opengl.c index 451bd03be..75f566ba9 100644 --- a/src/video/win32/SDL_win32opengl.c +++ b/src/video/win32/SDL_win32opengl.c @@ -30,6 +30,17 @@ #define DEFAULT_OPENGL "OPENGL32.DLL" +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2093 +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#endif + +typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int * attribList); int WIN_GL_LoadLibrary(_THIS, const char *path) @@ -485,7 +496,39 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window) HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; HGLRC context; - context = _this->gl_data->wglCreateContext(hdc); + if (_this->gl_config.major_version < 3) { + context = _this->gl_data->wglCreateContext(hdc); + } else { + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; + HGLRC temp_context = _this->gl_data->wglCreateContext(hdc); + if (!temp_context) { + SDL_SetError("Could not create GL context"); + return NULL; + } + + /* Make the context current */ + if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) { + WIN_GL_DeleteContext(_this, temp_context); + return NULL; + } + + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB"); + if (!wglCreateContextAttribsARB) { + SDL_SetError("GL 3.x is not supported"); + context = temp_context; + } else { + int attribs[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, + WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, + 0 + }; + /* Create the GL 3.x context */ + context = wglCreateContextAttribsARB(hdc, 0, attribs); + /* Delete the GL 2.x context */ + wglDeleteContext(temp_context); + } + } + if (!context) { SDL_SetError("Could not create GL context"); return NULL; diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 63b3ced38..7a34bec5f 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -53,6 +53,15 @@ #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D #endif +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#endif + #define OPENGL_REQUIRS_DLOPEN #if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN) #include @@ -67,6 +76,9 @@ static void X11_GL_InitExtensions(_THIS); +/* Typedef for the GL 3.0 context creation function */ +typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); + int X11_GL_LoadLibrary(_THIS, const char *path) { @@ -270,10 +282,9 @@ X11_GL_GetVisual(_THIS, Display * display, int screen) /* 64 seems nice. */ int attribs[64]; - int i; - + int i = 0; + /* Setup our GLX attributes according to the gl_config. */ - i = 0; attribs[i++] = GLX_RGBA; attribs[i++] = GLX_RED_SIZE; attribs[i++] = _this->gl_config.red_size; @@ -384,8 +395,43 @@ X11_GL_CreateContext(_THIS, SDL_Window * window) v.visualid = XVisualIDFromVisual(xattr.visual); vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n); if (vinfo) { - context = - _this->gl_data->glXCreateContext(display, vinfo, NULL, True); + if (_this->gl_config.major_version < 3) { + context = + _this->gl_data->glXCreateContext(display, vinfo, NULL, 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) { + SDL_SetError("Could not create GL context"); + return NULL; + } else { + int attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, + GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, + 0 + }; + + /* Get a pointer to the context creation function for GL 3.0 */ + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB"); + if (!glXCreateContextAttribs) { + SDL_SetError("GL 3.x is not supported"); + context = temp_context; + } else { + /* Create a GL 3.0 context */ + GLXFBConfig *framebuffer_config = NULL; + int fbcount = 0; + framebuffer_config = glXChooseFBConfig(display, DefaultScreen(display), NULL, &fbcount); + if (!framebuffer_config) { + SDL_SetError("No good framebuffers found. GL 3.0 disabled"); + context = temp_context; + } else { + context = glXCreateContextAttribs(display, framebuffer_config[0], NULL, True, attribs); + glXDestroyContext(display, temp_context); + } + } + } + } XFree(vinfo); } XSync(display, False);