root/OpenSceneGraph/trunk/src/osg/BufferObject.cpp @ 13041

Revision 13041, 52.5 kB (checked in by robert, 3 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#include <stdio.h>
14#include <math.h>
15#include <float.h>
16
17#include <osg/BufferObject>
18#include <osg/Notify>
19#include <osg/GLExtensions>
20#include <osg/GL2Extensions>
21#include <osg/Timer>
22#include <osg/Image>
23#include <osg/State>
24#include <osg/PrimitiveSet>
25#include <osg/Array>
26
27#include <OpenThreads/ScopedLock>
28#include <OpenThreads/Mutex>
29
30#if 0
31    #define CHECK_CONSISTENCY checkConsistency();
32#else
33    #define CHECK_CONSISTENCY
34#endif
35
36using namespace osg;
37
38//////////////////////////////////////////////////////////////////////////////////////////////////////
39//
40// GLBufferObject
41//
42GLBufferObject::GLBufferObject(unsigned int contextID, BufferObject* bufferObject, unsigned int glObjectID):
43    _contextID(contextID),
44    _glObjectID(glObjectID),
45    _profile(0,0,0),
46    _allocatedSize(0),
47    _dirty(true),
48    _bufferObject(0),
49    _set(0),
50    _previous(0),
51    _next(0),
52    _frameLastUsed(0),
53    _extensions(0)
54{
55    assign(bufferObject);
56
57    _extensions = GLBufferObject::getExtensions(contextID, true);
58
59    if (glObjectID==0)
60    {
61        _extensions->glGenBuffers(1, &_glObjectID);
62    }
63
64    // OSG_NOTICE<<"Constucting BufferObject "<<this<<std::endl;
65}
66
67GLBufferObject::~GLBufferObject()
68{
69    //OSG_NOTICE<<"Destucting BufferObject "<<this<<std::endl;
70}
71
72void GLBufferObject::setBufferObject(BufferObject* bufferObject)
73{
74    assign(bufferObject);
75}
76
77void GLBufferObject::assign(BufferObject* bufferObject)
78{
79    _bufferObject = bufferObject;
80
81    if (_bufferObject)
82    {
83        _profile = bufferObject->getProfile();
84
85        _dirty = true;
86
87        _bufferEntries.clear();
88    }
89    else
90    {
91        _profile.setProfile(0,0,0);
92
93        // clear all previous entries;
94        _bufferEntries.clear();
95    }
96}
97
98void GLBufferObject::clear()
99{
100    _bufferEntries.clear();
101    _dirty = true;
102}
103
104void GLBufferObject::compileBuffer()
105{
106    _dirty = false;
107
108    _bufferEntries.reserve(_bufferObject->getNumBufferData());
109
110    bool compileAll = false;
111    bool offsetChanged = false;
112
113    unsigned int bufferAlignment = 4;
114
115    unsigned int newTotalSize = 0;
116    unsigned int i=0;
117    for(; i<_bufferObject->getNumBufferData(); ++i)
118    {
119        BufferData* bd = _bufferObject->getBufferData(i);
120        if (i<_bufferEntries.size())
121        {
122            BufferEntry& entry = _bufferEntries[i];
123            if (offsetChanged ||
124                entry.dataSource != bd ||
125                entry.dataSize != bd->getTotalDataSize())
126            {
127                unsigned int previousEndOfBufferDataMarker = computeBufferAlignment(entry.offset + entry.dataSize, bufferAlignment);
128
129                // OSG_NOTICE<<"GLBufferObject::compileBuffer(..) updating BufferEntry"<<std::endl;
130
131
132                entry.offset = newTotalSize;
133                entry.modifiedCount = 0xffffff;
134                entry.dataSize = bd->getTotalDataSize();
135                entry.dataSource = bd;
136
137                newTotalSize += entry.dataSize;
138                if (previousEndOfBufferDataMarker!=newTotalSize)
139                {
140                    offsetChanged = true;
141                }
142            }
143            else
144            {
145                newTotalSize = computeBufferAlignment(newTotalSize + entry.dataSize, bufferAlignment);
146            }
147        }
148        else
149        {
150            BufferEntry entry;
151            entry.offset = newTotalSize;
152            entry.modifiedCount = 0xffffff;
153            entry.dataSize = bd ? bd->getTotalDataSize() : 0;
154            entry.dataSource = bd;
155#if 0
156            OSG_NOTICE<<"entry"<<std::endl;
157            OSG_NOTICE<<"   offset "<<entry.offset<<std::endl;
158            OSG_NOTICE<<"   dataSize "<<entry.dataSize<<std::endl;
159            OSG_NOTICE<<"   dataSource "<<entry.dataSource<<std::endl;
160            OSG_NOTICE<<"   modifiedCount "<<entry.modifiedCount<<std::endl;
161#endif
162            newTotalSize = computeBufferAlignment(newTotalSize + entry.dataSize, bufferAlignment);
163
164            _bufferEntries.push_back(entry);
165        }
166    }
167
168
169    if (i<_bufferEntries.size())
170    {
171        // triming end of bufferEntries as the source data is has less entries than the originally held.
172        _bufferEntries.erase(_bufferEntries.begin()+i, _bufferEntries.end());
173    }
174
175    _extensions->glBindBuffer(_profile._target, _glObjectID);
176
177    if (newTotalSize > _profile._size)
178    {
179        OSG_INFO<<"newTotalSize="<<newTotalSize<<", _profile._size="<<_profile._size<<std::endl;
180
181        _profile._size = newTotalSize;
182
183        if (_set)
184        {
185            _set->moveToSet(this, _set->getParent()->getGLBufferObjectSet(_profile));
186        }
187
188    }
189
190    if (_allocatedSize != _profile._size)
191    {
192        _allocatedSize = _profile._size;
193        _extensions->glBufferData(_profile._target, _profile._size, NULL, _profile._usage);
194        compileAll = true;
195    }
196
197    for(BufferEntries::iterator itr = _bufferEntries.begin();
198        itr != _bufferEntries.end();
199        ++itr)
200    {
201        BufferEntry& entry = *itr;
202        if (entry.dataSource && (compileAll || entry.modifiedCount != entry.dataSource->getModifiedCount()))
203        {
204            // OSG_NOTICE<<"GLBufferObject::compileBuffer(..) downloading BufferEntry "<<&entry<<std::endl;
205            entry.modifiedCount = entry.dataSource->getModifiedCount();
206
207            const osg::Image* image = entry.dataSource->asImage();
208            if (image && !(image->isDataContiguous()))
209            {
210                unsigned int offset = entry.offset;
211                for(osg::Image::DataIterator img_itr(image); img_itr.valid(); ++img_itr)
212                {
213                    //OSG_NOTICE<<"Copying to buffer object using DataIterator, offset="<<offset<<", size="<<img_itr.size()<<", data="<<(void*)img_itr.data()<<std::endl;
214                    _extensions->glBufferSubData(_profile._target, (GLintptrARB)offset, (GLsizeiptrARB)img_itr.size(), img_itr.data());
215                    offset += img_itr.size();
216                }
217            }
218            else
219            {
220                _extensions->glBufferSubData(_profile._target, (GLintptrARB)entry.offset, (GLsizeiptrARB)entry.dataSize, entry.dataSource->getDataPointer());
221            }
222
223        }
224    }
225}
226
227void GLBufferObject::deleteGLObject()
228{
229    OSG_INFO<<"GLBufferObject::deleteGLObject() "<<_glObjectID<<std::endl;
230    if (_glObjectID!=0)
231    {
232        _extensions->glDeleteBuffers(1, &_glObjectID);
233        _glObjectID = 0;
234
235        _allocatedSize = 0;
236        _bufferEntries.clear();
237    }
238}
239
240//////////////////////////////////////////////////////////////////////////////
241//
242//  Extension support
243//
244
245typedef buffered_value< ref_ptr<GLBufferObject::Extensions> > BufferedExtensions;
246static BufferedExtensions s_extensions;
247
248GLBufferObject::Extensions* GLBufferObject::getExtensions(unsigned int contextID,bool createIfNotInitalized)
249{
250    if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new GLBufferObject::Extensions(contextID);
251    return s_extensions[contextID].get();
252}
253
254void GLBufferObject::setExtensions(unsigned int contextID,Extensions* extensions)
255{
256    s_extensions[contextID] = extensions;
257}
258
259GLBufferObject::Extensions::Extensions(unsigned int contextID)
260{
261    setupGLExtensions(contextID);
262}
263
264GLBufferObject::Extensions::Extensions(const Extensions& rhs):
265    Referenced()
266{
267    _glGenBuffers = rhs._glGenBuffers;
268    _glBindBuffer = rhs._glBindBuffer;
269    _glBufferData = rhs._glBufferData;
270    _glBufferSubData = rhs._glBufferSubData;
271    _glDeleteBuffers = rhs._glDeleteBuffers;
272    _glIsBuffer = rhs._glIsBuffer;
273    _glGetBufferSubData = rhs._glGetBufferSubData;
274    _glMapBuffer = rhs._glMapBuffer;
275    _glUnmapBuffer = rhs._glUnmapBuffer;
276    _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
277    _glGetBufferPointerv = rhs._glGetBufferPointerv;
278    _glBindBufferRange = rhs._glBindBufferRange;
279    _glBindBufferBase = rhs._glBindBufferBase;
280
281}
282
283
284void GLBufferObject::Extensions::lowestCommonDenominator(const Extensions& rhs)
285{
286    if (!rhs._glGenBuffers) _glGenBuffers = rhs._glGenBuffers;
287    if (!rhs._glBindBuffer) _glBindBuffer = rhs._glBindBuffer;
288    if (!rhs._glBufferData) _glBufferData = rhs._glBufferData;
289    if (!rhs._glBufferSubData) _glBufferSubData = rhs._glBufferSubData;
290    if (!rhs._glDeleteBuffers) _glDeleteBuffers = rhs._glDeleteBuffers;
291    if (!rhs._glIsBuffer) _glIsBuffer = rhs._glIsBuffer;
292    if (!rhs._glGetBufferSubData) _glGetBufferSubData = rhs._glGetBufferSubData;
293    if (!rhs._glMapBuffer) _glMapBuffer = rhs._glMapBuffer;
294    if (!rhs._glUnmapBuffer) _glUnmapBuffer = rhs._glUnmapBuffer;
295    if (!rhs._glGetBufferParameteriv) _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
296    if (!rhs._glGetBufferParameteriv) _glGetBufferPointerv = rhs._glGetBufferPointerv;
297    if (!rhs._glBindBufferRange) _glBindBufferRange = rhs._glBindBufferRange;
298    if (!rhs._glBindBufferBase) _glBindBufferBase = rhs._glBindBufferBase;
299
300    _isPBOSupported = rhs._isPBOSupported;
301    _isUniformBufferObjectSupported = rhs._isUniformBufferObjectSupported;
302}
303
304void GLBufferObject::Extensions::setupGLExtensions(unsigned int contextID)
305{
306    setGLExtensionFuncPtr(_glGenBuffers, "glGenBuffers","glGenBuffersARB");
307    setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
308    setGLExtensionFuncPtr(_glBufferData, "glBufferData","glBufferDataARB");
309    setGLExtensionFuncPtr(_glBufferSubData, "glBufferSubData","glBufferSubDataARB");
310    setGLExtensionFuncPtr(_glDeleteBuffers, "glDeleteBuffers","glDeleteBuffersARB");
311    setGLExtensionFuncPtr(_glIsBuffer, "glIsBuffer","glIsBufferARB");
312    setGLExtensionFuncPtr(_glGetBufferSubData, "glGetBufferSubData","glGetBufferSubDataARB");
313    setGLExtensionFuncPtr(_glMapBuffer, "glMapBuffer","glMapBufferARB");
314    setGLExtensionFuncPtr(_glUnmapBuffer, "glUnmapBuffer","glUnmapBufferARB");
315    setGLExtensionFuncPtr(_glGetBufferParameteriv, "glGetBufferParameteriv","glGetBufferParameterivARB");
316    setGLExtensionFuncPtr(_glGetBufferPointerv, "glGetBufferPointerv","glGetBufferPointervARB");
317    setGLExtensionFuncPtr(_glBindBufferRange, "glBindBufferRange");
318    setGLExtensionFuncPtr(_glBindBufferBase, "glBindBufferBase");
319
320    _isPBOSupported = OSG_GL3_FEATURES || osg::isGLExtensionSupported(contextID,"GL_ARB_pixel_buffer_object");
321    _isUniformBufferObjectSupported = osg::isGLExtensionSupported(contextID, "GL_ARB_uniform_buffer_object");
322}
323
324void GLBufferObject::Extensions::glGenBuffers(GLsizei n, GLuint *buffers) const
325{
326    if (_glGenBuffers) _glGenBuffers(n, buffers);
327    else OSG_WARN<<"Error: glGenBuffers not supported by OpenGL driver"<<std::endl;
328}
329
330void GLBufferObject::Extensions::glBindBuffer(GLenum target, GLuint buffer) const
331{
332    if (_glBindBuffer) _glBindBuffer(target, buffer);
333    else OSG_WARN<<"Error: glBindBuffer not supported by OpenGL driver"<<std::endl;
334}
335
336void GLBufferObject::Extensions::glBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const
337{
338    if (_glBufferData) _glBufferData(target, size, data, usage);
339    else OSG_WARN<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
340}
341
342void GLBufferObject::Extensions::glBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const
343{
344    if (_glBufferSubData) _glBufferSubData(target, offset, size, data);
345    else OSG_WARN<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
346}
347
348void GLBufferObject::Extensions::glDeleteBuffers(GLsizei n, const GLuint *buffers) const
349{
350    if (_glDeleteBuffers) _glDeleteBuffers(n, buffers);
351    else OSG_WARN<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
352}
353
354GLboolean GLBufferObject::Extensions::glIsBuffer (GLuint buffer) const
355{
356    if (_glIsBuffer) return _glIsBuffer(buffer);
357    else
358    {
359        OSG_WARN<<"Error: glIsBuffer not supported by OpenGL driver"<<std::endl;
360        return GL_FALSE;
361    }
362}
363
364void GLBufferObject::Extensions::glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const
365{
366    if (_glGetBufferSubData) _glGetBufferSubData(target,offset,size,data);
367    else OSG_WARN<<"Error: glGetBufferSubData not supported by OpenGL driver"<<std::endl;
368}
369
370GLvoid* GLBufferObject::Extensions::glMapBuffer (GLenum target, GLenum access) const
371{
372    if (_glMapBuffer) return _glMapBuffer(target,access);
373    else
374    {
375        OSG_WARN<<"Error: glMapBuffer not supported by OpenGL driver"<<std::endl;
376        return 0;
377    }
378}
379
380GLboolean GLBufferObject::Extensions::glUnmapBuffer (GLenum target) const
381{
382    if (_glUnmapBuffer) return _glUnmapBuffer(target);
383    else
384    {
385        OSG_WARN<<"Error: glUnmapBuffer not supported by OpenGL driver"<<std::endl;
386        return GL_FALSE;
387    }
388}
389
390void GLBufferObject::Extensions::glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const
391{
392    if (_glGetBufferParameteriv) _glGetBufferParameteriv(target,pname,params);
393    else OSG_WARN<<"Error: glGetBufferParameteriv not supported by OpenGL driver"<<std::endl;
394}
395
396void GLBufferObject::Extensions::glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const
397{
398    if (_glGetBufferPointerv) _glGetBufferPointerv(target,pname,params);
399    else OSG_WARN<<"Error: glGetBufferPointerv not supported by OpenGL driver"<<std::endl;
400}
401
402void GLBufferObject::Extensions::glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
403{
404    if (_glBindBufferRange) _glBindBufferRange(target, index, buffer, offset, size);
405    else OSG_WARN<<"Error: glBindBufferRange not supported by OpenGL driver\n";
406}
407
408void GLBufferObject::Extensions::glBindBufferBase (GLenum target, GLuint index, GLuint buffer)
409{
410    if (_glBindBufferBase) _glBindBufferBase(target, index, buffer);
411    else OSG_WARN<<"Error: glBindBufferBase not supported by OpenGL driver\n";
412}
413//////////////////////////////////////////////////////////////////////////////////////////////////////
414//
415// GLBufferObjectSet
416//
417GLBufferObjectSet::GLBufferObjectSet(GLBufferObjectManager* parent, const BufferObjectProfile& profile):
418    _parent(parent),
419    _contextID(parent->getContextID()),
420    _profile(profile),
421    _numOfGLBufferObjects(0),
422    _head(0),
423    _tail(0)
424{
425    OSG_INFO<<"GLBufferObjectSet::GLBufferObjectSet _profile._size="<<_profile._size<<std::endl;
426}
427
428GLBufferObjectSet::~GLBufferObjectSet()
429{
430#if 0
431    OSG_NOTICE<<"GLBufferObjectSet::~GLBufferObjectSet(), _numOfGLBufferObjects="<<_numOfGLBufferObjects<<std::endl;
432    OSG_NOTICE<<"     _orphanedGLBufferObjects = "<<_orphanedGLBufferObjects.size()<<std::endl;
433    OSG_NOTICE<<"     _head = "<<_head<<std::endl;
434    OSG_NOTICE<<"     _tail = "<<_tail<<std::endl;
435#endif
436}
437
438bool GLBufferObjectSet::checkConsistency() const
439{
440    OSG_NOTICE<<"GLBufferObjectSet::checkConsistency()"<<std::endl;
441    // check consistency of linked list.
442    unsigned int numInList = 0;
443    GLBufferObject* to = _head;
444    while(to!=0)
445    {
446        ++numInList;
447
448        if (to->_next)
449        {
450            if ((to->_next)->_previous != to)
451            {
452                OSG_NOTICE<<"GLBufferObjectSet::checkConsistency() : Error (to->_next)->_previous != to "<<std::endl;
453                return false;
454            }
455        }
456        else
457        {
458            if (_tail != to)
459            {
460                OSG_NOTICE<<"GLBufferObjectSet::checkConsistency() : Error _trail != to"<<std::endl;
461                return false;
462            }
463        }
464
465        to = to->_next;
466    }
467
468    unsigned int totalNumber = numInList + _orphanedGLBufferObjects.size();
469    if (totalNumber != _numOfGLBufferObjects)
470    {
471        OSG_NOTICE<<"Error numInList + _orphanedGLBufferObjects.size() != _numOfGLBufferObjects"<<std::endl;
472        OSG_NOTICE<<"    numInList = "<<numInList<<std::endl;
473        OSG_NOTICE<<"    _orphanedGLBufferObjects.size() = "<<_orphanedGLBufferObjects.size()<<std::endl;
474        OSG_NOTICE<<"    _pendingOrphanedGLBufferObjects.size() = "<<_pendingOrphanedGLBufferObjects.size()<<std::endl;
475        OSG_NOTICE<<"    _numOfGLBufferObjects = "<<_numOfGLBufferObjects<<std::endl;
476        return false;
477    }
478
479    return true;
480}
481
482void GLBufferObjectSet::handlePendingOrphandedGLBufferObjects()
483{
484//    OSG_NOTICE<<"handlePendingOrphandedGLBufferObjects()"<<_pendingOrphanedGLBufferObjects.size()<<std::endl;
485
486    if (_pendingOrphanedGLBufferObjects.empty()) return;
487
488    unsigned int numOrphaned = _pendingOrphanedGLBufferObjects.size();
489
490    for(GLBufferObjectList::iterator itr = _pendingOrphanedGLBufferObjects.begin();
491        itr != _pendingOrphanedGLBufferObjects.end();
492        ++itr)
493    {
494        GLBufferObject* to = itr->get();
495
496        _orphanedGLBufferObjects.push_back(to);
497
498        remove(to);
499    }
500
501
502    // update the GLBufferObjectManager's running total of active + orphaned GLBufferObjects
503    _parent->getNumberOrphanedGLBufferObjects() += numOrphaned;
504    _parent->getNumberActiveGLBufferObjects() -= numOrphaned;
505
506    _pendingOrphanedGLBufferObjects.clear();
507
508    CHECK_CONSISTENCY
509}
510
511void GLBufferObjectSet::deleteAllGLBufferObjects()
512{
513    // OSG_NOTICE<<"GLBufferObjectSet::deleteAllGLBufferObjects()"<<std::endl;
514
515    {
516        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
517        if (!_pendingOrphanedGLBufferObjects.empty())
518        {
519            // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"<<std::endl;
520            handlePendingOrphandedGLBufferObjects();
521        }
522    }
523
524    CHECK_CONSISTENCY
525
526    unsigned int numOrphaned = 0;
527    GLBufferObject* to = _head;
528    while(to!=0)
529    {
530        ref_ptr<GLBufferObject> glbo = to;
531
532        to = to->_next;
533
534        _orphanedGLBufferObjects.push_back(glbo.get());
535
536        remove(glbo.get());
537
538        ++numOrphaned;
539
540        ref_ptr<BufferObject> original_BufferObject = glbo->getBufferObject();
541        if (original_BufferObject.valid())
542        {
543            // detect the GLBufferObject from the BufferObject
544            original_BufferObject->setGLBufferObject(_contextID,0);
545        }
546    }
547
548    _parent->getNumberOrphanedGLBufferObjects() += numOrphaned;
549    _parent->getNumberActiveGLBufferObjects() -= numOrphaned;
550
551    // do the actual delete.
552    flushAllDeletedGLBufferObjects();
553
554    // OSG_NOTICE<<"done GLBufferObjectSet::deleteAllGLBufferObjects()"<<std::endl;
555}
556
557void GLBufferObjectSet::discardAllGLBufferObjects()
558{
559    // OSG_NOTICE<<"GLBufferObjectSet::discardAllGLBufferObjects()"<<std::endl;
560
561    GLBufferObject* to = _head;
562    while(to!=0)
563    {
564        ref_ptr<GLBufferObject> glbo = to;
565
566        to = to->_next;
567
568        ref_ptr<BufferObject> original_BufferObject = glbo->getBufferObject();
569        if (original_BufferObject.valid())
570        {
571            // detect the GLBufferObject from the BufferObject
572            original_BufferObject->setGLBufferObject(_contextID,0);
573        }
574    }
575
576    // the linked list should now be empty
577    _head = 0;
578    _tail = 0;
579
580    _pendingOrphanedGLBufferObjects.clear();
581    _orphanedGLBufferObjects.clear();
582
583    unsigned int numDeleted = _numOfGLBufferObjects;
584    _numOfGLBufferObjects = 0;
585
586    // update the GLBufferObjectManager's running total of current pool size
587    _parent->getCurrGLBufferObjectPoolSize() -= numDeleted*_profile._size;
588    _parent->getNumberOrphanedGLBufferObjects() -= numDeleted;
589    _parent->getNumberDeleted() += numDeleted;
590}
591
592void GLBufferObjectSet::flushAllDeletedGLBufferObjects()
593{
594    {
595        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
596        if (!_pendingOrphanedGLBufferObjects.empty())
597        {
598            // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"<<std::endl;
599            handlePendingOrphandedGLBufferObjects();
600        }
601    }
602
603    for(GLBufferObjectList::iterator itr = _orphanedGLBufferObjects.begin();
604        itr != _orphanedGLBufferObjects.end();
605        ++itr)
606    {
607        (*itr)->deleteGLObject();
608    }
609
610    unsigned int numDeleted = _orphanedGLBufferObjects.size();
611    _numOfGLBufferObjects -= numDeleted;
612
613    // update the GLBufferObjectManager's running total of current pool size
614    _parent->getCurrGLBufferObjectPoolSize() -= numDeleted*_profile._size;
615    _parent->getNumberOrphanedGLBufferObjects() -= numDeleted;
616    _parent->getNumberDeleted() += numDeleted;
617
618    _orphanedGLBufferObjects.clear();
619}
620
621void GLBufferObjectSet::discardAllDeletedGLBufferObjects()
622{
623    // OSG_NOTICE<<"GLBufferObjectSet::discardAllDeletedGLBufferObjects()"<<std::endl;
624
625    // clean up the pending orphans.
626    {
627        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
628        if (!_pendingOrphanedGLBufferObjects.empty())
629        {
630            // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"<<std::endl;
631            handlePendingOrphandedGLBufferObjects();
632        }
633    }
634
635    unsigned int numDiscarded = _orphanedGLBufferObjects.size();
636
637    _numOfGLBufferObjects -= numDiscarded;
638
639    // update the GLBufferObjectManager's running total of current pool size
640    _parent->setCurrGLBufferObjectPoolSize( _parent->getCurrGLBufferObjectPoolSize() - numDiscarded*_profile._size );
641
642    // update the number of active and orphaned GLBufferObjects
643    _parent->getNumberOrphanedGLBufferObjects() -= numDiscarded;
644    _parent->getNumberActiveGLBufferObjects() += numDiscarded;
645    _parent->getNumberDeleted() += numDiscarded;
646
647
648    // just clear the list as there is nothing else we can do with them when discarding them
649    _orphanedGLBufferObjects.clear();
650}
651
652void GLBufferObjectSet::flushDeletedGLBufferObjects(double currentTime, double& availableTime)
653{
654    {
655        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
656        if (!_pendingOrphanedGLBufferObjects.empty())
657        {
658            // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"<<std::endl;
659            handlePendingOrphandedGLBufferObjects();
660        }
661    }
662
663    if (_parent->getCurrGLBufferObjectPoolSize()<=_parent->getMaxGLBufferObjectPoolSize())
664    {
665        OSG_INFO<<"Plenty of space in GLBufferObject pool"<<std::endl;
666        return;
667    }
668
669    // if nothing to delete return
670    if (_orphanedGLBufferObjects.empty()) return;
671
672    // if no time available don't try to flush objects.
673    if (availableTime<=0.0) return;
674
675    unsigned int numDeleted = 0;
676    unsigned int sizeRequired = _parent->getCurrGLBufferObjectPoolSize() - _parent->getMaxGLBufferObjectPoolSize();
677    unsigned int maxNumObjectsToDelete = static_cast<unsigned int>(ceil(double(sizeRequired) / double(_profile._size)));
678    OSG_INFO<<"_parent->getCurrGLBufferObjectPoolSize()="<<_parent->getCurrGLBufferObjectPoolSize() <<" _parent->getMaxGLBufferObjectPoolSize()="<< _parent->getMaxGLBufferObjectPoolSize()<<std::endl;
679    OSG_INFO<<"Looking to reclaim "<<sizeRequired<<", going to look to remove "<<maxNumObjectsToDelete<<" from "<<_orphanedGLBufferObjects.size()<<" orhpans"<<std::endl;
680
681    ElapsedTime timer;
682
683    GLBufferObjectList::iterator itr = _orphanedGLBufferObjects.begin();
684    for(;
685        itr != _orphanedGLBufferObjects.end() && timer.elapsedTime()<availableTime && numDeleted<maxNumObjectsToDelete;
686        ++itr)
687    {
688
689         (*itr)->deleteGLObject();
690
691        ++numDeleted;
692    }
693
694    // OSG_NOTICE<<"Size before = "<<_orphanedGLBufferObjects.size();
695    _orphanedGLBufferObjects.erase(_orphanedGLBufferObjects.begin(), itr);
696    // OSG_NOTICE<<", after = "<<_orphanedGLBufferObjects.size()<<" numDeleted = "<<numDeleted<<std::endl;
697
698    // update the number of TO's in this GLBufferObjectSet
699    _numOfGLBufferObjects -= numDeleted;
700
701    _parent->setCurrGLBufferObjectPoolSize( _parent->getCurrGLBufferObjectPoolSize() - numDeleted*_profile._size );
702
703    // update the number of active and orphaned TextureOjects
704    _parent->getNumberOrphanedGLBufferObjects() -= numDeleted;
705    _parent->getNumberActiveGLBufferObjects() += numDeleted;
706    _parent->getNumberDeleted() += numDeleted;
707
708    availableTime -= timer.elapsedTime();
709}
710
711bool GLBufferObjectSet::makeSpace(unsigned int& size)
712{
713    {
714        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
715        if (!_pendingOrphanedGLBufferObjects.empty())
716        {
717            // OSG_NOTICE<<"GLBufferSet::::makeSpace(..) handling orphans"<<std::endl;
718            handlePendingOrphandedGLBufferObjects();
719        }
720    }
721
722    if (!_orphanedGLBufferObjects.empty())
723    {
724        unsigned int sizeAvailable = _orphanedGLBufferObjects.size() * _profile._size;
725        if (size>sizeAvailable) size -= sizeAvailable;
726        else size = 0;
727
728        flushAllDeletedGLBufferObjects();
729    }
730
731    return size==0;
732}
733
734GLBufferObject* GLBufferObjectSet::takeFromOrphans(BufferObject* bufferObject)
735{
736    // take front of orphaned list.
737    ref_ptr<GLBufferObject> glbo = _orphanedGLBufferObjects.front();
738
739    // remove from orphan list.
740    _orphanedGLBufferObjects.pop_front();
741
742    // assign to new GLBufferObject
743    glbo->assign(bufferObject);
744    glbo->setProfile(_profile);
745
746    // update the number of active and orphaned GLBufferObjects
747    _parent->getNumberOrphanedGLBufferObjects() -= 1;
748    _parent->getNumberActiveGLBufferObjects() += 1;
749
750    // place at back of active list
751    addToBack(glbo.get());
752
753    //OSG_NOTICE<<"Reusing orphaned GLBufferObject, _numOfGLBufferObjects="<<_numOfGLBufferObjects<<" target="<<std::hex<<_profile._target<<std::dec<<std::endl;
754
755    return glbo.release();
756}
757
758
759GLBufferObject* GLBufferObjectSet::takeOrGenerate(BufferObject* bufferObject)
760{
761    // see if we can recyle GLBufferObject from the orphan list
762    {
763        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
764        if (!_pendingOrphanedGLBufferObjects.empty())
765        {
766            handlePendingOrphandedGLBufferObjects();
767            return takeFromOrphans(bufferObject);
768        }
769    }
770
771    if (!_orphanedGLBufferObjects.empty())
772    {
773        return takeFromOrphans(bufferObject);
774    }
775
776    unsigned int minFrameNumber = _parent->getFrameNumber();
777
778    // see if we can reuse GLBufferObject by taking the least recently used active GLBufferObject
779    if ((_parent->getMaxGLBufferObjectPoolSize()!=0) &&
780        (!_parent->hasSpace(_profile._size)) &&
781        (_numOfGLBufferObjects>1) &&
782        (_head != 0) &&
783        (_head->_frameLastUsed<minFrameNumber))
784    {
785
786        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
787
788        ref_ptr<GLBufferObject> glbo = _head;
789
790        ref_ptr<BufferObject> original_BufferObject = glbo->getBufferObject();
791
792        if (original_BufferObject.valid())
793        {
794            original_BufferObject->setGLBufferObject(_contextID,0);
795            OSG_INFO<<"GLBufferObjectSet="<<this<<": Reusing an active GLBufferObject "<<glbo.get()<<" _numOfGLBufferObjects="<<_numOfGLBufferObjects<<" size="<<_profile._size<<std::endl;
796        }
797        else
798        {
799            OSG_INFO<<"Reusing a recently orphaned active GLBufferObject "<<glbo.get()<<std::endl;
800        }
801
802        moveToBack(glbo.get());
803
804        // assign to new texture
805        glbo->setBufferObject(bufferObject);
806        glbo->setProfile(_profile);
807
808        return glbo.release();
809    }
810
811    //
812    GLBufferObject* glbo = new GLBufferObject(_contextID, const_cast<BufferObject*>(bufferObject));
813    glbo->setProfile(_profile);
814    glbo->_set = this;
815    ++_numOfGLBufferObjects;
816
817    // update the current texture pool size
818    _parent->getCurrGLBufferObjectPoolSize() += _profile._size;
819    _parent->getNumberActiveGLBufferObjects() += 1;
820
821    addToBack(glbo);
822
823    // OSG_NOTICE<<"Created new GLBufferObject, _numOfGLBufferObjects "<<_numOfGLBufferObjects<<std::endl;
824
825    return glbo;
826}
827
828void GLBufferObjectSet::moveToBack(GLBufferObject* to)
829{
830#if 0
831    OSG_NOTICE<<"GLBufferObjectSet::moveToBack("<<to<<")"<<std::endl;
832    OSG_NOTICE<<"    before _head = "<<_head<<std::endl;
833    OSG_NOTICE<<"    before _tail = "<<_tail<<std::endl;
834    OSG_NOTICE<<"    before to->_previous = "<<to->_previous<<std::endl;
835    OSG_NOTICE<<"    before to->_next = "<<to->_next<<std::endl;
836#endif
837
838    to->_frameLastUsed = _parent->getFrameNumber();
839
840    // nothing to do if we are already tail
841    if (to==_tail) return;
842
843    // if no tail exists then assign 'to' as tail and head
844    if (_tail==0)
845    {
846        OSG_NOTICE<<"Error ***************** Should not get here !!!!!!!!!"<<std::endl;
847        _head = to;
848        _tail = to;
849        return;
850    }
851
852    if (to->_next==0)
853    {
854        OSG_NOTICE<<"Error ***************** Should not get here either !!!!!!!!!"<<std::endl;
855        return;
856    }
857
858
859    if (to->_previous)
860    {
861        (to->_previous)->_next = to->_next;
862    }
863    else
864    {
865        // 'to' is the head, so moving it to the back will mean we need a new head
866        if (to->_next)
867        {
868            _head = to->_next;
869        }
870    }
871
872    (to->_next)->_previous = to->_previous;
873
874    _tail->_next = to;
875
876    to->_previous = _tail;
877    to->_next = 0;
878
879    _tail = to;
880
881#if 0
882    OSG_NOTICE<<"  m2B   after  _head = "<<_head<<std::endl;
883    OSG_NOTICE<<"  m2B   after _tail = "<<_tail<<std::endl;
884    OSG_NOTICE<<"  m2B   after to->_previous = "<<to->_previous<<std::endl;
885    OSG_NOTICE<<"  m2B   after to->_next = "<<to->_next<<std::endl;
886#endif
887    CHECK_CONSISTENCY
888}
889
890void GLBufferObjectSet::addToBack(GLBufferObject* to)
891{
892#if 0
893    OSG_NOTICE<<"GLBufferObjectSet::addToBack("<<to<<")"<<std::endl;
894    OSG_NOTICE<<"    before _head = "<<_head<<std::endl;
895    OSG_NOTICE<<"    before _tail = "<<_tail<<std::endl;
896    OSG_NOTICE<<"    before to->_previous = "<<to->_previous<<std::endl;
897    OSG_NOTICE<<"    before to->_next = "<<to->_next<<std::endl;
898#endif
899
900    if (to->_previous !=0 || to->_next !=0)
901    {
902        moveToBack(to);
903    }
904    else
905    {
906        to->_frameLastUsed = _parent->getFrameNumber();
907
908        if (_tail) _tail->_next = to;
909        to->_previous = _tail;
910
911        if (!_head) _head = to;
912        _tail = to;
913    }
914#if 0
915    OSG_NOTICE<<"  a2B  after  _head = "<<_head<<std::endl;
916    OSG_NOTICE<<"  a2B   after _tail = "<<_tail<<std::endl;
917    OSG_NOTICE<<"  a2B   after to->_previous = "<<to->_previous<<std::endl;
918    OSG_NOTICE<<"  a2B   after to->_next = "<<to->_next<<std::endl;
919#endif
920    CHECK_CONSISTENCY
921}
922
923void GLBufferObjectSet::orphan(GLBufferObject* to)
924{
925    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
926
927    // disconnect from original texture
928    to->setBufferObject(0);
929
930    // add orphan 'to' to the pending list of orphans, these will then be
931    // handled in the handlePendingOrphandedGLBufferObjects() where the TO's
932    // will be removed from the active list, and then placed in the orhpanGLBufferObject
933    // list.  This double buffered approach to handling orphaned TO's is used
934    // to avoid having to mutex the process of appling active TO's.
935    _pendingOrphanedGLBufferObjects.push_back(to);
936}
937
938void GLBufferObjectSet::remove(GLBufferObject* to)
939{
940    if (to->_previous!=0)
941    {
942        (to->_previous)->_next = to->_next;
943    }
944    else
945    {
946        // 'to' was head so assign _head to the next in list
947        _head = to->_next;
948    }
949
950    if (to->_next!=0)
951    {
952        (to->_next)->_previous = to->_previous;
953    }
954    else
955    {
956        // 'to' was tail so assing tail to the previous in list
957        _tail = to->_previous;
958    }
959
960    // reset the 'to' list pointers as it's no longer in the active list.
961    to->_next = 0;
962    to->_previous = 0;
963}
964
965
966void GLBufferObjectSet::moveToSet(GLBufferObject* to, GLBufferObjectSet* set)
967{
968    if (set==this) return;
969    if (!set) return;
970
971    // remove 'to' from original set
972    --_numOfGLBufferObjects;
973    remove(to);
974
975    // register 'to' with new set.
976    to->_set = set;
977    ++set->_numOfGLBufferObjects;
978    set->addToBack(to);
979}
980
981unsigned int GLBufferObjectSet::computeNumGLBufferObjectsInList() const
982{
983    unsigned int num=0;
984    GLBufferObject* obj = _head;
985    while(obj!=NULL)
986    {
987        ++num;
988        obj = obj->_next;
989    }
990    return num;
991}
992
993
994GLBufferObjectManager::GLBufferObjectManager(unsigned int contextID):
995    _contextID(contextID),
996    _numActiveGLBufferObjects(0),
997    _numOrphanedGLBufferObjects(0),
998    _currGLBufferObjectPoolSize(0),
999    _maxGLBufferObjectPoolSize(0),
1000    _frameNumber(0),
1001    _numFrames(0),
1002    _numDeleted(0),
1003    _deleteTime(0.0),
1004    _numGenerated(0),
1005    _generateTime(0.0),
1006    _numApplied(0),
1007    _applyTime(0.0)
1008{
1009}
1010
1011void GLBufferObjectManager::setMaxGLBufferObjectPoolSize(unsigned int size)
1012{
1013    if (_maxGLBufferObjectPoolSize == size) return;
1014
1015    if (size<_currGLBufferObjectPoolSize)
1016    {
1017        OSG_NOTICE<<"Warning: new MaxGLBufferObjectPoolSize="<<size<<" is smaller than current GLBufferObjectPoolSize="<<_currGLBufferObjectPoolSize<<std::endl;
1018    }
1019
1020    _maxGLBufferObjectPoolSize = size;
1021}
1022
1023bool GLBufferObjectManager::makeSpace(unsigned int size)
1024{
1025    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1026        itr != _glBufferObjectSetMap.end() && size>0;
1027        ++itr)
1028    {
1029        if ((*itr).second->makeSpace(size)) return true;
1030    }
1031
1032    return size==0;
1033}
1034
1035
1036GLBufferObject* GLBufferObjectManager::generateGLBufferObject(const BufferObject* bufferObject)
1037{
1038    ElapsedTime elapsedTime(&(getGenerateTime()));
1039    ++getNumberGenerated();
1040
1041    BufferObjectProfile profile(bufferObject->getTarget(), bufferObject->getUsage(), bufferObject->computeRequiredBufferSize());
1042
1043    // OSG_NOTICE<<"GLBufferObjectManager::generateGLBufferObject size="<<bufferObject->computeRequiredBufferSize()<<std::endl;
1044
1045    GLBufferObjectSet* glbos = getGLBufferObjectSet(profile);
1046    return glbos->takeOrGenerate(const_cast<BufferObject*>(bufferObject));
1047}
1048
1049GLBufferObjectSet* GLBufferObjectManager::getGLBufferObjectSet(const BufferObjectProfile& profile)
1050{
1051    osg::ref_ptr<GLBufferObjectSet>& tos = _glBufferObjectSetMap[profile];
1052    if (!tos) tos = new GLBufferObjectSet(this, profile);
1053    return tos.get();
1054}
1055
1056void GLBufferObjectManager::handlePendingOrphandedGLBufferObjects()
1057{
1058    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1059        itr != _glBufferObjectSetMap.end();
1060        ++itr)
1061    {
1062        (*itr).second->handlePendingOrphandedGLBufferObjects();
1063    }
1064}
1065
1066void GLBufferObjectManager::deleteAllGLBufferObjects()
1067{
1068    ElapsedTime elapsedTime(&(getDeleteTime()));
1069
1070    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1071        itr != _glBufferObjectSetMap.end();
1072        ++itr)
1073    {
1074        (*itr).second->deleteAllGLBufferObjects();
1075    }
1076}
1077
1078void GLBufferObjectManager::discardAllGLBufferObjects()
1079{
1080    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1081        itr != _glBufferObjectSetMap.end();
1082        ++itr)
1083    {
1084        (*itr).second->discardAllGLBufferObjects();
1085    }
1086}
1087
1088void GLBufferObjectManager::flushAllDeletedGLBufferObjects()
1089{
1090    ElapsedTime elapsedTime(&(getDeleteTime()));
1091
1092    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1093        itr != _glBufferObjectSetMap.end();
1094        ++itr)
1095    {
1096        (*itr).second->flushAllDeletedGLBufferObjects();
1097    }
1098}
1099
1100void GLBufferObjectManager::discardAllDeletedGLBufferObjects()
1101{
1102    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1103        itr != _glBufferObjectSetMap.end();
1104        ++itr)
1105    {
1106        (*itr).second->discardAllDeletedGLBufferObjects();
1107    }
1108}
1109
1110void GLBufferObjectManager::flushDeletedGLBufferObjects(double currentTime, double& availableTime)
1111{
1112    ElapsedTime elapsedTime(&(getDeleteTime()));
1113
1114    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1115        (itr != _glBufferObjectSetMap.end()) && (availableTime > 0.0);
1116        ++itr)
1117    {
1118        (*itr).second->flushDeletedGLBufferObjects(currentTime, availableTime);
1119    }
1120}
1121
1122void GLBufferObjectManager::releaseGLBufferObject(GLBufferObject* to)
1123{
1124    if (to->_set) to->_set->orphan(to);
1125    else OSG_NOTICE<<"GLBufferObjectManager::releaseGLBufferObject(GLBufferObject* to) Not implemented yet"<<std::endl;
1126}
1127
1128
1129void GLBufferObjectManager::newFrame(osg::FrameStamp* fs)
1130{
1131    if (fs) _frameNumber = fs->getFrameNumber();
1132    else ++_frameNumber;
1133
1134    ++_numFrames;
1135}
1136
1137void GLBufferObjectManager::reportStats(std::ostream& out)
1138{
1139    double numFrames(_numFrames==0 ? 1.0 : _numFrames);
1140    out<<"GLBufferObjectMananger::reportStats()"<<std::endl;
1141    out<<"   total _numOfGLBufferObjects="<<_numActiveGLBufferObjects<<", _numOrphanedGLBufferObjects="<<_numOrphanedGLBufferObjects<<" _currGLBufferObjectPoolSize="<<_currGLBufferObjectPoolSize<<std::endl;
1142    out<<"   total _numGenerated="<<_numGenerated<<", _generateTime="<<_generateTime<<", averagePerFrame="<<_generateTime/numFrames*1000.0<<"ms"<<std::endl;
1143    out<<"   total _numDeleted="<<_numDeleted<<", _deleteTime="<<_deleteTime<<", averagePerFrame="<<_deleteTime/numFrames*1000.0<<"ms"<<std::endl;
1144    out<<"   total _numApplied="<<_numApplied<<", _applyTime="<<_applyTime<<", averagePerFrame="<<_applyTime/numFrames*1000.0<<"ms"<<std::endl;
1145    out<<"   getMaxGLBufferObjectPoolSize()="<<getMaxGLBufferObjectPoolSize()<<" current/max size = "<<double(_currGLBufferObjectPoolSize)/double(getMaxGLBufferObjectPoolSize())<<std::endl;;
1146
1147    recomputeStats(out);
1148
1149}
1150
1151void GLBufferObjectManager::resetStats()
1152{
1153    _numFrames = 0;
1154    _numDeleted = 0;
1155    _deleteTime = 0;
1156
1157    _numGenerated = 0;
1158    _generateTime = 0;
1159
1160    _numApplied = 0;
1161    _applyTime = 0;
1162}
1163
1164void GLBufferObjectManager::recomputeStats(std::ostream& out)
1165{
1166    out<<"GLBufferObjectMananger::recomputeStats()"<<std::endl;
1167    unsigned int numObjectsInLists = 0;
1168    unsigned int numActive = 0;
1169    unsigned int numOrphans = 0;
1170    unsigned int numPendingOrphans = 0;
1171    unsigned int currentSize = 0;
1172    for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
1173        itr != _glBufferObjectSetMap.end();
1174        ++itr)
1175    {
1176         GLBufferObjectSet* os = itr->second.get();
1177         numObjectsInLists += os->computeNumGLBufferObjectsInList();
1178         numActive += os->getNumOfGLBufferObjects();
1179         numOrphans += os->getNumOrphans();
1180         numPendingOrphans += os->getNumPendingOrphans();
1181         currentSize += os->getProfile()._size * (os->computeNumGLBufferObjectsInList()+os->getNumOrphans());
1182         out<<"   size="<<os->getProfile()._size
1183           <<", os->computeNumGLBufferObjectsInList()"<<os->computeNumGLBufferObjectsInList()
1184           <<", os->getNumOfGLBufferObjects()"<<os->getNumOfGLBufferObjects()
1185           <<", os->getNumOrphans()"<<os->getNumOrphans()
1186           <<", os->getNumPendingOrphans()"<<os->getNumPendingOrphans()
1187           <<std::endl;
1188    }
1189    out<<"   numObjectsInLists="<<numObjectsInLists<<", numActive="<<numActive<<", numOrphans="<<numOrphans<<" currentSize="<<currentSize<<std::endl;
1190    out<<"   getMaxGLBufferObjectPoolSize()="<<getMaxGLBufferObjectPoolSize()<<" current/max size = "<<double(currentSize)/double(getMaxGLBufferObjectPoolSize())<<std::endl;
1191}
1192
1193
1194osg::ref_ptr<GLBufferObjectManager>& GLBufferObjectManager::getGLBufferObjectManager(unsigned int contextID)
1195{
1196    typedef osg::buffered_object< ref_ptr<GLBufferObjectManager> > GLBufferObjectManagerBuffer;
1197    static GLBufferObjectManagerBuffer s_GLBufferObjectManager;
1198    if (!s_GLBufferObjectManager[contextID]) s_GLBufferObjectManager[contextID] = new GLBufferObjectManager(contextID);
1199    return s_GLBufferObjectManager[contextID];
1200}
1201
1202GLBufferObject* GLBufferObject::createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject)
1203{
1204    return GLBufferObjectManager::getGLBufferObjectManager(contextID)->generateGLBufferObject(bufferObject);
1205}
1206
1207void GLBufferObject::deleteAllBufferObjects(unsigned int contextID)
1208{
1209    GLBufferObjectManager::getGLBufferObjectManager(contextID)->deleteAllGLBufferObjects();
1210}
1211
1212void GLBufferObject::discardAllBufferObjects(unsigned int contextID)
1213{
1214    GLBufferObjectManager::getGLBufferObjectManager(contextID)->discardAllGLBufferObjects();
1215}
1216
1217void GLBufferObject::flushAllDeletedBufferObjects(unsigned int contextID)
1218{
1219    GLBufferObjectManager::getGLBufferObjectManager(contextID)->flushAllDeletedGLBufferObjects();
1220}
1221
1222void GLBufferObject::discardAllDeletedBufferObjects(unsigned int contextID)
1223{
1224    GLBufferObjectManager::getGLBufferObjectManager(contextID)->discardAllDeletedGLBufferObjects();
1225}
1226
1227void GLBufferObject::flushDeletedBufferObjects(unsigned int contextID,double currentTime, double& availbleTime)
1228{
1229    GLBufferObjectManager::getGLBufferObjectManager(contextID)->flushDeletedGLBufferObjects(currentTime, availbleTime);
1230}
1231
1232void GLBufferObject::releaseGLBufferObject(unsigned int contextID, GLBufferObject* to)
1233{
1234    GLBufferObjectManager::getGLBufferObjectManager(contextID)->releaseGLBufferObject(to);
1235}
1236
1237
1238
1239//////////////////////////////////////////////////////////////////////////////////////////////////////
1240//
1241// BufferObject
1242//
1243BufferObject::BufferObject():
1244    _copyDataAndReleaseGLBufferObject(false)
1245{
1246}
1247
1248BufferObject::BufferObject(const BufferObject& bo,const CopyOp& copyop):
1249    Object(bo,copyop),
1250    _copyDataAndReleaseGLBufferObject(bo._copyDataAndReleaseGLBufferObject)
1251{
1252}
1253
1254BufferObject::~BufferObject()
1255{
1256    releaseGLObjects(0);
1257}
1258
1259
1260void BufferObject::setBufferData(unsigned int index, BufferData* bd)
1261{
1262    if (index>=_bufferDataList.size()) _bufferDataList.resize(index+1);
1263    _bufferDataList[index] = bd;
1264}
1265
1266void BufferObject::dirty()
1267{
1268    for(unsigned int i=0; i<_glBufferObjects.size(); ++i)
1269    {
1270        if (_glBufferObjects[i].valid()) _glBufferObjects[i]->dirty();
1271    }
1272}
1273
1274void BufferObject::resizeGLObjectBuffers(unsigned int maxSize)
1275{
1276    _glBufferObjects.resize(maxSize);
1277}
1278
1279void BufferObject::releaseGLObjects(State* state) const
1280{
1281    OSG_INFO<<"BufferObject::releaseGLObjects("<<state<<")"<<std::endl;
1282    if (state)
1283    {
1284        unsigned int contextID = state->getContextID();
1285        if (_glBufferObjects[contextID].valid())
1286        {
1287            GLBufferObject::releaseGLBufferObject(contextID, _glBufferObjects[contextID].get());
1288            _glBufferObjects[contextID] = 0;
1289        }
1290    }
1291    else
1292    {
1293        for(unsigned int i=0; i<_glBufferObjects.size();++i)
1294        {
1295            if (_glBufferObjects[i].valid())
1296            {
1297                // OSG_NOTICE<<"  GLBufferObject::releaseGLBufferObject("<<i<<", _glBufferObjects["<<i<<"]="<<_glBufferObjects[i].get()<<")"<<std::endl;
1298                GLBufferObject::releaseGLBufferObject(i, _glBufferObjects[i].get());
1299                _glBufferObjects[i] = 0;
1300            }
1301        }
1302    }
1303}
1304
1305unsigned int BufferObject::addBufferData(BufferData* bd)
1306{
1307    if (!bd) return 0;
1308
1309    // check to see if bd exists in BufferObject already, is so return without doing anything
1310    for(BufferDataList::iterator itr = _bufferDataList.begin();
1311        itr != _bufferDataList.end();
1312        ++itr)
1313    {
1314        if (*itr == bd) return bd->getBufferIndex();
1315    }
1316
1317    // bd->setBufferIndex(_bufferDataList.size());
1318
1319    _bufferDataList.push_back(bd);
1320
1321    dirty();
1322
1323//OSG_NOTICE<<"BufferObject "<<this<<":"<<className()<<"::addBufferData("<<bd<<"), bufferIndex= "<<_bufferDataList.size()-1<<std::endl;
1324
1325    return _bufferDataList.size()-1;
1326}
1327
1328void BufferObject::removeBufferData(unsigned int index)
1329{
1330    if (index>=_bufferDataList.size())
1331    {
1332        OSG_WARN<<"Error "<<className()<<"::removeBufferData("<<index<<") out of range."<<std::endl;
1333        return;
1334    }
1335
1336    //OSG_NOTICE<<"BufferObject::"<<this<<":"<<className()<<"::removeBufferData("<<index<<"), size= "<<_bufferDataList.size()<<std::endl;
1337
1338    // alter the indices of the BufferData after the entry to be removed so their indices are correctly placed.
1339    for(unsigned int i=index+1; i<_bufferDataList.size(); ++i)
1340    {
1341        _bufferDataList[i]->setBufferIndex(i-1);
1342    }
1343
1344    // remove the entry
1345    _bufferDataList.erase(_bufferDataList.begin() + index);
1346
1347    for(unsigned int i=0; i<_glBufferObjects.size(); ++i)
1348    {
1349        if (_glBufferObjects[i].valid()) _glBufferObjects[i]->clear();
1350    }
1351
1352}
1353
1354void BufferObject::removeBufferData(BufferData* bd)
1355{
1356    //OSG_NOTICE<<"BufferObject::"<<this<<":"<<className()<<"::removeBufferData("<<bd<<"), index="<<bd->getBufferIndex()<<" size= "<<_bufferDataList.size()<<std::endl;
1357
1358    if (!bd || bd->getBufferObject()!=this) return;
1359
1360    removeBufferData(bd->getBufferIndex());
1361}
1362
1363unsigned int BufferObject::computeRequiredBufferSize() const
1364{
1365    unsigned int newTotalSize = 0;
1366    for(BufferDataList::const_iterator itr = _bufferDataList.begin();
1367        itr != _bufferDataList.end();
1368        ++itr)
1369    {
1370        BufferData* bd = *itr;
1371        if (bd) newTotalSize += bd->getTotalDataSize();
1372        else
1373        {
1374            OSG_NOTICE<<"BufferObject::"<<this<<":"<<className()<<"::BufferObject::computeRequiredBufferSize() error, BufferData is 0x0"<<std::endl;
1375        }
1376    }
1377    //OSG_NOTICE<<"BufferObject::"<<this<<":"<<className()<<"::BufferObject::computeRequiredBufferSize() size="<<newTotalSize<<std::endl;
1378    return newTotalSize;
1379}
1380
1381void BufferObject::deleteBufferObject(unsigned int contextID,GLuint globj)
1382{
1383    // implement deleteBufferObject for backwards compatibility by adding
1384    // a GLBufferObject for the globj id to BufferObjectManager/Set for the specified context.
1385
1386    osg::ref_ptr<GLBufferObjectManager>& bufferObjectManager = GLBufferObjectManager::getGLBufferObjectManager(contextID);
1387    if (!bufferObjectManager)
1388    {
1389        OSG_NOTICE<<"Warning::BufferObject::deleteBufferObject("<<contextID<<", "<<globj<<") unable to get GLBufferObjectManager for context."<<std::endl;
1390        return;
1391    }
1392    osg::ref_ptr<GLBufferObject> glBufferObject = new GLBufferObject(contextID, 0, globj);
1393
1394    GLBufferObjectSet* bufferObjectSet = bufferObjectManager->getGLBufferObjectSet(glBufferObject->getProfile());
1395    if (!bufferObjectSet)
1396    {
1397        OSG_NOTICE<<"Warning::BufferObject::deleteBufferObject("<<contextID<<", "<<globj<<") unable to get GLBufferObjectSet for context."<<std::endl;
1398        return;
1399    }
1400
1401    // do the adding of the wrapper buffer object.
1402    bufferObjectSet->orphan(glBufferObject.get());
1403}
1404
1405//////////////////////////////////////////////////////////////////////////////////////////////////////
1406//
1407// BufferData
1408//
1409BufferData::~BufferData()
1410{
1411    setBufferObject(0);
1412}
1413
1414void BufferData::setBufferObject(BufferObject* bufferObject)
1415{
1416    if (_bufferObject==bufferObject) return;
1417
1418    if (_bufferObject.valid())
1419    {
1420        _bufferObject->removeBufferData(_bufferIndex);
1421    }
1422
1423    _bufferObject = bufferObject;
1424    _bufferIndex = _bufferObject.valid() ? _bufferObject->addBufferData(this) : 0;
1425}
1426
1427void BufferData::resizeGLObjectBuffers(unsigned int maxSize)
1428{
1429    if (_bufferObject.valid())
1430    {
1431        _bufferObject->resizeGLObjectBuffers(maxSize);
1432    }
1433}
1434
1435void BufferData::releaseGLObjects(State* state) const
1436{
1437    OSG_INFO<<"BufferData::releaseGLObjects("<<state<<")"<<std::endl;
1438    if (_bufferObject.valid())
1439    {
1440        _bufferObject->releaseGLObjects(state);
1441    }
1442}
1443
1444
1445//////////////////////////////////////////////////////////////////////////////////
1446//
1447//  VertexBufferObject
1448//
1449VertexBufferObject::VertexBufferObject()
1450{
1451    setTarget(GL_ARRAY_BUFFER_ARB);
1452    setUsage(GL_STATIC_DRAW_ARB);
1453//    _usage = GL_DYNAMIC_DRAW_ARB;
1454//    _usage = GL_STREAM_DRAW_ARB;
1455}
1456
1457VertexBufferObject::VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop):
1458    BufferObject(vbo,copyop)
1459{
1460}
1461
1462VertexBufferObject::~VertexBufferObject()
1463{
1464}
1465
1466unsigned int VertexBufferObject::addArray(osg::Array* array)
1467{
1468    return addBufferData(array);
1469}
1470
1471void VertexBufferObject::removeArray(osg::Array* array)
1472{
1473    removeBufferData(array);
1474}
1475
1476void VertexBufferObject::setArray(unsigned int i, Array* array)
1477{
1478    setBufferData(i,array);
1479}
1480
1481Array* VertexBufferObject::getArray(unsigned int i)
1482{
1483    return dynamic_cast<osg::Array*>(getBufferData(i));
1484}
1485
1486const Array* VertexBufferObject::getArray(unsigned int i) const
1487{
1488    return dynamic_cast<const osg::Array*>(getBufferData(i));
1489}
1490
1491//////////////////////////////////////////////////////////////////////////////////
1492//
1493//  ElementBufferObject
1494//
1495ElementBufferObject::ElementBufferObject()
1496{
1497    setTarget(GL_ELEMENT_ARRAY_BUFFER_ARB);
1498    setUsage(GL_STATIC_DRAW_ARB);
1499}
1500
1501ElementBufferObject::ElementBufferObject(const ElementBufferObject& vbo,const CopyOp& copyop):
1502    BufferObject(vbo,copyop)
1503{
1504}
1505
1506ElementBufferObject::~ElementBufferObject()
1507{
1508}
1509
1510unsigned int ElementBufferObject::addDrawElements(osg::DrawElements* drawElements)
1511{
1512    return addBufferData(drawElements);
1513}
1514
1515void ElementBufferObject::removeDrawElements(osg::DrawElements* drawElements)
1516{
1517    removeBufferData(drawElements);
1518}
1519
1520void ElementBufferObject::setDrawElements(unsigned int i, DrawElements* drawElements)
1521{
1522    setBufferData(i,drawElements);
1523}
1524
1525DrawElements* ElementBufferObject::getDrawElements(unsigned int i)
1526{
1527    return dynamic_cast<DrawElements*>(getBufferData(i));
1528}
1529
1530const DrawElements* ElementBufferObject::getDrawElements(unsigned int i) const
1531{
1532    return dynamic_cast<const DrawElements*>(getBufferData(i));
1533}
1534
1535
1536//////////////////////////////////////////////////////////////////////////////////
1537//
1538//  PixelBufferObject
1539//
1540PixelBufferObject::PixelBufferObject(osg::Image* image):
1541    BufferObject()
1542{
1543    setTarget(GL_PIXEL_UNPACK_BUFFER_ARB);
1544    setUsage(GL_STREAM_DRAW_ARB);
1545
1546    OSG_INFO<<"Constructing PixelBufferObject for image="<<image<<std::endl;
1547
1548    if (image) setBufferData(0, image);
1549}
1550
1551PixelBufferObject::PixelBufferObject(const PixelBufferObject& buffer,const CopyOp& copyop):
1552    BufferObject(buffer,copyop)
1553{
1554}
1555
1556PixelBufferObject::~PixelBufferObject()
1557{
1558}
1559
1560void PixelBufferObject::setImage(osg::Image* image)
1561{
1562    setBufferData(0, image);
1563}
1564
1565Image* PixelBufferObject::getImage()
1566{
1567    return dynamic_cast<Image*>(getBufferData(0));
1568}
1569
1570const Image* PixelBufferObject::getImage() const
1571{
1572    return dynamic_cast<const Image*>(getBufferData(0));
1573}
1574
1575
1576//////////////////////////////////////////////////////////////////////////////////
1577//
1578//  PixelDataBufferObject
1579//
1580//--------------------------------------------------------------------------------
1581PixelDataBufferObject::PixelDataBufferObject()
1582{
1583    setTarget(GL_ARRAY_BUFFER_ARB);
1584    setUsage(GL_DYNAMIC_DRAW_ARB);
1585}
1586
1587//--------------------------------------------------------------------------------
1588PixelDataBufferObject::PixelDataBufferObject(const PixelDataBufferObject& buffer,const CopyOp& copyop):
1589    BufferObject(buffer,copyop)
1590{
1591}
1592
1593//--------------------------------------------------------------------------------
1594PixelDataBufferObject::~PixelDataBufferObject()
1595{
1596}
1597
1598//--------------------------------------------------------------------------------
1599void PixelDataBufferObject::compileBuffer(State& state) const
1600{
1601    unsigned int contextID = state.getContextID();
1602    if ( _profile._size == 0) return;
1603
1604    GLBufferObject* bo = getOrCreateGLBufferObject(contextID);
1605    if (!bo || !bo->isDirty()) return;
1606
1607    bo->_extensions->glBindBuffer(_profile._target, bo->getGLObjectID());
1608    bo->_extensions->glBufferData(_profile._target, _profile._size, NULL, _profile._usage);
1609    bo->_extensions->glBindBuffer(_profile._target, 0);
1610}
1611
1612//--------------------------------------------------------------------------------
1613void PixelDataBufferObject::bindBufferInReadMode(State& state)
1614{
1615    unsigned int contextID = state.getContextID();
1616
1617    GLBufferObject* bo = getOrCreateGLBufferObject(contextID);
1618    if (!bo) return;
1619
1620    if (bo->isDirty()) compileBuffer(state);
1621
1622    bo->_extensions->glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bo->getGLObjectID());
1623
1624    _mode[contextID] = READ;
1625}
1626
1627//--------------------------------------------------------------------------------
1628void PixelDataBufferObject::bindBufferInWriteMode(State& state)
1629{
1630    unsigned int contextID = state.getContextID();
1631
1632    GLBufferObject* bo = getOrCreateGLBufferObject(contextID);
1633    if (!bo) return;
1634
1635    if (bo->isDirty()) compileBuffer(state);
1636
1637    bo->_extensions->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, bo->getGLObjectID());
1638
1639    _mode[contextID] = WRITE;
1640}
1641
1642//--------------------------------------------------------------------------------
1643void PixelDataBufferObject::unbindBuffer(unsigned int contextID) const
1644{
1645    GLBufferObject::Extensions* extensions = GLBufferObject::getExtensions(contextID,true);
1646
1647    switch(_mode[contextID])
1648    {
1649        case READ:
1650            extensions->glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
1651            break;
1652        case WRITE:
1653            extensions->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB,0);
1654            break;
1655        default:
1656            extensions->glBindBuffer(_profile._target,0);
1657            break;
1658    }
1659
1660    _mode[contextID] = NONE;
1661}
1662
1663//--------------------------------------------------------------------------------
1664void PixelDataBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
1665{
1666    BufferObject::resizeGLObjectBuffers(maxSize);
1667
1668    _mode.resize(maxSize);
1669}
1670
1671UniformBufferObject::UniformBufferObject()
1672{
1673    setTarget(GL_UNIFORM_BUFFER);
1674    setUsage(GL_STREAM_DRAW_ARB);
1675}
1676
1677UniformBufferObject::UniformBufferObject(const UniformBufferObject& ubo, const CopyOp& copyop)
1678    : BufferObject(ubo, copyop)
1679{
1680}
1681
1682UniformBufferObject::~UniformBufferObject()
1683{
1684}
Note: See TracBrowser for help on using the browser.