openscenegraph
ImagePager
Go to the documentation of this file.
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_IMAGEPAGER
15#define OSGDB_IMAGEPAGER 1
16
17#include <osg/Image>
18#include <osg/NodeVisitor>
19#include <osg/observer_ptr>
20#include <osg/OperationThread>
21#include <osg/FrameStamp>
22
23#include <OpenThreads/Mutex>
24#include <OpenThreads/Atomic>
25
26#include <osgDB/ReaderWriter>
27#include <osgDB/Options>
28
29namespace osgDB
30{
31
32class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler
33{
34 public:
35
36 ImagePager();
37
38 class OSGDB_EXPORT ImageThread : public osg::Referenced, public OpenThreads::Thread
39 {
40 public:
41
42 enum Mode
43 {
44 HANDLE_ALL_REQUESTS,
45 HANDLE_NON_HTTP,
46 HANDLE_ONLY_HTTP
47 };
48
49 ImageThread(ImagePager* pager, Mode mode, const std::string& name);
50
51 ImageThread(const ImageThread& dt, ImagePager* pager);
52
53 void setDone(bool done) { _done = done; }
54 bool getDone() const { return _done; }
55
56 virtual int cancel();
57
58 virtual void run();
59
60 protected:
61
62 virtual ~ImageThread();
63
64 bool _done;
65 Mode _mode;
66 ImagePager* _pager;
67 std::string _name;
68 };
69
70
71 ImageThread* getImageThread(unsigned int i) { return _imageThreads[i].get(); }
72
73 const ImageThread* getImageThread(unsigned int i) const { return _imageThreads[i].get(); }
74
75 unsigned int getNumImageThreads() const { return static_cast<unsigned int>(_imageThreads.size()); }
76
77
78 void setPreLoadTime(double preLoadTime) { _preLoadTime=preLoadTime; }
79 virtual double getPreLoadTime() const { return _preLoadTime; }
80
81 virtual osg::ref_ptr<osg::Image> readRefImageFile(const std::string& fileName, const osg::Referenced* options=0);
82
83 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);
84
85 /** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */
86 virtual bool requiresUpdateSceneGraph() const;
87
88 /** Merge the changes to the scene graph. */
89 virtual void updateSceneGraph(const osg::FrameStamp &frameStamp);
90
91 /** Signal the image thread that the update, cull and draw has begun for a new frame.
92 * 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. */
93 virtual void signalBeginFrame(const osg::FrameStamp* framestamp);
94
95 /** Signal the image thread that the update, cull and draw dispatch has completed.
96 * 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.*/
97 virtual void signalEndFrame();
98
99 int cancel();
100
101 protected:
102
103 virtual ~ImagePager();
104 // forward declare
105 struct RequestQueue;
106
107 struct SortFileRequestFunctor;
108 friend struct SortFileRequestFunctor;
109
110 struct ImageRequest : public osg::Referenced
111 {
112 ImageRequest():
113 osg::Referenced(true),
114 _frameNumber(0),
115 _timeToMergeBy(0.0),
116 _attachmentIndex(-1),
117 _requestQueue(0) {}
118
119 unsigned int _frameNumber;
120 double _timeToMergeBy;
121 std::string _fileName;
122 osg::ref_ptr<Options> _loadOptions;
123 osg::observer_ptr<osg::Object> _attachmentPoint;
124 int _attachmentIndex;
125 osg::ref_ptr<osg::Image> _loadedImage;
126 RequestQueue* _requestQueue;
127 osg::ref_ptr<osgDB::Options> _readOptions;
128
129 };
130
131 struct RequestQueue : public osg::Referenced
132 {
133 typedef std::vector< osg::ref_ptr<ImageRequest> > RequestList;
134
135 void sort();
136
137 unsigned int size() const;
138
139 RequestList _requestList;
140 mutable OpenThreads::Mutex _requestMutex;
141 };
142
143
144 struct ReadQueue : public RequestQueue
145 {
146 ReadQueue(ImagePager* pager, const std::string& name);
147
148 void block() { _block->block(); }
149
150 void release() { _block->release(); }
151
152 void updateBlock()
153 {
154 _block->set((!_requestList.empty() && !_pager->_databasePagerThreadPaused));
155 }
156
157 void clear();
158
159 void add(ImageRequest* imageRequest);
160
161 void takeFirst(osg::ref_ptr<ImageRequest>& databaseRequest);
162
163 osg::ref_ptr<osg::RefBlock> _block;
164
165 ImagePager* _pager;
166 std::string _name;
167 };
168
169 OpenThreads::Mutex _run_mutex;
170 bool _startThreadCalled;
171
172 bool _done;
173 bool _databasePagerThreadPaused;
174
175 OpenThreads::Atomic _frameNumber;
176
177 OpenThreads::Mutex _ir_mutex;
178 osg::ref_ptr<ReadQueue> _readQueue;
179
180 typedef std::vector< osg::ref_ptr<ImageThread> > ImageThreads;
181 ImageThreads _imageThreads;
182
183 osg::ref_ptr<RequestQueue> _completedQueue;
184
185 double _preLoadTime;
186};
187
188
189}
190
191#endif
192