root/OpenSceneGraph/trunk/src/osgUtil/GLObjectsVisitor.cpp @ 9868

Revision 9868, 9.4 kB (checked in by robert, 6 years ago)

Preliminary work on general purpose incremental compile support in osgViewer.

  • 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#include <osgUtil/GLObjectsVisitor>
14#include <osg/Drawable>
15#include <osg/Notify>
16#include <OpenThreads/ScopedLock>
17
18using namespace osg;
19using namespace osgUtil;
20
21
22/////////////////////////////////////////////////////////////////
23//
24// GLObjectsVisitor
25//
26GLObjectsVisitor::GLObjectsVisitor(Mode mode)
27{
28    setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
29
30    _mode = mode;
31
32}
33
34
35void GLObjectsVisitor::apply(osg::Node& node)
36{
37    if (node.getStateSet())
38    {
39        apply(*(node.getStateSet()));
40    }
41
42    traverse(node);
43}
44
45void GLObjectsVisitor::apply(osg::Geode& node)
46{
47    if (node.getStateSet())
48    {
49        apply(*(node.getStateSet()));
50    }
51
52    for(unsigned int i=0;i<node.getNumDrawables();++i)
53    {
54        Drawable* drawable = node.getDrawable(i);
55        if (drawable)
56        {
57            apply(*drawable);
58            if (drawable->getStateSet())
59            {
60                apply(*(drawable->getStateSet()));
61            }
62        }
63    }
64}
65
66void GLObjectsVisitor::apply(osg::Drawable& drawable)
67{
68    if (_drawablesAppliedSet.count(&drawable)!=0) return;
69   
70    _drawablesAppliedSet.insert(&drawable);
71
72    if (_mode&SWITCH_OFF_DISPLAY_LISTS)
73    {
74        drawable.setUseDisplayList(false);
75    }
76
77    if (_mode&SWITCH_ON_DISPLAY_LISTS)
78    {
79        drawable.setUseDisplayList(true);
80    }
81
82    if (_mode&COMPILE_DISPLAY_LISTS && _renderInfo.getState())
83    {
84        drawable.compileGLObjects(_renderInfo);
85    }
86
87    if (_mode&RELEASE_DISPLAY_LISTS)
88    {
89        drawable.releaseGLObjects(_renderInfo.getState());
90    }
91
92    if (_mode&SWITCH_ON_VERTEX_BUFFER_OBJECTS)
93    {
94        drawable.setUseVertexBufferObjects(true);
95    }
96
97    if (_mode&SWITCH_OFF_VERTEX_BUFFER_OBJECTS)
98    {
99        drawable.setUseVertexBufferObjects(false);
100    }
101}
102
103void GLObjectsVisitor::apply(osg::StateSet& stateset)
104{
105    if (_stateSetAppliedSet.count(&stateset)!=0) return;
106   
107    _stateSetAppliedSet.insert(&stateset);
108
109    if (_mode & COMPILE_STATE_ATTRIBUTES && _renderInfo.getState())
110    {
111        stateset.compileGLObjects(*_renderInfo.getState());
112       
113        osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
114        if (program) _lastCompiledProgram = program;
115
116        if (_lastCompiledProgram.valid() && !stateset.getUniformList().empty())
117        {
118            osg::Program::PerContextProgram* pcp = _lastCompiledProgram->getPCP(_renderInfo.getState()->getContextID());
119            if (pcp)
120            {
121                pcp->useProgram();
122               
123                _renderInfo.getState()->setLastAppliedProgramObject(pcp);
124           
125                osg::StateSet::UniformList& ul = stateset.getUniformList();
126                for(osg::StateSet::UniformList::iterator itr = ul.begin();
127                    itr != ul.end();
128                    ++itr)
129                {
130                    pcp->apply(*(itr->second.first));
131                }
132            }
133        }
134        else if(_renderInfo.getState()->getLastAppliedProgramObject()){
135                           
136            GL2Extensions* extensions = GL2Extensions::Get(_renderInfo.getState()->getContextID(), true);
137            extensions->glUseProgram(0);
138            _renderInfo.getState()->setLastAppliedProgramObject(0);
139        }
140       
141    }
142
143    if (_mode & RELEASE_STATE_ATTRIBUTES)
144    {
145        stateset.releaseGLObjects(_renderInfo.getState());
146    }
147   
148    if (_mode & CHECK_BLACK_LISTED_MODES)
149    {
150        stateset.checkValidityOfAssociatedModes(*_renderInfo.getState());
151    }
152}
153
154/////////////////////////////////////////////////////////////////
155//
156// GLObjectsVisitor
157//
158
159GLObjectsOperation::GLObjectsOperation(GLObjectsVisitor::Mode mode):
160    osg::GraphicsOperation("GLObjectOperation",false),
161    _mode(mode)
162{
163}
164
165GLObjectsOperation::GLObjectsOperation(osg::Node* subgraph, GLObjectsVisitor::Mode mode):
166    osg::GraphicsOperation("GLObjectOperation",false),
167    _subgraph(subgraph),
168    _mode(mode)
169{
170}
171
172void GLObjectsOperation::operator () (osg::GraphicsContext* context)
173{
174    GLObjectsVisitor glObjectsVisitor(_mode);
175   
176    context->getState()->initializeExtensionProcs();
177
178    glObjectsVisitor.setState(context->getState());
179   
180    // osg::notify(osg::NOTICE)<<"GLObjectsOperation::before <<<<<<<<<<<"<<std::endl;
181    if (_subgraph.valid())
182    {
183        _subgraph->accept(glObjectsVisitor);
184    }
185    else
186    {
187        for(osg::GraphicsContext::Cameras::iterator itr = context->getCameras().begin();
188            itr != context->getCameras().end();
189            ++itr)
190        {
191            (*itr)->accept(glObjectsVisitor);
192        }
193    }
194    // osg::notify(osg::NOTICE)<<"GLObjectsOperation::after >>>>>>>>>>> "<<std::endl;
195}
196
197/////////////////////////////////////////////////////////////////
198//
199// IncrementalCompileOperation
200//
201IncrementalCompileOperation::IncrementalCompileOperation():
202    osg::GraphicsOperation("IncrementalCompileOperation",true)
203{
204}
205
206IncrementalCompileOperation::~IncrementalCompileOperation()
207{
208}
209
210void IncrementalCompileOperation::assignContexts(Contexts& contexts)
211{
212    for(Contexts::iterator itr = contexts.begin();
213        itr != contexts.end();
214        ++itr)
215    {
216        osg::GraphicsContext* gc = *itr;
217        addGraphicsContext(gc);
218    }
219}
220
221void IncrementalCompileOperation::removeContexts(Contexts& contexts)
222{
223    for(Contexts::iterator itr = contexts.begin();
224        itr != contexts.end();
225        ++itr)
226    {
227        osg::GraphicsContext* gc = *itr;
228        removeGraphicsContext(gc);
229    }
230}
231
232
233void IncrementalCompileOperation::addGraphicsContext(osg::GraphicsContext* gc)
234{
235    if (_contexts.count(gc)==0)
236    {
237        gc->add(this);
238        _contexts.insert(gc);
239    }
240}
241
242void IncrementalCompileOperation::removeGraphicsContext(osg::GraphicsContext* gc)
243{
244    if (_contexts.count(gc)!=0)
245    {
246        gc->remove(this);
247        _contexts.erase(gc);
248    }
249}
250
251void IncrementalCompileOperation::add(osg::Node* subgraphToCompile)
252{
253    osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::add("<<subgraphToCompile<<")"<<std::endl;
254    add(new CompileSet(subgraphToCompile));
255}
256
257void IncrementalCompileOperation::add(osg::Group* attachmentPoint, osg::Node* subgraphToCompile)
258{
259    osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::add("<<attachmentPoint<<", "<<subgraphToCompile<<")"<<std::endl;
260    add(new CompileSet(attachmentPoint, subgraphToCompile));
261}
262
263
264void IncrementalCompileOperation::add(CompileSet* compileSet, bool callBuildCompileMap)
265{
266    if (!compileSet) return;
267   
268    if (callBuildCompileMap) compileSet->buildCompileMap(_contexts);
269
270    osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::add(CompileSet = "<<compileSet<<", "<<", "<<callBuildCompileMap<<")"<<std::endl;
271
272    OpenThreads::ScopedLock<OpenThreads::Mutex>  lock(_toCompileMutex);
273    _toCompile.push_back(compileSet);
274}
275
276void IncrementalCompileOperation::mergeCompiledSubgraphs()
277{
278    osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::mergeCompiledSubgraphs()"<<std::endl;
279
280    OpenThreads::ScopedLock<OpenThreads::Mutex>  compilded_lock(_compiledMutex);
281   
282    for(CompileSets::iterator itr = _compiled.begin();
283        itr != _compiled.end();
284        ++itr)
285    {
286        CompileSet* cs = itr->get();
287        if (cs->_attachmentPoint.valid())
288        {
289            cs->_attachmentPoint->addChild(cs->_subgraphToCompile.get());
290        }
291    }
292   
293    _compiled.clear();
294}
295
296void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& context)
297{
298}
299
300void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
301{
302    osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::operator () ("<<context<<")"<<std::endl;
303
304    OpenThreads::ScopedLock<OpenThreads::Mutex>  toCompile_lock(_toCompileMutex);
305    for(CompileSets::iterator itr = _toCompile.begin();
306        itr != _toCompile.end();
307        )
308    {
309        CompileSet* cs = itr->get();
310        CompileMap& cm = cs->_compileMap;
311        CompileData* cd = cm[context].get();
312       
313        if (cd)
314        {       
315            // compile textures
316            cd->_textures.clear();
317
318            // compile drawables
319            cd->_drawables.clear();
320
321            // compile programs
322            cd->_programs.clear();
323        }
324               
325        if (!cd || cd->empty())
326        {
327            if (cs->_compileCompletedCallback.valid())
328            {
329                if (cs->_compileCompletedCallback->compileCompleted(cs))
330                {
331                    // callback will handle merging of subgraph so no need to place CompileSet in merge.
332                }
333                else
334                {
335                    OpenThreads::ScopedLock<OpenThreads::Mutex>  compilded_lock(_compiledMutex);
336                    _compiled.push_back(cs);
337                }
338            }
339       
340            // remove from toCompileSet;
341            itr = _toCompile.erase(itr);
342        }
343        else
344        {
345            ++itr;
346        }
347    }
348}
Note: See TracBrowser for help on using the browser.