root/OpenSceneGraph/trunk/src/osgDB/DatabasePager.cpp @ 3328

Revision 3328, 27.0 kB (checked in by robert, 10 years ago)

Removed eroneous cancel() and join() from the DatabasePager::run() method.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osgDB/DatabasePager>
2#include <osgDB/ReadFile>
3
4#include <osg/Geode>
5#include <osg/Timer>
6#include <osg/Texture>
7#include <osg/Notify>
8
9#include <OpenThreads/ScopedLock>
10
11#ifdef WIN32
12#include <windows.h>
13#else
14#include <unistd.h>
15#endif
16
17using namespace osgDB;
18
19DatabasePager::DatabasePager()
20{
21    //osg::notify(osg::INFO)<<"Constructing DatabasePager()"<<std::endl;
22   
23    _useFrameBlock = false;
24    _frameNumber = 0;
25    _frameBlock = new Block;
26    _fileRequestListEmptyBlock = new Block;
27
28    _threadPriorityDuringFrame = PRIORITY_MIN;
29    _threadPriorityOutwithFrame = PRIORITY_MIN;
30
31    _changeAutoUnRef = true;
32    _valueAutoUnRef = true;
33    _changeAnisotropy = false;
34    _valueAnisotropy = 1.0f;
35
36
37#if 1
38    _deleteRemovedSubgraphsInDatabaseThread = true;
39#else
40    _deleteRemovedSubgraphsInDatabaseThread = false;
41#endif
42   
43    _expiryDelay = 30;
44
45    // make sure a SharedStateManager exists.
46    //osgDB::Registry::instance()->getOrCreateSharedStateManager();
47   
48    //if (osgDB::Registry::instance()->getSharedStateManager())
49        //osgDB::Registry::instance()->setUseObjectCacheHint(true);
50}
51
52DatabasePager::~DatabasePager()
53{
54
55
56    //std::cout<<"DatabasePager::~DatabasePager()"<<std::endl;
57    if( isRunning() )
58    {
59
60        // cancel the thread..
61        cancel();
62        //join();
63
64        // release the frameBlock and _fileRequestListEmptyBlock incase its holding up thread cancelation.
65        _frameBlock->release();
66        _fileRequestListEmptyBlock->release();
67
68        // then wait for the the thread to stop running.
69        while(isRunning())
70        {
71            osg::notify(osg::DEBUG_INFO)<<"Waiting for DatabasePager to cancel"<<std::endl;
72            OpenThreads::Thread::YieldCurrentThread();
73        }
74       
75    }
76    //std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
77}
78
79void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* group, float priority, const osg::FrameStamp* framestamp)
80{
81   
82    double timestamp = framestamp?framestamp->getReferenceTime():0.0;
83    int frameNumber = framestamp?framestamp->getFrameNumber():_frameNumber;
84   
85    // search to see if filename already exist in the file loaded list.
86    bool foundEntry = false;
87
88    _dataToCompileListMutex.lock();
89   
90        for(DatabaseRequestList::iterator litr = _dataToCompileList.begin();
91            litr != _dataToCompileList.end() && !foundEntry;
92            ++litr)
93        {
94            if ((*litr)->_fileName==fileName)
95            {
96                foundEntry = true;
97                (*litr)->_frameNumberLastRequest = frameNumber;
98                (*litr)->_timestampLastRequest = timestamp;
99                (*litr)->_priorityLastRequest = priority;
100                ++((*litr)->_numOfRequests);
101            }
102        }       
103
104    _dataToCompileListMutex.unlock();
105
106    if (!foundEntry)
107    {
108        _dataToMergeListMutex.lock();
109
110            for(DatabaseRequestList::iterator litr = _dataToMergeList.begin();
111                litr != _dataToMergeList.end() && !foundEntry;
112                ++litr)
113            {
114                if ((*litr)->_fileName==fileName)
115                {
116                    foundEntry = true;
117                    (*litr)->_frameNumberLastRequest = frameNumber;
118                    (*litr)->_timestampLastRequest = timestamp;
119                    (*litr)->_priorityLastRequest = priority;
120                    ++((*litr)->_numOfRequests);
121                }
122            }       
123
124        _dataToMergeListMutex.unlock();
125    }
126   
127    if (!foundEntry)
128    {
129   
130        _fileRequestListMutex.lock();
131
132            // search to see if entry already  in file request list.
133            bool foundEntry = false;
134            for(DatabaseRequestList::iterator ritr = _fileRequestList.begin();
135                ritr != _fileRequestList.end() && !foundEntry;
136                ++ritr)
137            {
138                if ((*ritr)->_fileName==fileName)
139                {
140                    foundEntry = true;
141                    (*ritr)->_timestampLastRequest = timestamp;
142                    (*ritr)->_priorityLastRequest = priority;
143                    (*ritr)->_frameNumberLastRequest = frameNumber;
144                    ++((*ritr)->_numOfRequests);
145                }
146            }       
147
148            if (!foundEntry)
149            {
150                osg::notify(osg::INFO)<<"In DatabasePager::fileRquest("<<fileName<<")"<<std::endl;
151
152                osg::ref_ptr<DatabaseRequest> databaseRequest = new DatabaseRequest;
153
154                databaseRequest->_fileName = fileName;
155                databaseRequest->_frameNumberFirstRequest = frameNumber;
156                databaseRequest->_timestampFirstRequest = timestamp;
157                databaseRequest->_priorityFirstRequest = priority;
158                databaseRequest->_frameNumberLastRequest = frameNumber;
159                databaseRequest->_timestampLastRequest = timestamp;
160                databaseRequest->_priorityLastRequest = priority;
161                databaseRequest->_groupForAddingLoadedSubgraph = group;
162
163                if (_fileRequestList.empty()) _fileRequestListEmptyBlock->release();
164
165                _fileRequestList.push_back(databaseRequest);
166            }
167
168        _fileRequestListMutex.unlock();
169    }
170   
171    if (!isRunning())
172    {
173        static OpenThreads::Mutex s_mutex;
174               
175        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex);
176       
177        static bool s_startThreadCalled = false;
178       
179        if (!s_startThreadCalled)
180        {
181            s_startThreadCalled = true;
182            osg::notify(osg::DEBUG_INFO)<<"DatabasePager::startThread()"<<std::endl;
183            setSchedulePriority(_threadPriorityDuringFrame);
184            startThread();
185        }
186               
187    }
188}
189
190void DatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp)
191{
192    if (framestamp)
193    {
194        //osg::notify(osg::INFO) << "signalBeginFrame "<<framestamp->getFrameNumber()<<">>>>>>>>>>>>>>>>"<<std::endl;
195        _frameNumber = framestamp->getFrameNumber();
196    } //else osg::notify(osg::INFO) << "signalBeginFrame >>>>>>>>>>>>>>>>"<<std::endl;
197
198    _frameBlock->reset();
199
200    if (_threadPriorityDuringFrame!=getSchedulePriority())
201        setSchedulePriority(_threadPriorityDuringFrame);
202
203}
204
205void DatabasePager::signalEndFrame()
206{
207    //osg::notify(osg::INFO) << "signalEndFrame <<<<<<<<<<<<<<<<<<<< "<<std::endl;
208    _frameBlock->release();
209
210    if (_threadPriorityOutwithFrame!=getSchedulePriority())
211        setSchedulePriority(_threadPriorityOutwithFrame);
212
213}
214
215class FindCompileableGLObjectsVisitor : public osg::NodeVisitor
216{
217public:
218    FindCompileableGLObjectsVisitor(DatabasePager::DataToCompile& dataToCompile,
219                               bool changeAutoUnRef, bool valueAutoUnRef,
220                               bool changeAnisotropy, float valueAnisotropy):
221                        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
222                        _dataToCompile(dataToCompile),
223                        _changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef),
224                        _changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy)
225    {
226    }
227   
228    virtual void apply(osg::Node& node)
229    {
230        apply(node.getStateSet());
231
232        traverse(node);
233    }
234   
235    virtual void apply(osg::Geode& geode)
236    {
237        apply(geode.getStateSet());
238   
239        for(unsigned int i=0;i<geode.getNumDrawables();++i)
240        {
241            apply(geode.getDrawable(i));
242        }
243
244        traverse(geode);
245    }
246   
247    inline void apply(osg::StateSet* stateset)
248    {
249        if (stateset)
250        {
251            // search for the existance of any texture object attributes
252            bool foundTextureState = false;
253            for(unsigned int i=0;i<stateset->getTextureAttributeList().size();++i)
254            {
255                osg::Texture* texture = dynamic_cast<osg::Texture*>(stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
256                if (texture)
257                {
258                    if (_changeAutoUnRef) texture->setUnRefImageDataAfterApply(_valueAutoUnRef);
259                    if (_changeAnisotropy) texture->setMaxAnisotropy(_valueAnisotropy);
260                    foundTextureState = true;
261                }
262            }
263
264            // if texture object attributes exist add the state to the list for later compilation.
265            if (foundTextureState)
266            {
267                //osg::notify(osg::DEBUG_INFO)<<"Found compilable texture state"<<std::endl;
268                _dataToCompile.first.push_back(stateset);
269            }
270        }
271    }
272   
273    inline void apply(osg::Drawable* drawable)
274    {
275        apply(drawable->getStateSet());
276
277        if (drawable->getUseDisplayList() || drawable->getUseVertexBufferObjects())
278        {
279            //osg::notify(osg::INFO)<<"Found compilable drawable"<<std::endl;
280            _dataToCompile.second.push_back(drawable);
281        }
282    }
283   
284    DatabasePager::DataToCompile&   _dataToCompile;
285    bool                            _changeAutoUnRef;
286    bool                            _valueAutoUnRef;
287    bool                            _changeAnisotropy;
288    float                           _valueAnisotropy;
289};
290
291
292struct SortFileRequestFunctor
293{
294    bool operator() (const osg::ref_ptr<DatabasePager::DatabaseRequest>& lhs,const osg::ref_ptr<DatabasePager::DatabaseRequest>& rhs) const
295    {
296        if (lhs->_timestampLastRequest>rhs->_timestampLastRequest) return true;
297        else if (lhs->_timestampLastRequest<rhs->_timestampLastRequest) return false;
298        else return (lhs->_priorityLastRequest>rhs->_priorityLastRequest);
299    }
300};
301
302
303void DatabasePager::run()
304{
305    osg::notify(osg::INFO)<<"DatabasePager::run()"<<std::endl;
306
307    // need to set the texture object manager to be able to reuse textures
308    // by keeping deleted texture objects around for 10 seconds after being deleted.
309    osg::Texture::getTextureObjectManager()->setExpiryDelay(10.0f);
310   
311    bool firstTime = true;
312   
313    do
314    {
315   
316        _fileRequestListEmptyBlock->block();
317
318        if (_useFrameBlock)
319        {
320            _frameBlock->block();
321        }     
322   
323        //
324        // delete any children if required.
325        //
326        if (_deleteRemovedSubgraphsInDatabaseThread)
327        {
328            _childrenToDeleteListMutex.lock();
329                if (!_childrenToDeleteList.empty())
330                {
331                    //std::cout<<"In DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" objects"<<std::endl;
332                    _childrenToDeleteList.clear();
333                    //std::cout<<"Done DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" objects"<<std::endl;
334                }
335            _childrenToDeleteListMutex.unlock();
336        }
337
338        //
339        // load any subgraphs that are required.
340        //
341        osg::ref_ptr<DatabaseRequest> databaseRequest;
342   
343        // get the front of the file request list.
344        _fileRequestListMutex.lock();
345            if (!_fileRequestList.empty())
346            {
347                std::sort(_fileRequestList.begin(),_fileRequestList.end(),SortFileRequestFunctor());
348                databaseRequest = _fileRequestList.front();
349            }
350        _fileRequestListMutex.unlock();
351       
352        if (databaseRequest.valid())
353        {
354            // check if databaseRequest is still relevant
355            if (_frameNumber-databaseRequest->_frameNumberLastRequest<=1)
356            {
357                       
358                // load the data, note safe to write to the databaseRequest since once
359                // it is created this thread is the only one to write to the _loadedModel pointer.
360                osg::notify(osg::INFO)<<"In DatabasePager thread readNodeFile("<<databaseRequest->_fileName<<")"<<std::endl;
361                osg::Timer_t before = osg::Timer::instance()->tick();
362                databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName);
363                osg::notify(osg::INFO)<<"     node read in "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<std::endl;
364               
365                bool loadedObjectsNeedToBeCompiled = false;
366
367                if (databaseRequest->_loadedModel.valid() && !_activeGraphicsContexts.empty())
368                {
369                    // force a compute of the loaded model's bounding volume, so that when the subgraph
370                    // merged with the main scene graph and large computeBound() isn't incurred.
371                    databaseRequest->_loadedModel->getBound();
372
373
374                    ActiveGraphicsContexts::iterator itr = _activeGraphicsContexts.begin();
375
376                    DataToCompile& dtc = databaseRequest->_dataToCompileMap[*itr];
377                    ++itr;               
378
379                    // find all the compileable rendering objects
380                    FindCompileableGLObjectsVisitor frov(dtc,
381                                                         _changeAutoUnRef, _valueAutoUnRef,
382                                                         _changeAnisotropy, _valueAnisotropy);
383
384                    databaseRequest->_loadedModel->accept(frov);
385
386                    if (!dtc.first.empty() || !dtc.second.empty())
387                    {
388                        loadedObjectsNeedToBeCompiled = true;               
389
390                        // copy the objects to compile list to the other graphics context list.
391                        for(;
392                            itr != _activeGraphicsContexts.end();
393                            ++itr)
394                        {
395                            databaseRequest->_dataToCompileMap[*itr] = dtc;
396                        }
397                    }
398                }           
399
400                // move the databaseRequest from the front of the fileRequest to the end of
401                // dataLoad list.
402                _fileRequestListMutex.lock();
403
404                    if (databaseRequest->_loadedModel.valid())
405                    {
406                        if (loadedObjectsNeedToBeCompiled)
407                        {
408                            _dataToCompileListMutex.lock();
409                                _dataToCompileList.push_back(databaseRequest);
410                            _dataToCompileListMutex.unlock();
411                        }
412                        else
413                        {
414                            _dataToMergeListMutex.lock();
415                                _dataToMergeList.push_back(databaseRequest);
416                            _dataToMergeListMutex.unlock();
417                        }
418                    }       
419
420                    _fileRequestList.erase(_fileRequestList.begin());
421
422                    if (_fileRequestList.empty()) _fileRequestListEmptyBlock->reset();
423
424                _fileRequestListMutex.unlock();
425
426            }
427            else
428            {
429                //std::cout<<"frame number delta for "<<databaseRequest->_fileName<<" "<<_frameNumber-databaseRequest->_frameNumberLastRequest<<std::endl;
430                // remove the databaseRequest from the front of the fileRequest to the end of
431                // dataLoad list as its is no longer relevant
432                _fileRequestListMutex.lock();
433
434                    _fileRequestList.erase(_fileRequestList.begin());
435
436                    if (_fileRequestList.empty()) _fileRequestListEmptyBlock->reset();
437
438                _fileRequestListMutex.unlock();
439
440            }
441        }
442       
443        // go to sleep till our the next time our thread gets scheduled.
444
445        if (firstTime)
446        {
447            // do a yield to get round a peculiar thread hang when testCancel() is called
448            // in certain cirumstances - of which there is no particular pattern.
449            YieldCurrentThread();
450            firstTime = false;
451        }
452
453    } while (!testCancel());
454
455}
456
457void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
458{
459    DatabaseRequestList localFileLoadedList;
460
461    // get the dat for the _dataToCompileList, leaving it empty via a std::vector<>.swap.
462    _dataToMergeListMutex.lock();
463        localFileLoadedList.swap(_dataToMergeList);
464    _dataToMergeListMutex.unlock();
465   
466    // add the loaded data into the scene graph.
467    for(DatabaseRequestList::iterator itr=localFileLoadedList.begin();
468        itr!=localFileLoadedList.end();
469        ++itr)
470    {
471        DatabaseRequest* databaseRequest = itr->get();
472
473       
474        if (osgDB::Registry::instance()->getSharedStateManager())
475            osgDB::Registry::instance()->getSharedStateManager()->share(databaseRequest->_loadedModel.get());
476
477       
478        registerPagedLODs(databaseRequest->_loadedModel.get());
479       
480        osg::Group* group = databaseRequest->_groupForAddingLoadedSubgraph.get();
481        osg::PagedLOD* plod = dynamic_cast<osg::PagedLOD*>(group);
482        if (plod)
483        {
484            plod->setTimeStamp(plod->getNumChildren(),timeStamp);
485        }
486        group->addChild(databaseRequest->_loadedModel.get());
487        osg::notify(osg::INFO)<<"merged subgraph"<<databaseRequest->_fileName<<" after "<<databaseRequest->_numOfRequests<<" requests."<<std::endl;
488
489    }
490   
491}
492
493
494/** Helper class used internally to force the release of texture objects
495  * and displace lists.*/
496class ReleaseTexturesAndDrawablesVisitor : public osg::NodeVisitor
497{
498public:
499    ReleaseTexturesAndDrawablesVisitor():
500        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
501    {
502    }
503
504    void releaseGLObjects(DatabasePager::ObjectList& objectsToDelete)
505    {
506        for(TextureSet::iterator titr=_textureSet.begin();
507            titr!=_textureSet.end();
508            ++titr)
509        {
510            if ((*titr)->referenceCount()==1)
511            {
512                osg::Texture* texture = const_cast<osg::Texture*>(titr->get());
513                texture->releaseGLObjects();
514                objectsToDelete.push_back(texture);
515            }
516        }
517
518        for(DrawableSet::iterator ditr=_drawableSet.begin();
519            ditr!=_drawableSet.end();
520            ++ditr)
521        {
522            if ((*ditr)->referenceCount()==1)
523            {
524                osg::Drawable* drawable = const_cast<osg::Drawable*>(ditr->get());
525                drawable->releaseGLObjects();
526                objectsToDelete.push_back(drawable);
527            }
528        }
529    }
530
531    inline void apply(osg::StateSet* stateset)
532    {
533        if (stateset)
534        {
535            // search for the existance of any texture object attributes
536            bool foundTextureState = false;
537            osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList();
538            for(osg::StateSet::TextureAttributeList::iterator itr=tal.begin();
539                itr!=tal.end() && !foundTextureState;
540                ++itr)
541            {
542                osg::StateSet::AttributeList& al = *itr;
543                osg::StateSet::AttributeList::iterator alitr = al.find(osg::StateAttribute::TEXTURE);
544                if (alitr!=al.end())
545                {
546                    // found texture, so place it in the texture list.
547                    osg::Texture* texture = static_cast<osg::Texture*>(alitr->second.first.get());
548                    _textureSet.insert(texture);
549                }
550               
551            }
552        }
553    }
554
555    inline void apply(osg::Drawable* drawable)
556    {
557        apply(drawable->getStateSet());
558
559        _drawableSet.insert(drawable);
560    }
561
562    virtual void apply(osg::Node& node)
563    {
564        apply(node.getStateSet());
565
566        traverse(node);
567    }
568
569    virtual void apply(osg::Geode& geode)
570    {
571        apply(geode.getStateSet());
572
573        for(unsigned int i=0;i<geode.getNumDrawables();++i)
574        {
575            apply(geode.getDrawable(i));
576        }
577    }
578
579
580    typedef std::set<  osg::ref_ptr<osg::Drawable> > DrawableSet;
581    typedef std::set<  osg::ref_ptr<osg::Texture> >  TextureSet;
582
583    TextureSet _textureSet;
584    DrawableSet _drawableSet;
585
586};
587
588void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
589{
590    double expiryTime = currentFrameTime - _expiryDelay;
591
592    osg::NodeList childrenRemoved;
593
594    //osg::notify(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs("<<expiryTime<<") "<<std::endl;
595    for(PagedLODList::iterator itr=_pagedLODList.begin();
596        itr!=_pagedLODList.end();
597        ++itr)
598    {
599        osg::PagedLOD* plod = itr->get();
600        plod->removeExpiredChildren(expiryTime,childrenRemoved);
601    }
602   
603
604    if (osgDB::Registry::instance()->getSharedStateManager())
605        osgDB::Registry::instance()->getSharedStateManager()->prune();
606
607
608    if (_deleteRemovedSubgraphsInDatabaseThread)
609    {
610
611        // for all the subgraphs to remove find all the textures and drawables and
612        // strip them from the display lists.   
613        ReleaseTexturesAndDrawablesVisitor rtadv;
614        for(osg::NodeList::iterator nitr=childrenRemoved.begin();
615            nitr!=childrenRemoved.end();
616            ++nitr)
617        {
618            (*nitr)->accept(rtadv);
619        }
620       
621        // unref' the children we need to remove, keeping behind the Texture's and Drawables for later deletion
622        // inside the database thread.
623        childrenRemoved.clear();
624
625        // transfer the removed children over to the to delete list so the database thread can delete them.
626        _childrenToDeleteListMutex.lock();
627
628            rtadv.releaseGLObjects(_childrenToDeleteList);
629
630        _childrenToDeleteListMutex.unlock();
631    }
632
633    // flush all the references from the child removed list.  If  _deleteRemovedSubgraphsInDatabaseThread
634    // is false then this will typically resulting in a delete, otherwise this will be left to the
635    // clean up of the _childrenToDeleteList from within the database paging thread.
636    childrenRemoved.clear();
637
638    for(unsigned int i=_pagedLODList.size();
639        i>0;
640        )
641    {
642        --i;
643       
644        osg::PagedLOD* plod = _pagedLODList[i].get();
645        if (plod->referenceCount()==1)
646        {
647            _pagedLODList.erase(_pagedLODList.begin()+i);
648        }
649        else
650        {
651            //osg::notify(osg::INFO)<<"    PagedLOD "<<plod<<" refcount "<<plod->referenceCount()<<std::endl;
652        }
653    }
654   
655    // update the Registry object cache.
656    osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExtenalReferences(currentFrameTime);
657    osgDB::Registry::instance()->removeExpiredObjectsInCache(expiryTime);
658}
659
660
661class FindPagedLODsVisitor : public osg::NodeVisitor
662{
663public:
664    FindPagedLODsVisitor(DatabasePager::PagedLODList& pagedLODList):
665        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
666        _pagedLODList(pagedLODList)
667    {
668    }
669   
670    virtual void apply(osg::PagedLOD& plod)
671    {
672        _pagedLODList.push_back(&plod);
673   
674        traverse(plod);
675    }
676   
677    DatabasePager::PagedLODList& _pagedLODList;
678};
679
680void DatabasePager::registerPagedLODs(osg::Node* subgraph)
681{
682    FindPagedLODsVisitor fplv(_pagedLODList);
683    if (subgraph) subgraph->accept(fplv);
684}
685
686void DatabasePager::setCompileGLObjectsForContexID(unsigned int contextID, bool on)
687{
688    if (on)
689    {
690        _activeGraphicsContexts.insert(contextID);
691    }
692    else
693    {
694        _activeGraphicsContexts.erase(contextID);
695    }
696}
697
698bool DatabasePager::getCompileGLObjectsForContexID(unsigned int contextID)
699{
700    return _activeGraphicsContexts.count(contextID)!=0;
701}
702
703
704void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
705{
706
707    const osg::Timer& timer = *osg::Timer::instance();
708    osg::Timer_t start_tick = timer.tick();
709    double elapsedTime = 0.0;
710
711    osg::ref_ptr<DatabaseRequest> databaseRequest;
712   
713    // get the first compileable entry.
714    _dataToCompileListMutex.lock();
715        if (!_dataToCompileList.empty())
716        {
717            std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor());
718            databaseRequest = _dataToCompileList.front();
719        }
720    _dataToCompileListMutex.unlock();
721
722    // while there are valid databaseRequest's in the to compile list and there is
723    // sufficient time left compile each databaseRequest's stateset and drawables.
724    while (databaseRequest.valid() && elapsedTime<availableTime)
725    {
726        DataToCompileMap& dcm = databaseRequest->_dataToCompileMap;
727        DataToCompile& dtc = dcm[state.getContextID()];
728        if (!dtc.first.empty() && elapsedTime<availableTime)
729        {
730            // we have StateSet's to compile
731            StateSetList& sslist = dtc.first;
732            //osg::notify(osg::INFO)<<"Compiling statesets"<<std::endl;
733            StateSetList::iterator itr=sslist.begin();
734            for(;
735                itr!=sslist.end() && elapsedTime<availableTime;
736                ++itr)
737            {
738                //osg::notify(osg::INFO)<<"    Compiling stateset "<<(*itr).get()<<std::endl;
739                (*itr)->compileGLObjects(state);
740                elapsedTime = timer.delta_s(start_tick,timer.tick());
741            }
742            // remove the compiled stateset from the list.
743            sslist.erase(sslist.begin(),itr);
744        }
745        if (!dtc.second.empty() && elapsedTime<availableTime)
746        {
747            // we have Drawable's to compile
748            //osg::notify(osg::INFO)<<"Compiling drawables"<<std::endl;
749            DrawableList& dwlist = dtc.second;
750            DrawableList::iterator itr=dwlist.begin();
751            for(;
752                itr!=dwlist.end() && elapsedTime<availableTime;
753                ++itr)
754            {
755                //osg::notify(osg::INFO)<<"    Compiling drawable "<<(*itr).get()<<std::endl;
756                (*itr)->compileGLObjects(state);
757                elapsedTime = timer.delta_s(start_tick,timer.tick());
758            }
759            // remove the compiled drawables from the list.
760            dwlist.erase(dwlist.begin(),itr);
761        }
762       
763        //osg::notify(osg::INFO)<<"Checking if compiled"<<std::endl;
764
765        // now check the to compile entries for all active graphics contexts
766        // to make sure that all have been compiled.
767        bool allCompiled = true;
768        for(DataToCompileMap::iterator itr=dcm.begin();
769            itr!=dcm.end() && allCompiled;
770            ++itr)
771        {
772            if (!(itr->second.first.empty())) allCompiled=false;
773            if (!(itr->second.second.empty())) allCompiled=false;
774        }
775       
776       
777        if (allCompiled)
778        {
779            osg::notify(osg::INFO)<<"All compiled"<<std::endl;
780
781            // we've compile all of the current databaseRequest so we can now pop it off the
782            // to compile list and place it on the merge list.
783            _dataToCompileListMutex.lock();
784           
785                _dataToMergeListMutex.lock();
786                    _dataToMergeList.push_back(databaseRequest);
787                _dataToMergeListMutex.unlock();
788
789                _dataToCompileList.erase(_dataToCompileList.begin());
790               
791                if (!_dataToCompileList.empty())
792                {
793                    std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor());
794                    databaseRequest = _dataToCompileList.front();
795                }
796                else databaseRequest = 0;
797
798            _dataToCompileListMutex.unlock();
799        }
800        else 
801        {
802            //osg::notify(osg::INFO)<<"Not all compiled"<<std::endl;
803            databaseRequest = 0;
804        }
805       
806        elapsedTime = timer.delta_s(start_tick,timer.tick());
807    }
808   
809    availableTime -= elapsedTime;
810}
Note: See TracBrowser for help on using the browser.