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:
|
public:
|
||||||
|
|
||||||
|
enum Mode
|
||||||
|
{
|
||||||
|
READ_PIXELS,
|
||||||
|
SINGLE_PBO,
|
||||||
|
DOUBLE_PBO
|
||||||
|
};
|
||||||
|
|
||||||
struct ContextData : public osg::Referenced
|
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),
|
_gc(gc),
|
||||||
|
_mode(mode),
|
||||||
_fileName(name),
|
_fileName(name),
|
||||||
_pixelFormat(GL_RGB),
|
_pixelFormat(GL_RGB),
|
||||||
_type(GL_UNSIGNED_BYTE),
|
_type(GL_UNSIGNED_BYTE),
|
||||||
@ -57,8 +65,23 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback
|
|||||||
_imageBuffer.push_back(new osg::Image);
|
_imageBuffer.push_back(new osg::Image);
|
||||||
|
|
||||||
// double buffer PBO.
|
// double buffer PBO.
|
||||||
_pboBuffer.push_back(new osg::PixelBufferObject);
|
switch(_mode)
|
||||||
_pboBuffer.push_back(new osg::PixelBufferObject);
|
{
|
||||||
|
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)
|
void getSize(osg::GraphicsContext* gc, int& width, int& height)
|
||||||
@ -72,39 +95,36 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback
|
|||||||
|
|
||||||
void read()
|
void read()
|
||||||
{
|
{
|
||||||
std::cout<<"Read to "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
|
osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions(_gc->getState()->getContextID(),true);
|
||||||
|
|
||||||
unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
|
|
||||||
unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
|
|
||||||
|
|
||||||
int width=0, height=0;
|
if (ext->isPBOSupported() && !_pboBuffer.empty())
|
||||||
getSize(_gc, width, height);
|
|
||||||
if (width!=_width || _height!=height)
|
|
||||||
{
|
{
|
||||||
std::cout<<" Window resized "<<width<<", "<<height<<std::endl;
|
if (_pboBuffer.size()==1)
|
||||||
_width = width;
|
{
|
||||||
_height = height;
|
singlePBO(ext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
multiPBO(ext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
osg::Image* image = _imageBuffer[_currentImageIndex].get();
|
|
||||||
|
|
||||||
image->readPixels(0,0,_width,_height,
|
|
||||||
_pixelFormat,_type);
|
|
||||||
|
|
||||||
if (!_fileName.empty())
|
|
||||||
{
|
{
|
||||||
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::Image> > ImageBuffer;
|
||||||
typedef std::vector< osg::ref_ptr<osg::PixelBufferObject> > PBOBuffer;
|
typedef std::vector< GLuint > PBOBuffer;
|
||||||
|
|
||||||
osg::GraphicsContext* _gc;
|
osg::GraphicsContext* _gc;
|
||||||
|
Mode _mode;
|
||||||
std::string _fileName;
|
std::string _fileName;
|
||||||
|
|
||||||
GLenum _pixelFormat;
|
GLenum _pixelFormat;
|
||||||
@ -119,7 +139,8 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback
|
|||||||
PBOBuffer _pboBuffer;
|
PBOBuffer _pboBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowCaptureCallback()
|
WindowCaptureCallback(Mode mode):
|
||||||
|
_mode(mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +148,7 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback
|
|||||||
{
|
{
|
||||||
std::stringstream filename;
|
std::stringstream filename;
|
||||||
filename << "test_"<<_contextDataMap.size()<<".jpg";
|
filename << "test_"<<_contextDataMap.size()<<".jpg";
|
||||||
return new ContextData(gc,filename.str());
|
return new ContextData(gc, _mode, filename.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextData* getContextData(osg::GraphicsContext* gc) const
|
ContextData* getContextData(osg::GraphicsContext* gc) const
|
||||||
@ -142,19 +163,200 @@ class WindowCaptureCallback : public osg::Camera::DrawCallback
|
|||||||
virtual void operator () (osg::RenderInfo& renderInfo) const
|
virtual void operator () (osg::RenderInfo& renderInfo) const
|
||||||
{
|
{
|
||||||
osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
|
osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
|
||||||
osg::notify(osg::NOTICE)<<"Capture screen image "<<gc<<std::endl;
|
|
||||||
|
|
||||||
osg::ref_ptr<ContextData> cd = getContextData(gc);
|
osg::ref_ptr<ContextData> cd = getContextData(gc);
|
||||||
cd->read();
|
cd->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap;
|
typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap;
|
||||||
|
|
||||||
|
Mode _mode;
|
||||||
mutable OpenThreads::Mutex _mutex;
|
mutable OpenThreads::Mutex _mutex;
|
||||||
mutable ContextDataMap _contextDataMap;
|
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)
|
void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback)
|
||||||
{
|
{
|
||||||
osgViewer::ViewerBase::Windows windows;
|
osgViewer::ViewerBase::Windows windows;
|
||||||
@ -281,6 +483,11 @@ int main(int argc, char** argv)
|
|||||||
// add the LOD Scale handler
|
// add the LOD Scale handler
|
||||||
viewer.addEventHandler(new osgViewer::LODScaleHandler);
|
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
|
// load the data
|
||||||
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
|
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
|
||||||
if (!loadedModel)
|
if (!loadedModel)
|
||||||
@ -308,7 +515,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
viewer.realize();
|
viewer.realize();
|
||||||
|
|
||||||
addCallbackToViewer(viewer, new WindowCaptureCallback);
|
addCallbackToViewer(viewer, new WindowCaptureCallback(mode));
|
||||||
|
|
||||||
return viewer.run();
|
return viewer.run();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user