diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index 84c261e24..2b3aa4123 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -108,6 +108,11 @@ class OSG_EXPORT GraphicsContext : public Object // V-sync bool vsync; + // Swap Group + bool swapGroupEnabled; + GLuint swapGroup; + GLuint swapBarrier; + // use multithreaded OpenGL-engine (OS X only) bool useMultiThreadedOpenGLEngine; diff --git a/include/osgViewer/GraphicsWindow b/include/osgViewer/GraphicsWindow index a2a60e672..e8f04cc9f 100644 --- a/include/osgViewer/GraphicsWindow +++ b/include/osgViewer/GraphicsWindow @@ -145,6 +145,14 @@ class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgG bool getSyncToVBlank() const { return _traits.valid() ? _traits->vsync : true; } + /** Set swap group. */ + virtual void setSwapGroup(bool on, GLuint group, GLuint barrier) + { + osg::notify(osg::NOTICE) << "GraphicsWindow::setSwapGroup(" << on << " " << group << " " << barrier << ") not implemented." << std::endl; + } + + void getSwapGroup(bool& on, GLuint& group, GLuint& barrier) const { on = _traits->swapGroupEnabled; group = _traits->swapGroup; barrier = _traits->swapBarrier; } + public: /** Return whether a valid and usable GraphicsContext has been created.*/ diff --git a/include/osgViewer/api/Win32/GraphicsWindowWin32 b/include/osgViewer/api/Win32/GraphicsWindowWin32 index b10790958..71846ef2a 100644 --- a/include/osgViewer/api/Win32/GraphicsWindowWin32 +++ b/include/osgViewer/api/Win32/GraphicsWindowWin32 @@ -90,6 +90,9 @@ class OSGVIEWER_EXPORT GraphicsWindowWin32 : public osgViewer::GraphicsWindow, p /** Set sync-to-vblank. */ virtual void setSyncToVBlank(bool on); + /** Set swap group. */ + virtual void setSwapGroup(bool on, GLuint group, GLuint barrier); + /** Handle a native (Win32) windowing event as received from the system */ virtual LRESULT handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index dc41d29e6..cd06b69e4 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -178,6 +178,9 @@ GraphicsContext::Traits::Traits(DisplaySettings* ds): face(0), mipMapGeneration(false), vsync(true), + swapGroupEnabled(false), + swapGroup(0), + swapBarrier(0), useMultiThreadedOpenGLEngine(false), useCursor(true), glContextVersion("1.0"), diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index df0ab6e9b..a060ec01b 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/src/osgViewer/GraphicsWindowWin32.cpp @@ -1815,7 +1815,7 @@ bool GraphicsWindowWin32::realizeImplementation() if (!_initialized) return false; } - if (_traits.valid() && (_traits->sharedContext /*|| _traits->vsync*/)) + if (_traits.valid() && (_traits->sharedContext || _traits->vsync || _traits->swapGroupEnabled)) { // make context current so we can test capabilities and set up context sharing struct RestoreContext @@ -1827,10 +1827,7 @@ bool GraphicsWindowWin32::realizeImplementation() } ~RestoreContext() { - if (_hdc) - { - wglMakeCurrent(_hdc,_hglrc); - } + wglMakeCurrent(_hdc,_hglrc); } protected: HDC _hdc; @@ -1862,6 +1859,12 @@ bool GraphicsWindowWin32::realizeImplementation() { setSyncToVBlank(_traits->vsync); } + + // If the swap group is active then enable it. + if (_traits->swapGroupEnabled) + { + setSwapGroup(_traits->swapGroupEnabled, _traits->swapGroup, _traits->swapBarrier); + } } if (_ownsWindow) @@ -2207,6 +2210,36 @@ HCURSOR GraphicsWindowWin32::getOrCreateCursor(MouseCursor mouseCursor) return _mouseCursorMap[mouseCursor]; } +void GraphicsWindowWin32::setSwapGroup(bool on, GLuint group, GLuint barrier) +{ + if (_traits.valid()) + { + _traits->swapGroupEnabled = on; + _traits->swapGroup = group; + _traits->swapBarrier = barrier; + } + + typedef BOOL (GL_APIENTRY *PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); + PFNWGLJOINSWAPGROUPNVPROC wglJoinSwapGroupNV = (PFNWGLJOINSWAPGROUPNVPROC)wglGetProcAddress( "wglJoinSwapGroupNV" ); + + typedef BOOL (GL_APIENTRY *PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); + PFNWGLBINDSWAPBARRIERNVPROC wglBindSwapBarrierNV = (PFNWGLBINDSWAPBARRIERNVPROC)wglGetProcAddress( "wglBindSwapBarrierNV" ); + + if ((!wglJoinSwapGroupNV) || (!wglBindSwapBarrierNV)) + { + OSG_INFO << "GraphicsWindowWin32::wglJoinSwapGroupNV(bool, GLuint, GLuint) not supported" << std::endl; + return; + } + + int swapGroup = (on ? group : 0); + BOOL resultJoin = wglJoinSwapGroupNV(_hdc, swapGroup); + OSG_INFO << "GraphicsWindowWin32::wglJoinSwapGroupNV (" << swapGroup << ") returned " << resultJoin << std::endl; + + int swapBarrier = (on ? barrier : 0); + BOOL resultBind = wglBindSwapBarrierNV(swapGroup, swapBarrier); + OSG_INFO << "GraphicsWindowWin32::wglBindSwapBarrierNV (" << swapGroup << ", " << swapBarrier << ") returned " << resultBind << std::endl; +} + void GraphicsWindowWin32::setSyncToVBlank( bool on ) { if (_traits.valid()) @@ -2214,7 +2247,7 @@ void GraphicsWindowWin32::setSyncToVBlank( bool on ) _traits->vsync = on; } -#if 0 +//#if 0 // we ought to properly check if the extension is listed as supported rather than just // if the function pointer resolves through wglGetProcAddress, but in practice everything // supports this extension @@ -2232,9 +2265,9 @@ void GraphicsWindowWin32::setSyncToVBlank( bool on ) { OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not supported" << std::endl; } -#else - OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not yet implemented."<< std::endl; -#endif +//#else +// OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not yet implemented."<< std::endl; +//#endif } void GraphicsWindowWin32::adaptKey( WPARAM wParam, LPARAM lParam, int& keySymbol, unsigned int& modifierMask, int& unmodifiedKeySymbol)