void PixelBufferX11::init() { if (_initialized) return; if (!_traits) { _valid = false; return; } if (_traits->target != 0) { // we don't support Pbuffer render to texture under GLX. _valid = false; return; } _display = XOpenDisplay(_traits->displayName().c_str()); unsigned int screen = _traits->screenNum; if (!_display) { OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl; _valid = false; return; } // Query for GLX extension int errorBase, eventBase; if( glXQueryExtension( _display, &errorBase, &eventBase) == False ) { OSG_NOTICE<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } // OSG_NOTICE<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl; int major, minor; if (glXQueryVersion(_display, &major, &minor) == False) { OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str()) << " can not query GLX version." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } // Just be paranoid, if we are older than 1.1, we cannot even call glxQueryExtensionString if (major < 1 || (1 == major && minor < 1)) { OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str()) << " 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) && defined(GLX_SGIX_pbuffer) // 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); if (haveSGIX_pbuffer) { osg::setGLExtensionFuncPtr(_glXCreateGLXPbufferSGIX, "glXDestroyGLXPbufferSGIX"); osg::setGLExtensionFuncPtr(_glXDestroyGLXPbufferSGIX, "glXDestroyGLXPbufferSGIX"); osg::setGLExtensionFuncPtr(_glXQueryGLXPbufferSGIX, "glXDestroyGLXPbufferSGIX"); osg::setGLExtensionFuncPtr(_glXGetFBConfigFromVisualSGIX, "glXGetFBConfigFromVisualSGIX"); if (_glXCreateGLXPbufferSGIX == NULL || _glXDestroyGLXPbufferSGIX == NULL || _glXQueryGLXPbufferSGIX == NULL || _glXGetFBConfigFromVisualSGIX == NULL) { haveSGIX_pbuffer = false; } } } #endif if (!haveGLX1_3 && !haveSGIX_pbuffer) { 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()) { _traits->red /= 2; _traits->green /= 2; _traits->blue /= 2; _traits->alpha /= 2; _traits->depth /= 2; OSG_INFO<<"Relaxing traits"<<std::endl; if (!createVisualInfo()) { OSG_NOTICE<<"Error: Not able to create requested visual." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } } // get any shared GLX contexts GraphicsHandleX11* graphicsHandleX11 = dynamic_cast<GraphicsHandleX11*>(_traits->sharedContext.get()); Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0; _context = glXCreateContext( _display, _visualInfo, sharedContext, True ); if (!_context) { OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<<std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } #ifdef GLX_VERSION_1_3 // First try the regular glx extension if we have a new enough version available. if (haveGLX1_3) { 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 <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( GLX_LARGEST_PBUFFER ); attributes.push_back( GL_TRUE ); attributes.push_back( 0L ); _pbuffer = glXCreatePbuffer(_display, fbconfigs[i], &attributes.front() ); _useGLX1_3 = true; } } } if (_pbuffer) { int iWidth = 0; int iHeight = 0; glXQueryDrawable(_display, _pbuffer, GLX_WIDTH , (unsigned int *)&iWidth); glXQueryDrawable(_display, _pbuffer, GLX_HEIGHT , (unsigned int *)&iHeight); if (_traits->width != iWidth || _traits->height != iHeight) { OSG_NOTICE << "PixelBufferX11::init(), pbuffer created with different size then requsted" << std::endl; OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl; OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl; _traits->width = iWidth; _traits->height = iHeight; } } XFree( fbconfigs ); } #endif #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; AttributeList attributes; attributes.push_back( GLX_LARGEST_PBUFFER_SGIX ); attributes.push_back( GL_TRUE ); attributes.push_back( 0L ); _pbuffer = _glXCreateGLXPbufferSGIX(_display, fbconfig, _traits->width, _traits->height, &attributes.front() ); if (_pbuffer) { _useSGIX = true; int iWidth = 0; int iHeight = 0; _glXQueryGLXPbufferSGIX(_display, _pbuffer, GLX_WIDTH_SGIX , (unsigned int *)&iWidth); _glXQueryGLXPbufferSGIX(_display, _pbuffer, GLX_HEIGHT_SGIX, (unsigned int *)&iHeight); if (_traits->width != iWidth || _traits->height != iHeight) { OSG_NOTICE << "PixelBufferX11::init(), SGIX_pbuffer created with different size then requsted" << std::endl; OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl; OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl; _traits->width = iWidth; _traits->height = iHeight; } } XFree( fbconfig ); } #endif if (!_pbuffer) { OSG_NOTICE<<"Error: Unable to create pbuffer."<<std::endl; XCloseDisplay( _display ); _display = 0; _context = 0; _valid = false; return; } XFlush( _display ); XSync( _display, 0 ); _valid = true; _initialized = true; }