summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video/opengl.cpp36
-rw-r--r--src/video/opengl.h9
-rw-r--r--src/video/win32_v.cpp8
3 files changed, 47 insertions, 6 deletions
diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp
index 4d759e60f..c811be2ef 100644
--- a/src/video/opengl.cpp
+++ b/src/video/opengl.cpp
@@ -32,6 +32,8 @@
/* static */ OpenGLBackend *OpenGLBackend::instance = nullptr;
+GetOGLProcAddressProc GetOGLProcAddress;
+
/**
* Find a substring in a string made of space delimited elements. The substring
* has to match the complete element, partial matches don't count.
@@ -65,7 +67,31 @@ static const char *FindStringInExtensionList(const char *string, const char *sub
*/
static bool IsOpenGLExtensionSupported(const char *extension)
{
- return FindStringInExtensionList((const char *)glGetString(GL_EXTENSIONS), extension) != nullptr;
+ static PFNGLGETSTRINGIPROC glGetStringi = nullptr;
+ static bool glGetStringi_loaded = false;
+
+ /* Starting with OpenGL 3.0 the preferred API to get the extensions
+ * has changed. Try to load the required function once. */
+ if (!glGetStringi_loaded) {
+ if (IsOpenGLVersionAtLeast(3, 0)) glGetStringi = (PFNGLGETSTRINGIPROC)GetOGLProcAddress("glGetStringi");
+ glGetStringi_loaded = true;
+ }
+
+ if (glGetStringi != nullptr) {
+ /* New style: Each supported extension can be queried and compared independently. */
+ GLint num_exts;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
+
+ for (GLint i = 0; i < num_exts; i++) {
+ const char *entry = (const char *)glGetStringi(GL_EXTENSIONS, i);
+ if (strcmp(entry, extension) == 0) return true;
+ }
+ } else {
+ /* Old style: A single, space-delimited string for all extensions. */
+ return FindStringInExtensionList((const char *)glGetString(GL_EXTENSIONS), extension) != nullptr;
+ }
+
+ return false;
}
static byte _gl_major_ver = 0; ///< Major OpenGL version.
@@ -78,7 +104,7 @@ static byte _gl_minor_ver = 0; ///< Minor OpenGL version.
* @pre OpenGL was initialized.
* @return True if the OpenGL version is equal or higher than the requested one.
*/
-static bool IsOpenGLVersionAtLeast(byte major, byte minor)
+bool IsOpenGLVersionAtLeast(byte major, byte minor)
{
return (_gl_major_ver > major) || (_gl_major_ver == major && _gl_minor_ver >= minor);
}
@@ -86,11 +112,15 @@ static bool IsOpenGLVersionAtLeast(byte major, byte minor)
/**
* Create and initialize the singleton back-end class.
+ * @param get_proc Callback to get an OpenGL function from the OS driver.
+ * @return nullptr on success, error message otherwise.
*/
-/* static */ const char *OpenGLBackend::Create()
+/* static */ const char *OpenGLBackend::Create(GetOGLProcAddressProc get_proc)
{
if (OpenGLBackend::instance != nullptr) OpenGLBackend::Destroy();
+ GetOGLProcAddress = get_proc;
+
OpenGLBackend::instance = new OpenGLBackend();
return OpenGLBackend::instance->Init();
}
diff --git a/src/video/opengl.h b/src/video/opengl.h
index 9db1be5f5..08ef56b9a 100644
--- a/src/video/opengl.h
+++ b/src/video/opengl.h
@@ -14,7 +14,12 @@
#include "../core/alloc_type.hpp"
-/** Platform-independent back-end singleton class for OpenGL video drivers. */
+typedef void (*OGLProc)();
+typedef OGLProc (*GetOGLProcAddressProc)(const char *proc);
+
+bool IsOpenGLVersionAtLeast(byte major, byte minor);
+
+/** Platform-independent back-end class for OpenGL video drivers. */
class OpenGLBackend : public ZeroedMemoryAllocator {
private:
static OpenGLBackend *instance; ///< Singleton instance pointer.
@@ -33,7 +38,7 @@ public:
{
return OpenGLBackend::instance;
}
- static const char *Create();
+ static const char *Create(GetOGLProcAddressProc get_proc);
static void Destroy();
bool Resize(int w, int h, bool force = false);
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index c97dccf44..ddfe365f7 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -1331,6 +1331,12 @@ void VideoDriver_Win32GDI::PaintThread()
# define PFD_SUPPORT_COMPOSITION 0x00008000
#endif
+/** Platform-specific callback to get an OpenGL funtion pointer. */
+static OGLProc GetOGLProcAddressCallback(const char *proc)
+{
+ return reinterpret_cast<OGLProc>(wglGetProcAddress(proc));
+}
+
static FVideoDriver_Win32OpenGL iFVideoDriver_Win32OpenGL;
const char *VideoDriver_Win32OpenGL::Start(const StringList &param)
@@ -1412,7 +1418,7 @@ const char *VideoDriver_Win32OpenGL::AllocateContext()
if (this->gl_rc == 0) return "Can't create OpenGL context";
if (!wglMakeCurrent(this->dc, this->gl_rc)) return "Can't active GL context";
- return OpenGLBackend::Create();
+ return OpenGLBackend::Create(&GetOGLProcAddressCallback);
}
bool VideoDriver_Win32OpenGL::ToggleFullscreen(bool full_screen)