From 4c1fd0625220da5c36c002ead8f72b5e7cc4c4f5 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 21 Oct 2014 14:46:12 +0000 Subject: [PATCH] Added osg::SyncSwapBuffersCallback to include/osg/GraphicsContext and support for enabling it to include/osg/DisplaySettings, and to the Viewer/CompositeViewer::realize() methods. To enable the sync of swap buffers set the env var OSG_SYNC_SWAP_BUFFERS to ON or 1, to switch off set to OFF or 0. One can also use the --sync command line option for application that pass on command line options to the osg::DisplaySettings::instance(). git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14456 16af8721-9629-0410-8352-f15c8da7e697 --- include/osg/DisplaySettings | 11 +++++- include/osg/GraphicsContext | 51 +++++++++++++++++++++++++++ src/osg/DisplaySettings.cpp | 24 +++++++++++++ src/osg/GraphicsContext.cpp | 58 +++++++++++++++++++++++++++++++ src/osgViewer/CompositeViewer.cpp | 2 ++ src/osgViewer/Viewer.cpp | 2 ++ 6 files changed, 147 insertions(+), 1 deletion(-) diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index c0746cb62..c4b03e4ab 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -266,6 +266,15 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced /** Get preferred swap method */ SwapMethod getSwapMethod( void ) { return _swapMethod; } + + /** Set whether Arb Sync should be used to manage the swaps buffers, 0 disables the use of the sync, greater than zero enables sync based on number of frames specified.*/ + void setSyncSwapBuffers(unsigned int numFrames=0) { _syncSwapBuffers = numFrames; } + + /** Set whether Arb Sync should be used to manage the swaps buffers.*/ + unsigned int getSyncSwapBuffers() const { return _syncSwapBuffers; } + + + /** Set the hint of which OpenGL version to attempt to create a graphics context for.*/ void setGLContextVersion(const std::string& version) { _glContextVersion = version; } @@ -372,7 +381,7 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced unsigned int _glContextProfileMask; SwapMethod _swapMethod; - + unsigned int _syncSwapBuffers; bool _keystoneHint; FileNames _keystoneFileNames; diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index 625165f42..89b3aa815 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -531,6 +531,57 @@ class OSG_EXPORT GraphicsContext : public Object GLuint _defaultFboId; }; +//#include + +#ifndef GL_ARB_sync +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#endif + +class OSG_EXPORT SyncSwapBuffersCallback : public GraphicsContext::SwapCallback +{ +public: + SyncSwapBuffersCallback(); + + void setUpExtensions(); + + virtual void swapBuffersImplementation(GraphicsContext* gc); + + typedef struct __GLsync *GLsync; + + typedef GLsync (GL_APIENTRY * PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); + typedef GLboolean (GL_APIENTRY * PFNGLISSYNCPROC) (GLsync sync); + typedef void (GL_APIENTRY * PFNGLDELETESYNCPROC) (GLsync sync); + typedef GLenum (GL_APIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); + typedef void (GL_APIENTRY * PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); + typedef void (GL_APIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params); + typedef void (GL_APIENTRY * PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); + + bool _extensionInitialized; + + PFNGLFENCESYNCPROC _glFenceSync; + PFNGLISSYNCPROC _glIsSync; + PFNGLDELETESYNCPROC _glDeleteSync; + PFNGLCLIENTWAITSYNCPROC _glClientWaitSync; + PFNGLWAITSYNCPROC _glWaitSync; + PFNGLGETINTEGER64VPROC _glGetInteger64v; + PFNGLGETSYNCIVPROC _glGetSynciv; + + GLsync _previousSync; +}; } diff --git a/src/osg/DisplaySettings.cpp b/src/osg/DisplaySettings.cpp index d4a227d06..de261b665 100644 --- a/src/osg/DisplaySettings.cpp +++ b/src/osg/DisplaySettings.cpp @@ -218,6 +218,7 @@ void DisplaySettings::setDefaults() _glContextProfileMask = 0; _swapMethod = SWAP_DEFAULT; + _syncSwapBuffers = 0; _keystoneHint = false; @@ -630,6 +631,23 @@ void DisplaySettings::readEnvironmentalVariables() } + if ((ptr = getenv("OSG_SYNC_SWAP_BUFFERS")) != 0) + { + if (strcmp(ptr,"OFF")==0) + { + _syncSwapBuffers = 0; + } + else + if (strcmp(ptr,"ON")==0) + { + _syncSwapBuffers = 1; + } + else + { + _syncSwapBuffers = atoi(ptr); + } + } + if( (ptr = getenv("OSG_KEYSTONE")) != 0) { if (strcmp(ptr,"OFF")==0) @@ -715,6 +733,7 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) arguments.getApplicationUsage()->addCommandLineOption("--keystone-on","Set the keystone hint to true to tell the viewer to do keystone correction."); arguments.getApplicationUsage()->addCommandLineOption("--keystone-off","Set the keystone hint to false."); arguments.getApplicationUsage()->addCommandLineOption("--menubar-behavior ","Set the menubar behavior (AUTO_HIDE | FORCE_HIDE | FORCE_SHOW)"); + arguments.getApplicationUsage()->addCommandLineOption("--sync","Enable sync of swap buffers"); } std::string str; @@ -769,6 +788,11 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) _numMultiSamples = atoi(str.c_str()); } + while(arguments.read("--sync")) + { + _syncSwapBuffers = 1; + } + if (arguments.read("--keystone",str)) { _keystoneHint = true; diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index df2e2492f..df8e75512 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -975,3 +976,60 @@ void GraphicsContext::resizedImplementation(int x, int y, int width, int height) _traits->width = width; _traits->height = height; } + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// SyncSwapBuffersCallback +// +SyncSwapBuffersCallback::SyncSwapBuffersCallback(): + _extensionInitialized(false), + _glFenceSync(0), + _glIsSync(0), + _glDeleteSync(0), + _glClientWaitSync(0), + _glWaitSync(0), + _glGetInteger64v(0), + _glGetSynciv(0), + _previousSync(0) +{ + OSG_NOTICE<<"Created Swap callback."<swapBuffersImplementation(); + //glFinish(); + + if (!_extensionInitialized) setUpExtensions(); + + if (_glClientWaitSync) + { + if (_previousSync) + { + unsigned int num_seconds = 1; + GLuint64 timeout = num_seconds * ((GLuint64)1000 * 1000 * 1000); + _glClientWaitSync(_previousSync, 0, timeout); + + _glDeleteSync(_previousSync); + } + + _previousSync = _glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } + //gc->getState()->checkGLErrors("after glWaitSync"); + + //OSG_NOTICE<<"After swap"<getSyncSwapBuffers()) gc->setSwapCallback(new osg::SyncSwapBuffersCallback); + // set the pool sizes, 0 the default will result in no GL object pools. gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize); gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize); diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 177eb95aa..df6c0ec3b 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -544,6 +544,8 @@ void Viewer::realize() { osg::GraphicsContext* gc = *citr; + if (ds->getSyncSwapBuffers()) gc->setSwapCallback(new osg::SyncSwapBuffersCallback); + // set the pool sizes, 0 the default will result in no GL object pools. gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize); gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize);