~saiarcot895/ubuntu/trusty/openscenegraph/armhf-support

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgDB/ImagePager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Loic Dachary (OuoU)
  • Date: 2009-03-23 14:08:20 UTC
  • mfrom: (1.1.7 upstream) (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090323140820-i4j3jozdlhyn4lre
rules prevent lib64 with -D LIB_POSTFIX="" (Closes: #517671)

Show diffs side-by-side

added added

removed removed

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