]> git.tdb.fi Git - libs/gui.git/commitdiff
Add support for using the latest available OpenGL version
authorMikko Rasa <tdb@tdb.fi>
Mon, 25 Jan 2021 23:30:56 +0000 (01:30 +0200)
committerMikko Rasa <tdb@tdb.fi>
Mon, 25 Jan 2021 23:30:56 +0000 (01:30 +0200)
source/graphics/glcontext.cpp
source/graphics/glcontext.h
source/graphics/glx/glcontext.cpp
source/graphics/wgl/glcontext.cpp

index 0274c9e216bdd7065084b73f74cf69a6ce2077e0..ec073cb79c2c9928fc6dece00604807f2aa540dc 100644 (file)
@@ -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):
index ef6ef1b60f25989431e4d710c5916a84bdc64af1..f6357c3cce475513df04dc276a101d79bba42a15 100644 (file)
@@ -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:
index 3ee8865d7559e0890df797cb79ef893097f50847..34daa08d1ce1e022648626ac9279d1ab771e7f2a 100644 (file)
@@ -2,6 +2,7 @@
 #include <vector>
 #include <GL/glx.h>
 #include <GL/glxext.h>
+#include <msp/strings/lexicalcast.h>
 #include <msp/strings/utils.h>
 #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<const char *>(glGetString(GL_VERSION));
+                               if(!gl_ver_ptr)
+                                       throw unsupported_gl_mode(opts);
+
+                               string gl_ver = gl_ver_ptr;
+                               vector<string> parts = split(gl_ver.substr(0, gl_ver.find(' ')), '.');
+
+                               gl_version_major = lexical_cast<unsigned>(parts[0]);
+                               gl_version_minor = lexical_cast<unsigned>(parts[1]);
+
+                               glXMakeContextCurrent(dpy, 0, 0, 0);
+                               glXDestroyContext(dpy, probe_context);
+                       }
+
                        vector<int> 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);
index 68088970ac13cab32cd856a2a23980d838ad3bf7..b0f685b582a835e38b9639073c6da8564b855e32 100644 (file)
@@ -2,6 +2,8 @@
 #include <windows.h>
 #include <GL/gl.h>
 #include <GL/wglext.h>
+#include <msp/strings/lexicalcast.h>
+#include <msp/strings/utils.h>
 #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<const char *>(glGetString(GL_VERSION));
+                       if(!gl_ver_ptr)
+                               throw unsupported_gl_mode(opts);
+
+                       string gl_ver = gl_ver_ptr;
+                       vector<string> parts = split(gl_ver.substr(0, gl_ver.find(' ')), '.');
+
+                       gl_version_major = lexical_cast<unsigned>(parts[0]);
+                       gl_version_minor = lexical_cast<unsigned>(parts[1]);
+               }
+
                vector<int> 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);