Added single buffered and double buffered PBO support, and --no-pbo,
--single-pbo and --double-pbo command line parameters
This commit is contained in:
parent
f9f1aab67d
commit
90308d22aa
@ -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."<<std::endl;
|
||||
break;
|
||||
case(SINGLE_PBO):
|
||||
osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a single PixelBufferObject."<<std::endl;
|
||||
_pboBuffer.push_back(0);
|
||||
break;
|
||||
case(DOUBLE_PBO):
|
||||
osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a double buffer PixelBufferObject."<<std::endl;
|
||||
_pboBuffer.push_back(0);
|
||||
_pboBuffer.push_back(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void getSize(osg::GraphicsContext* gc, int& width, int& height)
|
||||
@ -72,39 +95,36 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback
|
||||
|
||||
void read()
|
||||
{
|
||||
std::cout<<"Read to "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
|
||||
|
||||
unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
|
||||
unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
|
||||
osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions(_gc->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 "<<width<<", "<<height<<std::endl;
|
||||
_width = width;
|
||||
_height = height;
|
||||
if (_pboBuffer.size()==1)
|
||||
{
|
||||
singlePBO(ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
multiPBO(ext);
|
||||
}
|
||||
}
|
||||
|
||||
osg::Image* image = _imageBuffer[_currentImageIndex].get();
|
||||
|
||||
image->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<osg::Image> > ImageBuffer;
|
||||
typedef std::vector< osg::ref_ptr<osg::PixelBufferObject> > 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 "<<gc<<std::endl;
|
||||
|
||||
osg::ref_ptr<ContextData> cd = getContextData(gc);
|
||||
cd->read();
|
||||
}
|
||||
|
||||
typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap;
|
||||
|
||||
|
||||
Mode _mode;
|
||||
mutable OpenThreads::Mutex _mutex;
|
||||
mutable ContextDataMap _contextDataMap;
|
||||
|
||||
};
|
||||
|
||||
void WindowCaptureCallback::ContextData::readPixels()
|
||||
{
|
||||
// std::cout<<"readPixels("<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
|
||||
|
||||
unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
|
||||
unsigned int nextPboIndex = _pboBuffer.empty() ? 0 : (_currentPboIndex+1)%_pboBuffer.size();
|
||||
|
||||
int width=0, height=0;
|
||||
getSize(_gc, width, height);
|
||||
if (width!=_width || _height!=height)
|
||||
{
|
||||
std::cout<<" Window resized "<<width<<", "<<height<<std::endl;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
osg::Image* image = _imageBuffer[_currentImageIndex].get();
|
||||
|
||||
image->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<<std::endl;
|
||||
|
||||
unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
|
||||
|
||||
int width=0, height=0;
|
||||
getSize(_gc, width, height);
|
||||
if (width!=_width || _height!=height)
|
||||
{
|
||||
std::cout<<" Window resized "<<width<<", "<<height<<std::endl;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
GLuint& pbo = _pboBuffer[0];
|
||||
|
||||
osg::Image* image = _imageBuffer[_currentImageIndex].get();
|
||||
if (image->s() != _width ||
|
||||
image->t() != _height)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
|
||||
image->allocateImage(_width, _height, 1, _pixelFormat, _type);
|
||||
|
||||
if (pbo!=0)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"deleting pbo "<<pbo<<std::endl;
|
||||
ext->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 "<<pbo<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext->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<<std::endl;
|
||||
unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
|
||||
unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
|
||||
|
||||
int width=0, height=0;
|
||||
getSize(_gc, width, height);
|
||||
if (width!=_width || _height!=height)
|
||||
{
|
||||
std::cout<<" Window resized "<<width<<", "<<height<<std::endl;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
GLuint& copy_pbo = _pboBuffer[_currentPboIndex];
|
||||
GLuint& read_pbo = _pboBuffer[nextPboIndex];
|
||||
|
||||
osg::Image* image = _imageBuffer[_currentImageIndex].get();
|
||||
if (image->s() != _width ||
|
||||
image->t() != _height)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
|
||||
image->allocateImage(_width, _height, 1, _pixelFormat, _type);
|
||||
|
||||
if (read_pbo!=0)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"deleting pbo "<<read_pbo<<std::endl;
|
||||
ext->glDeleteBuffers (1, &read_pbo);
|
||||
read_pbo = 0;
|
||||
}
|
||||
|
||||
if (copy_pbo!=0)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"deleting pbo "<<copy_pbo<<std::endl;
|
||||
ext->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 "<<read_pbo<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext->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<osg::Node> 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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user