mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-03-21 18:21:08 +00:00
Add r_glDebugContext to enable OpenGL debug context and -callback
needs SDL2 and GL_ARB_debug_output
This commit is contained in:
parent
47bd8afa91
commit
69e121727d
5 changed files with 122 additions and 3 deletions
|
@ -78,6 +78,7 @@ typedef struct glconfig_s {
|
|||
bool twoSidedStencilAvailable;
|
||||
bool textureNonPowerOfTwoAvailable;
|
||||
bool depthBoundsTestAvailable;
|
||||
bool glDebugOutputAvailable;
|
||||
|
||||
// GL framebuffer size, see also winWidth and winHeight
|
||||
int vidWidth, vidHeight; // passed to R_BeginFrame
|
||||
|
@ -95,6 +96,8 @@ typedef struct glconfig_s {
|
|||
bool shouldFillWindowAlpha;
|
||||
bool isWayland; // DG: for other wayland-specific hacks.. (does *not* detect XWayland!)
|
||||
|
||||
bool haveDebugContext;
|
||||
|
||||
// For some reason people decided that we need displays with ultra small pixels,
|
||||
// so everything rendered on them must be scaled up to be legible.
|
||||
// unfortunately, this bullshit feature was "improved" upon by deciding that the best
|
||||
|
|
|
@ -239,6 +239,8 @@ idCVar r_screenshotPngCompression("r_screenshotPngCompression", "3", CVAR_RENDER
|
|||
idCVar r_windowResizable("r_windowResizable", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Allow resizing (and maximizing) the window (needs SDL2; with 2.0.5 or newer it's applied immediately)" );
|
||||
idCVar r_vidRestartAlwaysFull( "r_vidRestartAlwaysFull", 0, CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Always do a full vid_restart (ignore 'partial' argument), e.g. when changing window size" );
|
||||
|
||||
idCVar r_glDebugContext( "r_glDebugContext", "0", CVAR_RENDERER | CVAR_BOOL, "Enable OpenGL Debug context - requires vid_restart, needs SDL2" );
|
||||
|
||||
// define qgl functions
|
||||
#define QGLPROC(name, rettype, args) rettype (APIENTRYP q##name) args;
|
||||
#include "renderer/qgl_proc.h"
|
||||
|
@ -288,6 +290,9 @@ PFNGLDEPTHBOUNDSEXTPROC qglDepthBoundsEXT;
|
|||
// DG: couldn't find any extension for this, it's supported in GL2.0 and newer, incl OpenGL ES2.0
|
||||
PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;
|
||||
|
||||
// GL_ARB_debug_output
|
||||
PFNGLDEBUGMESSAGECALLBACKARBPROC qglDebugMessageCallbackARB;
|
||||
|
||||
// eez: This is a slight hack for letting us select the desired screenshot format in other functions
|
||||
// This is a hack to avoid adding another function parameter to idRenderSystem::TakeScreenshot(),
|
||||
// which would break the API of the dhewm3 SDK for mods.
|
||||
|
@ -296,6 +301,60 @@ PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;
|
|||
// it must set g_screenshotFormat accordingly before each call to TakeScreenshot().
|
||||
int g_screenshotFormat = -1;
|
||||
|
||||
enum {
|
||||
// Not all GL.h header know about GL_DEBUG_SEVERITY_NOTIFICATION_*.
|
||||
QGL_DEBUG_SEVERITY_NOTIFICATION = 0x826B
|
||||
};
|
||||
|
||||
/*
|
||||
* Callback function for debug output.
|
||||
*/
|
||||
static void APIENTRY
|
||||
DebugCallback( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
|
||||
const GLchar *message, const void *userParam )
|
||||
{
|
||||
const char* sourceStr = "Source: Unknown";
|
||||
const char* typeStr = "Type: Unknown";
|
||||
const char* severityStr = "Severity: Unknown";
|
||||
|
||||
switch (severity)
|
||||
{
|
||||
#define SVRCASE(X, STR) case GL_DEBUG_SEVERITY_ ## X ## _ARB : severityStr = STR; break;
|
||||
case QGL_DEBUG_SEVERITY_NOTIFICATION: return;
|
||||
SVRCASE(HIGH, "Severity: High")
|
||||
SVRCASE(MEDIUM, "Severity: Medium")
|
||||
SVRCASE(LOW, "Severity: Low")
|
||||
#undef SVRCASE
|
||||
}
|
||||
|
||||
switch (source)
|
||||
{
|
||||
#define SRCCASE(X) case GL_DEBUG_SOURCE_ ## X ## _ARB: sourceStr = "Source: " #X; break;
|
||||
SRCCASE(API);
|
||||
SRCCASE(WINDOW_SYSTEM);
|
||||
SRCCASE(SHADER_COMPILER);
|
||||
SRCCASE(THIRD_PARTY);
|
||||
SRCCASE(APPLICATION);
|
||||
SRCCASE(OTHER);
|
||||
#undef SRCCASE
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
#define TYPECASE(X) case GL_DEBUG_TYPE_ ## X ## _ARB: typeStr = "Type: " #X; break;
|
||||
TYPECASE(ERROR);
|
||||
TYPECASE(DEPRECATED_BEHAVIOR);
|
||||
TYPECASE(UNDEFINED_BEHAVIOR);
|
||||
TYPECASE(PORTABILITY);
|
||||
TYPECASE(PERFORMANCE);
|
||||
TYPECASE(OTHER);
|
||||
#undef TYPECASE
|
||||
}
|
||||
|
||||
common->Warning( "GLDBG %s %s %s: %s\n", sourceStr, typeStr, severityStr, message );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CheckExtension
|
||||
|
@ -415,15 +474,15 @@ static void R_CheckPortableExtensions( void ) {
|
|||
qglActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)GLimp_ExtensionPointer( "glActiveStencilFaceEXT" );
|
||||
|
||||
if( glConfig.glVersion >= 2.0) {
|
||||
common->Printf( "... got GL2.0+ glStencilOpSeparate()\n" );
|
||||
common->Printf( "...got GL2.0+ glStencilOpSeparate()\n" );
|
||||
qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)GLimp_ExtensionPointer( "glStencilOpSeparate" );
|
||||
} else if( R_CheckExtension( "GL_ATI_separate_stencil" ) ) {
|
||||
common->Printf( "... got glStencilOpSeparateATI() (GL_ATI_separate_stencil)\n" );
|
||||
common->Printf( "...got glStencilOpSeparateATI() (GL_ATI_separate_stencil)\n" );
|
||||
// the ATI version of glStencilOpSeparate() has the same signature and should also
|
||||
// behave identical to the GL2 version (in Mesa3D it's just an alias)
|
||||
qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)GLimp_ExtensionPointer( "glStencilOpSeparateATI" );
|
||||
} else {
|
||||
common->Printf( "... don't have glStencilOpSeparateATI() or (GL2.0+) glStencilOpSeparate()\n" );
|
||||
common->Printf( "X..don't have glStencilOpSeparateATI() or (GL2.0+) glStencilOpSeparate()\n" );
|
||||
qglStencilOpSeparate = NULL;
|
||||
}
|
||||
|
||||
|
@ -482,6 +541,37 @@ static void R_CheckPortableExtensions( void ) {
|
|||
qglDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)GLimp_ExtensionPointer( "glDepthBoundsEXT" );
|
||||
}
|
||||
|
||||
// GL_ARB_debug_output
|
||||
glConfig.glDebugOutputAvailable = false;
|
||||
if ( glConfig.haveDebugContext ) {
|
||||
if ( strstr( glConfig.extensions_string, "GL_ARB_debug_output" ) ) {
|
||||
glConfig.glDebugOutputAvailable = true;
|
||||
qglDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)GLimp_ExtensionPointer( "glDebugMessageCallbackARB" );
|
||||
if ( r_glDebugContext.GetBool() ) {
|
||||
common->Printf( "...using GL_ARB_debug_output (r_glDebugContext is set)\n" );
|
||||
qglDebugMessageCallbackARB(DebugCallback, NULL);
|
||||
qglEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
} else {
|
||||
common->Printf( "...found GL_ARB_debug_output, but not using it (r_glDebugContext is not set)\n" );
|
||||
}
|
||||
} else {
|
||||
common->Printf( "X..GL_ARB_debug_output not found\n" );
|
||||
qglDebugMessageCallbackARB = NULL;
|
||||
if ( r_glDebugContext.GetBool() ) {
|
||||
common->Warning( "r_glDebugContext is set, but can't be used because GL_ARB_debug_output is not supported" );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( strstr( glConfig.extensions_string, "GL_ARB_debug_output" ) ) {
|
||||
if ( r_glDebugContext.GetBool() ) {
|
||||
common->Printf( "...found GL_ARB_debug_output, but not using it (no debug context)\n" );
|
||||
} else {
|
||||
common->Printf( "...found GL_ARB_debug_output, but not using it (r_glDebugContext is not set)\n" );
|
||||
}
|
||||
} else {
|
||||
common->Printf( "X..GL_ARB_debug_output not found\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC qglProgramLocalParameter4fvARB;
|
|||
// GL_EXT_depth_bounds_test
|
||||
extern PFNGLDEPTHBOUNDSEXTPROC qglDepthBoundsEXT;
|
||||
|
||||
// GL_ARB_debug_output
|
||||
extern PFNGLDEBUGMESSAGECALLBACKARBPROC qglDebugMessageCallbackARB;
|
||||
|
||||
#if defined( _WIN32 ) && defined(ID_ALLOW_TOOLS)
|
||||
|
||||
extern BOOL(WINAPI * qwglSwapBuffers)(HDC);
|
||||
|
|
|
@ -983,6 +983,8 @@ extern idCVar r_materialOverride; // override all materials
|
|||
|
||||
extern idCVar r_debugRenderToTexture;
|
||||
|
||||
extern idCVar r_glDebugContext;
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
|
|
|
@ -279,6 +279,11 @@ try_again:
|
|||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
||||
if ( r_glDebugContext.GetBool() ) {
|
||||
common->Printf( "Requesting an OpenGL Debug Context (r_glDebugContext is enabled)\n" );
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
}
|
||||
|
||||
if ( parms.fullScreen && parms.fullScreenDesktop ) {
|
||||
common->Printf( "Will create a pseudo-fullscreen window at the current desktop resolution\n" );
|
||||
} else {
|
||||
|
@ -435,6 +440,10 @@ try_again:
|
|||
if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, r_swapInterval.GetInteger()) < 0)
|
||||
common->Warning("SDL_GL_SWAP_CONTROL not supported");
|
||||
|
||||
if ( r_glDebugContext.GetBool() ) {
|
||||
common->Warning( "r_glDebugContext is set, but not supported by SDL1.2!\n" );
|
||||
}
|
||||
|
||||
r_swapInterval.ClearModified();
|
||||
|
||||
window = SDL_SetVideoMode(parms.width, parms.height, colorbits, flags);
|
||||
|
@ -588,6 +597,18 @@ try_again:
|
|||
}
|
||||
#endif
|
||||
|
||||
glConfig.haveDebugContext = false;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
int cflags = 0;
|
||||
if ( SDL_GL_GetAttribute( SDL_GL_CONTEXT_FLAGS, &cflags ) == 0 ) {
|
||||
glConfig.haveDebugContext = (cflags & SDL_GL_CONTEXT_DEBUG_FLAG) != 0;
|
||||
if ( glConfig.haveDebugContext )
|
||||
common->Printf( "Got a debug context!\n" );
|
||||
else if( r_glDebugContext.GetBool() ) {
|
||||
common->Warning( "Requested a debug context, but didn't get one!\n" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue