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

Revision 12912, 52.5 kB (checked in by robert, 2 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

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