#define GL_TEXTURE_3D 0x806F
#define GL_HALF_FLOAT 0x140B
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
#define GL_NUM_EXTENSIONS 0x821D
cvar_t r_shadow_bouncegrid_threaded = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_threaded", "1", "enables use of taskqueue_maxthreads to perform the traces and slice rendering of bouncegrid"};
cvar_t r_coronas = {CF_CLIENT | CF_ARCHIVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
cvar_t r_coronas_occlusionsizescale = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
-cvar_t r_coronas_occlusionquery = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility"};
+cvar_t r_coronas_occlusionquery = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility, requires OpenGL 4.4"};
cvar_t gl_flashblend = {CF_CLIENT | CF_ARCHIVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
cvar_t r_editlights = {CF_CLIENT, "r_editlights", "0", "enables .rtlights file editing mode"};
cvar_t r_editlights_cursordistance = {CF_CLIENT, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
{
case RENDERPATH_GL32:
case RENDERPATH_GLES2:
- usequery = r_coronas_occlusionquery.integer;
+ // buffer binding target GL_QUERY_BUFFER: Core since version 4.4
+ usequery = r_coronas_occlusionquery.integer && vid.support.glversion >= 44;
#ifndef USE_GLES2
if (usequery)
{
typedef struct viddef_support_s
{
+ int glversion; // this is at least 32
int glshaderversion; // this is at least 150 (GL 3.2)
qbool amd_texture_texture4;
qbool arb_texture_gather;
void VID_Shared_Init(void);
+void GL_InitFunctions(void);
void GL_Setup(void);
void VID_ClearExtensions(void);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+ /* Requesting a Core profile and 3.2 minimum is mandatory on macOS and older Mesa drivers.
+ * It works fine on other drivers too except NVIDIA, see HACK below.
+ */
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, (gl_debug.integer > 0 ? SDL_GL_CONTEXT_DEBUG_FLAG : 0));
return false;
}
+ GL_InitFunctions();
+
+#if !defined(USE_GLES2) && !defined(MACOSX)
+ // NVIDIA hates the Core profile and limits the version to the minimum we specified.
+ // HACK: to detect NVIDIA we first need a context, fortunately replacing it takes a few milliseconds
+ gl_vendor = (const char *)qglGetString(GL_VENDOR);
+ if (strncmp(gl_vendor, "NVIDIA", 6) == 0)
+ {
+ Con_DPrint("The Way It's Meant To Be Played: replacing OpenGL Core profile with Compatibility profile...\n");
+ SDL_GL_DeleteContext(context);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
+ context = SDL_GL_CreateContext(window);
+ if (context == NULL)
+ {
+ Con_Printf(CON_ERROR "Failed to initialize OpenGL context: %s\n", SDL_GetError());
+ VID_Shutdown();
+ return false;
+ }
+ }
+#endif
+
SDL_GL_SetSwapInterval(bound(-1, vid_vsync.integer, 1));
vid_usingvsync = (vid_vsync.integer != 0);
memset(&vid.support, 0, sizeof(vid.support));
}
-void GL_Setup(void)
+void GL_InitFunctions(void)
{
- char *s;
- int j;
- GLint numextensions = 0;
+#ifndef USE_GLES2
const glfunction_t *func;
qbool missingrequiredfuncs = false;
static char missingfuncs[16384];
-#ifndef USE_GLES2
// first fetch the function pointers for everything - after this we can begin making GL calls.
for (func = openglfuncs; func->name != NULL; func++)
*func->funcvariable = (void *)GL_GetProcAddress(func->name);
+
+ missingfuncs[0] = 0;
+ for (func = openglfuncs; func && func->name != NULL; func++)
+ {
+ if (!*func->funcvariable && !strcmp(func->extension, "core"))
+ {
+ Con_DPrintf("GL context is missing required function \"%s\"!\n", func->name);
+ missingrequiredfuncs = true;
+ strlcat(missingfuncs, " ", sizeof(missingfuncs));
+ strlcat(missingfuncs, func->name, sizeof(missingfuncs));
+ }
+ }
+
+ if (missingrequiredfuncs)
+ Sys_Error("OpenGL driver/hardware lacks required features:\n%s", missingfuncs);
#endif
+}
+
+void GL_Setup(void)
+{
+ char *s;
+ int j;
+ GLint numextensions = 0;
+ int majorv, minorv;
gl_renderer = (const char *)qglGetString(GL_RENDERER);
gl_vendor = (const char *)qglGetString(GL_VENDOR);
Con_Printf("GL_VERSION: %s\n", gl_version);
#ifndef USE_GLES2
+ qglGetIntegerv(GL_MAJOR_VERSION, &majorv);
+ qglGetIntegerv(GL_MINOR_VERSION, &minorv);
+ vid.support.glversion = 10 * majorv + minorv;
+ if (vid.support.glversion < 32)
+ // fallback, should never get here: GL context creation should have failed
+ Sys_Error("OpenGL driver/hardware supports version %i.%i but 3.2 is the minimum\n", majorv, minorv);
+
qglGetIntegerv(GL_NUM_EXTENSIONS, &numextensions);
Con_DPrint("GL_EXTENSIONS:\n");
for (j = 0; j < numextensions; j++)
Con_DPrint("\n");
#endif //USE_GLES2
-#ifndef USE_GLES2
- missingfuncs[0] = 0;
- for (func = openglfuncs; func && func->name != NULL; func++)
- {
- if (!*func->funcvariable && !strcmp(func->extension, "core"))
- {
- Con_DPrintf("GL context is missing required function \"%s\"!\n", func->name);
- missingrequiredfuncs = true;
- strlcat(missingfuncs, " ", sizeof(missingfuncs));
- strlcat(missingfuncs, func->name, sizeof(missingfuncs));
- }
- }
-
- if (missingrequiredfuncs)
- Sys_Error("OpenGL driver/hardware lacks required features:\n%s", missingfuncs);
-#endif
-
Con_DPrint("Checking OpenGL extensions...\n");
// detect what GLSL version is available, to enable features like higher quality reliefmapping