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

Revision 12522, 51.8 kB (checked in by robert, 4 years ago)

Added GLBufferObject::computeBufferAlignment(..) method to enable buffer entries to be aligned along specified buffer alignment boundaries, currently defaulting to 4.

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