diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 39c2dd3edd..cc63b1177e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -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); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 39803d4d7c..4f7cc182d2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -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 _extensions; public: @@ -582,7 +588,6 @@ public: PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC _glCompressedTexSubImage3D; PFNGLGETCOMPRESSEDTEXIMAGEPROC _glGetCompressedTexImage; - bool _cube_map_seamless; bool _supports_bgr; bool _supports_rescale_normal; diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 0562a97434..0b9bcff9d7 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -126,6 +126,31 @@ ConfigVariableEnum 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 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 " diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index 8888013087..d999172aa1 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -55,6 +55,9 @@ extern ConfigVariableBool gl_interleaved_arrays; extern ConfigVariableBool gl_parallel_arrays; extern ConfigVariableInt gl_max_errors; extern ConfigVariableEnum gl_min_buffer_usage_hint; +extern ConfigVariableBool gl_debug; +extern ConfigVariableBool gl_debug_synchronous; +extern ConfigVariableEnum gl_debug_abort_level; extern ConfigVariableBool gl_debug_buffers; extern ConfigVariableBool gl_finish; extern ConfigVariableBool gl_force_depth_stencil; diff --git a/panda/src/glstuff/panda_glext.h b/panda/src/glstuff/panda_glext.h index 93a90c5742..4f5e724d1e 100644 --- a/panda/src/glstuff/panda_glext.h +++ b/panda/src/glstuff/panda_glext.h @@ -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 diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx index 83013117bf..96471c1b9d 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx @@ -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]; - _context = - _glXCreateNewContext(_display, _fbconfig, GLX_RGBA_TYPE, _share_context, - GL_TRUE); + + 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, 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(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.h b/panda/src/glxdisplay/glxGraphicsStateGuardian.h index f0af77ae60..3a6431c865 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.h +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.h @@ -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);