root/OpenSceneGraph/trunk/src/osgDB/ImagePager.cpp @ 13159

Revision 13159, 10.8 kB (checked in by robert, 3 hours ago)

From Mattias Helsing, "Seems I was only half right given what you asked for. CMP0017 only
says that modules that are found and ran from cmake modules dir should
prefer cmake-provided modules. find_package() and include() still look
in CMAKE_MODULE_PATH first.

After some investigating I've come up with a proposal examplified in
the attached FindGDAL.cmake script. It simply calls the cmake provided
FindGDAL.cmake if it exists and returns if it succeeds in finding GDAL
using that, otherwise continue with our local cmake code.
Pro: Wont clutter our root CMakeLists.txt
Con: If we begin to write more advanced Findxxx modules (using
COMPONENTS, REQUIRED etc.) we may have to revise this scheme.
"

  • Property svn:eol-style set to native
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#include <osgDB/ImagePager>
15#include <osgDB/ReadFile>
16
17#include <osg/Notify>
18#include <osg/ImageSequence>
19
20using namespace osgDB;
21
22
23/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24//
25//  SortFileRequestFunctor
26//
27struct ImagePager::SortFileRequestFunctor
28{
29    bool operator() (const osg::ref_ptr<ImagePager::ImageRequest>& lhs,const osg::ref_ptr<ImagePager::ImageRequest>& rhs) const
30    {
31        return (lhs->_timeToMergeBy < rhs->_timeToMergeBy);
32    }
33};
34
35
36/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37//
38//  RequestQueue
39//
40void ImagePager::RequestQueue::sort()
41{
42    std::sort(_requestList.begin(),_requestList.end(),SortFileRequestFunctor());
43}
44
45unsigned int ImagePager::RequestQueue::size() const
46{
47    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
48    return _requestList.size();
49}
50
51
52
53/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54//
55//  ReadQueue
56//
57ImagePager::ReadQueue::ReadQueue(ImagePager* pager, const std::string& name):
58    _pager(pager),
59    _name(name)
60{
61    _block = new osg::RefBlock;
62}
63
64void ImagePager::ReadQueue::clear()
65{
66    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
67
68    for(RequestList::iterator citr = _requestList.begin();
69        citr != _requestList.end();
70        ++citr)
71    {
72        (*citr)->_attachmentPoint = 0;
73        (*citr)->_requestQueue = 0;
74    }
75
76    _requestList.clear();
77
78    updateBlock();
79}
80
81void ImagePager::ReadQueue::add(ImagePager::ImageRequest* databaseRequest)
82{
83    // tempo hack to avoid the ImagePager accumulating requests when it can keep up,
84    // note this will mean that only one ImageSequence can be properly managed at one time,
85    // this hack will be removed once a better system for managing expiry of requests is introduced.
86    clear();
87
88    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
89   
90    _requestList.push_back(databaseRequest);
91    databaseRequest->_requestQueue = this;
92
93    OSG_INFO<<"ImagePager::ReadQueue::add(..), size()="<<_requestList.size()<<std::endl;
94
95    updateBlock();
96}
97
98void ImagePager::ReadQueue::takeFirst(osg::ref_ptr<ImageRequest>& databaseRequest)
99{
100    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
101
102    if (!_requestList.empty())
103    {
104        sort();
105
106        OSG_INFO<<"ImagePager::ReadQueue::takeFirst(..), size()="<<_requestList.size()<<std::endl;
107
108        databaseRequest = _requestList.front();
109        databaseRequest->_requestQueue = 0;
110        _requestList.erase(_requestList.begin());
111
112        updateBlock();
113    }
114}
115
116//////////////////////////////////////////////////////////////////////////////////////
117//
118// ImageThread
119//
120ImagePager::ImageThread::ImageThread(ImagePager* pager, Mode mode, const std::string& name):
121    _done(false),
122    _mode(mode),
123    _pager(pager),
124    _name(name)
125{
126}
127
128ImagePager::ImageThread::ImageThread(const ImageThread& dt, ImagePager* pager):
129    _done(false),
130    _mode(dt._mode),
131    _pager(pager),
132    _name(dt._name)
133{
134}
135
136ImagePager::ImageThread::~ImageThread()
137{
138}
139
140int ImagePager::ImageThread::cancel()
141{
142    int result = 0;
143
144    if( isRunning() )
145    {
146
147        _done = true;
148
149        switch(_mode)
150        {
151            case(HANDLE_ALL_REQUESTS):
152                _pager->_readQueue->release();
153                break;
154            case(HANDLE_NON_HTTP):
155                _pager->_readQueue->release();
156                break;
157            case(HANDLE_ONLY_HTTP):
158                _pager->_readQueue->release();
159                break;
160        }
161
162        // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
163        // _databasePagerThreadBlock->release();
164
165        // then wait for the the thread to stop running.
166        while(isRunning())
167        {
168            // commenting out debug info as it was cashing crash on exit, presumable
169            // due to osg::notify or std::cout destructing earlier than this destructor.
170            // OSG_DEBUG<<"Waiting for DatabasePager to cancel"<<std::endl;
171            OpenThreads::Thread::YieldCurrentThread();
172        }
173
174        // _startThreadCalled = false;
175    }
176    //std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
177    return result;
178}
179
180void ImagePager::ImageThread::run()
181{
182    OSG_INFO<<"ImagePager::ImageThread::run() "<<this<<std::endl;
183    bool firstTime = true;
184
185    osg::ref_ptr<ImagePager::ReadQueue> read_queue;
186
187    switch(_mode)
188    {
189        case(HANDLE_ALL_REQUESTS):
190            read_queue = _pager->_readQueue;
191            break;
192        case(HANDLE_NON_HTTP):
193            read_queue = _pager->_readQueue;
194            break;
195        case(HANDLE_ONLY_HTTP):
196            read_queue = _pager->_readQueue;
197            break;
198    }
199
200    do
201    {
202        read_queue->block();
203
204        osg::ref_ptr<ImageRequest> imageRequest;
205        read_queue->takeFirst(imageRequest);
206
207        if (imageRequest.valid())
208        {
209            osg::ref_ptr<osg::Image> image = osgDB::readImageFile(imageRequest->_fileName);
210            if (image.valid())
211            {
212                osg::ImageSequence* is = dynamic_cast<osg::ImageSequence*>(imageRequest->_attachmentPoint.get());
213                if (is)
214                {
215                    if (imageRequest->_attachmentIndex >= 0)
216                    {
217                        is->setImage(imageRequest->_attachmentIndex, image.get());
218                    }
219                    else
220                    {
221                        is->addImage(image.get());
222                    }
223                }
224                else
225                {
226                    imageRequest->_loadedImage = image;
227
228                    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_pager->_completedQueue->_requestMutex);
229                    _pager->_completedQueue->_requestList.push_back(imageRequest);
230                }
231            }
232
233        }
234        else
235        {
236            OpenThreads::Thread::YieldCurrentThread();
237        }
238
239
240        // go to sleep till our the next time our thread gets scheduled.
241
242        if (firstTime)
243        {
244            // do a yield to get round a peculiar thread hang when testCancel() is called
245            // in certain circumstances - of which there is no particular pattern.
246            YieldCurrentThread();
247            firstTime = false;
248        }
249
250    } while (!testCancel() && !_done);
251
252    OSG_INFO<<"ImagePager::ImageThread::done()"<<std::endl;
253
254}
255
256//////////////////////////////////////////////////////////////////////////////////////
257//
258// ImagePager
259//
260ImagePager::ImagePager():
261    _done(false)
262{
263    _startThreadCalled = false;
264    _databasePagerThreadPaused = false;
265
266    _readQueue = new ReadQueue(this,"Image Queue");
267    _completedQueue = new RequestQueue;
268    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 1"));
269    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 2"));
270    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 3"));
271    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 4"));
272    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 5"));
273    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 6"));
274
275    // 1 second
276    _preLoadTime = 1.0;
277}
278
279ImagePager::~ImagePager()
280{
281    cancel();
282}
283
284int ImagePager::cancel()
285{
286    int result = 0;
287
288    for(ImageThreads::iterator itr = _imageThreads.begin();
289        itr != _imageThreads.end();
290        ++itr)
291    {
292        (*itr)->setDone(true);
293    }
294
295    // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
296    _readQueue->release();
297
298    for(ImageThreads::iterator itr = _imageThreads.begin();
299        itr != _imageThreads.end();
300        ++itr)
301    {
302        (*itr)->cancel();
303    }
304
305    _done = true;
306    _startThreadCalled = false;
307
308    //std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
309    return result;
310}
311
312osg::Image* ImagePager::readImageFile(const std::string& fileName)
313{
314    return osgDB::readImageFile(fileName);
315}
316
317void ImagePager::requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, int attachmentIndex, double timeToMergeBy, const osg::FrameStamp*)
318{
319    OSG_INFO<<"ImagePager::requestNodeFile("<<fileName<<")"<<std::endl;
320
321    osg::ref_ptr<ImageRequest> request = new ImageRequest;
322    request->_timeToMergeBy = timeToMergeBy;
323    request->_fileName = fileName;
324    request->_attachmentPoint = attachmentPoint;
325    request->_attachmentIndex = attachmentIndex;
326    request->_requestQueue = _readQueue.get();
327
328    _readQueue->add(request.get());
329
330    if (!_startThreadCalled)
331    {
332        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_run_mutex);
333
334        if (!_startThreadCalled)
335        {
336            _startThreadCalled = true;
337            _done = false;
338
339            for(ImageThreads::iterator itr = _imageThreads.begin();
340                itr != _imageThreads.end();
341                ++itr)
342            {
343                (*itr)->startThread();
344            }
345
346        }
347    }
348}
349
350bool ImagePager::requiresUpdateSceneGraph() const
351{
352    //OSG_NOTICE<<"ImagePager::requiresUpdateSceneGraph()"<<std::endl;
353    return !(_completedQueue->_requestList.empty());
354}
355
356void ImagePager::updateSceneGraph(const osg::FrameStamp&)
357{
358    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_completedQueue->_requestMutex);
359
360    for(RequestQueue::RequestList::iterator itr = _completedQueue->_requestList.begin();
361        itr != _completedQueue->_requestList.end();
362        ++itr)
363    {
364        ImageRequest* imageRequest = itr->get();
365        osg::Texture* texture = dynamic_cast<osg::Texture*>(imageRequest->_attachmentPoint.get());
366        if (texture)
367        {
368            int attachmentIndex = imageRequest->_attachmentIndex > 0 ? imageRequest->_attachmentIndex : 0;
369            texture->setImage(attachmentIndex, imageRequest->_loadedImage.get());
370        }
371        else
372        {
373            OSG_NOTICE<<"ImagePager::updateSceneGraph() : error, image request attachment type not handled yet."<<std::endl;
374        }
375    }
376
377    _completedQueue->_requestList.clear();
378}
Note: See TracBrowser for help on using the browser.