Implemented ImagePager internals
This commit is contained in:
@@ -105,6 +105,7 @@ class OSG_EXPORT ImageSequence : public ImageStream
|
||||
Images _images;
|
||||
Images::iterator _imageIterator;
|
||||
double _imageIteratorTime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -292,7 +292,7 @@ class OSG_EXPORT NodeVisitor : public virtual Referenced
|
||||
ImageRequestHandler():
|
||||
Referenced(true) {}
|
||||
|
||||
virtual void requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const FrameStamp* framestamp, osg::ref_ptr<osg::Referenced>& imageRequest) = 0;
|
||||
virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const FrameStamp* framestamp) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~ImageRequestHandler() {}
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
#include <osg/Image>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/observer_ptr>
|
||||
#include <osg/OperationThread>
|
||||
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
#include <osgDB/ReaderWriter>
|
||||
@@ -30,7 +31,11 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler
|
||||
public:
|
||||
|
||||
ImagePager();
|
||||
|
||||
|
||||
|
||||
// forward declare
|
||||
struct RequestQueue;
|
||||
|
||||
struct ImageRequest : public osg::Referenced
|
||||
{
|
||||
ImageRequest():
|
||||
@@ -40,11 +45,49 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler
|
||||
double _timeToMergeBy;
|
||||
std::string _fileName;
|
||||
osg::ref_ptr<ReaderWriter::Options> _loadOptions;
|
||||
osg::ref_ptr<osg::Object> _objectToAttachTo;
|
||||
osg::observer_ptr<osg::Object> _objectToAttachTo;
|
||||
osg::ref_ptr<osg::Image> _loadedImage;
|
||||
|
||||
RequestQueue* _requestQueue;
|
||||
|
||||
};
|
||||
|
||||
struct RequestQueue : public osg::Referenced
|
||||
{
|
||||
typedef std::vector< osg::ref_ptr<ImageRequest> > RequestList;
|
||||
|
||||
void sort();
|
||||
|
||||
RequestList _requestList;
|
||||
OpenThreads::Mutex _requestMutex;
|
||||
};
|
||||
|
||||
|
||||
struct ReadQueue : public RequestQueue
|
||||
{
|
||||
ReadQueue(ImagePager* pager, const std::string& name);
|
||||
|
||||
void block() { _block->block(); }
|
||||
|
||||
void release() { _block->release(); }
|
||||
|
||||
void updateBlock()
|
||||
{
|
||||
_block->set((!_requestList.empty() || !_pager->_databasePagerThreadPaused));
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
void add(ImageRequest* imageRequest);
|
||||
|
||||
void takeFirst(osg::ref_ptr<ImageRequest>& databaseRequest);
|
||||
|
||||
osg::ref_ptr<osg::RefBlock> _block;
|
||||
|
||||
ImagePager* _pager;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
|
||||
class OSGDB_EXPORT ImageThread : public osg::Referenced, public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
@@ -72,22 +115,34 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler
|
||||
virtual ~ImageThread();
|
||||
|
||||
bool _done;
|
||||
ImagePager* _pager;
|
||||
Mode _mode;
|
||||
ImagePager* _pager;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
virtual void requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp, osg::ref_ptr<osg::Referenced>& imageRequest);
|
||||
virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp);
|
||||
|
||||
/** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */
|
||||
virtual bool requiresUpdateSceneGraph() const;
|
||||
|
||||
/** Merge the changes to the scene graph. */
|
||||
virtual void updateSceneGraph(double currentFrameTime);
|
||||
|
||||
int cancel();
|
||||
|
||||
public:
|
||||
|
||||
virtual ~ImagePager();
|
||||
|
||||
OpenThreads::Mutex _run_mutex;
|
||||
bool _startThreadCalled;
|
||||
|
||||
bool _done;
|
||||
bool _databasePagerThreadPaused;
|
||||
|
||||
osg::ref_ptr<ReadQueue> _readQueue;
|
||||
osg::ref_ptr<ImageThread> _imageThread;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ ImageSequence::ImageSequence()
|
||||
_duration = 1.0;
|
||||
_preLoadTime = 1.0;
|
||||
_timePerImage = 1.0;
|
||||
_pruneOldImages = false;
|
||||
_pruneOldImages = true;
|
||||
|
||||
_fileNamesIterator = _fileNames.end();
|
||||
_fileNamesIteratorTime = DBL_MAX;
|
||||
@@ -153,10 +153,12 @@ void ImageSequence::update(osg::NodeVisitor* nv)
|
||||
double time = (fs->getSimulationTime() - _referenceTime)*_timeMultiplier;
|
||||
double preLoadTime = (time+_preLoadTime)*_timeMultiplier;
|
||||
|
||||
FileNames::iterator previous_fileNamesIterator = _fileNamesIterator;
|
||||
Images::iterator previous_imageIterator = _imageIterator;
|
||||
|
||||
// osg::notify(osg::NOTICE)<<"time = "<<time<<std::endl;
|
||||
|
||||
if (irh)
|
||||
{
|
||||
//
|
||||
// Advance imageIterator
|
||||
@@ -171,11 +173,16 @@ void ImageSequence::update(osg::NodeVisitor* nv)
|
||||
osg::notify(osg::NOTICE)<<" need to preLoad = "<<*_fileNamesIterator<<std::endl;
|
||||
++_fileNamesIterator;
|
||||
|
||||
if (previous_fileNamesIterator==_fileNamesIterator) break;
|
||||
|
||||
if (_fileNamesIterator ==_fileNames.end())
|
||||
{
|
||||
// return iterator to begining of set.
|
||||
_fileNamesIterator = _fileNames.begin();
|
||||
}
|
||||
|
||||
irh->requestImageFile(*_fileNamesIterator, this, _fileNamesIteratorTime, fs);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +193,7 @@ void ImageSequence::update(osg::NodeVisitor* nv)
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
//
|
||||
// Advance imageIterator
|
||||
//
|
||||
@@ -204,6 +212,7 @@ void ImageSequence::update(osg::NodeVisitor* nv)
|
||||
if (_pruneOldImages)
|
||||
{
|
||||
_images.erase(previous_imageIterator, _imageIterator);
|
||||
previous_imageIterator = _images.begin();
|
||||
}
|
||||
|
||||
// return iterator to begining of set.
|
||||
|
||||
@@ -12,20 +12,107 @@
|
||||
*/
|
||||
|
||||
#include <osgDB/ImagePager>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osg/ImageSequence>
|
||||
|
||||
using namespace osgDB;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SortFileRequestFunctor
|
||||
//
|
||||
struct SortFileRequestFunctor
|
||||
{
|
||||
bool operator() (const osg::ref_ptr<ImagePager::ImageRequest>& lhs,const osg::ref_ptr<ImagePager::ImageRequest>& rhs) const
|
||||
{
|
||||
return (lhs->_timeToMergeBy < rhs->_timeToMergeBy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ReadQueue
|
||||
//
|
||||
void ImagePager::RequestQueue::sort()
|
||||
{
|
||||
std::sort(_requestList.begin(),_requestList.end(),SortFileRequestFunctor());
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ReadQueue
|
||||
//
|
||||
ImagePager::ReadQueue::ReadQueue(ImagePager* pager, const std::string& name):
|
||||
_pager(pager),
|
||||
_name(name)
|
||||
{
|
||||
_block = new osg::RefBlock;
|
||||
}
|
||||
|
||||
void ImagePager::ReadQueue::clear()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
|
||||
|
||||
for(RequestList::iterator citr = _requestList.begin();
|
||||
citr != _requestList.end();
|
||||
++citr)
|
||||
{
|
||||
(*citr)->_objectToAttachTo = 0;
|
||||
(*citr)->_requestQueue = 0;
|
||||
}
|
||||
|
||||
_requestList.clear();
|
||||
|
||||
updateBlock();
|
||||
}
|
||||
|
||||
void ImagePager::ReadQueue::add(ImagePager::ImageRequest* databaseRequest)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
|
||||
_requestList.push_back(databaseRequest);
|
||||
databaseRequest->_requestQueue = this;
|
||||
|
||||
updateBlock();
|
||||
}
|
||||
|
||||
void ImagePager::ReadQueue::takeFirst(osg::ref_ptr<ImageRequest>& databaseRequest)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
|
||||
|
||||
if (!_requestList.empty())
|
||||
{
|
||||
sort();
|
||||
|
||||
databaseRequest = _requestList.front();
|
||||
databaseRequest->_requestQueue = 0;
|
||||
_requestList.erase(_requestList.begin());
|
||||
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ImageThread
|
||||
//
|
||||
ImagePager::ImageThread::ImageThread(ImagePager* pager, Mode mode, const std::string& name)
|
||||
ImagePager::ImageThread::ImageThread(ImagePager* pager, Mode mode, const std::string& name):
|
||||
_done(false),
|
||||
_mode(mode),
|
||||
_pager(pager),
|
||||
_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
ImagePager::ImageThread::ImageThread(const ImageThread& dt, ImagePager* pager)
|
||||
ImagePager::ImageThread::ImageThread(const ImageThread& dt, ImagePager* pager):
|
||||
_done(false),
|
||||
_mode(dt._mode),
|
||||
_pager(pager),
|
||||
_name(dt._name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,28 +122,177 @@ ImagePager::ImageThread::~ImageThread()
|
||||
|
||||
int ImagePager::ImageThread::cancel()
|
||||
{
|
||||
return OpenThreads::Thread::cancel();
|
||||
int result = 0;
|
||||
|
||||
if( isRunning() )
|
||||
{
|
||||
|
||||
_done = true;
|
||||
|
||||
switch(_mode)
|
||||
{
|
||||
case(HANDLE_ALL_REQUESTS):
|
||||
_pager->_readQueue->release();
|
||||
break;
|
||||
case(HANDLE_NON_HTTP):
|
||||
_pager->_readQueue->release();
|
||||
break;
|
||||
case(HANDLE_ONLY_HTTP):
|
||||
_pager->_readQueue->release();
|
||||
break;
|
||||
}
|
||||
|
||||
// release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
|
||||
// _databasePagerThreadBlock->release();
|
||||
|
||||
// then wait for the the thread to stop running.
|
||||
while(isRunning())
|
||||
{
|
||||
// commenting out debug info as it was cashing crash on exit, presumable
|
||||
// due to osg::notify or std::cout destructing earlier than this destructor.
|
||||
// osg::notify(osg::DEBUG_INFO)<<"Waiting for DatabasePager to cancel"<<std::endl;
|
||||
OpenThreads::Thread::YieldCurrentThread();
|
||||
}
|
||||
|
||||
// _startThreadCalled = false;
|
||||
}
|
||||
//std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ImagePager::ImageThread::run()
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"ImagePager::ImageThread::run()"<<std::endl;
|
||||
bool firstTime = true;
|
||||
|
||||
osg::ref_ptr<ImagePager::ReadQueue> read_queue;
|
||||
|
||||
switch(_mode)
|
||||
{
|
||||
case(HANDLE_ALL_REQUESTS):
|
||||
read_queue = _pager->_readQueue;
|
||||
break;
|
||||
case(HANDLE_NON_HTTP):
|
||||
read_queue = _pager->_readQueue;
|
||||
break;
|
||||
case(HANDLE_ONLY_HTTP):
|
||||
read_queue = _pager->_readQueue;
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
read_queue->block();
|
||||
|
||||
osg::ref_ptr<ImageRequest> imageRequest;
|
||||
read_queue->takeFirst(imageRequest);
|
||||
|
||||
if (imageRequest.valid())
|
||||
{
|
||||
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(imageRequest->_fileName);
|
||||
if (image.valid())
|
||||
{
|
||||
osg::ImageSequence* is = dynamic_cast<osg::ImageSequence*>(imageRequest->_objectToAttachTo.get());
|
||||
if (is)
|
||||
{
|
||||
is->addImage(image.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Texture* texture = dynamic_cast<osg::Texture*>(imageRequest->_objectToAttachTo.get());
|
||||
if (texture)
|
||||
{
|
||||
texture->setImage(0, image.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
OpenThreads::Thread::YieldCurrentThread();
|
||||
}
|
||||
|
||||
|
||||
// go to sleep till our the next time our thread gets scheduled.
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
// do a yield to get round a peculiar thread hang when testCancel() is called
|
||||
// in certain circumstances - of which there is no particular pattern.
|
||||
YieldCurrentThread();
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
} while (!testCancel() && !_done);
|
||||
|
||||
osg::notify(osg::NOTICE)<<"ImagePager::ImageThread::done()"<<std::endl;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ImagePager
|
||||
//
|
||||
ImagePager::ImagePager()
|
||||
ImagePager::ImagePager():
|
||||
_done(false)
|
||||
{
|
||||
_startThreadCalled = false;
|
||||
_databasePagerThreadPaused = false;
|
||||
|
||||
_readQueue = new ReadQueue(this,"Image Queue");
|
||||
_imageThread = new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread");
|
||||
}
|
||||
|
||||
ImagePager::~ImagePager()
|
||||
{
|
||||
cancel();
|
||||
}
|
||||
|
||||
void ImagePager::requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp, osg::ref_ptr<osg::Referenced>& imageRequest)
|
||||
int ImagePager::cancel()
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"ImagePager::requestNodeFile("<<fileName<<")"<<std::endl;
|
||||
int result = 0;
|
||||
|
||||
_imageThread->setDone(true);
|
||||
|
||||
// release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
|
||||
_readQueue->release();
|
||||
|
||||
_imageThread->cancel();
|
||||
|
||||
_done = true;
|
||||
_startThreadCalled = false;
|
||||
|
||||
//std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ImagePager::requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp)
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<"ImagePager::requestNodeFile("<<fileName<<")"<<std::endl;
|
||||
|
||||
|
||||
osg::ref_ptr<ImageRequest> request = new ImageRequest;
|
||||
request->_timeToMergeBy = timeToMergeBy;
|
||||
request->_fileName = fileName;
|
||||
request->_objectToAttachTo = attachmentPoint;
|
||||
request->_requestQueue = _readQueue.get();
|
||||
|
||||
_readQueue->add(request.get());
|
||||
|
||||
if (!_startThreadCalled)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_run_mutex);
|
||||
|
||||
if (!_startThreadCalled)
|
||||
{
|
||||
_startThreadCalled = true;
|
||||
_done = false;
|
||||
_imageThread->startThread();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ImagePager::requiresUpdateSceneGraph() const
|
||||
|
||||
Reference in New Issue
Block a user