root/OpenSceneGraph/trunk/src/osgDB/SharedStateManager.cpp @ 13041

Revision 13041, 10.7 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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 <osg/Timer>
15#include <osgDB/SharedStateManager>
16
17using namespace osgDB;
18
19SharedStateManager::SharedStateManager(unsigned int mode):
20    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
21{
22    setShareMode(mode);
23    _mutex=0;
24}
25
26void SharedStateManager::setShareMode(unsigned int mode)
27{
28    _shareMode = mode;
29
30    _shareTexture[osg::Object::DYNAMIC] =       (_shareMode & SHARE_DYNAMIC_TEXTURES)!=0;
31    _shareTexture[osg::Object::STATIC] =        (_shareMode & SHARE_STATIC_TEXTURES)!=0;
32    _shareTexture[osg::Object::UNSPECIFIED] =   (_shareMode & SHARE_UNSPECIFIED_TEXTURES)!=0;
33
34    _shareStateSet[osg::Object::DYNAMIC] =      (_shareMode & SHARE_DYNAMIC_STATESETS)!=0;
35    _shareStateSet[osg::Object::STATIC] =       (_shareMode & SHARE_STATIC_STATESETS)!=0;
36    _shareStateSet[osg::Object::UNSPECIFIED] =  (_shareMode & SHARE_UNSPECIFIED_STATESETS)!=0;
37}
38
39//----------------------------------------------------------------
40// SharedStateManager::prune
41//----------------------------------------------------------------
42void SharedStateManager::prune()
43{
44    StateSetSet::iterator sitr;
45    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
46    for(sitr=_sharedStateSetList.begin(); sitr!=_sharedStateSetList.end();)
47    {
48        if ((*sitr)->referenceCount()<=1)
49            _sharedStateSetList.erase(sitr++);
50        else
51            ++sitr;
52    }
53
54    TextureSet::iterator titr;
55    for(titr=_sharedTextureList.begin(); titr!=_sharedTextureList.end();)
56    {
57        if ((*titr)->referenceCount()<=1)
58            _sharedTextureList.erase(titr++);
59        else
60            ++titr;
61    }
62
63}
64
65
66//----------------------------------------------------------------
67// SharedStateManager::share
68//----------------------------------------------------------------
69void SharedStateManager::share(osg::Node *node, OpenThreads::Mutex *mt)
70{
71//    const osg::Timer& timer = *osg::Timer::instance();
72//    osg::Timer_t start_tick = timer.tick();
73
74    _mutex = mt;
75    node->accept(*this);
76    tmpSharedTextureList.clear();
77    tmpSharedStateSetList.clear();
78    _mutex = 0;
79
80//    osg::Timer_t end_tick = timer.tick();
81//     std::cout << "SHARING TIME = "<<timer.delta_m(start_tick,end_tick)<<"ms"<<std::endl;
82//     std::cout << "   _sharedStateSetList.size() = "<<_sharedStateSetList.size()<<std::endl;
83//     std::cout << "   _sharedTextureList.size() = "<<_sharedTextureList.size()<<std::endl;
84}
85
86
87//----------------------------------------------------------------
88// SharedStateManager::apply
89//----------------------------------------------------------------
90void SharedStateManager::apply(osg::Node& node)
91{
92    osg::StateSet* ss = node.getStateSet();
93    if(ss) process(ss, &node);
94    traverse(node);
95}
96void SharedStateManager::apply(osg::Geode& geode)
97{
98    osg::StateSet* ss = geode.getStateSet();
99    if(ss) process(ss, &geode);
100    for(unsigned int i=0;i<geode.getNumDrawables();++i)
101    {
102        osg::Drawable* drawable = geode.getDrawable(i);
103        if(drawable)
104        {
105            ss = drawable->getStateSet();
106            if(ss) process(ss, drawable);
107        }
108    }
109}
110
111bool SharedStateManager::isShared(osg::StateSet* ss)
112{
113    if (shareStateSet(ss->getDataVariance()))
114    {
115        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
116        return find(ss) != 0;
117    }
118    else
119        return false;
120}
121
122bool SharedStateManager::isShared(osg::Texture* texture)
123{
124    if (shareTexture(texture->getDataVariance()))
125    {
126        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
127        return find(texture) != 0;
128    }
129    else
130        return false;
131}
132
133//----------------------------------------------------------------
134// SharedStateManager::find
135//----------------------------------------------------------------
136//
137// The find methods don't need to lock _listMutex because the thread
138// from which they are called is doing the writing to the lists.
139osg::StateSet *SharedStateManager::find(osg::StateSet *ss)
140{
141    StateSetSet::iterator result
142        = _sharedStateSetList.find(osg::ref_ptr<osg::StateSet>(ss));
143    if (result == _sharedStateSetList.end())
144        return NULL;
145    else
146        return result->get();
147}
148
149osg::StateAttribute *SharedStateManager::find(osg::StateAttribute *sa)
150{
151    TextureSet::iterator result
152        = _sharedTextureList.find(osg::ref_ptr<osg::StateAttribute>(sa));
153    if (result == _sharedTextureList.end())
154        return NULL;
155    else
156        return result->get();
157}
158
159
160//----------------------------------------------------------------
161// SharedStateManager::setStateSet
162//----------------------------------------------------------------
163void SharedStateManager::setStateSet(osg::StateSet* ss, osg::Object* object)
164{
165    osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(object);
166    if (drawable)
167    {
168        drawable->setStateSet(ss);
169    }
170    else
171    {
172        osg::Node* node = dynamic_cast<osg::Node*>(object);
173        if (node)
174        {
175            node->setStateSet(ss);
176        }
177    }
178}
179
180
181//----------------------------------------------------------------
182// SharedStateManager::shareTextures
183//----------------------------------------------------------------
184void SharedStateManager::shareTextures(osg::StateSet* ss)
185{
186    osg::StateSet::TextureAttributeList& texAttributes = ss->getTextureAttributeList();
187    for(unsigned int unit=0;unit<texAttributes.size();++unit)
188    {
189        osg::StateAttribute *texture = ss->getTextureAttribute(unit, osg::StateAttribute::TEXTURE);
190
191        // Valid Texture to be shared
192        if(texture && shareTexture(texture->getDataVariance()))
193        {
194            TextureTextureSharePairMap::iterator titr = tmpSharedTextureList.find(texture);
195            if(titr==tmpSharedTextureList.end())
196            {
197                // Texture is not in tmp list:
198                // First time it appears in this file, search Texture in sharedAttributeList
199                osg::StateAttribute *textureFromSharedList = find(texture);
200                if(textureFromSharedList)
201                {
202                    // Texture is in sharedAttributeList:
203                    // Share now. Required to be shared all next times
204                    if(_mutex) _mutex->lock();
205                    ss->setTextureAttributeAndModes(unit, textureFromSharedList, osg::StateAttribute::ON);
206                    if(_mutex) _mutex->unlock();
207                    tmpSharedTextureList[texture] = TextureSharePair(textureFromSharedList, true);
208                }
209                else
210                {
211                    // Texture is not in _sharedAttributeList:
212                    // Add to _sharedAttributeList. Not needed to be
213                    // shared all next times.
214                    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
215                    _sharedTextureList.insert(texture);
216                    tmpSharedTextureList[texture] = TextureSharePair(texture, false);
217                }
218            }
219            else if(titr->second.second)
220            {
221                // Texture is in tmpSharedAttributeList and share flag is on:
222                // It should be shared
223                if(_mutex) _mutex->lock();
224                ss->setTextureAttributeAndModes(unit, titr->second.first, osg::StateAttribute::ON);
225                if(_mutex) _mutex->unlock();
226            }
227        }
228    }
229}
230
231
232//----------------------------------------------------------------
233// SharedStateManager::process
234//----------------------------------------------------------------
235void SharedStateManager::process(osg::StateSet* ss, osg::Object* parent)
236{
237    // Valid StateSet to be shared
238    if (shareStateSet(ss->getDataVariance()))
239    {
240        StateSetStateSetSharePairMap::iterator sitr = tmpSharedStateSetList.find(ss);
241        if (sitr==tmpSharedStateSetList.end())
242        {
243            // StateSet is not in tmp list:
244            // First time it appears in this file, search StateSet in sharedObjectList
245            osg::StateSet *ssFromSharedList = find(ss);
246            if (ssFromSharedList)
247            {
248                // StateSet is in sharedStateSetList:
249                // Share now. Required to be shared all next times
250                if (_mutex) _mutex->lock();
251                setStateSet(ssFromSharedList, parent);
252                if (_mutex) _mutex->unlock();
253                tmpSharedStateSetList[ss] = StateSetSharePair(ssFromSharedList, true);
254            }
255            else
256            {
257                // StateSet is not in sharedStateSetList:
258                // Add to sharedStateSetList. Not needed to be shared all next times.
259                {
260                    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
261                    _sharedStateSetList.insert(ss);
262                    tmpSharedStateSetList[ss]
263                        = StateSetSharePair(ss, false);
264                }
265                // Only in this case sharing textures is also required
266                if (_shareMode & (SHARE_DYNAMIC_TEXTURES | SHARE_STATIC_TEXTURES | SHARE_UNSPECIFIED_TEXTURES))
267                {
268                    shareTextures(ss);
269                }
270            }
271        }
272        else if (sitr->second.second)
273        {
274            // StateSet is in tmpSharedStateSetList and share flag is on:
275            // It should be shared
276            if(_mutex) _mutex->lock();
277            setStateSet(sitr->second.first, parent);
278            if(_mutex) _mutex->unlock();
279        }
280    }
281    else if (_shareMode & (SHARE_DYNAMIC_TEXTURES | SHARE_STATIC_TEXTURES | SHARE_UNSPECIFIED_TEXTURES))
282    {
283        shareTextures(ss);
284    }
285}
286
287void SharedStateManager::releaseGLObjects(osg::State* state) const
288{
289    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
290
291    {
292        TextureSet::const_iterator it;
293        for ( it = _sharedTextureList.begin(); it != _sharedTextureList.end(); ++it )
294        {
295            if ( it->valid() )
296            {
297                it->get()->releaseGLObjects(state);
298            }
299        }
300    }
301
302    {
303        StateSetSet::const_iterator it;
304        for( it = _sharedStateSetList.begin(); it != _sharedStateSetList.end(); ++it )
305        {
306            if ( it->valid() )
307            {
308                it->get()->releaseGLObjects(state);
309            }
310        }
311    }
312}
Note: See TracBrowser for help on using the browser.