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#ifndef    OSGDB_SHAREDSTATEMANAGER
15#define OSGDB_SHAREDSTATEMANAGER 1
16
17
18#include <osg/NodeVisitor>
19#include <osg/Geode>
20
21#include <osgDB/Export>
22
23#include <OpenThreads/Mutex>
24
25#include <set>
26
27
28namespace osgDB {
29
30    class OSGDB_EXPORT SharedStateManager : public osg::NodeVisitor
31    {
32    public:
33
34        enum ShareMode
35        {
36            SHARE_NONE                  = 0,
37            SHARE_STATIC_TEXTURES       = 1<<0,
38            SHARE_UNSPECIFIED_TEXTURES  = 1<<1,
39            SHARE_DYNAMIC_TEXTURES      = 1<<2,
40            SHARE_STATIC_STATESETS      = 1<<3,
41            SHARE_UNSPECIFIED_STATESETS = 1<<4,
42            SHARE_DYNAMIC_STATESETS     = 1<<5,
43            SHARE_TEXTURES  = SHARE_STATIC_TEXTURES | SHARE_UNSPECIFIED_TEXTURES,
44            SHARE_STATESETS = SHARE_STATIC_STATESETS | SHARE_UNSPECIFIED_STATESETS,
45            SHARE_ALL       = SHARE_TEXTURES |
46                              SHARE_STATESETS
47        };
48
49        SharedStateManager(unsigned int mode = SHARE_ALL);
50
51        META_NodeVisitor(osgDB, SharedStateManager)
52
53        void setShareMode(unsigned int mode);
54
55        unsigned int getShareMode() { return _shareMode; }
56
57        // Call right after each unload and before Registry cache prune.
58        void prune();
59
60        // Call right after each load
61        void share(osg::Node *node, OpenThreads::Mutex *mt=0);
62
63        void apply(osg::Node& node);
64        void apply(osg::Geode& geode);
65
66        // Answers the question "Will this state set be eliminated by
67        // the SharedStateManager because an equivalent one has been
68        // seen already?" Safe to call from the pager thread.
69        bool isShared(osg::StateSet* stateSet);
70
71        bool isShared(osg::Texture* texture);
72
73        void releaseGLObjects(osg::State* state ) const;
74
75    protected:
76
77        inline bool shareTexture(osg::Object::DataVariance variance)
78        {
79            return _shareTexture[variance];
80        }
81
82        inline bool shareStateSet(osg::Object::DataVariance variance)
83        {
84            return _shareStateSet[variance];
85        }
86
87
88        void process(osg::StateSet* ss, osg::Object* parent);
89        osg::StateAttribute *find(osg::StateAttribute *sa);
90        osg::StateSet *find(osg::StateSet *ss);
91        void setStateSet(osg::StateSet* ss, osg::Object* object);
92        void shareTextures(osg::StateSet* ss);
93
94        struct CompareStateAttributes
95        {
96            bool operator()(const osg::ref_ptr<osg::StateAttribute>& lhs,
97                            const osg::ref_ptr<osg::StateAttribute>& rhs) const
98            {
99                return *lhs < *rhs;
100            }
101        };
102
103        struct CompareStateSets
104        {
105            bool operator()(const osg::ref_ptr<osg::StateSet>& lhs,
106                            const osg::ref_ptr<osg::StateSet>& rhs) const
107            {
108                return lhs->compare(*rhs, true) < 0;
109            }
110        };
111
112        // Lists of shared objects
113        typedef std::set< osg::ref_ptr<osg::StateAttribute>, CompareStateAttributes > TextureSet;
114        TextureSet _sharedTextureList;
115
116        typedef std::set< osg::ref_ptr<osg::StateSet>, CompareStateSets > StateSetSet;
117        StateSetSet _sharedStateSetList;
118
119        // Temporary lists just to avoid unnecessary find calls
120        typedef std::pair<osg::StateAttribute*, bool> TextureSharePair;
121        typedef std::map<osg::StateAttribute*, TextureSharePair> TextureTextureSharePairMap;
122        TextureTextureSharePairMap tmpSharedTextureList;
123
124        typedef std::pair<osg::StateSet*, bool> StateSetSharePair;
125        typedef std::map<osg::StateSet*, StateSetSharePair> StateSetStateSetSharePairMap;
126        StateSetStateSetSharePairMap tmpSharedStateSetList;
127
128        unsigned int    _shareMode;
129        bool            _shareTexture[3];
130        bool            _shareStateSet[3];
131
132        // Share connection mutex
133
134        OpenThreads::Mutex *_mutex;
135        // Mutex for doing isShared queries from other threads
136        mutable OpenThreads::Mutex _listMutex;
137    };
138
139}
140
141#endif
142