Support OpenGL debugging features (see gl-debug).

Also fixed the GLX code not to call reset() on the temp context but on the real context instead.
This commit is contained in:
rdb 2014-06-20 13:17:01 +00:00
parent ef9f985406
commit 128f82863e
7 changed files with 390 additions and 159 deletions

View File

@ -337,6 +337,49 @@ CLP(GraphicsStateGuardian)::
}
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::debug_callback
// Access: Public, Static
// Description: This is called by the GL if an error occurs, if
// gl_debug has been enabled (and the driver supports
// the GL_ARB_debug_output extension).
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) {
// Determine how to map the severity level.
NotifySeverity level;
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH:
level = NS_error;
break;
case GL_DEBUG_SEVERITY_MEDIUM:
level = NS_warning;
break;
case GL_DEBUG_SEVERITY_LOW:
level = NS_info;
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
level = NS_debug;
break;
default:
level = NS_fatal; //???
break;
}
string msg_str(message, length);
GLCAT.out(level) << msg_str << "\n";
#ifndef NDEBUG
if (level >= gl_debug_abort_level.get_value()) {
abort();
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::reset
// Access: Public, Virtual
@ -386,10 +429,65 @@ reset() {
}
// Save the extensions tokens.
_extensions.clear();
save_extensions((const char *)glGetString(GL_EXTENSIONS));
get_extra_extensions();
report_extensions();
// Initialize OpenGL debugging output first, if enabled and supported.
if (gl_debug) {
bool supports_debug = false;
PFNGLDEBUGMESSAGECALLBACKPROC _glDebugMessageCallback;
PFNGLDEBUGMESSAGECONTROLPROC _glDebugMessageControl;
if (is_at_least_gl_version(4, 3) || has_extension("GL_KHR_debug")) {
#ifdef OPENGLES
_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)
get_extension_func("glDebugMessageCallbackKHR");
_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)
get_extension_func("glDebugMessageControlKHR");
#else
_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)
get_extension_func("glDebugMessageCallback");
_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)
get_extension_func("glDebugMessageControl");
#endif
glEnable(GL_DEBUG_OUTPUT); // Not supported in ARB version
supports_debug = true;
} else if (has_extension("GL_ARB_debug_output")) {
_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)
get_extension_func("glDebugMessageCallbackARB");
_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)
get_extension_func("glDebugMessageControlARB");
supports_debug = true;
}
if (supports_debug) {
// Set the categories we want to listen to.
_glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH,
0, NULL, GLCAT.is_error());
_glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM,
0, NULL, GLCAT.is_warning());
_glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW,
0, NULL, GLCAT.is_info());
_glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION,
0, NULL, GLCAT.is_debug());
// Enable the callback.
_glDebugMessageCallback(&debug_callback, (void*)this);
if (gl_debug_synchronous) {
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
GLCAT.error() << "gl-debug enabled.\n";
} else {
GLCAT.error() << "gl-debug enabled, but NOT supported.\n";
}
} else {
GLCAT.debug() << "gl-debug NOT enabled.\n";
}
_supported_geom_rendering =
Geom::GR_indexed_point |
Geom::GR_point | Geom::GR_point_uniform_size |
@ -634,7 +732,6 @@ reset() {
}
#endif
_cube_map_seamless = false;
#ifdef OPENGLES_2
_supports_cube_map = true;
#else
@ -644,7 +741,7 @@ reset() {
if (_supports_cube_map && gl_cube_map_seamless) {
if (is_at_least_gl_version(3, 2) || has_extension("GL_ARB_seamless_cube_map")) {
_cube_map_seamless = true;
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
}
#endif
@ -2235,10 +2332,6 @@ begin_frame(Thread *current_thread) {
}
#endif // NDEBUG
if (_cube_map_seamless) {
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
if (_current_properties->get_srgb_color()) {
glEnable(GL_FRAMEBUFFER_SRGB);
}

View File

@ -55,6 +55,9 @@ typedef double GLdouble;
// functions are defined, and the system gl.h sometimes doesn't
// declare these typedefs.
#if !defined( __EDG__ ) || defined( __INTEL_COMPILER ) // Protect the following from the Tau instrumentor and expose it for the intel compiler.
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
@ -196,6 +199,8 @@ public:
virtual int get_driver_shader_version_major();
virtual int get_driver_shader_version_minor();
static void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
virtual void reset();
virtual void prepare_display_region(DisplayRegionPipelineReader *dr);
@ -543,6 +548,7 @@ protected:
int _gl_version_major, _gl_version_minor;
//#--- Zhao Nov/2011
int _gl_shadlang_ver_major, _gl_shadlang_ver_minor;
pset<string> _extensions;
public:
@ -582,7 +588,6 @@ public:
PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC _glCompressedTexSubImage3D;
PFNGLGETCOMPRESSEDTEXIMAGEPROC _glGetCompressedTexImage;
bool _cube_map_seamless;
bool _supports_bgr;
bool _supports_rescale_normal;

View File

@ -126,6 +126,31 @@ ConfigVariableEnum<GeomEnums::UsageHint> gl_min_buffer_usage_hint
"of reusing the same buffers. Consider increasing "
"released-vbuffer-cache-size instead."));
ConfigVariableBool gl_debug
("gl-debug", false,
PRC_DESC("Setting this to true will cause OpenGL to emit more useful "
"error and debug messages, at a slight runtime performance cost. "
"notify-level-glgsg controls which severity levels are shown."));
ConfigVariableBool gl_debug_synchronous
("gl-debug-synchronous", false,
PRC_DESC("Set this true to make sure that the errors generated by "
"gl-debug are reported as soon as they happen. This is "
"highly recommended if you want to attach a debugger since "
"the call stack may otherwise not point to the GL call "
"where the error originated."));
ConfigVariableEnum<NotifySeverity> gl_debug_abort_level
("gl-debug-abort-level", NS_fatal,
PRC_DESC("Set this to a setting other than 'fatal' to cause an "
"abort to be triggered when an error of the indicated "
"severity level (or a more severe one) occurs. This is "
"useful if you want to attach a debugger. If you set this, "
"it is highly recommended to also set gl-debug-synchronous, "
"since the call stack will otherwise not point to the GL call "
"that triggered the error message. "
"This feature is not available when NDEBUG has been defined."));
ConfigVariableBool gl_debug_buffers
("gl-debug-buffers", false,
PRC_DESC("Set this true, in addition to enabling debug notify for "

View File

@ -55,6 +55,9 @@ extern ConfigVariableBool gl_interleaved_arrays;
extern ConfigVariableBool gl_parallel_arrays;
extern ConfigVariableInt gl_max_errors;
extern ConfigVariableEnum<GeomEnums::UsageHint> gl_min_buffer_usage_hint;
extern ConfigVariableBool gl_debug;
extern ConfigVariableBool gl_debug_synchronous;
extern ConfigVariableEnum<NotifySeverity> gl_debug_abort_level;
extern ConfigVariableBool gl_debug_buffers;
extern ConfigVariableBool gl_finish;
extern ConfigVariableBool gl_force_depth_stencil;

View File

@ -2398,6 +2398,50 @@ extern "C" {
#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
#endif
#ifndef GL_KHR_debug
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
#define GL_DEBUG_SOURCE_API 0x8246
#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
#define GL_DEBUG_SOURCE_APPLICATION 0x824A
#define GL_DEBUG_SOURCE_OTHER 0x824B
#define GL_DEBUG_TYPE_ERROR 0x824C
#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
#define GL_DEBUG_TYPE_PORTABILITY 0x824F
#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
#define GL_DEBUG_TYPE_OTHER 0x8251
#define GL_DEBUG_TYPE_MARKER 0x8268
#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
#define GL_DEBUG_TYPE_POP_GROUP 0x826A
#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
#define GL_BUFFER 0x82E0
#define GL_SHADER 0x82E1
#define GL_PROGRAM 0x82E2
#define GL_QUERY 0x82E3
#define GL_PROGRAM_PIPELINE 0x82E4
#define GL_SAMPLER 0x82E6
#define GL_DISPLAY_LIST 0x82E7
/* DISPLAY_LIST used in compatibility profile only */
#define GL_MAX_LABEL_LENGTH 0x82E8
#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
#define GL_DEBUG_LOGGED_MESSAGES 0x9145
#define GL_DEBUG_SEVERITY_HIGH 0x9146
#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
#define GL_DEBUG_SEVERITY_LOW 0x9148
#define GL_DEBUG_OUTPUT 0x92E0
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
/* reuse GL_STACK_UNDERFLOW */
/* reuse GL_STACK_OVERFLOW */
#endif
#ifndef GL_ARB_compute_shader
#define GL_COMPUTE_SHADER 0x91B9
#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
@ -5597,6 +5641,10 @@ typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLen
typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
#endif
#ifndef GL_KHR_debug
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
#endif
#ifndef GL_NV_vdpau_interop
typedef GLintptr GLvdpauSurfaceNV;
#endif
@ -7903,6 +7951,32 @@ typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum ta
typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
#endif
#ifndef GL_KHR_debug
#define GL_KHR_debug 1
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
GLAPI void APIENTRY glPopDebugGroup (void);
GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
#endif /* GL_GLEXT_PROTOTYPES */
typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
#endif
#ifndef GL_ARB_compute_shader
#define GL_ARB_compute_shader 1
#ifdef GL_GLEXT_PROTOTYPES

View File

@ -295,6 +295,11 @@ choose_pixel_format(const FrameBufferProperties &properties,
int best_result = 0;
FrameBufferProperties best_props;
int render_type = GLX_RGBA_TYPE;
if (properties.get_indexed_color()) {
render_type = GLX_COLOR_INDEX_TYPE;
}
static const int max_attrib_list = 32;
int attrib_list[max_attrib_list];
int n = 0;
@ -324,7 +329,8 @@ choose_pixel_format(const FrameBufferProperties &properties,
const char *pixmaptext = context_has_pixmap ? " (pixmap)" : "";
const char *slowtext = slow ? " (slow)" : "";
glxdisplay_cat.debug()
<< i << ": " << fbprops << " quality=" << quality << pbuffertext << pixmaptext << slowtext << "\n";
<< i << ": " << fbprops << " quality=" << quality << pbuffertext
<< pixmaptext << slowtext << "\n";
}
if (need_pbuffer && !context_has_pbuffer) {
continue;
@ -343,10 +349,29 @@ choose_pixel_format(const FrameBufferProperties &properties,
if (best_quality > 0) {
_fbconfig = configs[best_result];
if (_glXCreateContextAttribs != NULL) {
// NB. This is a wholly different type of attrib list
// than below, the same values are not used!
n = 0;
attrib_list[n++] = GLX_RENDER_TYPE;
attrib_list[n++] = render_type;
if (gl_debug) {
attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB;
attrib_list[n++] = GLX_CONTEXT_DEBUG_BIT_ARB;
}
attrib_list[n] = None;
_context = _glXCreateContextAttribs(_display, _fbconfig, _share_context,
GL_TRUE, attrib_list);
} else {
_context =
_glXCreateNewContext(_display, _fbconfig, GLX_RGBA_TYPE, _share_context,
_glXCreateNewContext(_display, _fbconfig, render_type, _share_context,
GL_TRUE);
}
if (_context) {
mark_new();
if (_visuals != (XVisualInfo *)NULL) {
XFree(_visuals);
_visuals = NULL;
@ -398,150 +423,6 @@ choose_pixel_format(const FrameBufferProperties &properties,
_context_has_pbuffer = false;
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsStateGuardian::reset
// Access: Public, Virtual
// Description: Resets all internal state as if the gsg were newly
// created.
////////////////////////////////////////////////////////////////////
void glxGraphicsStateGuardian::
reset() {
PosixGraphicsStateGuardian::reset();
_supports_swap_control = has_extension("GLX_SGI_swap_control");
if (_supports_swap_control) {
_glXSwapIntervalSGI =
(PFNGLXSWAPINTERVALSGIPROC)get_extension_func("glXSwapIntervalSGI");
if (_glXSwapIntervalSGI == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
_supports_swap_control = false;
}
}
if (_supports_swap_control) {
// Set the video-sync setting up front, if we have the extension
// that supports it.
_glXSwapIntervalSGI(sync_video ? 1 : 0);
}
if (glx_support_fbconfig) {
if (glx_is_at_least_version(1, 3)) {
// If we have glx 1.3 or better, we have the FBConfig interface.
_supports_fbconfig = true;
_glXChooseFBConfig =
(PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfig");
_glXCreateNewContext =
(PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateNewContext");
_glXGetVisualFromFBConfig =
(PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfig");
_glXGetFBConfigAttrib =
(PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttrib");
_glXCreatePixmap =
(PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreatePixmap");
if (_glXChooseFBConfig == NULL ||
_glXCreateNewContext == NULL ||
_glXGetVisualFromFBConfig == NULL ||
_glXGetFBConfigAttrib == NULL ||
_glXCreatePixmap == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
_supports_fbconfig = false;
}
} else if (has_extension("GLX_SGIX_fbconfig")) {
// Or maybe we have the old SGIX extension for FBConfig. This is
// the same, but the function names are different--we just remap
// them to the same function pointers.
_supports_fbconfig = true;
_glXChooseFBConfig =
(PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfigSGIX");
_glXCreateNewContext =
(PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateContextWithConfigSGIX");
_glXGetVisualFromFBConfig =
(PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfigSGIX");
_glXGetFBConfigAttrib =
(PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttribSGIX");
_glXCreatePixmap =
(PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreateGLXPixmapWithConfigSGIX");
if (_glXChooseFBConfig == NULL ||
_glXCreateNewContext == NULL ||
_glXGetVisualFromFBConfig == NULL ||
_glXGetFBConfigAttrib == NULL ||
_glXCreatePixmap == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
_supports_fbconfig = false;
}
}
if (glx_is_at_least_version(1, 3)) {
// If we have glx 1.3 or better, we have the PBuffer interface.
_supports_pbuffer = true;
_uses_sgix_pbuffer = false;
_glXCreatePbuffer =
(PFNGLXCREATEPBUFFERPROC)get_extension_func("glXCreatePbuffer");
_glXCreateGLXPbufferSGIX = NULL;
_glXDestroyPbuffer =
(PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyPbuffer");
if (_glXCreatePbuffer == NULL ||
_glXDestroyPbuffer == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
_supports_pbuffer = false;
}
} else if (has_extension("GLX_SGIX_pbuffer")) {
// Or maybe we have the old SGIX extension for PBuffers.
_uses_sgix_pbuffer = true;
// CreatePbuffer has a different form between SGIX and 1.3,
// however, so we must treat it specially. But we can use the
// same function pointer for DestroyPbuffer.
_glXCreatePbuffer = NULL;
_glXCreateGLXPbufferSGIX =
(PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func("glXCreateGLXPbufferSGIX");
_glXDestroyPbuffer =
(PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyGLXPbufferSGIX");
if (_glXCreateGLXPbufferSGIX == NULL ||
_glXDestroyPbuffer == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
_supports_pbuffer = false;
}
}
}
if (glxdisplay_cat.is_debug()) {
glxdisplay_cat.debug()
<< "supports_swap_control = " << _supports_swap_control << "\n";
glxdisplay_cat.debug()
<< "supports_fbconfig = " << _supports_fbconfig << "\n";
glxdisplay_cat.debug()
<< "supports_pbuffer = " << _supports_pbuffer
<< " sgix = " << _uses_sgix_pbuffer << "\n";
}
// If "Mesa" is present, assume software. However, if "Mesa DRI" is
// found, it's actually a Mesa-based OpenGL layer running over a
// hardware driver.
if (_gl_renderer.find("Mesa") != string::npos &&
_gl_renderer.find("Mesa DRI") == string::npos) {
// It's Mesa, therefore probably a software context.
_fbprops.set_force_software(1);
_fbprops.set_force_hardware(0);
} else {
_fbprops.set_force_hardware(1);
_fbprops.set_force_software(0);
}
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsStateGuardian::glx_is_at_least_version
// Access: Public
@ -692,6 +573,153 @@ do_get_extension_func(const char *name) {
return PosixGraphicsStateGuardian::do_get_extension_func(name);
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsStateGuardian::query_glx_extensions
// Access: Private
// Description: Queries the GLX extension pointers.
////////////////////////////////////////////////////////////////////
void glxGraphicsStateGuardian::
query_glx_extensions() {
_supports_swap_control = has_extension("GLX_SGI_swap_control");
if (_supports_swap_control) {
_glXSwapIntervalSGI =
(PFNGLXSWAPINTERVALSGIPROC)get_extension_func("glXSwapIntervalSGI");
if (_glXSwapIntervalSGI == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
_supports_swap_control = false;
}
}
if (_supports_swap_control) {
// Set the video-sync setting up front, if we have the extension
// that supports it.
_glXSwapIntervalSGI(sync_video ? 1 : 0);
}
if (glx_support_fbconfig) {
if (glx_is_at_least_version(1, 3)) {
// If we have glx 1.3 or better, we have the FBConfig interface.
_supports_fbconfig = true;
_glXChooseFBConfig =
(PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfig");
_glXCreateNewContext =
(PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateNewContext");
_glXGetVisualFromFBConfig =
(PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfig");
_glXGetFBConfigAttrib =
(PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttrib");
_glXCreatePixmap =
(PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreatePixmap");
if (_glXChooseFBConfig == NULL ||
_glXCreateNewContext == NULL ||
_glXGetVisualFromFBConfig == NULL ||
_glXGetFBConfigAttrib == NULL ||
_glXCreatePixmap == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
_supports_fbconfig = false;
}
} else if (has_extension("GLX_SGIX_fbconfig")) {
// Or maybe we have the old SGIX extension for FBConfig. This is
// the same, but the function names are different--we just remap
// them to the same function pointers.
_supports_fbconfig = true;
_glXChooseFBConfig =
(PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfigSGIX");
_glXCreateNewContext =
(PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateContextWithConfigSGIX");
_glXGetVisualFromFBConfig =
(PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfigSGIX");
_glXGetFBConfigAttrib =
(PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttribSGIX");
_glXCreatePixmap =
(PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreateGLXPixmapWithConfigSGIX");
if (_glXChooseFBConfig == NULL ||
_glXCreateNewContext == NULL ||
_glXGetVisualFromFBConfig == NULL ||
_glXGetFBConfigAttrib == NULL ||
_glXCreatePixmap == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
_supports_fbconfig = false;
}
}
if (glx_is_at_least_version(1, 3)) {
// If we have glx 1.3 or better, we have the PBuffer interface.
_supports_pbuffer = true;
_uses_sgix_pbuffer = false;
_glXCreatePbuffer =
(PFNGLXCREATEPBUFFERPROC)get_extension_func("glXCreatePbuffer");
_glXCreateGLXPbufferSGIX = NULL;
_glXDestroyPbuffer =
(PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyPbuffer");
if (_glXCreatePbuffer == NULL ||
_glXDestroyPbuffer == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
_supports_pbuffer = false;
}
} else if (has_extension("GLX_SGIX_pbuffer")) {
// Or maybe we have the old SGIX extension for PBuffers.
_uses_sgix_pbuffer = true;
// CreatePbuffer has a different form between SGIX and 1.3,
// however, so we must treat it specially. But we can use the
// same function pointer for DestroyPbuffer.
_glXCreatePbuffer = NULL;
_glXCreateGLXPbufferSGIX =
(PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func("glXCreateGLXPbufferSGIX");
_glXDestroyPbuffer =
(PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyGLXPbufferSGIX");
if (_glXCreateGLXPbufferSGIX == NULL ||
_glXDestroyPbuffer == NULL) {
glxdisplay_cat.error()
<< "Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
_supports_pbuffer = false;
}
}
if (has_extension("GLX_ARB_create_context")) {
_glXCreateContextAttribs =
(PFNGLXCREATECONTEXTATTRIBSARBPROC)get_extension_func("glXCreateContextAttribsARB");
} else {
_glXCreateContextAttribs = NULL;
}
}
if (glxdisplay_cat.is_debug()) {
glxdisplay_cat.debug()
<< "supports_swap_control = " << _supports_swap_control << "\n";
glxdisplay_cat.debug()
<< "supports_fbconfig = " << _supports_fbconfig << "\n";
glxdisplay_cat.debug()
<< "supports_pbuffer = " << _supports_pbuffer
<< " sgix = " << _uses_sgix_pbuffer << "\n";
}
// If "Mesa" is present, assume software. However, if "Mesa DRI" is
// found, it's actually a Mesa-based OpenGL layer running over a
// hardware driver.
if (_gl_renderer.find("Mesa") != string::npos &&
_gl_renderer.find("Mesa DRI") == string::npos) {
// It's Mesa, therefore probably a software context.
_fbprops.set_force_software(1);
_fbprops.set_force_hardware(0);
} else {
_fbprops.set_force_hardware(1);
_fbprops.set_force_software(0);
}
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsStateGuardian::show_glx_client_string
// Access: Protected
@ -814,8 +842,11 @@ init_temp_context() {
return;
}
// Now use it to query the available GLX features.
glXMakeCurrent(_display, _temp_xwindow, _temp_context);
reset();
query_gl_version();
get_extra_extensions();
query_glx_extensions();
}
////////////////////////////////////////////////////////////////////

View File

@ -67,7 +67,7 @@ typedef int (* PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig confi
typedef GLXPixmap (* PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
typedef GLXPbuffer (* PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list);
typedef void (* PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf);
typedef GLXContext ( *PFNGLXCREATECONTEXTATTRIBSARBPROC) (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
#endif // __EDG__
////////////////////////////////////////////////////////////////////
@ -92,8 +92,6 @@ public:
virtual ~glxGraphicsStateGuardian();
virtual void reset();
bool glx_is_at_least_version(int major_version, int minor_version) const;
GLXContext _share_context;
@ -119,6 +117,7 @@ public:
PFNGLXGETVISUALFROMFBCONFIGPROC _glXGetVisualFromFBConfig;
PFNGLXGETFBCONFIGATTRIBPROC _glXGetFBConfigAttrib;
PFNGLXCREATEPIXMAPPROC _glXCreatePixmap;
PFNGLXCREATECONTEXTATTRIBSARBPROC _glXCreateContextAttribs;
bool _supports_pbuffer; // true if the interface is available.
bool _uses_sgix_pbuffer;
@ -135,6 +134,7 @@ protected:
virtual void *do_get_extension_func(const char *name);
private:
void query_glx_extensions();
void show_glx_client_string(const string &name, int id);
void show_glx_server_string(const string &name, int id);
void choose_temp_visual(const FrameBufferProperties &properties);