2012-03-22 01:36:20 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2008-07-21 18:10:01 +08:00
*
2012-03-22 01:36:20 +08:00
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
2008-07-21 18:10:01 +08:00
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
2012-03-22 01:36:20 +08:00
*
2008-07-21 18:10:01 +08:00
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2012-03-22 01:36:20 +08:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-07-21 18:10:01 +08:00
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGDB_IMAGEPAGER
#define OSGDB_IMAGEPAGER 1
#include <osg/Image>
2008-07-22 05:00:57 +08:00
#include <osg/NodeVisitor>
2008-07-24 03:04:46 +08:00
#include <osg/observer_ptr>
#include <osg/OperationThread>
2008-08-18 00:52:35 +08:00
#include <osg/FrameStamp>
2008-07-21 18:10:01 +08:00
#include <OpenThreads/Mutex>
2012-11-13 19:45:20 +08:00
#include <OpenThreads/Atomic>
2008-07-21 18:10:01 +08:00
#include <osgDB/ReaderWriter>
2009-05-09 16:49:27 +08:00
#include <osgDB/Options>
2008-07-21 18:10:01 +08:00
namespace osgDB
{
2008-07-22 05:00:57 +08:00
class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler
2008-07-21 18:10:01 +08:00
{
public:
2012-03-22 01:36:20 +08:00
2008-07-21 18:10:01 +08:00
ImagePager();
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
class OSGDB_EXPORT ImageThread : public osg::Referenced, public OpenThreads::Thread
{
public:
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
enum Mode
{
HANDLE_ALL_REQUESTS,
HANDLE_NON_HTTP,
HANDLE_ONLY_HTTP
};
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
ImageThread(ImagePager* pager, Mode mode, const std::string& name);
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
ImageThread(const ImageThread& dt, ImagePager* pager);
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
void setDone(bool done) { _done = done; }
bool getDone() const { return _done; }
virtual int cancel();
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
virtual void run();
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
protected:
virtual ~ImageThread();
2012-03-22 01:36:20 +08:00
2012-11-08 19:19:31 +08:00
bool _done;
Mode _mode;
ImagePager* _pager;
std::string _name;
2008-07-24 05:49:07 +08:00
};
2008-07-25 21:45:07 +08:00
ImageThread* getImageThread(unsigned int i) { return _imageThreads[i].get(); }
2012-03-22 01:36:20 +08:00
2008-07-25 21:45:07 +08:00
const ImageThread* getImageThread(unsigned int i) const { return _imageThreads[i].get(); }
2013-05-15 00:12:21 +08:00
unsigned int getNumImageThreads() const { return static_cast<unsigned int>(_imageThreads.size()); }
2012-03-22 01:36:20 +08:00
2008-07-25 21:45:07 +08:00
2008-07-26 00:11:51 +08:00
void setPreLoadTime(double preLoadTime) { _preLoadTime=preLoadTime; }
virtual double getPreLoadTime() const { return _preLoadTime; }
2013-01-19 01:11:49 +08:00
virtual osg::Image* readImageFile(const std::string& fileName, const osg::Referenced* options=0);
2008-07-26 00:11:51 +08:00
2012-11-08 19:19:31 +08:00
virtual void requestImageFile(const std::string& fileName, osg::Object* attachmentPoint, int attachmentIndex, double timeToMergeBy, const osg::FrameStamp* framestamp, osg::ref_ptr<osg::Referenced>& imageRequest, const osg::Referenced* options);
2008-07-26 00:11:51 +08:00
2008-07-24 05:49:07 +08:00
/** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */
virtual bool requiresUpdateSceneGraph() const;
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
/** Merge the changes to the scene graph. */
2008-08-18 00:52:35 +08:00
virtual void updateSceneGraph(const osg::FrameStamp &frameStamp);
2012-03-22 01:36:20 +08:00
2012-11-13 19:45:20 +08:00
/** Signal the image thread that the update, cull and draw has begun for a new frame.
* Note, this is called by the application so that the image pager can go to sleep while the CPU is busy on the main rendering threads. */
virtual void signalBeginFrame(const osg::FrameStamp* framestamp);
/** Signal the image thread that the update, cull and draw dispatch has completed.
* Note, this is called by the application so that the image pager can go to wake back up now the main rendering threads are iddle waiting for the next frame.*/
virtual void signalEndFrame();
2008-07-24 05:49:07 +08:00
int cancel();
protected:
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
virtual ~ImagePager();
2012-03-22 01:36:20 +08:00
// forward declare
2008-07-24 03:04:46 +08:00
struct RequestQueue;
2012-03-22 01:36:20 +08:00
2008-07-24 05:49:07 +08:00
struct SortFileRequestFunctor;
friend struct SortFileRequestFunctor;
2012-03-22 01:36:20 +08:00
2008-07-21 18:10:01 +08:00
struct ImageRequest : public osg::Referenced
{
ImageRequest():
2008-07-22 05:00:57 +08:00
osg::Referenced(true),
2008-10-07 01:02:56 +08:00
_timeToMergeBy(0.0),
_attachmentIndex(-1) {}
2012-03-22 01:36:20 +08:00
2012-11-13 19:45:20 +08:00
unsigned int _frameNumber;
2008-07-22 05:00:57 +08:00
double _timeToMergeBy;
2008-07-21 18:10:01 +08:00
std::string _fileName;
2009-05-09 16:49:27 +08:00
osg::ref_ptr<Options> _loadOptions;
2008-10-07 01:02:56 +08:00
osg::observer_ptr<osg::Object> _attachmentPoint;
int _attachmentIndex;
2008-07-21 18:10:01 +08:00
osg::ref_ptr<osg::Image> _loadedImage;
2008-07-24 03:04:46 +08:00
RequestQueue* _requestQueue;
2012-11-08 19:19:31 +08:00
osg::ref_ptr<osgDB::Options> _readOptions;
2012-03-22 01:36:20 +08:00
2008-07-21 18:10:01 +08:00
};
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
struct RequestQueue : public osg::Referenced
{
typedef std::vector< osg::ref_ptr<ImageRequest> > RequestList;
void sort();
2012-03-22 01:36:20 +08:00
2012-09-20 19:14:10 +08:00
unsigned int size() const;
2008-07-24 03:04:46 +08:00
RequestList _requestList;
2012-09-20 19:14:10 +08:00
mutable OpenThreads::Mutex _requestMutex;
2008-07-24 03:04:46 +08:00
};
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
struct ReadQueue : public RequestQueue
{
ReadQueue(ImagePager* pager, const std::string& name);
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
void block() { _block->block(); }
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
void release() { _block->release(); }
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
void updateBlock()
{
2015-09-04 23:05:06 +08:00
_block->set((!_requestList.empty() && !_pager->_databasePagerThreadPaused));
2008-07-24 03:04:46 +08:00
}
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
void clear();
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
void add(ImageRequest* imageRequest);
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
void takeFirst(osg::ref_ptr<ImageRequest>& databaseRequest);
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
osg::ref_ptr<osg::RefBlock> _block;
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
ImagePager* _pager;
std::string _name;
};
2012-03-22 01:36:20 +08:00
2008-07-24 03:04:46 +08:00
OpenThreads::Mutex _run_mutex;
bool _startThreadCalled;
bool _done;
bool _databasePagerThreadPaused;
2012-03-22 01:36:20 +08:00
2012-11-13 19:45:20 +08:00
OpenThreads::Atomic _frameNumber;
OpenThreads::Mutex _ir_mutex;
2008-07-24 03:04:46 +08:00
osg::ref_ptr<ReadQueue> _readQueue;
2012-03-22 01:36:20 +08:00
2008-07-25 21:45:07 +08:00
typedef std::vector< osg::ref_ptr<ImageThread> > ImageThreads;
ImageThreads _imageThreads;
2012-03-22 01:36:20 +08:00
2008-07-25 21:45:07 +08:00
osg::ref_ptr<RequestQueue> _completedQueue;
2012-03-22 01:36:20 +08:00
2008-07-26 00:11:51 +08:00
double _preLoadTime;
2008-07-21 18:10:01 +08:00
};
}
#endif