diff --git a/include/osgViewer/api/Win32/GraphicsWindowWin32 b/include/osgViewer/api/Win32/GraphicsWindowWin32 index d66d222d0..69c8d6e31 100644 --- a/include/osgViewer/api/Win32/GraphicsWindowWin32 +++ b/include/osgViewer/api/Win32/GraphicsWindowWin32 @@ -29,7 +29,7 @@ namespace osgViewer { -class GraphicsWindowWin32 : public osgViewer::GraphicsWindow +class OSGVIEWER_EXPORT GraphicsWindowWin32 : public osgViewer::GraphicsWindow { public: diff --git a/include/osgViewer/api/X11/GraphicsWindowX11 b/include/osgViewer/api/X11/GraphicsWindowX11 index 03f4bdf49..d344753c9 100644 --- a/include/osgViewer/api/X11/GraphicsWindowX11 +++ b/include/osgViewer/api/X11/GraphicsWindowX11 @@ -29,7 +29,7 @@ namespace osgViewer { -class GraphicsWindowX11 : public osgViewer::GraphicsWindow +class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow { public: diff --git a/include/osgViewer/api/X11/PixelBufferX11 b/include/osgViewer/api/X11/PixelBufferX11 new file mode 100644 index 000000000..cfd75e5f9 --- /dev/null +++ b/include/osgViewer/api/X11/PixelBufferX11 @@ -0,0 +1,130 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +/* Note, elements of PixelBufferX11 have used Prodcer/RenderSurface_X11.cpp as both + * a guide to use of X11/GLX and copiying directly in the case of setBorder(). + * These elements are license under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. + */ + +#ifndef OSGVIEWER_PIXELBUFFERX11 +#define OSGVIEWER_PIXELBUFFERX11 1 + +#include +#include + +#define GLX_GLXEXT_PROTOTYPES 1 + +#include +#include + +namespace osgViewer +{ + +class OSGVIEWER_EXPORT PixelBufferX11 : public osg::GraphicsContext +{ + public: + + PixelBufferX11(osg::GraphicsContext::Traits* traits): + _valid(false), + _display(0), + _parent(0), + _window(0), + _visualInfo(0), + _glxContext(0), + _initialized(false), + _realized(false) + { + _traits = traits; + + init(); + + if (valid()) + { + setState( new osg::State ); + getState()->setGraphicsContext(this); + + if (_traits.valid() && _traits->sharedContext) + { + getState()->setContextID( _traits->sharedContext->getState()->getContextID() ); + incrementContextIDUsageCount( getState()->getContextID() ); + } + else + { + getState()->setContextID( osg::GraphicsContext::createNewContextID() ); + } + + } + } + + virtual bool isSameKindAs(const Object* object) const { return dynamic_cast(object)!=0; } + virtual const char* libraryName() const { return "osgViewer"; } + virtual const char* className() const { return "PixelBufferX11"; } + + virtual bool valid() const { return _valid; } + + /** 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 bool makeCurrentImplementation(); + + /** Make this graphics context current with specified read context implementation. */ + virtual bool makeContextCurrentImplementation(osg::GraphicsContext* readContext); + + /** Release the graphics context.*/ + virtual bool releaseContextImplementation(); + + /** Bind the graphics context to associated texture implementation.*/ + virtual void bindPBufferToTextureImplementation(GLenum buffer); + + /** Swap the front and back buffers.*/ + virtual void swapBuffersImplementation(); + + public: + + // X11 specific aces functions + + Display* getDisplay() const { return _display; } + + Window& getParent() { return _parent; } + Window& getWindow() { return _window; } + GLXContext& getGLXContext() { return _glxContext; } + + protected: + + ~PixelBufferX11(); + + bool createVisualInfo(); + + void init(); + + bool _valid; + Display* _display; + Window _parent; + Window _window; + XVisualInfo* _visualInfo; + GLXContext _glxContext; + + bool _initialized; + bool _realized; +}; + +} + +#endif diff --git a/src/osgViewer/CMakeLists.txt b/src/osgViewer/CMakeLists.txt index 4b23661a1..3410c3f5c 100644 --- a/src/osgViewer/CMakeLists.txt +++ b/src/osgViewer/CMakeLists.txt @@ -46,8 +46,14 @@ ELSE(WIN32) ELSE(APPLE) # X11 for everybody else - SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} ${HEADER_PATH}/api/X11/GraphicsWindowX11) - SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowX11.cpp) + SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} + ${HEADER_PATH}/api/X11/GraphicsWindowX11 + ${HEADER_PATH}/api/X11/PixelBufferX11 + ) + SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} + GraphicsWindowX11.cpp + PixelBufferX11.cpp + ) ENDIF(APPLE) ENDIF(WIN32) diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index 91db38d5d..754dc81ab 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -33,66 +34,6 @@ using namespace osgViewer; -namespace osgViewer -{ - -class GraphicsContextX11 : public osg::GraphicsContext -{ - public: - - GraphicsContextX11(osg::GraphicsContext::Traits* traits): - _valid(false), - _display(0), - _parent(0), - _window(0) - { - _traits = traits; - } - - virtual bool valid() const { return _valid; } - - /** 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."<(_traits->sharedContext); - if (sharedContextX11) + GLXContext sharedContextGLX = NULL; + + // get any shared GLX contexts + GraphicsWindowX11* graphicsWindowX11 = dynamic_cast(_traits->sharedContext); + if (graphicsWindowX11) { - _glxContext = glXCreateContext( _display, _visualInfo, sharedContextX11->getGLXContext(), True ); + sharedContextGLX = graphicsWindowX11->getGLXContext(); } else { - _glxContext = glXCreateContext( _display, _visualInfo, NULL, True ); + PixelBufferX11* pixelBufferX11 = dynamic_cast(_traits->sharedContext); + if (pixelBufferX11) + { + sharedContextGLX = pixelBufferX11->getGLXContext(); + } } + _glxContext = glXCreateContext( _display, _visualInfo, sharedContextGLX, True ); + if (!_glxContext) { osg::notify(osg::NOTICE)<<"Error: Unable to create OpenGL graphics context."<pbuffer) { - osg::ref_ptr pbuffer = new GraphicsContextX11(traits); +#if 1 + osg::ref_ptr pbuffer = new PixelBufferX11(traits); if (pbuffer->valid()) return pbuffer.release(); else return 0; +#else + osg::ref_ptr window = new GraphicsWindowX11(traits); + if (window->valid()) return window.release(); + else return 0; +#endif } else { diff --git a/src/osgViewer/PixelBufferX11.cpp b/src/osgViewer/PixelBufferX11.cpp new file mode 100644 index 000000000..15a0036f4 --- /dev/null +++ b/src/osgViewer/PixelBufferX11.cpp @@ -0,0 +1,331 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +/* Note, elements of PixelBufferX11 have used Prodcer/RenderSurface_X11.cpp as both + * a guide to use of X11/GLX and copiying directly in the case of setBorder(). + * These elements are license under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. + */ + +#include +#include + +#include + +#include + +using namespace osgViewer; + +PixelBufferX11::~PixelBufferX11() +{ + close(true); +} + +bool PixelBufferX11::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); + + 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); } + +#if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES) + + if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } + if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); } + +#endif + // TODO + // GLX_AUX_BUFFERS + // GLX_ACCUM_RED_SIZE + // GLX_ACCUM_GREEN_SIZE + + attributes.push_back(None); + + _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) ); + + return _visualInfo != 0; +} + +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::notify(osg::NOTICE)<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<displayName().c_str()) <<" has no GLX extension." << std::endl; + + XCloseDisplay( _display ); + _display = 0; + _valid = false; + return; + } + + // osg::notify(osg::NOTICE)<<"GLX extension, errorBase="<(_traits->sharedContext); + if (graphicsWindowX11) + { + sharedContextGLX = graphicsWindowX11->getGLXContext(); + } + else + { + PixelBufferX11* pixelBufferX11 = dynamic_cast(_traits->sharedContext); + if (pixelBufferX11) + { + sharedContextGLX = pixelBufferX11->getGLXContext(); + } + } + + _glxContext = glXCreateContext( _display, _visualInfo, sharedContextGLX, True ); + + if (!_glxContext) + { + osg::notify(osg::NOTICE)<<"Error: Unable to create OpenGL graphics context."<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; + 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."<width != watt.width && _traits->height != watt.height) + { + resized( _traits->x, _traits->y, _traits->width, _traits->height ); + } + + + _valid = true; + _initialized = true; +} + +bool PixelBufferX11::realizeImplementation() +{ + if (_realized) + { + osg::notify(osg::NOTICE)<<"PixelBufferX11::realizeImplementation() Already realized"<