From cad2f6d4fc9441139d4f126772479b8ae16ccf81 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 21 Jul 2008 21:28:48 +0000 Subject: [PATCH] From Jean-Sebastien Guay, "Changes attached so that the CaptureOperation is passed in the constructor of the ScreenCaptureHandler (default 0 = default CaptureOperation). This way, you can do: viewer.addEventHandler(new osgViewer::ScreenCaptureHandler( new osgViewer::WriteToFileCaptureOperation("filename", "jpg"))); and the filename will be what you want. The WriteToFileCaptureOperation will add the context ID and the file number (if in SEQUENTIAL_NUMBER mode) to the file name. (The attached also clarifies some notify messages, and corrects the comment when adding the handler in osgviewer.cpp) I also remembered, the current architecture could allow a different CaptureOperation for each context, but currently the API only allows setting one CaptureOperation for all contexts. This could be improved if need be. " --- applications/osgviewer/osgviewer.cpp | 2 +- include/osgViewer/ViewerEventHandlers | 8 +- src/osgViewer/ScreenCaptureHandler.cpp | 124 +++++++++---------------- 3 files changed, 49 insertions(+), 85 deletions(-) diff --git a/applications/osgviewer/osgviewer.cpp b/applications/osgviewer/osgviewer.cpp index 32cbb72e7..642233db3 100644 --- a/applications/osgviewer/osgviewer.cpp +++ b/applications/osgviewer/osgviewer.cpp @@ -123,7 +123,7 @@ int main(int argc, char** argv) // add the LOD Scale handler viewer.addEventHandler(new osgViewer::LODScaleHandler); - // add the LOD Scale handler + // add the screen capture handler viewer.addEventHandler(new osgViewer::ScreenCaptureHandler); // load the data diff --git a/include/osgViewer/ViewerEventHandlers b/include/osgViewer/ViewerEventHandlers index 08b02b180..a5d88ac7d 100644 --- a/include/osgViewer/ViewerEventHandlers +++ b/include/osgViewer/ViewerEventHandlers @@ -355,6 +355,7 @@ class OSGVIEWER_EXPORT WindowCaptureCallback : public osg::Camera::DrawCallback void updateTimings(osg::Timer_t tick_start, osg::Timer_t tick_afterReadPixels, osg::Timer_t tick_afterMemCpy, + osg::Timer_t tick_afterCaptureOperation, unsigned int dataSize); void read(); @@ -384,8 +385,10 @@ class OSGVIEWER_EXPORT WindowCaptureCallback : public osg::Camera::DrawCallback unsigned int _reportTimingFrequency; unsigned int _numTimeValuesRecorded; double _timeForReadPixels; - double _timeForFullCopy; double _timeForMemCpy; + double _timeForCaptureOperation; + double _timeForFullCopy; + double _timeForFullCopyAndOperation; osg::Timer_t _previousFrameTick; osg::ref_ptr _captureOperation; @@ -411,13 +414,14 @@ class OSGVIEWER_EXPORT WindowCaptureCallback : public osg::Camera::DrawCallback mutable OpenThreads::Mutex _mutex; mutable ContextDataMap _contextDataMap; + osg::ref_ptr _defaultCaptureOperation; }; /** Event handler that will capture the screen on key press. */ class OSGVIEWER_EXPORT ScreenCaptureHandler : public osgGA::GUIEventHandler { public: - ScreenCaptureHandler(); + ScreenCaptureHandler(CaptureOperation* defaultOperation = 0); void setKeyEventTakeScreenShot(int key) { _keyEventTakeScreenShot = key; } int getKeyEventTakeScreenShot() const { return _keyEventTakeScreenShot; } diff --git a/src/osgViewer/ScreenCaptureHandler.cpp b/src/osgViewer/ScreenCaptureHandler.cpp index ca7d18e7f..c6d8c37b7 100644 --- a/src/osgViewer/ScreenCaptureHandler.cpp +++ b/src/osgViewer/ScreenCaptureHandler.cpp @@ -50,7 +50,7 @@ void WriteToFileCaptureOperation::operator () (const osg::Image& image, const un osgDB::writeImageFile(image, filename.str()); - osg::notify(osg::INFO)<<"Taking a screenshot, saved as '"<getTraits()->alpha) { - osg::notify(level)<<"Select GL_RGBA read back format"<delta_s(tick_start, tick_afterReadPixels); - double timeForFullCopy = osg::Timer::instance()->delta_s(tick_start, tick_afterMemCpy); - double timeForMemCpy = osg::Timer::instance()->delta_s(tick_afterReadPixels, tick_afterMemCpy); - - _timeForReadPixels += timeForReadPixels; - _timeForFullCopy += timeForFullCopy; - _timeForMemCpy += timeForMemCpy; - - ++_numTimeValuesRecorded; - - if (_numTimeValuesRecorded==_reportTimingFrequency) - { - timeForReadPixels = _timeForReadPixels/double(_numTimeValuesRecorded); - timeForFullCopy = _timeForFullCopy/double(_numTimeValuesRecorded); - timeForMemCpy = _timeForMemCpy/double(_numTimeValuesRecorded); - - double averageFrameTime = osg::Timer::instance()->delta_s(_previousFrameTick, tick_afterMemCpy)/double(_numTimeValuesRecorded); - double fps = 1.0/averageFrameTime; - _previousFrameTick = tick_afterMemCpy; - - _timeForReadPixels = 0.0; - _timeForFullCopy = 0.0; - _timeForMemCpy = 0.0; - - _numTimeValuesRecorded = 0; - - double numMPixels = double(_width * _height) / 1000000.0; - double numMb = double(dataSize) / (1024*1024); - - int prec = osg::notify(osg::NOTICE).precision(5); - - if (timeForMemCpy==0.0) - { - osg::notify(osg::NOTICE)<<"fps = "<delta_s(tick_start, tick_afterReadPixels); - _timeForFullCopy = osg::Timer::instance()->delta_s(tick_start, tick_afterMemCpy); _timeForMemCpy = osg::Timer::instance()->delta_s(tick_afterReadPixels, tick_afterMemCpy); + _timeForCaptureOperation = osg::Timer::instance()->delta_s(tick_afterMemCpy, tick_afterCaptureOperation); + + _timeForFullCopy = osg::Timer::instance()->delta_s(tick_start, tick_afterMemCpy); + _timeForFullCopyAndOperation = osg::Timer::instance()->delta_s(tick_start, tick_afterCaptureOperation); } void WindowCaptureCallback::ContextData::read() @@ -220,8 +177,6 @@ void WindowCaptureCallback::ContextData::read() void WindowCaptureCallback::ContextData::readPixels() { - // std::cout<<"readPixels("<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<tick(); - updateTimings(tick_start, tick_afterReadPixels, tick_afterReadPixels, image->getTotalSizeInBytes()); - if (_captureOperation.valid()) { (*_captureOperation)(*image, _index); } + osg::Timer_t tick_afterCaptureOperation = osg::Timer::instance()->tick(); + updateTimings(tick_start, tick_afterReadPixels, tick_afterReadPixels, tick_afterCaptureOperation, image->getTotalSizeInBytes()); + _currentImageIndex = nextImageIndex; _currentPboIndex = nextPboIndex; } void WindowCaptureCallback::ContextData::singlePBO(osg::BufferObject::Extensions* ext) { - // std::cout<<"singelPBO( "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<s() != _width || image->t() != _height) { - //osg::notify(osg::NOTICE)<<"Allocating image "<allocateImage(_width, _height, 1, _pixelFormat, _type); if (pbo!=0) { - //osg::notify(osg::NOTICE)<<"deleting pbo "<glDeleteBuffers (1, &pbo); pbo = 0; } @@ -295,7 +249,7 @@ void WindowCaptureCallback::ContextData::singlePBO(osg::BufferObject::Extensions ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); - //osg::notify(osg::NOTICE)<<"Generating pbo "<tick(); - updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes()); - if (_captureOperation.valid()) { (*_captureOperation)(*image, _index); } + osg::Timer_t tick_afterCaptureOperation = osg::Timer::instance()->tick(); + updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, tick_afterCaptureOperation, image->getTotalSizeInBytes()); _currentImageIndex = nextImageIndex; } void WindowCaptureCallback::ContextData::multiPBO(osg::BufferObject::Extensions* ext) { - // std::cout<<"multiPBO( "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<s() != _width || image->t() != _height) { - //osg::notify(osg::NOTICE)<<"Allocating image "<allocateImage(_width, _height, 1, _pixelFormat, _type); if (read_pbo!=0) { - //osg::notify(osg::NOTICE)<<"deleting pbo "<glDeleteBuffers (1, &read_pbo); read_pbo = 0; } if (copy_pbo!=0) { - //osg::notify(osg::NOTICE)<<"deleting pbo "<glDeleteBuffers (1, ©_pbo); copy_pbo = 0; } @@ -381,7 +334,7 @@ void WindowCaptureCallback::ContextData::multiPBO(osg::BufferObject::Extensions* ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo); ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); - //osg::notify(osg::NOTICE)<<"Generating pbo "<glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo); ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); - //osg::notify(osg::NOTICE)<<"Generating pbo "<tick(); - updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes()); + updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, tick_afterMemCpy, image->getTotalSizeInBytes()); _currentImageIndex = nextImageIndex; _currentPboIndex = nextPboIndex; @@ -444,10 +397,8 @@ WindowCaptureCallback::WindowCaptureCallback(Mode mode, FramePosition position, WindowCaptureCallback::ContextData* WindowCaptureCallback::createContextData(osg::GraphicsContext* gc) const { - std::stringstream filename; - filename << "screen_shot_"<<_contextDataMap.size(); WindowCaptureCallback::ContextData* cd = new WindowCaptureCallback::ContextData(gc, _mode, _readBuffer); - cd->_captureOperation = new WriteToFileCaptureOperation(filename.str(), "jpg", WriteToFileCaptureOperation::SEQUENTIAL_NUMBER); + cd->_captureOperation = _defaultCaptureOperation; return cd; } @@ -462,6 +413,8 @@ WindowCaptureCallback::ContextData* WindowCaptureCallback::getContextData(osg::G void WindowCaptureCallback::setCaptureOperation(CaptureOperation* operation) { + _defaultCaptureOperation = operation; + // Set the capture operation for each ContextData. for (ContextDataMap::iterator it = _contextDataMap.begin(); it != _contextDataMap.end(); ++it) { @@ -486,14 +439,17 @@ void WindowCaptureCallback::operator () (osg::RenderInfo& renderInfo) const renderInfo.getCurrentCamera()->setFinalDrawCallback(0); int prec = osg::notify(osg::INFO).precision(5); - osg::notify(osg::INFO)<<"Took a screenshot in " << (cd->_timeForFullCopy*1000.0f) << "ms" << std::endl; + osg::notify(osg::INFO) << "ScreenCaptureHandler: " + << "copy=" << (cd->_timeForFullCopy*1000.0f) << "ms, " + << "operation=" << (cd->_timeForCaptureOperation*1000.0f) << "ms, " + << "total=" << (cd->_timeForFullCopyAndOperation*1000.0f) << std::endl; osg::notify(osg::INFO).precision(prec); cd->_timeForFullCopy = 0; } -ScreenCaptureHandler::ScreenCaptureHandler() +ScreenCaptureHandler::ScreenCaptureHandler(CaptureOperation* defaultOperation) : _keyEventTakeScreenShot('c'), _callback(new WindowCaptureCallback( WindowCaptureCallback::READ_PIXELS, @@ -502,6 +458,10 @@ ScreenCaptureHandler::ScreenCaptureHandler() // WindowCaptureCallback::TRIPLE_PBO, WindowCaptureCallback::END_FRAME, GL_BACK)) { + if (defaultOperation) + setCaptureOperation(defaultOperation); + else + setCaptureOperation(new WriteToFileCaptureOperation("screen_shot", "jpg")); } void ScreenCaptureHandler::addCallbackToViewer(osgViewer::ViewerBase& viewer) @@ -551,13 +511,13 @@ void ScreenCaptureHandler::addCallbackToViewer(osgViewer::ViewerBase& viewer) if (firstCamera) { - //osg::notify(osg::NOTICE)<<"First camera "<setInitialDrawCallback(_callback.get()); } else { - osg::notify(osg::NOTICE)<<"No camera found"<setFinalDrawCallback(_callback.get()); } else { - osg::notify(osg::NOTICE)<<"No camera found"<