From 3333ca2b46ef2f1f716132bcf2b8eebc1495f69e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 22 Feb 2008 18:38:30 +0000 Subject: [PATCH] From Mathias Froehlich, "I have extended the X11 pbuffer code to use either the complete set of glx 1.3 pbuffer functions or exactly ask for the extensions we need to call the apropriate glx extension functions for and around pbuffers extensions. The glx 1.3 version of this functios are prefered. If this is not pressent we are looking for the glx extensions and check for them. Prevously we just used some mix of the glx 1.3 functions or the extension functions without making sure that this extension is present. " --- include/osg/GLExtensions | 4 + include/osgViewer/api/X11/PixelBufferX11 | 4 +- src/osg/GLExtensions.cpp | 16 +++ src/osgViewer/PixelBufferX11.cpp | 152 +++++++++++++---------- 4 files changed, 111 insertions(+), 65 deletions(-) diff --git a/include/osg/GLExtensions b/include/osg/GLExtensions index c80230d36..d5c546650 100644 --- a/include/osg/GLExtensions +++ b/include/osg/GLExtensions @@ -28,6 +28,10 @@ namespace osg { */ extern OSG_EXPORT float getGLVersionNumber(); +/** Return true if "extension" is contained in "extensionString". +*/ +extern OSG_EXPORT bool isExtensionInExtensionString(const char *extension, const char *extensionString); + /** Return true if OpenGL "extension" is supported. * Note: Must only be called within a valid OpenGL context, * undefined behavior may occur otherwise. diff --git a/include/osgViewer/api/X11/PixelBufferX11 b/include/osgViewer/api/X11/PixelBufferX11 index e015e9157..fa0f5c847 100644 --- a/include/osgViewer/api/X11/PixelBufferX11 +++ b/include/osgViewer/api/X11/PixelBufferX11 @@ -77,7 +77,6 @@ class OSGVIEWER_EXPORT PixelBufferX11 : public osg::GraphicsContext Display* getDisplay() const { return _display; } - Window& getParent() { return _parent; } GLXPbuffer& getPbuffer() { return _pbuffer; } GLXContext& getGLXContext() { return _glxContext; } @@ -91,13 +90,14 @@ class OSGVIEWER_EXPORT PixelBufferX11 : public osg::GraphicsContext bool _valid; Display* _display; - Window _parent; GLXPbuffer _pbuffer; XVisualInfo* _visualInfo; GLXContext _glxContext; bool _initialized; bool _realized; + + bool _useGLX1_3; }; } diff --git a/src/osg/GLExtensions.cpp b/src/osg/GLExtensions.cpp index 0cd8531c2..b969340c6 100644 --- a/src/osg/GLExtensions.cpp +++ b/src/osg/GLExtensions.cpp @@ -48,6 +48,22 @@ float osg::getGLVersionNumber() return( atof( vs.substr( 0, vs.find( " " ) ).c_str() ) ); } +bool osg::isExtensionInExtensionString(const char *extension, const char *extensionString) +{ + const char *startOfWord = extensionString; + const char *endOfWord; + while ((endOfWord = strchr(startOfWord,' ')) != 0) + { + if (strncmp(extension, startOfWord, endOfWord - startOfWord) == 0) + return true; + startOfWord = endOfWord+1; + } + if (*startOfWord && strcmp(extension, startOfWord) == 0) + return true; + + return false; +} + bool osg::isGLExtensionSupported(unsigned int contextID, const char *extension) { ExtensionSet& extensionSet = s_glExtensionSetList[contextID]; diff --git a/src/osgViewer/PixelBufferX11.cpp b/src/osgViewer/PixelBufferX11.cpp index 156d8dfcf..4ed82e916 100644 --- a/src/osgViewer/PixelBufferX11.cpp +++ b/src/osgViewer/PixelBufferX11.cpp @@ -18,6 +18,7 @@ #include #include +#include #include @@ -25,38 +26,15 @@ using namespace osgViewer; -#ifdef GLX_VERSION_1_3 -static GLXFBConfig getFBConfigFromVisual(::Display* dpy, XVisualInfo* visualInfo) -{ -#if defined(__APPLE__) || defined(_AIX) || defined(__hpux) - int screen = visualInfo->screen; - int nelements; - GLXFBConfig *configs = glXGetFBConfigs(dpy, screen, &nelements); - for( int i = 0; i < nelements; i++ ) - { - int visual_id; - if( glXGetFBConfigAttrib( dpy, configs[i], GLX_VISUAL_ID, &visual_id ) == 0 ) - { - if( (unsigned int)visual_id == visualInfo->visualid ) - return configs[i]; - } - } - return NULL; -#else - return glXGetFBConfigFromVisualSGIX( dpy, visualInfo ); -#endif -} -#endif - PixelBufferX11::PixelBufferX11(osg::GraphicsContext::Traits* traits) : _valid(false), _display(0), - _parent(0), _pbuffer(0), _visualInfo(0), _glxContext(0), _initialized(false), - _realized(false) + _realized(false), + _useGLX1_3(false) { _traits = traits; @@ -85,7 +63,7 @@ PixelBufferX11::~PixelBufferX11() close(true); } -#ifdef GLX_VERSION_1_3 +#if defined(GLX_VERSION_1_3) || defined(GLX_SGIX_pbuffer) bool PixelBufferX11::createVisualInfo() { typedef std::vector Attributes; @@ -153,7 +131,7 @@ void PixelBufferX11::init() return; } - // Query for GLX extension + // Query for GLX extension int errorBase, eventBase; if( glXQueryExtension( _display, &errorBase, &eventBase) == False ) { @@ -178,16 +156,46 @@ void PixelBufferX11::init() return; } - // We need to have at least GLX 1.3 to use getFBConfigFromVisual and glXCreatePbuffer - if (major < 1 || (major == 1 && minor < 3)) + // Just be paranoid, if we are older than 1.1, we cannot even call glxQueryExtensionString + if (1 < major || (1 == major && minor < 1)) { osg::notify(osg::NOTICE) << "Error: " << XDisplayName(_traits->displayName().c_str()) - << " GLX version " << major << "." << minor << " is too little." << std::endl; + << " GLX version " << major << "." << minor << " is too old." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } + + bool haveGLX1_3 = false; + bool haveSGIX_pbuffer = false; + + // We need to have at least GLX 1.3 to use getFBConfigFromVisual and glXCreatePbuffer + if (1 < major || (1 == major && 3 <= minor)) + { + haveGLX1_3 = true; + } + +#if defined(GLX_VERSION_1_1) + // We need at least GLX 1.1 for glXQueryExtensionsString + if (!haveGLX1_3 && 1 <= minor) + { + const char *extensions = glXQueryExtensionsString(_display, screen); + haveSGIX_pbuffer = osg::isExtensionInExtensionString("GLX_SGIX_pbuffer", extensions) + && osg::isExtensionInExtensionString("GLX_SGIX_fbconfig", extensions); + } +#endif + + if (!haveGLX1_3 && !haveSGIX_pbuffer) + { + osg::notify(osg::NOTICE) << "Error: " << XDisplayName(_traits->displayName().c_str()) + << " no Pbuffer support in GLX available." << std::endl; + XCloseDisplay( _display ); + _display = 0; + _valid = false; + return; + } + if (!createVisualInfo()) { @@ -237,43 +245,53 @@ void PixelBufferX11::init() return; } - _parent = RootWindow( _display, screen ); - - XWindowAttributes watt; - XGetWindowAttributes( _display, _parent, &watt ); - // unsigned int parentWindowHeight = watt.height; - - XSetWindowAttributes swatt; - swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone); - //swatt.colormap = DefaultColormap( _dpy, 10 ); - swatt.background_pixel = 0; - swatt.border_pixel = 0; - swatt.event_mask = 0; - unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; - - bool overrideRedirect = false; - if (overrideRedirect) +#ifdef GLX_VERSION_1_3 + // First try the regular glx extension if we have a new enough version available. + if (haveGLX1_3) { - swatt.override_redirect = true; - mask |= CWOverrideRedirect; + int nelements; + GLXFBConfig *fbconfigs = glXGetFBConfigs( _display, screen, &nelements ); + for ( int i = 0; i < nelements; ++i ) + { + int visual_id; + if ( glXGetFBConfigAttrib( _display, fbconfigs[i], GLX_VISUAL_ID, &visual_id ) == 0 ) + { + if ( !_pbuffer && (unsigned int)visual_id == _visualInfo->visualid ) + { + typedef std::vector AttributeList; + + AttributeList attributes; + attributes.push_back( GLX_PBUFFER_WIDTH ); + attributes.push_back( _traits->width ); + attributes.push_back( GLX_PBUFFER_HEIGHT ); + attributes.push_back( _traits->height ); + attributes.push_back( 0L ); + + _pbuffer = glXCreatePbuffer(_display, fbconfigs[i], &attributes.front() ); + _useGLX1_3 = true; + } + } + } + + XFree( fbconfigs ); } +#endif - GLXFBConfig fbconfig = getFBConfigFromVisual( _display, _visualInfo ); +#ifdef GLX_SGIX_pbuffer + // If we still have no pbuffer but a capable display with the SGIX extension, try to use that + if (!_pbuffer && haveSGIX_pbuffer) + { + GLXFBConfigSGIX fbconfig = glXGetFBConfigFromVisualSGIX( _display, _visualInfo ); - typedef std::vector AttributeList; + _pbuffer = glXCreateGLXPbufferSGIX(_display, fbconfig, _traits->width, _traits->height, 0 ); - AttributeList attributes; - attributes.push_back( GLX_PBUFFER_WIDTH ); - attributes.push_back( _traits->width ); - attributes.push_back( GLX_PBUFFER_HEIGHT ); - attributes.push_back( _traits->height ); - attributes.push_back( 0L ); + XFree( fbconfig ); + } +#endif - _pbuffer = glXCreatePbuffer(_display, fbconfig, &attributes.front() ); - if (!_pbuffer) { - osg::notify(osg::NOTICE)<<"Error: Unable to create Window."<