Introduce new run frame rate management support to allow control of maximum frame rate and to support on demand rendering of frames

This commit is contained in:
Robert Osfield
2009-04-24 16:20:50 +00:00
parent 860ae27faf
commit a50f0ccfaf
10 changed files with 198 additions and 57 deletions

View File

@@ -37,7 +37,17 @@ CompositeViewer::CompositeViewer(const CompositeViewer& cv,const osg::CopyOp& co
CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments)
{
constructorInit();
arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required.");
arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously.");
arguments.getApplicationUsage()->addCommandLineOption("--run-max-frame-rate","Set the run methods maximum permissable frame rate, 0.0 is default and switching off frame rate capping.");
std::string filename;
bool readConfig = false;
while (arguments.read("-c",filename))
@@ -50,6 +60,14 @@ CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments)
while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext);
while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext);
while(arguments.read("--run-on-demand")) { setRunFrameScheme(ON_DEMAND); }
while(arguments.read("--run-continuous")) { setRunFrameScheme(CONTINUOUS); }
double runMaxFrameRate;
while(arguments.read("--run-max-frame-rate", runMaxFrameRate)) { setRunMaxFrameRate(runMaxFrameRate); }
osg::DisplaySettings::instance()->readCommandLine(arguments);
osgDB::readCommandLine(arguments);
}
@@ -222,6 +240,34 @@ bool CompositeViewer::isRealized() const
return numRealizedWindows > 0;
}
bool CompositeViewer::checkNeedToDoFrame()
{
if (_requestRedraw) return true;
if (_requestContinousUpdate) return true;
for(RefViews::iterator itr = _views.begin();
itr != _views.end();
++itr)
{
osgViewer::View* view = itr->get();
if (view)
{
// If the database pager is going to update the scene the render flag is
// set so that the updates show up
if (view->getDatabasePager()->requiresUpdateSceneGraph() ||
view->getDatabasePager()->getRequestsInProgress()) return true;
}
}
// now do a eventTraversal to see if any events might require a new frame.
eventTraversal();
if (_requestRedraw) return true;
if (_requestContinousUpdate) return true;
return false;
}
int CompositeViewer::run()
{
for(RefViews::iterator itr = _views.begin();

View File

@@ -183,7 +183,7 @@ bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdap
break;
}
aa.requestRedraw();
}
return true;
}

View File

@@ -1696,10 +1696,12 @@ void View::assignSceneDataToCameras()
void View::requestRedraw()
{
getViewerBase()->_requestRedraw = true;
}
void View::requestContinuousUpdate(bool)
void View::requestContinuousUpdate(bool flag)
{
getViewerBase()->_requestContinousUpdate = flag;
}
void View::requestWarpPointer(float x,float y)

View File

@@ -53,6 +53,11 @@ Viewer::Viewer(osg::ArgumentParser& arguments)
arguments.getApplicationUsage()->addCommandLineOption("--clear-color <color>","Set the background color of the viewer in the form \"r,g,b[,a]\".");
arguments.getApplicationUsage()->addCommandLineOption("--screen <num>","Set the screen to use when multiple screens are present.");
arguments.getApplicationUsage()->addCommandLineOption("--window <x y w h>","Set the position (x,y) and size (w,h) of the viewer window.");
arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required.");
arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously.");
arguments.getApplicationUsage()->addCommandLineOption("--run-max-frame-rate","Set the run methods maximum permissable frame rate, 0.0 is default and switching off frame rate capping.");
// FIXME: Uncomment these lines when the options have been documented properly
//arguments.getApplicationUsage()->addCommandLineOption("--3d-sd","");
//arguments.getApplicationUsage()->addCommandLineOption("--panoramic-sd","");
@@ -84,13 +89,21 @@ Viewer::Viewer(osg::ArgumentParser& arguments)
if( cnt==3 || cnt==4 ) getCamera()->setClearColor( osg::Vec4(r,g,b,a) );
else osg::notify(osg::WARN)<<"Invalid clear color \""<<colorStr<<"\""<<std::endl;
}
while(arguments.read("--run-on-demand")) { setRunFrameScheme(ON_DEMAND); }
while(arguments.read("--run-continuous")) { setRunFrameScheme(CONTINUOUS); }
double runMaxFrameRate;
while(arguments.read("--run-max-frame-rate", runMaxFrameRate)) { setRunMaxFrameRate(runMaxFrameRate); }
int screenNum = -1;
while (arguments.read("--screen",screenNum)) {}
int x = -1, y = -1, width = -1, height = -1;
while (arguments.read("--window",x,y,width,height)) {}
bool ss3d = false;
bool wowvx20 = false;
bool wowvx42 = false;
@@ -309,22 +322,40 @@ bool Viewer::isRealized() const
return numRealizedWindows > 0;
}
bool Viewer::checkNeedToDoFrame()
{
if (_requestRedraw) return true;
if (_requestContinousUpdate) return true;
// If the database pager is going to update the scene the render flag is
// set so that the updates show up
if(getDatabasePager()->requiresUpdateSceneGraph() || getDatabasePager()->getRequestsInProgress()) return true;
// now do a eventTraversal to see if any events might require a new frame.
eventTraversal();
if (_requestRedraw) return true;
if (_requestContinousUpdate) return true;
return false;
}
int Viewer::run()
{
if (!getCameraManipulator() && getCamera()->getAllowEventFocus())
{
setCameraManipulator(new osgGA::TrackballManipulator());
}
setReleaseContextAtEndOfFrameHint(false);
return ViewerBase::run();
}
void Viewer::setStartTick(osg::Timer_t tick)
{
View::setStartTick(tick);
Contexts contexts;
getContexts(contexts,false);

View File

@@ -33,25 +33,24 @@ static osg::ApplicationUsageProxy ViewerBase_e0(osg::ApplicationUsage::ENVIRONME
static osg::ApplicationUsageProxy ViewerBase_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREADING <value>","Set the threading model using by Viewer, <value> can be SingleThreaded, CullDrawThreadPerContext, DrawThreadPerContext or CullThreadPerCameraDrawThreadPerContext.");
static osg::ApplicationUsageProxy ViewerBase_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN <value>","Set the default screen that windows should open up on.");
static osg::ApplicationUsageProxy ViewerBase_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x y width height","Set the default window dimensions that windows should open up on.");
static osg::ApplicationUsageProxy ViewerBase_e4(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_FRAME_SCHEME","Frame rate manage scheme that viewer run should use, ON_DEMAND or CONTINUOUS (default).");
static osg::ApplicationUsageProxy ViewerBase_e5(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_MAX_FRAME_RATE","Set the maximum number of frame as second that viewer run. 0.0 is default and disables an frame rate capping.");
using namespace osgViewer;
ViewerBase::ViewerBase():
osg::Object(true)
{
_firstFrame = true;
_done = false;
_keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape;
_quitEventSetsDone = true;
_releaseContextAtEndOfFrameHint = true;
_threadingModel = AutomaticSelection;
_threadsRunning = false;
_endBarrierPosition = AfterSwapBuffers;
viewerBaseInit();
}
ViewerBase::ViewerBase(const ViewerBase& base):
osg::Object(true)
{
viewerBaseInit();
}
void ViewerBase::viewerBaseInit()
{
_firstFrame = true;
_done = false;
@@ -61,6 +60,24 @@ ViewerBase::ViewerBase(const ViewerBase& base):
_threadingModel = AutomaticSelection;
_threadsRunning = false;
_endBarrierPosition = AfterSwapBuffers;
_requestRedraw = true;
_requestContinousUpdate = false;
_runFrameScheme = CONTINUOUS;
_runMaxFrameRate = 0.0f;
const char* str = getenv("OSG_RUN_FRAME_SCHEME");
if (str)
{
if (strcmp(str, "ON_DEMAND")==0) _runFrameScheme = ON_DEMAND;
else if (strcmp(str, "CONTINUOUS")==0) _runFrameScheme = CONTINUOUS;
}
str = getenv("OSG_RUN_MAX_FRAME_RATE");
if (str)
{
_runMaxFrameRate = atof(str);
}
}
void ViewerBase::setThreadingModel(ThreadingModel threadingModel)
@@ -573,30 +590,28 @@ int ViewerBase::run()
realize();
}
#if 0
while (!done())
{
frame();
}
#else
const char* str = getenv("OSG_RUN_FRAME_COUNT");
if (str)
int runTillFrameNumber = str==0 ? -1 : atoi(str);
while(!done() || (runTillFrameNumber>=0 && getViewerFrameStamp()->getFrameNumber()>runTillFrameNumber))
{
int runTillFrameNumber = atoi(str);
while (!done() && getViewerFrameStamp()->getFrameNumber()<runTillFrameNumber)
double minFrameTime = _runMaxFrameRate>0.0 ? 1.0/_runMaxFrameRate : 0.0;
osg::Timer_t startFrameTick = osg::Timer::instance()->tick();
if (_runFrameScheme==ON_DEMAND)
{
if (checkNeedToDoFrame()) frame();
}
else
{
frame();
}
// work out if we need to force a sleep to hold back the frame rate
osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
double frameTime = osg::Timer::instance()->delta_s(startFrameTick, endFrameTick);
if (frameTime < minFrameTime) OpenThreads::Thread::microSleep(1000000.0*(minFrameTime-frameTime));
}
else
{
while (!done())
{
frame();
}
}
#endif
return 0;
}
@@ -842,5 +857,7 @@ void ViewerBase::renderingTraversals()
getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals);
getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals);
}
_requestRedraw = false;
}

View File

@@ -100,6 +100,8 @@ bool WindowSizeHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActio
{
toggleFullscreen(*itr);
}
aa.requestRedraw();
return true;
}
else if (_changeWindowedResolution == true && ea.getKey() == _keyEventWindowedResolutionUp)
@@ -114,6 +116,8 @@ bool WindowSizeHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActio
{
changeWindowedResolution(*itr, true);
}
aa.requestRedraw();
return true;
}
else if (_changeWindowedResolution == true && ea.getKey() == _keyEventWindowedResolutionDown)
@@ -128,6 +132,8 @@ bool WindowSizeHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActio
{
changeWindowedResolution(*itr, false);
}
aa.requestRedraw();
return true;
}
break;
@@ -317,6 +323,7 @@ bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIAction
if (_changeThreadingModel == true && ea.getKey() == _keyEventChangeThreadingModel && delta > 1.0)
{
_tickOrLastKeyPress = osg::Timer::instance()->tick();
switch(viewerBase->getThreadingModel())
@@ -348,6 +355,8 @@ bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIAction
#endif
break;
}
aa.requestRedraw();
return true;
}
if (viewer && _changeEndBarrierPosition == true && ea.getKey() == _keyEventChangeEndBarrierPosition)
@@ -363,6 +372,8 @@ bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIAction
osg::notify(osg::NOTICE)<<"Threading model 'BeforeSwapBuffers' selected."<<std::endl;
break;
}
aa.requestRedraw();
return true;
}
break;
@@ -575,6 +586,8 @@ bool LODScaleHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionA
{
camera->setLODScale(camera->getLODScale()*1.1);
osg::notify(osg::NOTICE)<<"LODScale = "<<camera->getLODScale()<<std::endl;
aa.requestRedraw();
return true;
}
@@ -582,8 +595,10 @@ bool LODScaleHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionA
{
camera->setLODScale(camera->getLODScale()/1.1);
osg::notify(osg::NOTICE)<<"LODScale = "<<camera->getLODScale()<<std::endl;
aa.requestRedraw();
return true;
}
}
break;
}