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.
"
This commit is contained in:
Robert Osfield 2008-02-22 18:38:30 +00:00
parent 67f1503c7d
commit 3333ca2b46
4 changed files with 111 additions and 65 deletions

View File

@ -28,6 +28,10 @@ namespace osg {
*/ */
extern OSG_EXPORT float getGLVersionNumber(); 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. /** Return true if OpenGL "extension" is supported.
* Note: Must only be called within a valid OpenGL context, * Note: Must only be called within a valid OpenGL context,
* undefined behavior may occur otherwise. * undefined behavior may occur otherwise.

View File

@ -77,7 +77,6 @@ class OSGVIEWER_EXPORT PixelBufferX11 : public osg::GraphicsContext
Display* getDisplay() const { return _display; } Display* getDisplay() const { return _display; }
Window& getParent() { return _parent; }
GLXPbuffer& getPbuffer() { return _pbuffer; } GLXPbuffer& getPbuffer() { return _pbuffer; }
GLXContext& getGLXContext() { return _glxContext; } GLXContext& getGLXContext() { return _glxContext; }
@ -91,13 +90,14 @@ class OSGVIEWER_EXPORT PixelBufferX11 : public osg::GraphicsContext
bool _valid; bool _valid;
Display* _display; Display* _display;
Window _parent;
GLXPbuffer _pbuffer; GLXPbuffer _pbuffer;
XVisualInfo* _visualInfo; XVisualInfo* _visualInfo;
GLXContext _glxContext; GLXContext _glxContext;
bool _initialized; bool _initialized;
bool _realized; bool _realized;
bool _useGLX1_3;
}; };
} }

View File

@ -48,6 +48,22 @@ float osg::getGLVersionNumber()
return( atof( vs.substr( 0, vs.find( " " ) ).c_str() ) ); 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) bool osg::isGLExtensionSupported(unsigned int contextID, const char *extension)
{ {
ExtensionSet& extensionSet = s_glExtensionSetList[contextID]; ExtensionSet& extensionSet = s_glExtensionSetList[contextID];

View File

@ -18,6 +18,7 @@
#include <osgViewer/api/X11/PixelBufferX11> #include <osgViewer/api/X11/PixelBufferX11>
#include <osgViewer/api/X11/GraphicsWindowX11> #include <osgViewer/api/X11/GraphicsWindowX11>
#include <osg/GLExtensions>
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -25,38 +26,15 @@
using namespace osgViewer; 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) PixelBufferX11::PixelBufferX11(osg::GraphicsContext::Traits* traits)
: _valid(false), : _valid(false),
_display(0), _display(0),
_parent(0),
_pbuffer(0), _pbuffer(0),
_visualInfo(0), _visualInfo(0),
_glxContext(0), _glxContext(0),
_initialized(false), _initialized(false),
_realized(false) _realized(false),
_useGLX1_3(false)
{ {
_traits = traits; _traits = traits;
@ -85,7 +63,7 @@ PixelBufferX11::~PixelBufferX11()
close(true); close(true);
} }
#ifdef GLX_VERSION_1_3 #if defined(GLX_VERSION_1_3) || defined(GLX_SGIX_pbuffer)
bool PixelBufferX11::createVisualInfo() bool PixelBufferX11::createVisualInfo()
{ {
typedef std::vector<int> Attributes; typedef std::vector<int> Attributes;
@ -153,7 +131,7 @@ void PixelBufferX11::init()
return; return;
} }
// Query for GLX extension // Query for GLX extension
int errorBase, eventBase; int errorBase, eventBase;
if( glXQueryExtension( _display, &errorBase, &eventBase) == False ) if( glXQueryExtension( _display, &errorBase, &eventBase) == False )
{ {
@ -178,16 +156,46 @@ void PixelBufferX11::init()
return; return;
} }
// We need to have at least GLX 1.3 to use getFBConfigFromVisual and glXCreatePbuffer // Just be paranoid, if we are older than 1.1, we cannot even call glxQueryExtensionString
if (major < 1 || (major == 1 && minor < 3)) if (1 < major || (1 == major && minor < 1))
{ {
osg::notify(osg::NOTICE) << "Error: " << XDisplayName(_traits->displayName().c_str()) 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 ); XCloseDisplay( _display );
_display = 0; _display = 0;
_valid = false; _valid = false;
return; 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()) if (!createVisualInfo())
{ {
@ -237,43 +245,53 @@ void PixelBufferX11::init()
return; return;
} }
_parent = RootWindow( _display, screen ); #ifdef GLX_VERSION_1_3
// First try the regular glx extension if we have a new enough version available.
XWindowAttributes watt; if (haveGLX1_3)
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)
{ {
swatt.override_redirect = true; int nelements;
mask |= CWOverrideRedirect; 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 <int> 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 <int> AttributeList; _pbuffer = glXCreateGLXPbufferSGIX(_display, fbconfig, _traits->width, _traits->height, 0 );
AttributeList attributes; XFree( fbconfig );
attributes.push_back( GLX_PBUFFER_WIDTH ); }
attributes.push_back( _traits->width ); #endif
attributes.push_back( GLX_PBUFFER_HEIGHT );
attributes.push_back( _traits->height );
attributes.push_back( 0L );
_pbuffer = glXCreatePbuffer(_display, fbconfig, &attributes.front() );
if (!_pbuffer) if (!_pbuffer)
{ {
osg::notify(osg::NOTICE)<<"Error: Unable to create Window."<<std::endl; osg::notify(osg::NOTICE)<<"Error: Unable to create pbuffer."<<std::endl;
XCloseDisplay( _display ); XCloseDisplay( _display );
_display = 0; _display = 0;
_glxContext = 0; _glxContext = 0;
@ -301,16 +319,25 @@ void PixelBufferX11::closeImplementation()
if (_pbuffer) if (_pbuffer)
{ {
glXDestroyPbuffer(_display, _pbuffer); if (_useGLX1_3)
{
#ifdef GLX_VERSION_1_3
glXDestroyPbuffer(_display, _pbuffer);
#endif
}
else
{
#ifdef GLX_SGIX_pbuffer
glXDestroyGLXPbufferSGIX(_display, _pbuffer);
#endif
}
} }
XFlush( _display ); XFlush( _display );
XSync( _display,0 ); XSync( _display,0 );
} }
_pbuffer = 0; _pbuffer = 0;
_parent = 0;
_glxContext = 0; _glxContext = 0;
if (_visualInfo) if (_visualInfo)
@ -347,7 +374,6 @@ void PixelBufferX11::closeImplementation()
{ {
// osg::notify(osg::NOTICE)<<"Closing PixelBufferX11"<<std::endl; // osg::notify(osg::NOTICE)<<"Closing PixelBufferX11"<<std::endl;
_pbuffer = 0; _pbuffer = 0;
_parent = 0;
_glxContext = 0; _glxContext = 0;
_initialized = false; _initialized = false;
_realized = false; _realized = false;