#include #include #include #include #include #define GLX_GLXEXT_PROTOTYPES 1 #include class GraphicsContextX11 : public osg::GraphicsContext { public: GraphicsContextX11(osg::GraphicsContext::Traits* traits): _display(0), _parent(0), _window(0) { _traits = traits; } /** Realise the GraphicsContext implementation, * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual bool realizeImplementation() { osg::notify(osg::NOTICE)<<"GraphicsWindow::realizeImplementation() not implemented."<setContextID( osg::GraphicsContext::createNewContextID() ); } /** Realise the GraphicsContext.*/ virtual bool realizeImplementation(); /** Return true if the graphics context has been realised and is ready to use.*/ virtual bool isRealizedImplementation() const { return _realized; } /** Close the graphics context.*/ virtual void closeImplementation(); /** Make this graphics context current.*/ virtual void makeCurrentImplementation(); /** swap the front and back buffers.*/ virtual void swapBuffersImplementation(); protected: bool createVisualInfo(); void setBorder(bool flag); void init(); Display* _display; Window _parent; Window _window; XVisualInfo* _visualInfo; GLXContext _glxContext; Cursor _defaultCursor; Cursor _nullCursor; Cursor _currentCursor; bool _initialized; bool _realized; }; bool GraphicsWindowX11::createVisualInfo() { typedef std::vector Attributes; Attributes attributes; attributes.push_back(GLX_USE_GL); attributes.push_back(GLX_RGBA); if (_traits->_doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER); if (_traits->_quadBufferStereo) attributes.push_back(GLX_STEREO); attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->_red); attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->_green); attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->_blue); attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->_depth); if (_traits->_alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->_alpha); } if (_traits->_stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->_stencil); } // TODO // GLX_AUX_BUFFERS // GLX_ACCUM_RED_SIZE // GLX_ACCUM_GREEN_SIZE // GLX_SAMPLE_BUFFERS // GLX_SAMPLES attributes.push_back(None); _visualInfo = glXChooseVisual( _display, _traits->_screenNum, &(attributes.front()) ); return _visualInfo != 0; } void GraphicsWindowX11::setBorder(bool flag) { Atom atom; if( (atom = XInternAtom( _display, "_MOTIF_WM_HINTS", 0 )) != None ) { // Hack for sending 64 bit atom to Xserver #if defined( _MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64) || defined ( __ia64 ) || defined (__amd64 ) || defined(__x86_64__) struct { CARD32 flags0; CARD32 flags1; CARD32 functions0; CARD32 functions1; CARD32 decorations0; CARD32 decorations1; INT32 input_mode0; INT32 input_mode1; CARD32 status0; CARD32 status1; } wmHints; #if defined( __ia64 ) || defined (__amd64) || defined (__x86_64__) wmHints.flags0 = (1L << 1); wmHints.functions0 = 0; wmHints.decorations0 = flag; wmHints.input_mode0 = 0; #else wmHints.flags1 = (1L << 1); wmHints.functions1 = 0; wmHints.decorations1 = flag; wmHints.input_mode1 = 0; #endif #else struct { CARD32 flags; CARD32 functions; CARD32 decorations; INT32 input_mode; CARD32 status; } wmHints; wmHints.flags = (1L << 1); wmHints.functions = 0; wmHints.decorations = flag; wmHints.input_mode = 0; #endif XUnmapWindow(_display, _window ); XChangeProperty( _display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 ); XMapWindow(_display, _window ); XFlush(_display); XSync(_display,0); } else osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl; } void GraphicsWindowX11::init() { if (!_traits || _initialized) return; const char* displayString = _traits->_hostName.c_str(); _display = XOpenDisplay(displayString); unsigned int screen = _traits->_screenNum; if (!_display) { osg::notify(osg::NOTICE)<<"Error: Unable to open display \"" << XDisplayName(displayString) << "\". Is the DISPLAY environmental variable set?"<visual, AllocNone); //swatt.colormap = DefaultColormap( _dpy, 0 ); 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; mask |= CWOverrideRedirect; } _window = XCreateWindow( _display, _parent, _traits->_x, _traits->_y, _traits->_width, _traits->_height, 0, _visualInfo->depth, InputOutput, _visualInfo->visual, mask, &swatt ); if (!_window) { osg::notify(osg::NOTICE)<<"Error: Unable to create Window."<_x; sh.y = _traits->_y; sh.width = _traits->_width; sh.height = _traits->_height; XSetStandardProperties( _display, _window, _traits->_windowName.c_str(), _traits->_windowName.c_str(), None, 0, 0, &sh); setBorder(_traits->_windowDecoration); // Create default Cursor _defaultCursor = XCreateFontCursor( _display, XC_left_ptr ); // Create Null Cursor { Pixmap pixmap; static char buff[2] = {0,0}; static XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0}; pixmap = XCreateBitmapFromData( _display, _parent, buff, 1, 1); _nullCursor = XCreatePixmapCursor( _display, pixmap, pixmap, &ncol, &ncol, 0, 0 ); } #if 1 _currentCursor = _defaultCursor; #else _currentCursor = _nullCursor; #endif { XDefineCursor( _display, _window, _currentCursor ); XFlush(_display); XSync(_display,0); } _initialized = true; } bool GraphicsWindowX11::realizeImplementation() { if (_realized) return true; if (!_initialized) init(); if (!_initialized) return false; XMapWindow( _display, _window ); Window temp = _window; XSetWMColormapWindows( _display, _window, &temp, 1); makeCurrent(); _realized = true; return true; } void GraphicsWindowX11::makeCurrentImplementation() { glXMakeCurrent( _display, _window, _glxContext ); } void GraphicsWindowX11::closeImplementation() { //glXDestroyContext(_display, _glxContext ); XDestroyWindow(_display, _window); XFlush( _display ); XSync( _display,0 ); _window = 0; _parent = 0; if(_visualInfo) { XFree(_visualInfo); _visualInfo = 0; } _initialized = false; _realized = false; } void GraphicsWindowX11::swapBuffersImplementation() { glXSwapBuffers(_display, _window); } struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface { virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) { const char* displayString = si._hostName.c_str(); Display* display = XOpenDisplay(displayString); if(display) { unsigned int numScreens = ScreenCount(display); XCloseDisplay(display); return numScreens; } else { osg::notify(osg::NOTICE) << "Unable to open display \"" << XDisplayName(displayString) << "\". Is the DISPLAY environmental variable set?"<_pbuffer) { return new GraphicsContextX11(traits); } else { return new GraphicsWindowX11(traits); } } }; struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface); } ~RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(0); } }; RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;