From: Mikko Rasa Date: Mon, 25 Jan 2021 23:30:56 +0000 (+0200) Subject: Add support for using the latest available OpenGL version X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=be455be47a214f8fba1224ef1fb4158a073bc4e3;p=libs%2Fgui.git Add support for using the latest available OpenGL version --- diff --git a/source/graphics/glcontext.cpp b/source/graphics/glcontext.cpp index 0274c9e..ec073cb 100644 --- a/source/graphics/glcontext.cpp +++ b/source/graphics/glcontext.cpp @@ -15,16 +15,26 @@ GLOptions::GLOptions(): multisample(0), forward_compatible(false), core_profile(false), - gl_version_major(0), - gl_version_minor(0) + gl_version_major(DEFAULT_VERSION), + gl_version_minor(DEFAULT_VERSION) { } unsupported_gl_mode::unsupported_gl_mode(const GLOptions &opts): - runtime_error(format("{ .alpha=%s, .stencil=%s, .doublebuffer=%s, .multisample=%d, .forward_compatible=%s, .core_profile=%s, .gl_version=%d.%d }", - opts.alpha, opts.stencil, opts.doublebuffer, opts.multisample, opts.forward_compatible, opts.core_profile, opts.gl_version_major, opts.gl_version_minor)) + runtime_error(format("{ .alpha=%s, .stencil=%s, .doublebuffer=%s, .multisample=%d, .forward_compatible=%s, .core_profile=%s, .gl_version=%s }", + opts.alpha, opts.stencil, opts.doublebuffer, opts.multisample, opts.forward_compatible, opts.core_profile, format_version(opts))) { } +string unsupported_gl_mode::format_version(const GLOptions &opts) +{ + if(opts.gl_version_major==GLOptions::LATEST_VERSION) + return "LATEST"; + else if(opts.gl_version_major==GLOptions::DEFAULT_VERSION) + return "DEFAULT"; + else + return format("%d.%d", opts.gl_version_major, opts.gl_version_minor); +} + GLContext::GLContext(Window &wnd, const GLOptions &opts): diff --git a/source/graphics/glcontext.h b/source/graphics/glcontext.h index ef6ef1b..f6357c3 100644 --- a/source/graphics/glcontext.h +++ b/source/graphics/glcontext.h @@ -11,6 +11,12 @@ class Window; struct GLOptions { + enum + { + DEFAULT_VERSION = 0, + LATEST_VERSION = 0xFFFFFFFF + }; + bool alpha; bool stencil; bool doublebuffer; @@ -29,6 +35,9 @@ class unsupported_gl_mode: public std::runtime_error public: unsupported_gl_mode(const GLOptions &); virtual ~unsupported_gl_mode() throw () { } + +private: + static std::string format_version(const GLOptions &); }; @@ -43,6 +52,7 @@ private: public: GLContext(Window &wnd, const GLOptions &opts = GLOptions()); + GLContext(Window &wnd, unsigned, unsigned); private: void platform_init(const GLOptions &); public: diff --git a/source/graphics/glx/glcontext.cpp b/source/graphics/glx/glcontext.cpp index 3ee8865..34daa08 100644 --- a/source/graphics/glx/glcontext.cpp +++ b/source/graphics/glx/glcontext.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "glcontext.h" #include "display_private.h" @@ -98,11 +99,32 @@ void GLContext::platform_init(const GLOptions &opts) priv->glxwnd = glXCreateWindow(dpy, fb_configs[0], priv->subwnd, 0); - if(opts.forward_compatible || opts.gl_version_major) + if(opts.forward_compatible || opts.gl_version_major!=GLOptions::DEFAULT_VERSION) { if(!extensions.count("GLX_ARB_create_context") || !extensions.count("GLX_ARB_get_proc_address")) throw unsupported_gl_mode(opts); + unsigned gl_version_major = opts.gl_version_major; + unsigned gl_version_minor = opts.gl_version_minor; + if(opts.gl_version_major==GLOptions::LATEST_VERSION) + { + ContextHandle probe_context = glXCreateNewContext(dpy, fb_configs[0], GLX_RGBA_TYPE, 0, true); + glXMakeContextCurrent(dpy, priv->glxwnd, priv->glxwnd, probe_context); + + const char *gl_ver_ptr = reinterpret_cast(glGetString(GL_VERSION)); + if(!gl_ver_ptr) + throw unsupported_gl_mode(opts); + + string gl_ver = gl_ver_ptr; + vector parts = split(gl_ver.substr(0, gl_ver.find(' ')), '.'); + + gl_version_major = lexical_cast(parts[0]); + gl_version_minor = lexical_cast(parts[1]); + + glXMakeContextCurrent(dpy, 0, 0, 0); + glXDestroyContext(dpy, probe_context); + } + vector ctx_attribs; ctx_attribs.push_back(GLX_RENDER_TYPE); @@ -123,9 +145,9 @@ void GLContext::platform_init(const GLOptions &opts) if(opts.gl_version_major) { ctx_attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); - ctx_attribs.push_back(opts.gl_version_major); + ctx_attribs.push_back(gl_version_major); ctx_attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); - ctx_attribs.push_back(opts.gl_version_minor); + ctx_attribs.push_back(gl_version_minor); } ctx_attribs.push_back(0); diff --git a/source/graphics/wgl/glcontext.cpp b/source/graphics/wgl/glcontext.cpp index 6808897..b0f685b 100644 --- a/source/graphics/wgl/glcontext.cpp +++ b/source/graphics/wgl/glcontext.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "glcontext.h" #include "window_private.h" @@ -53,7 +55,7 @@ void GLContext::platform_init(const GLOptions &opts) SetPixelFormat(dc, pf_index, &pfd); priv = new Private; - if(opts.forward_compatible || opts.gl_version_major) + if(opts.forward_compatible || opts.gl_version_major!=DEFAULT_VERSION) { ContextHandle fake_context = wglCreateContext(dc); wglMakeCurrent(dc, fake_context); @@ -62,6 +64,21 @@ void GLContext::platform_init(const GLOptions &opts) if(!wglCreateContextAttribs) throw unsupported_gl_mode(opts); + unsigned gl_version_major = opts.gl_version_major; + unsigned gl_version_minor = opts.gl_version_minor; + if(opts.gl_version_major==GLOptions::LATEST_VERSION) + { + const char *gl_ver_ptr = reinterpret_cast(glGetString(GL_VERSION)); + if(!gl_ver_ptr) + throw unsupported_gl_mode(opts); + + string gl_ver = gl_ver_ptr; + vector parts = split(gl_ver.substr(0, gl_ver.find(' ')), '.'); + + gl_version_major = lexical_cast(parts[0]); + gl_version_minor = lexical_cast(parts[1]); + } + vector ctx_attribs; if(opts.forward_compatible) @@ -79,9 +96,9 @@ void GLContext::platform_init(const GLOptions &opts) if(opts.gl_version_major) { ctx_attribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); - ctx_attribs.push_back(opts.gl_version_major); + ctx_attribs.push_back(gl_version_major); ctx_attribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); - ctx_attribs.push_back(opts.gl_version_minor); + ctx_attribs.push_back(gl_version_minor); } ctx_attribs.push_back(0);