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

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

Changed the database pager run message to only output at an info level

  • 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    cancel();
456    join();   
457}
458
459void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
460{
461    DatabaseRequestList localFileLoadedList;
462
463    // get the dat for the _dataToCompileList, leaving it empty via a std::vector<>.swap.
464    _dataToMergeListMutex.lock();
465        localFileLoadedList.swap(_dataToMergeList);
466    _dataToMergeListMutex.unlock();
467   
468    // add the loaded data into the scene graph.
469    for(DatabaseRequestList::iterator itr=localFileLoadedList.begin();
470        itr!=localFileLoadedList.end();
471        ++itr)
472    {
473        DatabaseRequest* databaseRequest = itr->get();
474
475       
476        if (osgDB::Registry::instance()->getSharedStateManager())
477            osgDB::Registry::instance()->getSharedStateManager()->share(databaseRequest->_loadedModel.get());
478
479       
480        registerPagedLODs(databaseRequest->_loadedModel.get());
481       
482        osg::Group* group = databaseRequest->_groupForAddingLoadedSubgraph.get();
483        osg::PagedLOD* plod = dynamic_cast<osg::PagedLOD*>(group);
484        if (plod)
485        {
486            plod->setTimeStamp(plod->getNumChildren(),timeStamp);
487        }
488        group->addChild(databaseRequest->_loadedModel.get());
489        osg::notify(osg::INFO)<<"merged subgraph"<<databaseRequest->_fileName<<" after "<<databaseRequest->_numOfRequests<<" requests."<<std::endl;
490
491    }
492   
493}
494
495
496/** Helper class used internally to force the release of texture objects
497  * and displace lists.*/
498class ReleaseTexturesAndDrawablesVisitor : public osg::NodeVisitor
499{
500public:
501    ReleaseTexturesAndDrawablesVisitor():
502        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
503    {
504    }
505
506    void releaseGLObjects(DatabasePager::ObjectList& objectsToDelete)
507    {
508        for(TextureSet::iterator titr=_textureSet.begin();
509            titr!=_textureSet.end();
510            ++titr)
511        {
512            if ((*titr)->referenceCount()==1)
513            {
514                osg::Texture* texture = const_cast<osg::Texture*>(titr->get());
515                texture->releaseGLObjects();
516                objectsToDelete.push_back(texture);
517            }
518        }
519
520        for(DrawableSet::iterator ditr=_drawableSet.begin();
521            ditr!=_drawableSet.end();
522            ++ditr)
523        {
524            if ((*ditr)->referenceCount()==1)
525            {
526                osg::Drawable* drawable = const_cast<osg::Drawable*>(ditr->get());
527                drawable->releaseGLObjects();
528                objectsToDelete.push_back(drawable);
529            }
530        }
531    }
532
533    inline void apply(osg::StateSet* stateset)
534    {
535        if (stateset)
536        {
537            // search for the existance of any texture object attributes
538            bool foundTextureState = false;
539            osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList();
540            for(osg::StateSet::TextureAttributeList::iterator itr=tal.begin();
541                itr!=tal.end() && !foundTextureState;
542                ++itr)
543            {
544                osg::StateSet::AttributeList& al = *itr;
545                osg::StateSet::AttributeList::iterator alitr = al.find(osg::StateAttribute::TEXTURE);
546                if (alitr!=al.end())
547                {
548                    // found texture, so place it in the texture list.
549                    osg::Texture* texture = static_cast<osg::Texture*>(alitr->second.first.get());
550                    _textureSet.insert(texture);
551                }
552               
553            }
554        }
555    }
556
557    inline void apply(osg::Drawable* drawable)
558    {
559        apply(drawable->getStateSet());
560
561        _drawableSet.insert(drawable);
562    }
563
564    virtual void apply(osg::Node& node)
565    {
566        apply(node.getStateSet());
567
568        traverse(node);
569    }
570
571    virtual void apply(osg::Geode& geode)
572    {
573        apply(geode.getStateSet());
574
575        for(unsigned int i=0;i<geode.getNumDrawables();++i)
576        {
577            apply(geode.getDrawable(i));
578        }
579    }
580
581
582    typedef std::set<  osg::ref_ptr<osg::Drawable> > DrawableSet;
583    typedef std::set<  osg::ref_ptr<osg::Texture> >  TextureSet;
584
585    TextureSet _textureSet;
586    DrawableSet _drawableSet;
587
588};
589
590void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
591{
592    double expiryTime = currentFrameTime - _expiryDelay;
593
594    osg::NodeList childrenRemoved;
595
596    //osg::notify(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs("<<expiryTime<<") "<<std::endl;
597    for(PagedLODList::iterator itr=_pagedLODList.begin();
598        itr!=_pagedLODList.end();
599        ++itr)
600    {
601        osg::PagedLOD* plod = itr->get();
602        plod->removeExpiredChildren(expiryTime,childrenRemoved);
603    }
604   
605
606    if (osgDB::Registry::instance()->getSharedStateManager())
607        osgDB::Registry::instance()->getSharedStateManager()->prune();
608
609
610    if (_deleteRemovedSubgraphsInDatabaseThread)
611    {
612
613        // for all the subgraphs to remove find all the textures and drawables and
614        // strip them from the display lists.   
615        ReleaseTexturesAndDrawablesVisitor rtadv;
616        for(osg::NodeList::iterator nitr=childrenRemoved.begin();
617            nitr!=childrenRemoved.end();
618            ++nitr)
619        {
620            (*nitr)->accept(rtadv);
621        }
622       
623        // unref' the children we need to remove, keeping behind the Texture's and Drawables for later deletion
624        // inside the database thread.
625        childrenRemoved.clear();
626
627        // transfer the removed children over to the to delete list so the database thread can delete them.
628        _childrenToDeleteListMutex.lock();
629
630            rtadv.releaseGLObjects(_childrenToDeleteList);
631
632        _childrenToDeleteListMutex.unlock();
633    }
634
635    // flush all the references from the child removed list.  If  _deleteRemovedSubgraphsInDatabaseThread
636    // is false then this will typically resulting in a delete, otherwise this will be left to the
637    // clean up of the _childrenToDeleteList from within the database paging thread.
638    childrenRemoved.clear();
639
640    for(unsigned int i=_pagedLODList.size();
641        i>0;
642        )
643    {
644        --i;
645       
646        osg::PagedLOD* plod = _pagedLODList[i].get();
647        if (plod->referenceCount()==1)
648        {
649            _pagedLODList.erase(_pagedLODList.begin()+i);
650        }
651        else
652        {
653            //osg::notify(osg::INFO)<<"    PagedLOD "<<plod<<" refcount "<<plod->referenceCount()<<std::endl;
654        }
655    }
656   
657    // update the Registry object cache.
658    osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExtenalReferences(currentFrameTime);
659    osgDB::Registry::instance()->removeExpiredObjectsInCache(expiryTime);
660}
661
662
663class FindPagedLODsVisitor : public osg::NodeVisitor
664{
665public:
666    FindPagedLODsVisitor(DatabasePager::PagedLODList& pagedLODList):
667        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
668        _pagedLODList(pagedLODList)
669    {
670    }
671   
672    virtual void apply(osg::PagedLOD& plod)
673    {
674        _pagedLODList.push_back(&plod);
675   
676        traverse(plod);
677    }
678   
679    DatabasePager::PagedLODList& _pagedLODList;
680};
681
682void DatabasePager::registerPagedLODs(osg::Node* subgraph)
683{
684    FindPagedLODsVisitor fplv(_pagedLODList);
685    if (subgraph) subgraph->accept(fplv);
686}
687
688void DatabasePager::setCompileGLObjectsForContexID(unsigned int contextID, bool on)
689{
690    if (on)
691    {
692        _activeGraphicsContexts.insert(contextID);
693    }
694    else
695    {
696        _activeGraphicsContexts.erase(contextID);
697    }
698}
699
700bool DatabasePager::getCompileGLObjectsForContexID(unsigned int contextID)
701{
702    return _activeGraphicsContexts.count(contextID)!=0;
703}
704
705
706void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
707{
708
709    const osg::Timer& timer = *osg::Timer::instance();
710    osg::Timer_t start_tick = timer.tick();
711    double elapsedTime = 0.0;
712
713    osg::ref_ptr<DatabaseRequest> databaseRequest;
714   
715    // get the first compileable entry.
716    _dataToCompileListMutex.lock();
717        if (!_dataToCompileList.empty())
718        {
719            std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor());
720            databaseRequest = _dataToCompileList.front();
721        }
722    _dataToCompileListMutex.unlock();
723
724    // while there are valid databaseRequest's in the to compile list and there is
725    // sufficient time left compile each databaseRequest's stateset and drawables.
726    while (databaseRequest.valid() && elapsedTime<availableTime)
727    {
728        DataToCompileMap& dcm = databaseRequest->_dataToCompileMap;
729        DataToCompile& dtc = dcm[state.getContextID()];
730        if (!dtc.first.empty() && elapsedTime<availableTime)
731        {
732            // we have StateSet's to compile
733            StateSetList& sslist = dtc.first;
734            //osg::notify(osg::INFO)<<"Compiling statesets"<<std::endl;
735            StateSetList::iterator itr=sslist.begin();
736            for(;
737                itr!=sslist.end() && elapsedTime<availableTime;
738                ++itr)
739            {
740                //osg::notify(osg::INFO)<<"    Compiling stateset "<<(*itr).get()<<std::endl;
741                (*itr)->compileGLObjects(state);
742                elapsedTime = timer.delta_s(start_tick,timer.tick());
743            }
744            // remove the compiled stateset from the list.
745            sslist.erase(sslist.begin(),itr);
746        }
747        if (!dtc.second.empty() && elapsedTime<availableTime)
748        {
749            // we have Drawable's to compile
750            //osg::notify(osg::INFO)<<"Compiling drawables"<<std::endl;
751            DrawableList& dwlist = dtc.second;
752            DrawableList::iterator itr=dwlist.begin();
753            for(;
754                itr!=dwlist.end() && elapsedTime<availableTime;
755                ++itr)
756            {
757                //osg::notify(osg::INFO)<<"    Compiling drawable "<<(*itr).get()<<std::endl;
758                (*itr)->compileGLObjects(state);
759                elapsedTime = timer.delta_s(start_tick,timer.tick());
760            }
761            // remove the compiled drawables from the list.
762            dwlist.erase(dwlist.begin(),itr);
763        }
764       
765        //osg::notify(osg::INFO)<<"Checking if compiled"<<std::endl;
766
767        // now check the to compile entries for all active graphics contexts
768        // to make sure that all have been compiled.
769        bool allCompiled = true;
770        for(DataToCompileMap::iterator itr=dcm.begin();
771            itr!=dcm.end() && allCompiled;
772            ++itr)
773        {
774            if (!(itr->second.first.empty())) allCompiled=false;
775            if (!(itr->second.second.empty())) allCompiled=false;
776        }
777       
778       
779        if (allCompiled)
780        {
781            osg::notify(osg::INFO)<<"All compiled"<<std::endl;
782
783            // we've compile all of the current databaseRequest so we can now pop it off the
784            // to compile list and place it on the merge list.
785            _dataToCompileListMutex.lock();
786           
787                _dataToMergeListMutex.lock();
788                    _dataToMergeList.push_back(databaseRequest);
789                _dataToMergeListMutex.unlock();
790
791                _dataToCompileList.erase(_dataToCompileList.begin());
792               
793                if (!_dataToCompileList.empty())
794                {
795                    std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor());
796                    databaseRequest = _dataToCompileList.front();
797                }
798                else databaseRequest = 0;
799
800            _dataToCompileListMutex.unlock();
801        }
802        else 
803        {
804            //osg::notify(osg::INFO)<<"Not all compiled"<<std::endl;
805            databaseRequest = 0;
806        }
807       
808        elapsedTime = timer.delta_s(start_tick,timer.tick());
809    }
810   
811    availableTime -= elapsedTime;
812}
Note: See TracBrowser for help on using the browser.