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

Revision 10601, 44.9 kB (checked in by robert, 5 years ago)

Introduced new GLBufferObject pool for managing the memory footprint taken up by VertexBufferObejct?, ElementBufferObject? and PixelBufferObject?.

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