147 lines
4.1 KiB
C++
147 lines
4.1 KiB
C++
/*
|
|
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
|
* It is copyright by its individual contributors, as recorded in the
|
|
* project's Git history. See COPYING.txt at the top level for license
|
|
* terms and a link to the Git history.
|
|
*/
|
|
|
|
/* OpenGL extensions:
|
|
* We use global function pointer for any extension function we want to use.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <SDL.h>
|
|
|
|
#include "ogl_extensions.h"
|
|
#include "console.h"
|
|
|
|
#include "dxxsconf.h"
|
|
#include "dsx-ns.h"
|
|
#include <array>
|
|
|
|
namespace dcx {
|
|
|
|
/* GL_ARB_sync */
|
|
bool ogl_have_ARB_sync = false;
|
|
PFNGLFENCESYNCPROC glFenceSyncFunc = NULL;
|
|
PFNGLDELETESYNCPROC glDeleteSyncFunc = NULL;
|
|
PFNGLCLIENTWAITSYNCPROC glClientWaitSyncFunc = NULL;
|
|
|
|
/* GL_EXT_texture_filter_anisotropic */
|
|
GLfloat ogl_maxanisotropy = 0.0f;
|
|
|
|
namespace {
|
|
|
|
static std::array<long, 2> parse_version_str(const char *v)
|
|
{
|
|
std::array<long, 2> version;
|
|
version[0]=1;
|
|
version[1]=0;
|
|
if (v) {
|
|
char *ptr;
|
|
if (v[0] == 'O') {
|
|
// OpenGL ES uses the format "OpenGL ES-xx major.minor"
|
|
const auto &prefix_gles = "OpenGL ES-";
|
|
if (!strncmp(v, prefix_gles, sizeof(prefix_gles)-1)) {
|
|
// skip the prefix
|
|
v += sizeof(prefix_gles)-1;
|
|
// skip the profile marker
|
|
if (v[0] && v[1]) {
|
|
v +=2;
|
|
}
|
|
}
|
|
}
|
|
version[0]=strtol(v,&ptr,10);
|
|
if (ptr[0])
|
|
version[1]=strtol(ptr+1,NULL,10);
|
|
}
|
|
return version;
|
|
}
|
|
|
|
static bool is_ext_supported(const char *extensions, const char *name)
|
|
{
|
|
if (extensions && name) {
|
|
const char *found=strstr(extensions, name);
|
|
if (found) {
|
|
// check that the name is actually complete */
|
|
char c = found[strlen(name)];
|
|
if (c == ' ' || c == 0)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
enum support_mode {
|
|
NO_SUPPORT=0,
|
|
SUPPORT_CORE=1,
|
|
SUPPORT_EXT=2
|
|
};
|
|
|
|
static support_mode is_supported(const char *extensions, const std::array<long, 2> &version, const char *name, long major, long minor, long major_es, long minor_es)
|
|
{
|
|
#if DXX_USE_OGLES
|
|
static_cast<void>(major);
|
|
static_cast<void>(minor);
|
|
if ( (major_es > 0) && ((version[0] > major_es) || (version[0] == major_es && version[1] >= minor_es)) )
|
|
return SUPPORT_CORE;
|
|
#else
|
|
static_cast<void>(major_es);
|
|
static_cast<void>(minor_es);
|
|
if ( (major > 0) && ((version[0] > major) || (version[0] == major && version[1] >= minor)) )
|
|
return SUPPORT_CORE;
|
|
#endif
|
|
|
|
if (is_ext_supported(extensions, name))
|
|
return SUPPORT_EXT;
|
|
return NO_SUPPORT;
|
|
}
|
|
|
|
}
|
|
|
|
void ogl_extensions_init()
|
|
{
|
|
const auto version_str = reinterpret_cast<const char *>(glGetString(GL_VERSION));
|
|
if (!version_str) {
|
|
con_puts(CON_URGENT, "DXX-Rebirth: no valid OpenGL context when querying GL extensions!");
|
|
return;
|
|
}
|
|
const auto version = parse_version_str(version_str);
|
|
const auto extension_str = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
|
|
|
|
#if DXX_USE_OGLES
|
|
#define DXX_OGL_STRING " ES"
|
|
#else
|
|
#define DXX_OGL_STRING ""
|
|
#endif
|
|
con_printf(CON_VERBOSE, "DXX-Rebirth: OpenGL" DXX_OGL_STRING ": version %ld.%ld (%s)", version[0], version[1], version_str);
|
|
#undef DXX_OGL_STRING
|
|
|
|
/* GL_EXT_texture_filter_anisotropic */
|
|
if (is_supported(extension_str, version, "GL_EXT_texture_filter_anisotropic", -1, -1, -1, -1)) {
|
|
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ogl_maxanisotropy);
|
|
con_printf(CON_VERBOSE, "DXX-Rebirth: OpenGL: GL_EXT_texture_filter_anisotropic available, max anisotropy: %f", ogl_maxanisotropy);
|
|
} else {
|
|
ogl_maxanisotropy=0.0f;
|
|
con_puts(CON_VERBOSE, "DXX-Rebirth: OpenGL: GL_EXT_texture_filter_anisotropic not available");
|
|
}
|
|
|
|
/* GL_ARB_sync */
|
|
if (is_supported(extension_str, version, "GL_ARB_sync", 3, 2, 3, 0)) {
|
|
glFenceSyncFunc = reinterpret_cast<PFNGLFENCESYNCPROC>(SDL_GL_GetProcAddress("glFenceSync"));
|
|
glDeleteSyncFunc = reinterpret_cast<PFNGLDELETESYNCPROC>(SDL_GL_GetProcAddress("glDeleteSync"));
|
|
glClientWaitSyncFunc = reinterpret_cast<PFNGLCLIENTWAITSYNCPROC>(SDL_GL_GetProcAddress("glClientWaitSync"));
|
|
|
|
}
|
|
const char *s;
|
|
if (glFenceSyncFunc && glDeleteSyncFunc && glClientWaitSyncFunc) {
|
|
ogl_have_ARB_sync=true;
|
|
s = "DXX-Rebirth: OpenGL: GL_ARB_sync available";
|
|
} else {
|
|
s = "DXX-Rebirth: OpenGL: GL_ARB_sync not available";
|
|
}
|
|
con_puts(CON_VERBOSE, s);
|
|
}
|
|
|
|
}
|