root/OpenSceneGraph/trunk/include/osgDB/DatabasePager @ 13041

Revision 13041, 19.3 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSGDB_DATABASEPAGER
15#define OSGDB_DATABASEPAGER 1
16
17#include <osg/NodeVisitor>
18#include <osg/Group>
19#include <osg/PagedLOD>
20#include <osg/Drawable>
21#include <osg/GraphicsThread>
22#include <osg/FrameStamp>
23#include <osg/ObserverNodePath>
24#include <osg/observer_ptr>
25
26#include <OpenThreads/Thread>
27#include <OpenThreads/Mutex>
28#include <OpenThreads/ScopedLock>
29#include <OpenThreads/Condition>
30
31#include <osgUtil/IncrementalCompileOperation>
32
33#include <osgDB/SharedStateManager>
34#include <osgDB/ReaderWriter>
35#include <osgDB/Options>
36
37
38#include <map>
39#include <list>
40#include <algorithm>
41#include <functional>
42
43namespace osgDB {
44
45
46
47/** Database paging class which manages the loading of files in a background thread,
48  * and synchronizing of loaded models with the main scene graph.*/
49class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandler
50{
51    public :
52
53        typedef OpenThreads::Thread::ThreadPriority ThreadPriority;
54
55        DatabasePager();
56
57        DatabasePager(const DatabasePager& rhs);
58
59        virtual const char* className() const { return "DatabasePager"; }
60
61        /** Create a shallow copy on the DatabasePager.*/
62        virtual DatabasePager* clone() const { return new DatabasePager(*this); }
63
64        /** get the prototype singleton used by DatabasePager::create().*/
65        static osg::ref_ptr<DatabasePager>& prototype();
66
67        /** create a DatabasePager by cloning DatabasePager::prototype().*/
68        static DatabasePager* create();
69
70
71
72        /** Add a request to load a node file to end the the database request list.*/
73        virtual void requestNodeFile(const std::string& fileName, osg::NodePath& nodePath,
74                                     float priority, const osg::FrameStamp* framestamp,
75                                     osg::ref_ptr<osg::Referenced>& databaseRequest,
76                                     const osg::Referenced* options);
77
78        /** Set the priority of the database pager thread(s).*/
79        int setSchedulePriority(OpenThreads::Thread::ThreadPriority priority);
80
81        /** Cancel the database pager thread(s).*/
82        virtual int cancel();
83
84        virtual bool isRunning() const;
85
86        /** Clear all internally cached structures.*/
87        virtual void clear();
88
89        class OSGDB_EXPORT DatabaseThread : public osg::Referenced, public OpenThreads::Thread
90        {
91        public:
92
93            enum Mode
94            {
95                HANDLE_ALL_REQUESTS,
96                HANDLE_NON_HTTP,
97                HANDLE_ONLY_HTTP
98            };
99
100            DatabaseThread(DatabasePager* pager, Mode mode, const std::string& name);
101
102            DatabaseThread(const DatabaseThread& dt, DatabasePager* pager);
103
104            void setName(const std::string& name) { _name = name; }
105            const std::string& getName() const { return _name; }
106
107            void setDone(bool done) { _done.exchange(done?1:0); }
108            bool getDone() const { return _done!=0; }
109
110            void setActive(bool active) { _active = active; }
111            bool getActive() const { return _active; }
112
113            virtual int cancel();
114
115            virtual void run();
116
117        protected:
118
119            virtual ~DatabaseThread();
120
121            OpenThreads::Atomic _done;
122            volatile bool       _active;
123            DatabasePager*      _pager;
124            Mode                _mode;
125            std::string         _name;
126
127        };
128
129        void setUpThreads(unsigned int totalNumThreads=2, unsigned int numHttpThreads=1);
130
131        virtual unsigned int addDatabaseThread(DatabaseThread::Mode mode, const std::string& name);
132
133        DatabaseThread* getDatabaseThread(unsigned int i) { return _databaseThreads[i].get(); }
134
135        const DatabaseThread* getDatabaseThread(unsigned int i) const { return _databaseThreads[i].get(); }
136
137        unsigned int getNumDatabaseThreads() const { return _databaseThreads.size(); }
138
139        /** Set whether the database pager thread should be paused or not.*/
140        void setDatabasePagerThreadPause(bool pause);
141
142        /** Get whether the database pager thread should is paused or not.*/
143        bool getDatabasePagerThreadPause() const { return _databasePagerThreadPaused; }
144
145        /** Set whether new database request calls are accepted or ignored.*/
146        void setAcceptNewDatabaseRequests(bool acceptNewRequests) { _acceptNewRequests = acceptNewRequests; }
147
148        /** Get whether new database request calls are accepted or ignored.*/
149        bool getAcceptNewDatabaseRequests() const { return _acceptNewRequests; }
150
151        /** Get the number of frames that are currently active.*/
152        int getNumFramesActive() const { return _numFramesActive; }
153
154        /** Signal the database thread that the update, cull and draw has begun for a new frame.
155          * Note, this is called by the application so that the database pager can go to sleep while the CPU is busy on the main rendering threads. */
156        virtual void signalBeginFrame(const osg::FrameStamp* framestamp);
157
158        /** Signal the database thread that the update, cull and draw dispatch has completed.
159          * Note, this is called by the application so that the database pager can go to wake back up now the main rendering threads are iddle waiting for the next frame.*/
160        virtual void signalEndFrame();
161
162
163        /** Find all PagedLOD nodes in a subgraph and register them with
164          * the DatabasePager so it can keep track of expired nodes.
165          * note, should be only be called from the update thread. */
166        virtual void registerPagedLODs(osg::Node* subgraph, unsigned int frameNumber = 0);
167
168        /** Set the incremental compile operation.
169          * Used to manage the OpenGL object compilation and merging of subgraphs in a way that avoids overloading
170          * the rendering of frame with too many new objects in one frame. */
171        void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico);
172
173        /** Get the incremental compile operation. */
174        osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation() { return _incrementalCompileOperation.get(); }
175
176
177        /** Set whether the database pager should pre compile OpenGL objects before allowing
178          * them to be merged into the scene graph.
179          * Pre compilation helps reduce the chances of frame drops, but also slows the
180          * speed at which tiles are merged as they have to be compiled first.*/
181        void setDoPreCompile(bool flag) { _doPreCompile = flag; }
182
183        /** Get whether the database pager should pre compile OpenGL objects before allowing
184          * them to be merged into the scene graph.*/
185        bool getDoPreCompile() const { return _doPreCompile; }
186
187
188
189        /** Set the target maximum number of PagedLOD to maintain in memory.
190          * Note, if more than the target number are required for rendering of a frame then these active PagedLOD are excempt from being expiried.
191          * But once the number of active drops back below the target the inactive PagedLOD will be trimmed back to the target number.*/
192        void setTargetMaximumNumberOfPageLOD(unsigned int target) { _targetMaximumNumberOfPageLOD = target; }
193
194        /** Get the target maximum number of PagedLOD to maintain in memory.*/
195        unsigned int getTargetMaximumNumberOfPageLOD() const { return _targetMaximumNumberOfPageLOD; }
196
197
198        /** Set whether the removed subgraphs should be deleted in the database thread or not.*/
199        void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; }
200
201        /** Get whether the removed subgraphs should be deleted in the database thread or not.*/
202        bool getDeleteRemovedSubgraphsInDatabaseThread() const { return _deleteRemovedSubgraphsInDatabaseThread; }
203
204        enum DrawablePolicy
205        {
206            DO_NOT_MODIFY_DRAWABLE_SETTINGS,
207            USE_DISPLAY_LISTS,
208            USE_VERTEX_BUFFER_OBJECTS,
209            USE_VERTEX_ARRAYS
210        };
211
212        /** Set how loaded drawables should be handled w.r.t their display list/vertex buffer object/vertex array settings.*/
213        void setDrawablePolicy(DrawablePolicy policy) { _drawablePolicy = policy; }
214
215        /** Get how loaded drawables should be handled w.r.t their display list/vertex buffer object/vertex array settings.*/
216        DrawablePolicy getDrawablePolicy() const { return _drawablePolicy; }
217
218
219        /** Set whether newly loaded textures should have a PixelBufferObject assigned to them to aid download to the GPU.*/
220        void setApplyPBOToImages(bool assignPBOToImages) { _assignPBOToImages = assignPBOToImages; }
221
222        /** Get whether newly loaded textures should have a PixelBufferObject assigned to them..*/
223        bool getApplyPBOToImages() const { return _assignPBOToImages; }
224
225
226        /** Set whether newly loaded textures should have their UnrefImageDataAfterApply set to a specified value.*/
227        void setUnrefImageDataAfterApplyPolicy(bool changeAutoUnRef, bool valueAutoUnRef) { _changeAutoUnRef = changeAutoUnRef; _valueAutoUnRef = valueAutoUnRef; }
228
229        /** Get whether newly loaded textures should have their UnrefImageDataAfterApply set to a specified value.*/
230        void getUnrefImageDataAfterApplyPolicy(bool& changeAutoUnRef, bool& valueAutoUnRef) const { changeAutoUnRef = _changeAutoUnRef; valueAutoUnRef = _valueAutoUnRef; }
231
232
233        /** Set whether newly loaded textures should have their MaxAnisotopy set to a specified value.*/
234        void setMaxAnisotropyPolicy(bool changeAnisotropy, float valueAnisotropy) { _changeAnisotropy = changeAnisotropy; _valueAnisotropy = valueAnisotropy; }
235
236        /** Set whether newly loaded textures should have their MaxAnisotopy set to a specified value.*/
237        void getMaxAnisotropyPolicy(bool& changeAnisotropy, float& valueAnisotropy) const { changeAnisotropy = _changeAnisotropy; valueAnisotropy = _valueAnisotropy; }
238
239
240        /** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */
241        bool requiresUpdateSceneGraph() const;
242
243        /** Merge the changes to the scene graph by calling calling removeExpiredSubgraphs then addLoadedDataToSceneGraph.
244          * Note, must only be called from single thread update phase. */
245        virtual void updateSceneGraph(const osg::FrameStamp& frameStamp);
246
247        /** Report how many items are in the _fileRequestList queue */
248        unsigned int getFileRequestListSize() const { return _fileRequestQueue->size() + _httpRequestQueue->size(); }
249
250        /** Report how many items are in the _dataToCompileList queue */
251        unsigned int getDataToCompileListSize() const { return _dataToCompileList->size(); }
252
253        /** Report how many items are in the _dataToMergeList queue */
254        unsigned int getDataToMergeListSize() const { return _dataToMergeList->size(); }
255
256        /** Report whether any requests are in the pager.*/
257        bool getRequestsInProgress() const;
258
259        /** Get the minimum time between the first request for a tile to be loaded and the time of its merge into the main scene graph.*/
260        double getMinimumTimeToMergeTile() const { return _minimumTimeToMergeTile; }
261
262        /** Get the maximum time between the first request for a tile to be loaded and the time of its merge into the main scene graph.*/
263        double getMaximumTimeToMergeTile() const { return _maximumTimeToMergeTile; }
264
265        /** Get the average time between the first request for a tile to be loaded and the time of its merge into the main scene graph.*/
266        double getAverageTimeToMergeTiles() const { return (_numTilesMerges > 0) ? _totalTimeToMergeTiles/static_cast<double>(_numTilesMerges) : 0; }
267
268        /** Reset the Stats variables.*/
269        void resetStats();
270
271        typedef std::set< osg::ref_ptr<osg::StateSet> >                 StateSetList;
272        typedef std::vector< osg::ref_ptr<osg::Drawable> >              DrawableList;
273
274        class ExpirePagedLODsVisitor;
275
276        typedef std::list<  osg::ref_ptr<osg::Object> > ObjectList;
277
278        struct PagedLODList : public osg::Referenced
279        {
280            virtual PagedLODList* clone() = 0;
281            virtual void clear() = 0;
282            virtual unsigned int size() = 0;
283            virtual void removeExpiredChildren(int numberChildrenToRemove, double expiryTime, unsigned int expiryFrame, ObjectList& childrenRemoved, bool visitActive) = 0;
284            virtual void removeNodes(osg::NodeList& nodesToRemove) = 0;
285            virtual void insertPagedLOD(const osg::observer_ptr<osg::PagedLOD>& plod) = 0;
286            virtual bool containsPagedLOD(const osg::observer_ptr<osg::PagedLOD>& plod) const = 0;
287        };
288
289
290    protected:
291
292        virtual ~DatabasePager();
293
294        friend class DatabaseThread;
295        friend struct DatabaseRequest;
296
297        struct RequestQueue;
298
299        struct OSGDB_EXPORT DatabaseRequest : public osg::Referenced
300        {
301            DatabaseRequest():
302                osg::Referenced(true),
303                _valid(false),
304                _frameNumberFirstRequest(0),
305                _timestampFirstRequest(0.0),
306                _priorityFirstRequest(0.f),
307                _frameNumberLastRequest(0),
308                _timestampLastRequest(0.0),
309                _priorityLastRequest(0.0f),
310                _numOfRequests(0),
311                _groupExpired(false)
312            {}
313
314            void invalidate();
315
316            bool valid() const { return _valid; }
317
318            bool                        _valid;
319            std::string                 _fileName;
320            unsigned int                _frameNumberFirstRequest;
321            double                      _timestampFirstRequest;
322            float                       _priorityFirstRequest;
323            unsigned int                _frameNumberLastRequest;
324            double                      _timestampLastRequest;
325            float                       _priorityLastRequest;
326            unsigned int                _numOfRequests;
327
328            osg::observer_ptr<osg::Node>        _terrain;
329            osg::observer_ptr<osg::Group>       _group;
330
331            osg::ref_ptr<osg::Node>             _loadedModel;
332            osg::ref_ptr<Options>               _loadOptions;
333
334            osg::observer_ptr<osgUtil::IncrementalCompileOperation::CompileSet> _compileSet;
335            bool                        _groupExpired; // flag used only in update thread
336
337            bool isRequestCurrent (int frameNumber) const
338            {
339                return _valid && (frameNumber - _frameNumberLastRequest <= 1);
340            }
341        };
342
343
344        struct OSGDB_EXPORT RequestQueue : public osg::Referenced
345        {
346        public:
347
348            RequestQueue(DatabasePager* pager);
349
350            void add(DatabaseRequest* databaseRequest);
351            void remove(DatabaseRequest* databaseRequest);
352
353            void addNoLock(DatabaseRequest* databaseRequest);
354
355            void takeFirst(osg::ref_ptr<DatabaseRequest>& databaseRequest);
356
357            /// prune all the old requests and then return true if requestList left empty
358            bool pruneOldRequestsAndCheckIfEmpty();
359
360            virtual void updateBlock() {}
361
362            void invalidate(DatabaseRequest* dr);
363
364            bool empty();
365
366            unsigned int size();
367
368            void clear();
369
370
371            typedef std::list< osg::ref_ptr<DatabaseRequest> > RequestList;
372            void swap(RequestList& requestList);
373
374            DatabasePager*              _pager;
375            RequestList                 _requestList;
376            OpenThreads::Mutex          _requestMutex;
377            unsigned int                _frameNumberLastPruned;
378
379        protected:
380            virtual ~RequestQueue();
381        };
382
383
384        typedef std::vector< osg::ref_ptr<DatabaseThread> > DatabaseThreadList;
385
386        struct OSGDB_EXPORT ReadQueue : public RequestQueue
387        {
388            ReadQueue(DatabasePager* pager, const std::string& name);
389
390            void block() { _block->block(); }
391
392            void release() { _block->release(); }
393
394            virtual void updateBlock();
395
396
397            osg::ref_ptr<osg::RefBlock> _block;
398
399            std::string                 _name;
400
401            OpenThreads::Mutex          _childrenToDeleteListMutex;
402            ObjectList                  _childrenToDeleteList;
403        };
404
405        // forward declare inner helper classes
406        class FindCompileableGLObjectsVisitor;
407        friend class FindCompileableGLObjectsVisitor;
408
409        struct DatabasePagerCompileCompletedCallback;
410        friend struct DatabasePagerCompileCompletedCallback;
411
412        class FindPagedLODsVisitor;
413        friend class FindPagedLODsVisitor;
414
415        struct SortFileRequestFunctor;
416        friend struct SortFileRequestFunctor;
417
418
419        OpenThreads::Mutex              _run_mutex;
420        OpenThreads::Mutex              _dr_mutex;
421        bool                            _startThreadCalled;
422
423        void compileCompleted(DatabaseRequest* databaseRequest);
424
425        /** Iterate through the active PagedLOD nodes children removing
426          * children which havn't been visited since specified expiryTime.
427          * note, should be only be called from the update thread. */
428        virtual void removeExpiredSubgraphs(const osg::FrameStamp &frameStamp);
429
430        /** Add the loaded data to the scene graph.*/
431        void addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp);
432
433
434        bool                            _done;
435        bool                            _acceptNewRequests;
436        bool                            _databasePagerThreadPaused;
437
438        DatabaseThreadList              _databaseThreads;
439
440        int                             _numFramesActive;
441        mutable OpenThreads::Mutex      _numFramesActiveMutex;
442        OpenThreads::Atomic             _frameNumber;
443
444        osg::ref_ptr<ReadQueue>         _fileRequestQueue;
445        osg::ref_ptr<ReadQueue>         _httpRequestQueue;
446        osg::ref_ptr<RequestQueue>      _dataToCompileList;
447        osg::ref_ptr<RequestQueue>      _dataToMergeList;
448
449        DrawablePolicy                  _drawablePolicy;
450
451        bool                            _assignPBOToImages;
452        bool                            _changeAutoUnRef;
453        bool                            _valueAutoUnRef;
454        bool                            _changeAnisotropy;
455        float                           _valueAnisotropy;
456
457        bool                            _deleteRemovedSubgraphsInDatabaseThread;
458
459
460        osg::ref_ptr<PagedLODList>      _activePagedLODList;
461
462        unsigned int                    _targetMaximumNumberOfPageLOD;
463
464        bool                            _doPreCompile;
465        osg::ref_ptr<osgUtil::IncrementalCompileOperation>  _incrementalCompileOperation;
466
467
468        double                          _minimumTimeToMergeTile;
469        double                          _maximumTimeToMergeTile;
470        double                          _totalTimeToMergeTiles;
471        unsigned int                    _numTilesMerges;
472};
473
474}
475
476#endif
Note: See TracBrowser for help on using the browser.