From 90308d22aa903c876d66b8e9cc4ee0e290e3669e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 23 May 2008 16:26:03 +0000 Subject: [PATCH] Added single buffered and double buffered PBO support, and --no-pbo, --single-pbo and --double-pbo command line parameters --- .../osgscreencapture/osgscreencapture.cpp | 271 +++++++++++++++--- 1 file changed, 239 insertions(+), 32 deletions(-) diff --git a/examples/osgscreencapture/osgscreencapture.cpp b/examples/osgscreencapture/osgscreencapture.cpp index a1d80c7b0..581187627 100644 --- a/examples/osgscreencapture/osgscreencapture.cpp +++ b/examples/osgscreencapture/osgscreencapture.cpp @@ -36,11 +36,19 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback { public: + enum Mode + { + READ_PIXELS, + SINGLE_PBO, + DOUBLE_PBO + }; + struct ContextData : public osg::Referenced { - ContextData(osg::GraphicsContext* gc, const std::string& name): + ContextData(osg::GraphicsContext* gc, Mode mode, const std::string& name): _gc(gc), + _mode(mode), _fileName(name), _pixelFormat(GL_RGB), _type(GL_UNSIGNED_BYTE), @@ -57,8 +65,23 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback _imageBuffer.push_back(new osg::Image); // double buffer PBO. - _pboBuffer.push_back(new osg::PixelBufferObject); - _pboBuffer.push_back(new osg::PixelBufferObject); + switch(_mode) + { + case(READ_PIXELS): + osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with out PixelBufferObject."<getState()->getContextID(),true); - int width=0, height=0; - getSize(_gc, width, height); - if (width!=_width || _height!=height) + if (ext->isPBOSupported() && !_pboBuffer.empty()) { - std::cout<<" Window resized "<readPixels(0,0,_width,_height, - _pixelFormat,_type); - - if (!_fileName.empty()) + else { - osgDB::writeImageFile(*image, _fileName); + readPixels(); } - - _currentImageIndex = nextImageIndex; - _currentPboIndex = nextPboIndex; - } + + void readPixels(); + + void singlePBO(osg::BufferObject::Extensions* ext); + + void multiPBO(osg::BufferObject::Extensions* ext); typedef std::vector< osg::ref_ptr > ImageBuffer; - typedef std::vector< osg::ref_ptr > PBOBuffer; + typedef std::vector< GLuint > PBOBuffer; osg::GraphicsContext* _gc; + Mode _mode; std::string _fileName; GLenum _pixelFormat; @@ -119,7 +139,8 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback PBOBuffer _pboBuffer; }; - WindowCaptureCallback() + WindowCaptureCallback(Mode mode): + _mode(mode) { } @@ -127,7 +148,7 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback { std::stringstream filename; filename << "test_"<<_contextDataMap.size()<<".jpg"; - return new ContextData(gc,filename.str()); + return new ContextData(gc, _mode, filename.str()); } ContextData* getContextData(osg::GraphicsContext* gc) const @@ -142,19 +163,200 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback virtual void operator () (osg::RenderInfo& renderInfo) const { osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext(); - osg::notify(osg::NOTICE)<<"Capture screen image "< cd = getContextData(gc); cd->read(); } typedef std::map > ContextDataMap; - + + Mode _mode; mutable OpenThreads::Mutex _mutex; mutable ContextDataMap _contextDataMap; }; +void WindowCaptureCallback::ContextData::readPixels() +{ + // std::cout<<"readPixels("<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<readPixels(0,0,_width,_height, + _pixelFormat,_type); + + if (!_fileName.empty()) + { + // osgDB::writeImageFile(*image, _fileName); + } + + _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; + } + } + + + if (pbo==0) + { + ext->glGenBuffers(1, &pbo); + 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 "<glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); + } + + glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0); + + GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, + GL_READ_ONLY_ARB); + + if(src) + { + memcpy(image->data(), src, image->getTotalSizeInBytes()); + + ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); + } + + if (!_fileName.empty()) + { + // osgDB::writeImageFile(*image, _fileName); + } + + ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + + _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; + } + } + + + if (read_pbo==0) + { + ext->glGenBuffers(1, &read_pbo); + ext->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 "<glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo); + } + + glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0); + + + if (copy_pbo!=0) + { + + ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo); + + GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, + GL_READ_ONLY_ARB); + + if(src) + { + memcpy(image->data(), src, image->getTotalSizeInBytes()); + + ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); + } + + if (!_fileName.empty()) + { + // osgDB::writeImageFile(*image, _fileName); + } + } + + ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + + _currentImageIndex = nextImageIndex; + _currentPboIndex = nextPboIndex; +} + void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback) { osgViewer::ViewerBase::Windows windows; @@ -281,6 +483,11 @@ int main(int argc, char** argv) // add the LOD Scale handler viewer.addEventHandler(new osgViewer::LODScaleHandler); + WindowCaptureCallback::Mode mode = WindowCaptureCallback::DOUBLE_PBO; + while (arguments.read("--no-pbo")) mode = WindowCaptureCallback::READ_PIXELS; + while (arguments.read("--single-pbo")) mode = WindowCaptureCallback::SINGLE_PBO; + while (arguments.read("--double-pbo")) mode = WindowCaptureCallback::DOUBLE_PBO; + // load the data osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); if (!loadedModel) @@ -308,7 +515,7 @@ int main(int argc, char** argv) viewer.realize(); - addCallbackToViewer(viewer, new WindowCaptureCallback); + addCallbackToViewer(viewer, new WindowCaptureCallback(mode)); return viewer.run();