diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index a59e81856..76f65656d 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -29,6 +29,15 @@ class OSG_EXPORT GraphicsContext : public Referenced ScreenIdentifier(): _displayNum(0), _screenNum(0) {} + + ScreenIdentifier(unsigned int screenNum): + _displayNum(0), + _screenNum(screenNum) {} + + ScreenIdentifier(const std::string& hostName,unsigned int displayNum, unsigned int screenNum): + _hostName(hostName), + _displayNum(displayNum), + _screenNum(screenNum) {} std::string _hostName; unsigned int _displayNum; diff --git a/include/osg/View b/include/osg/View index 5aaa0440c..f164a5f58 100644 --- a/include/osg/View +++ b/include/osg/View @@ -74,11 +74,11 @@ class OSG_EXPORT View : public virtual osg::Referenced Slave& getSlave(unsigned int pos) { return _slaves[pos]; } const Slave& getSlave(unsigned int pos) const { return _slaves[pos]; } + void updateSlaves(); + protected : virtual ~View(); - - void updateSlaves(); osg::ref_ptr _camera; diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index f99e5347f..6316eebd9 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -33,13 +33,17 @@ namespace osgUtil { * global state, lights and the scene itself. Provides * methods for setting up the view and rendering it. */ -class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSettings +class OSGUTIL_EXPORT SceneView : public osg::Object, public osg::CullSettings { public: /** Construct a default scene view.*/ SceneView(osg::DisplaySettings* ds=NULL); + SceneView(const SceneView& sceneview, const osg::CopyOp& copyop = osg::CopyOp()); + + META_Object(osgUtil, SceneView); + enum Options { NO_SCENEVIEW_LIGHT = 0x0, diff --git a/include/osgViewer/GraphicsWindowX11 b/include/osgViewer/GraphicsWindowX11 new file mode 100644 index 000000000..ea0894854 --- /dev/null +++ b/include/osgViewer/GraphicsWindowX11 @@ -0,0 +1,451 @@ +#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; diff --git a/include/osgViewer/View b/include/osgViewer/View index dcd940c39..18a542719 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -21,15 +21,15 @@ namespace osgViewer { /** View holds a single view on a scene, this view may be composed of one or more slave cameras.*/ -class OSGVIEWER_EXPORT View : public osg::View, public osgViewer::Scene +class OSGVIEWER_EXPORT View : public osg::View { public: View(); void setSceneData(osg::Node* node); - osg::Node* getSceneData(); - const osg::Node* getSceneData() const; + osg::Node* getSceneData() { return _scene.valid() ? _scene->getSceneData() : 0; } + const osg::Node* getSceneData() const { return _scene.valid() ? _scene->getSceneData() : 0; } void setCameraManipulator(osgGA::MatrixManipulator* manipulator); osgGA::MatrixManipulator* getCameraManipulator() { return _cameraManipulator.get(); } @@ -40,18 +40,22 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgViewer::Scene void addEventHandler(osgGA::GUIEventHandler* eventHandler); EventHandlers& getEventHandlers() { return _eventHandlers; } const EventHandlers& getEventHandlers() const { return _eventHandlers; } + + /** Convinience method for creating slave Cameras and associated GraphicsWindows across all screens.*/ + void setUpViewAcrossAllScreens(); + public: - void init(); + void setUpRenderingSupport(); + + void assignSceneDataToCameras(); protected: virtual ~View(); osg::ref_ptr _scene; - - osg::ref_ptr _sceneView; osg::ref_ptr _cameraManipulator; EventHandlers _eventHandlers; diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index fc5b6a05e..8d39a853f 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -28,6 +28,9 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View Viewer(); virtual ~Viewer(); + + /** set up windows and associated threads.*/ + void realize(); /** Render a complete new frame. * Calls frameAdvance(), frameEventTraversal(), frameUpateTraversal(), frameCullTraversal() and frameDrawTraversal(). diff --git a/src/osg/View.cpp b/src/osg/View.cpp index 565a2db58..b4c452fa1 100644 --- a/src/osg/View.cpp +++ b/src/osg/View.cpp @@ -17,10 +17,16 @@ using namespace osg; View::View() { + // osg::notify(osg::NOTICE)<<"Constructing osg::View"<setProjectionMatrixAsPerspective(50.0f,1.4f,1.0f,10000.0f); } View::~View() { + // osg::notify(osg::NOTICE)<<"Destructing osg::View"<setView(0); cd._camera->setCullCallback(0); } + + // osg::notify(osg::NOTICE)<<"Done destructing osg::View"<setProjectionMatrix(cd._projectionOffset * _camera->getProjectionMatrix()); - cd._camera->setViewMatrix(cd._viewOffset * _camera->getViewMatrix()); - cd._camera->inheritCullSettings(*_camera); + Slave& slave = *itr; + slave._camera->setProjectionMatrix(_camera->getProjectionMatrix() * slave._projectionOffset); + slave._camera->setViewMatrix(_camera->getViewMatrix() * slave._viewOffset); + slave._camera->inheritCullSettings(*_camera); + if (_camera->getInheritanceMask() & osg::CullSettings::CLEAR_COLOR) slave._camera->setClearColor(_camera->getClearColor()); } @@ -62,6 +71,8 @@ bool View::addSlave(osg::Camera* camera, const osg::Matrix& projectionOffset, co camera->setProjectionMatrix(projectionOffset * _camera->getProjectionMatrix()); camera->setViewMatrix(viewOffset * _camera->getViewMatrix()); camera->inheritCullSettings(*_camera); + + if (_camera->getInheritanceMask() & osg::CullSettings::CLEAR_COLOR) camera->setClearColor(_camera->getClearColor()); } _slaves.push_back(Slave(camera, projectionOffset, viewOffset)); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index 874416d92..4657b71e4 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -90,8 +90,6 @@ SceneView::SceneView(DisplaySettings* ds) { _displaySettings = ds; - - _fusionDistanceMode = PROPORTIONAL_TO_SCREEN_DISTANCE; _fusionDistanceValue = 1.0f; @@ -119,6 +117,34 @@ SceneView::SceneView(DisplaySettings* ds) _interlacedStereoStencilHeight = 0; } +SceneView::SceneView(const SceneView& rhs, const osg::CopyOp&) +{ + _displaySettings = rhs._displaySettings; + + _fusionDistanceMode = rhs._fusionDistanceMode; + _fusionDistanceValue = rhs._fusionDistanceValue; + + _lightingMode = rhs._lightingMode; + + _prioritizeTextures = rhs._prioritizeTextures; + + _camera = rhs._camera; + + _initCalled = rhs._initCalled; + + + _drawBufferValue = rhs._drawBufferValue; + + _requiresFlush = rhs._requiresFlush; + + _activeUniforms = rhs._activeUniforms; + + _previousFrameTime = rhs._previousFrameTime; + + _redrawInterlacedStereoStencilMask = rhs._redrawInterlacedStereoStencilMask; + _interlacedStereoStencilWidth = rhs._interlacedStereoStencilWidth; + _interlacedStereoStencilHeight = rhs._interlacedStereoStencilHeight; +} SceneView::~SceneView() { diff --git a/src/osgViewer/Scene.cpp b/src/osgViewer/Scene.cpp index e2bc5e81e..2976ab929 100644 --- a/src/osgViewer/Scene.cpp +++ b/src/osgViewer/Scene.cpp @@ -25,6 +25,7 @@ Scene::Scene(): _updateVisitor = new osgUtil::UpdateVisitor; + _eventQueue = new osgGA::EventQueue; _eventQueue->setStartTick(_startTick); _eventVisitor = new osgGA::EventVisitor; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index f30a4f376..8115f7854 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -12,13 +12,163 @@ */ #include +#include + +#include using namespace osgViewer; View::View() { + // osg::notify(osg::NOTICE)<<"Constructing osgViewer::View"<setSceneData(node); + + assignSceneDataToCameras(); +} + +void View::setUpViewAcrossAllScreens() +{ + osg::GraphicsContext::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); + if (!wsi) + { + osg::notify(osg::NOTICE)<<"View::setUpViewAcrossAllScreens() : Error, no WindowSystemInterface available, cannot create windows."<getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar); + + double fovx = atan(tan(osg::DegreesToRadians(fovy*0.5)) * aspectRatio) * 2.0; + + unsigned int numScreens = wsi->getNumScreens(); + if (numScreens==1) + { + unsigned int width, height; + wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height); + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->_x = 0; + traits->_y = 0; + traits->_width = width; + traits->_height = height; + traits->_windowDecoration = false; + traits->_doubleBuffer = true; + traits->_sharedContext = 0; + + osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + + _camera->setGraphicsContext(gc.get()); + + osgViewer::GraphicsWindow* gw = dynamic_cast(gc.get()); + if (gw) + { + osg::notify(osg::NOTICE)<<" GraphicsWindow has been created successfully."<setViewport(new osg::Viewport(0, 0, width, height)); + } + else + { + double rotate_x = - double(numScreens-1) * 0.5 * fovx; + + for(unsigned int i=0; igetScreenResolution(osg::GraphicsContext::ScreenIdentifier(i), width, height); + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->_screenNum = i; + traits->_x = 0; + traits->_y = 0; + traits->_width = width; + traits->_height = height; + traits->_windowDecoration = false; + traits->_doubleBuffer = true; + traits->_sharedContext = 0; + + osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + + osg::ref_ptr camera = new osg::Camera; + camera->setGraphicsContext(gc.get()); + + osgViewer::GraphicsWindow* gw = dynamic_cast(gc.get()); + if (gw) + { + osg::notify(osg::NOTICE)<<" GraphicsWindow has been created successfully."<setViewport(new osg::Viewport(0, 0, width, height)); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate( rotate_x, 0.0, 1.0, 0.0)); + + } + } + + setUpRenderingSupport(); + assignSceneDataToCameras(); +} + +void View::setUpRenderingSupport() +{ + if (_camera.valid() && _camera->getGraphicsContext()) + { + osg::ref_ptr sceneView = new osgUtil::SceneView; + sceneView->setState(_camera->getGraphicsContext()->getState()); + sceneView->setCamera(_camera.get()); + _camera->setRenderingCache(0, sceneView.get()); + } + + for(unsigned i=0; igetGraphicsContext()) + { + osg::ref_ptr sceneView = new osgUtil::SceneView; + sceneView->setDefaults(); + sceneView->setState(slave._camera->getGraphicsContext()->getState()); + sceneView->setCamera(slave._camera.get()); + slave._camera->setRenderingCache(0, sceneView.get()); + } + } +} + +void View::assignSceneDataToCameras() +{ + osg::Node* sceneData = _scene.valid() ? _scene->getSceneData() : 0; + + if (_camera.valid()) + { + _camera->removeChildren(0,_camera->getNumChildren()); + if (sceneData) _camera->addChild(sceneData); + } + + for(unsigned i=0; iremoveChildren(0,slave._camera->getNumChildren()); + if (sceneData) slave._camera->addChild(sceneData); + } + } } diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 43ec72960..cce0f3649 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -20,13 +20,33 @@ using namespace osgViewer; Viewer::Viewer() { - osg::notify(osg::NOTICE)<<"Viewer::Viewer() not implemented yet."<getGraphicsContext()) + { + _camera->getGraphicsContext()->realize(); + } + + for(unsigned int i=0; igetGraphicsContext()) + { + osg::notify(osg::NOTICE)<<" slave realize()"<getGraphicsContext()->realize(); + } + } +} + + void Viewer::frame() { osg::notify(osg::NOTICE)<<"Viewer::frame() not implemented yet."<