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

Revision 10600, 33.6 kB (checked in by robert, 5 years ago)

Introduced new BufferObject? design + implementation in preperation of implementing a pool system for buffer objects

  • 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
[10600]40//////////////////////////////////////////////////////////////////////////////////////////////////////
41//
42// GLBufferObject
43//
44GLBufferObject::GLBufferObject(unsigned int contextID, BufferObject* bufferObject):
45    _contextID(contextID),
46    _glObjectID(0),
47    _target(0),
48    _usage(0),
49    _dirty(true),
50    _totalSize(0),
51    _bufferObject(0),
52    _extensions(0)
[3819]53{
[10600]54    assign(bufferObject);
55    _extensions = GLBufferObject::getExtensions(contextID, true);
56    _extensions->glGenBuffers(1, &_glObjectID);
57}
58
59GLBufferObject::~GLBufferObject()
60{
61    if (_glObjectID!=0) GLBufferObject::deleteBufferObject(_contextID, _glObjectID);
62
63}
64
65void GLBufferObject::assign(BufferObject* bufferObject)
66{
67    _bufferObject = bufferObject;
68
69    if (_bufferObject)
70    {
71        _target = bufferObject->getTarget();
72        _usage = bufferObject->getUsage();
73
74        _totalSize = 0;
75
76        _dirty = true;
77
78        _bufferEntries.clear();
79    }
80    else
81    {
82        _target = 0;
83        _usage = 0;
84
85        _totalSize = 0;
86
87        // clear all previous entries;
88        _bufferEntries.clear();
89    }
90}
91
92void GLBufferObject::clear()
93{
94    _bufferEntries.clear();
95    _dirty = true;
96}
97
98void GLBufferObject::compileBuffer()
99{
100    _dirty = false;
101
102    _bufferEntries.reserve(_bufferObject->getNumBufferData());
103
104    _totalSize = 0;
105
106    bool compileAll = false;
107    bool offsetChanged = false;
108
109    GLsizeiptrARB newTotalSize = 0;
110    unsigned int i=0;
111    for(; i<_bufferObject->getNumBufferData(); ++i)
112    {
113        BufferData* bd = _bufferObject->getBufferData(i);
114        if (i<_bufferEntries.size())
115        {
116            BufferEntry& entry = _bufferEntries[i];
117            if (offsetChanged ||
118                entry.dataSource != bd ||
119                entry.dataSize != bd->getTotalDataSize())
120            {
121                GLsizeiptrARB previousEndOfBufferDataMarker = GLsizeiptrARB(entry.offset) + entry.dataSize;
122
123                // osg::notify(osg::NOTICE)<<"GLBufferObject::compileBuffer(..) updating BufferEntry"<<std::endl;
124
125
126                entry.offset = newTotalSize;
127                entry.modifiedCount = 0xffffff;
128                entry.dataSize = bd->getTotalDataSize();
129                entry.dataSource = bd;
130
131                newTotalSize += entry.dataSize;
132                if (previousEndOfBufferDataMarker==newTotalSize)
133                {
134                    offsetChanged = true;
135                }
136            }
137        }
138        else
139        {
140            BufferEntry entry;
141            entry.offset = newTotalSize;
142            entry.modifiedCount = 0xffffff;
143            entry.dataSize = bd->getTotalDataSize();
144            entry.dataSource = bd;
145#if 0
146            osg::notify(osg::NOTICE)<<"entry"<<std::endl;
147            osg::notify(osg::NOTICE)<<"   offset "<<entry.offset<<std::endl;
148            osg::notify(osg::NOTICE)<<"   dataSize "<<entry.dataSize<<std::endl;
149            osg::notify(osg::NOTICE)<<"   dataSource "<<entry.dataSource<<std::endl;
150            osg::notify(osg::NOTICE)<<"   modifiedCount "<<entry.modifiedCount<<std::endl;
151#endif
152            newTotalSize += entry.dataSize;
153
154            _bufferEntries.push_back(entry);
155        }
156    }
157
158    if (i<_bufferEntries.size())
159    {
160        // triming end of bufferEntries as the source data is has less entries than the originally held.
161        _bufferEntries.erase(_bufferEntries.begin()+i, _bufferEntries.end());
162    }
163
164    _extensions->glBindBuffer(_target, _glObjectID);
165
166    if (newTotalSize != _totalSize)
167    {
168        _totalSize = newTotalSize;
169        _extensions->glBufferData(_target, _totalSize, NULL, _usage);
170    }
171
172    char* vboMemory = 0;
173
174#if 0
175    vboMemory = extensions->glMapBuffer(_target, GL_WRITE_ONLY_ARB);
176#endif
177
178    for(BufferEntries::iterator itr = _bufferEntries.begin();
179        itr != _bufferEntries.end();
180        ++itr)
181    {
182        BufferEntry& entry = *itr;
183        if (compileAll || entry.modifiedCount != entry.dataSource->getModifiedCount())
184        {
185            // osg::notify(osg::NOTICE)<<"GLBufferObject::compileBuffer(..) downloading BufferEntry "<<&entry<<std::endl;
186            entry.modifiedCount = entry.dataSource->getModifiedCount();
187
188            if (vboMemory)
189                memcpy(vboMemory + (GLsizeiptrARB)entry.offset, entry.dataSource->getDataPointer(), entry.dataSize);
190            else
191                _extensions->glBufferSubData(_target, (GLintptrARB)entry.offset, (GLsizeiptrARB)entry.dataSize, entry.dataSource->getDataPointer());
192
193        }
194    }
195
196    // Unmap the texture image buffer
197    if (vboMemory) _extensions->glUnmapBuffer(_target);
198}
199
200GLBufferObject* GLBufferObject::createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject)
201{
202    return new GLBufferObject(contextID, const_cast<BufferObject*>(bufferObject));
203}
204
205void GLBufferObject::deleteGLObject()
206{
207    if (_glObjectID!=0)
208    {
209        _extensions->glDeleteBuffers(1, &_glObjectID);
210        _glObjectID = 0;
211
212        _totalSize = 0;
213        _bufferEntries.clear();
214    }
215}
216
217
218void GLBufferObject::deleteBufferObject(unsigned int contextID,GLuint globj)
219{
[3819]220    if (globj!=0)
221    {
222        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
[8530]223
[3819]224        // insert the globj into the cache for the appropriate context.
[9055]225        s_deletedBufferObjectCache[contextID].insert(BufferObjectMap::value_type(0,globj));
[3819]226    }
227}
228
[10600]229void GLBufferObject::flushDeletedBufferObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
[3819]230{
231    // if no time available don't try to flush objects.
232    if (availableTime<=0.0) return;
233
234    const osg::Timer& timer = *osg::Timer::instance();
235    osg::Timer_t start_tick = timer.tick();
236    double elapsedTime = 0.0;
237
238
239    {
240        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
241
[5358]242        const Extensions* extensions = getExtensions(contextID,true);
[3819]243
[5358]244        unsigned int noDeleted = 0;
[3819]245
[9055]246        BufferObjectMap& dll = s_deletedBufferObjectCache[contextID];
[3819]247
[9055]248        BufferObjectMap::iterator ditr=dll.begin();
[5358]249        for(;
250            ditr!=dll.end() && elapsedTime<availableTime;
251            ++ditr)
252        {
253            extensions->glDeleteBuffers(1,&(ditr->second));
254            elapsedTime = timer.delta_s(start_tick,timer.tick());
255            ++noDeleted;
[3819]256        }
[5358]257        if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr);
258
[9055]259        // if (noDeleted!=0) notify(osg::NOTICE)<<"Number VBOs deleted = "<<noDeleted<<" BO's left"<<dll.size()<<std::endl;
[8530]260    }
261
[3819]262    availableTime -= elapsedTime;
263}
264
[10600]265void GLBufferObject::discardDeletedBufferObjects(unsigned int contextID)
[7773]266{
267    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
[9055]268    BufferObjectMap& dll = s_deletedBufferObjectCache[contextID];
[7773]269    dll.clear();
270}
[3819]271
272//////////////////////////////////////////////////////////////////////////////
273//
274//  Extension support
275//
276
[10600]277typedef buffered_value< ref_ptr<GLBufferObject::Extensions> > BufferedExtensions;
[3819]278static BufferedExtensions s_extensions;
279
[10600]280GLBufferObject::Extensions* GLBufferObject::getExtensions(unsigned int contextID,bool createIfNotInitalized)
[3819]281{
[10600]282    if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new GLBufferObject::Extensions(contextID);
[3819]283    return s_extensions[contextID].get();
284}
285
[10600]286void GLBufferObject::setExtensions(unsigned int contextID,Extensions* extensions)
[3819]287{
288    s_extensions[contextID] = extensions;
289}
290
[10600]291GLBufferObject::Extensions::Extensions(unsigned int contextID)
[3819]292{
[7038]293    setupGLExtensions(contextID);
[3819]294}
295
[10600]296GLBufferObject::Extensions::Extensions(const Extensions& rhs):
[3819]297    Referenced()
298{
299    _glGenBuffers = rhs._glGenBuffers;
300    _glBindBuffer = rhs._glBindBuffer;
301    _glBufferData = rhs._glBufferData;
302    _glBufferSubData = rhs._glBufferSubData;
303    _glDeleteBuffers = rhs._glDeleteBuffers;
304    _glIsBuffer = rhs._glIsBuffer;
305    _glGetBufferSubData = rhs._glGetBufferSubData;
306    _glMapBuffer = rhs._glMapBuffer;
307    _glUnmapBuffer = rhs._glUnmapBuffer;
308    _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
309    _glGetBufferPointerv = rhs._glGetBufferPointerv;
310}
311
312
[10600]313void GLBufferObject::Extensions::lowestCommonDenominator(const Extensions& rhs)
[3819]314{
315    if (!rhs._glGenBuffers) _glGenBuffers = rhs._glGenBuffers;
316    if (!rhs._glBindBuffer) _glBindBuffer = rhs._glBindBuffer;
317    if (!rhs._glBufferData) _glBufferData = rhs._glBufferData;
318    if (!rhs._glBufferSubData) _glBufferSubData = rhs._glBufferSubData;
319    if (!rhs._glDeleteBuffers) _glDeleteBuffers = rhs._glDeleteBuffers;
320    if (!rhs._glIsBuffer) _glIsBuffer = rhs._glIsBuffer;
321    if (!rhs._glGetBufferSubData) _glGetBufferSubData = rhs._glGetBufferSubData;
322    if (!rhs._glMapBuffer) _glMapBuffer = rhs._glMapBuffer;
323    if (!rhs._glUnmapBuffer) _glUnmapBuffer = rhs._glUnmapBuffer;
324    if (!rhs._glGetBufferParameteriv) _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
325    if (!rhs._glGetBufferParameteriv) _glGetBufferPointerv = rhs._glGetBufferPointerv;
326}
327
[10600]328void GLBufferObject::Extensions::setupGLExtensions(unsigned int contextID)
[3819]329{
[7379]330    setGLExtensionFuncPtr(_glGenBuffers, "glGenBuffers","glGenBuffersARB");
331    setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
332    setGLExtensionFuncPtr(_glBufferData, "glBufferData","glBufferDataARB");
333    setGLExtensionFuncPtr(_glBufferSubData, "glBufferSubData","glBufferSubDataARB");
334    setGLExtensionFuncPtr(_glDeleteBuffers, "glDeleteBuffers","glDeleteBuffersARB");
335    setGLExtensionFuncPtr(_glIsBuffer, "glIsBuffer","glIsBufferARB");
336    setGLExtensionFuncPtr(_glGetBufferSubData, "glGetBufferSubData","glGetBufferSubDataARB");
337    setGLExtensionFuncPtr(_glMapBuffer, "glMapBuffer","glMapBufferARB");
338    setGLExtensionFuncPtr(_glUnmapBuffer, "glUnmapBuffer","glUnmapBufferARB");
339    setGLExtensionFuncPtr(_glGetBufferParameteriv, "glGetBufferParameteriv","glGetBufferParameterivARB");
340    setGLExtensionFuncPtr(_glGetBufferPointerv, "glGetBufferPointerv","glGetBufferPointervARB");
[5474]341    _isPBOSupported = osg::isGLExtensionSupported(contextID,"GL_ARB_pixel_buffer_object");
[3819]342}
343
[10600]344void GLBufferObject::Extensions::glGenBuffers(GLsizei n, GLuint *buffers) const
[3819]345{
[8530]346    if (_glGenBuffers) _glGenBuffers(n, buffers);
[3819]347    else notify(WARN)<<"Error: glGenBuffers not supported by OpenGL driver"<<std::endl;
348}
349
[10600]350void GLBufferObject::Extensions::glBindBuffer(GLenum target, GLuint buffer) const
[3819]351{
[8530]352    if (_glBindBuffer) _glBindBuffer(target, buffer);
[3819]353    else notify(WARN)<<"Error: glBindBuffer not supported by OpenGL driver"<<std::endl;
354}
355
[10600]356void GLBufferObject::Extensions::glBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const
[3819]357{
[8530]358    if (_glBufferData) _glBufferData(target, size, data, usage);
[3819]359    else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
360}
361
[10600]362void GLBufferObject::Extensions::glBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const
[3819]363{
[8530]364    if (_glBufferSubData) _glBufferSubData(target, offset, size, data);
[3819]365    else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
366}
367
[10600]368void GLBufferObject::Extensions::glDeleteBuffers(GLsizei n, const GLuint *buffers) const
[3819]369{
[8530]370    if (_glDeleteBuffers) _glDeleteBuffers(n, buffers);
[3819]371    else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
372}
373
[10600]374GLboolean GLBufferObject::Extensions::glIsBuffer (GLuint buffer) const
[3819]375{
376    if (_glIsBuffer) return _glIsBuffer(buffer);
[8530]377    else
[3819]378    {
379        notify(WARN)<<"Error: glIsBuffer not supported by OpenGL driver"<<std::endl;
380        return GL_FALSE;
381    }
382}
383
[10600]384void GLBufferObject::Extensions::glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const
[3819]385{
386    if (_glGetBufferSubData) _glGetBufferSubData(target,offset,size,data);
387    else notify(WARN)<<"Error: glGetBufferSubData not supported by OpenGL driver"<<std::endl;
388}
389
[10600]390GLvoid* GLBufferObject::Extensions::glMapBuffer (GLenum target, GLenum access) const
[3819]391{
392    if (_glMapBuffer) return _glMapBuffer(target,access);
[8530]393    else
[3819]394    {
395        notify(WARN)<<"Error: glMapBuffer not supported by OpenGL driver"<<std::endl;
396        return 0;
397    }
398}
399
[10600]400GLboolean GLBufferObject::Extensions::glUnmapBuffer (GLenum target) const
[3819]401{
402    if (_glUnmapBuffer) return _glUnmapBuffer(target);
[8530]403    else
[3819]404    {
405        notify(WARN)<<"Error: glUnmapBuffer not supported by OpenGL driver"<<std::endl;
406        return GL_FALSE;
407    }
408}
409
[10600]410void GLBufferObject::Extensions::glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const
[3819]411{
412    if (_glGetBufferParameteriv) _glGetBufferParameteriv(target,pname,params);
413    else notify(WARN)<<"Error: glGetBufferParameteriv not supported by OpenGL driver"<<std::endl;
414}
415
[10600]416void GLBufferObject::Extensions::glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const
[3819]417{
418    if (_glGetBufferPointerv) _glGetBufferPointerv(target,pname,params);
419    else notify(WARN)<<"Error: glGetBufferPointerv not supported by OpenGL driver"<<std::endl;
420}
421
[10600]422#if 1
423
424//////////////////////////////////////////////////////////////////////////////////////////////////////
425//
426// BufferObject
427//
428BufferObject::BufferObject():
429    _target(0),
430    _usage(0)
431{
432}
433
434BufferObject::BufferObject(const BufferObject& bo,const CopyOp& copyop):
435    Object(bo,copyop)
436{
437}
438
439BufferObject::~BufferObject()
440{
441    releaseGLObjects(0);
442}
443
444void BufferObject::setBufferData(unsigned int index, BufferData* bd)
445{
446    if (index>=_bufferDataList.size()) _bufferDataList.resize(index+1);
447    _bufferDataList[index] = bd;
448}
449
450void BufferObject::dirty()
451{
452    for(unsigned int i=0; i<_glBufferObjects.size(); ++i)
453    {
454        if (_glBufferObjects[i].valid()) _glBufferObjects[i]->dirty();
455    }
456}
457
458void BufferObject::resizeGLObjectBuffers(unsigned int maxSize)
459{
460    _glBufferObjects.resize(maxSize);
461}
462
463void BufferObject::releaseGLObjects(State* state) const
464{
465    if (state)
466    {
467        _glBufferObjects[state->getContextID()] = 0;
468    }
469    else
470    {
471        _glBufferObjects.clear();
472    }
473}
474
475unsigned int BufferObject::addBufferData(BufferData* bd)
476{
477    if (!bd) return 0;
478
479    // check to see if bd exists in BufferObject already, is so return without doing anything
480    for(BufferDataList::iterator itr = _bufferDataList.begin();
481        itr != _bufferDataList.end();
482        ++itr)
483    {
484        if (*itr == bd) return bd->getBufferIndex();
485    }
486
487    // bd->setBufferIndex(_bufferDataList.size());
488
489    _bufferDataList.push_back(bd);
490
491    // osg::notify(osg::NOTICE)<<"BufferObject "<<this<<":"<<className()<<"::addBufferData("<<bd<<"), bufferIndex= "<<_bufferDataList.size()-1<<std::endl;
492
493    return _bufferDataList.size()-1;
494}
495
496void BufferObject::removeBufferData(unsigned int index)
497{
498    if (index>=_bufferDataList.size())
499    {
500        osg::notify(osg::WARN)<<"Error "<<className()<<"::removeBufferData("<<index<<") out of range."<<std::endl;
501        return;
502    }
503
504    // osg::notify(osg::NOTICE)<<"BufferObject::"<<this<<":"<<className()<<"::removeBufferData("<<index<<"), size= "<<_bufferDataList.size()<<std::endl;
505
506    // alter the indices of the BufferData after the entry to be removed so their indices are correctly placed.
507    for(unsigned int i=index+1; i<_bufferDataList.size(); ++i)
508    {
509        _bufferDataList[i]->setBufferIndex(i-1);
510    }
511
512    // remove the entry
513    _bufferDataList.erase(_bufferDataList.begin() + index);
514
515    for(unsigned int i=0; i<_glBufferObjects.size(); ++i)
516    {
517        if (_glBufferObjects[i].valid()) _glBufferObjects[i]->clear();
518    }
519
520}
521
522void BufferObject::removeBufferData(BufferData* bd)
523{
524    // osg::notify(osg::NOTICE)<<"BufferObject::"<<this<<":"<<className()<<"::removeBufferData("<<bd<<"), index="<<bd->getBufferIndex()<<" size= "<<_bufferDataList.size()<<std::endl;
525
526    if (!bd || bd->getBufferObject()!=this) return;
527
528    removeBufferData(bd->getBufferIndex());
529}
530
531//////////////////////////////////////////////////////////////////////////////////////////////////////
532//
533// BufferData
534//
535BufferData::~BufferData()
536{
537    setBufferObject(0);
538}
539
540void BufferData::setBufferObject(BufferObject* bufferObject)
541{
542    if (_bufferObject==bufferObject) return;
543
544    if (_bufferObject.valid())
545    {
546        _bufferObject->removeBufferData(_bufferIndex);
547    }
548
549    _bufferObject = bufferObject;
550    _bufferIndex = _bufferObject.valid() ? _bufferObject->addBufferData(this) : 0;
551}
552
[6555]553//////////////////////////////////////////////////////////////////////////////////
554//
555//  VertexBufferObject
556//
557VertexBufferObject::VertexBufferObject()
558{
[6559]559    _target = GL_ARRAY_BUFFER_ARB;
560    _usage = GL_STATIC_DRAW_ARB;
[6565]561//    _usage = GL_DYNAMIC_DRAW_ARB;
562//    _usage = GL_STREAM_DRAW_ARB;
[6555]563}
[3819]564
[6555]565VertexBufferObject::VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop):
566    BufferObject(vbo,copyop)
567{
568}
[3819]569
[6555]570VertexBufferObject::~VertexBufferObject()
571{
572}
573
574unsigned int VertexBufferObject::addArray(osg::Array* array)
575{
[10600]576    return addBufferData(array);
[6555]577}
578
[6582]579void VertexBufferObject::removeArray(osg::Array* array)
580{
[10600]581    removeBufferData(array);
[6582]582}
583
[6555]584void VertexBufferObject::setArray(unsigned int i, Array* array)
585{
[10600]586    setBufferData(i,array);
587}
[8530]588
[10600]589Array* VertexBufferObject::getArray(unsigned int i)
590{
591    return dynamic_cast<osg::Array*>(getBufferData(i));
592}
[6574]593
[10600]594const Array* VertexBufferObject::getArray(unsigned int i) const
595{
596    return dynamic_cast<const osg::Array*>(getBufferData(i));
[8530]597}
[10600]598#if 0
[6582]599void VertexBufferObject::compileBuffer(State& state) const
[6555]600{
[6559]601    unsigned int contextID = state.getContextID();
[6574]602
603    _compiledList[contextID] = 1;
[8530]604
[6559]605    Extensions* extensions = getExtensions(contextID,true);
606
[6582]607    // osg::notify(osg::NOTICE)<<"VertexBufferObject::compileBuffer frameNumber="<<state.getFrameStamp()->getFrameNumber()<<std::endl;
[6565]608
[6559]609    unsigned int totalSizeRequired = 0;
[9362]610    unsigned int numNewArrays = 0;
[6559]611    for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
612        itr != _bufferEntryArrayPairs.end();
613        ++itr)
614    {
615        const BufferEntryArrayPair& bep = *itr;
616        if (bep.second)
617        {
618            totalSizeRequired += bep.second->getTotalDataSize();
[9362]619            if (bep.first.dataSize == 0) ++numNewArrays;
[6559]620        }
621    }
622
623    bool copyAll = false;
624    GLuint& vbo = buffer(contextID);
625    if (vbo==0)
626    {
627        // building for the first time.
628
629        _totalSize = totalSizeRequired;
630
[8530]631        // don't generate buffer if size is zero.
[6559]632        if (_totalSize==0) return;
633
634        extensions->glGenBuffers(1, &vbo);
635        extensions->glBindBuffer(_target, vbo);
636        extensions->glBufferData(_target, _totalSize, NULL, _usage);
[8530]637
638        copyAll = true;
[6559]639    }
640    else
641    {
642        extensions->glBindBuffer(_target, vbo);
643
644        if (_totalSize != totalSizeRequired)
645        {
646            // resize vbo.
647            _totalSize = totalSizeRequired;
648            extensions->glBufferData(_target, _totalSize, NULL, _usage);
[8530]649
650            copyAll = true;
[6559]651        }
652    }
653
[9353]654    typedef std::map<unsigned int,std::vector<unsigned int> > SizePosMap_t;
655    SizePosMap_t freeList;
[9362]656    if (copyAll == false && numNewArrays > 0)
[9353]657    {
658        std::map<unsigned int,unsigned int> usedList;
659        for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
660            itr != _bufferEntryArrayPairs.end();
661            ++itr)
662        {
663            const BufferEntryArrayPair& bep = *itr;
664            if (bep.second==NULL) continue;
665            if (bep.first.dataSize == 0) continue;
666            usedList[bep.first.offset] = bep.first.dataSize;
667        }
668        unsigned int numFreeBlocks = 0;
669        unsigned int pos=0;
670
671        for (std::map<unsigned int,unsigned int>::const_iterator it=usedList.begin(); it!=usedList.end(); ++it)
672        {
673            unsigned int start = it->first;
674            unsigned int length = it->second;
675            if (pos < start)
676            {
677                freeList[start-pos].push_back(pos);
678                ++numFreeBlocks;
679            }
680            pos = start+length;
681        }
682        if (pos < totalSizeRequired)
683        {
684            freeList[totalSizeRequired-pos].push_back(pos);
685            ++numFreeBlocks;
686        }
687        if (numNewArrays < numFreeBlocks)
688        {
689            copyAll = true;     // too fragmented, fallback to copyAll
690            freeList.clear();
691        }
692    }
693
694
[6559]695//    osg::Timer_t start_tick = osg::Timer::instance()->tick();
696
697
[8530]698    void* vboMemory = 0;
[6559]699
700#if 0
701    vboMemory = extensions->glMapBuffer(_target, GL_WRITE_ONLY_ARB);
702#endif
703
704    unsigned int offset = 0;
705    for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
706        itr != _bufferEntryArrayPairs.end();
707        ++itr)
708    {
709        const BufferEntryArrayPair& bep = *itr;
710        const Array* de = bep.second;
711        if (de)
712        {
[9353]713            const unsigned int arraySize = de->getTotalDataSize();
[8530]714            if (copyAll ||
[6559]715                bep.first.modifiedCount[contextID] != bep.second->getModifiedCount() ||
[9353]716                bep.first.dataSize != arraySize)
[6559]717            {
718                // copy data across
[9353]719                unsigned int newOffset = bep.first.offset;             
[8530]720                if (copyAll)
[6559]721                {
[9353]722                    newOffset = offset;
723                    offset += arraySize;
[6559]724                }
[9353]725                else if (bep.first.dataSize == 0)
726                {
727                    SizePosMap_t::iterator findIt = freeList.lower_bound(arraySize);
728                    if (findIt==freeList.end())
729                    {
730                        osg::notify(osg::FATAL)<<"No suitable Memory in VBO found!"<<std::endl;
731                        continue;
732                    }
733                    const unsigned int oldOffset = findIt->second.back();
734                    newOffset = oldOffset;
735                    if (findIt->first > arraySize) // using larger block
736                    {
737                        freeList[findIt->first-arraySize].push_back(oldOffset+arraySize);
738                    }
739                    findIt->second.pop_back();
740                    if (findIt->second.empty())
741                    {
742                        freeList.erase(findIt);
743                    }
744                }
745                bep.first.dataSize = arraySize;
746                bep.first.modifiedCount[contextID] = de->getModifiedCount();
747                bep.first.offset = newOffset;
748                de->setVertexBufferObjectOffset((GLvoid*)newOffset);
[8530]749
[6565]750                // osg::notify(osg::NOTICE)<<"   copying vertex buffer data "<<bep.first.dataSize<<" bytes"<<std::endl;
[8530]751
[6559]752                if (vboMemory)
753                    memcpy((char*)vboMemory + bep.first.offset, de->getDataPointer(), bep.first.dataSize);
754                else
755                    extensions->glBufferSubData(_target, bep.first.offset, bep.first.dataSize, de->getDataPointer());
756
757            }
758        }
759    }
760
[8530]761
[6559]762    // Unmap the texture image buffer
763    if (vboMemory) extensions->glUnmapBuffer(_target);
[8530]764
[6559]765//    osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
766//    osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
[6555]767}
[10600]768#endif
[6555]769
770//////////////////////////////////////////////////////////////////////////////////
771//
[6578]772//  ElementBufferObject
[6555]773//
[6578]774ElementBufferObject::ElementBufferObject()
[6555]775{
[6559]776    _target = GL_ELEMENT_ARRAY_BUFFER_ARB;
777    _usage = GL_STATIC_DRAW_ARB;
[6555]778}
779
[6578]780ElementBufferObject::ElementBufferObject(const ElementBufferObject& vbo,const CopyOp& copyop):
[6555]781    BufferObject(vbo,copyop)
782{
783}
784
[6578]785ElementBufferObject::~ElementBufferObject()
[6555]786{
787}
788
[6578]789unsigned int ElementBufferObject::addDrawElements(osg::DrawElements* drawElements)
[6555]790{
[10600]791    return addBufferData(drawElements);
[6555]792}
793
[6582]794void ElementBufferObject::removeDrawElements(osg::DrawElements* drawElements)
795{
[10600]796    removeBufferData(drawElements);
[6582]797}
798
[6578]799void ElementBufferObject::setDrawElements(unsigned int i, DrawElements* drawElements)
[6555]800{
[10600]801    setBufferData(i,drawElements);
802}
[8530]803
[10600]804DrawElements* ElementBufferObject::getDrawElements(unsigned int i)
805{
806    return dynamic_cast<DrawElements*>(getBufferData(i));
[6555]807}
808
[10600]809const DrawElements* ElementBufferObject::getDrawElements(unsigned int i) const
810{
811    return dynamic_cast<const DrawElements*>(getBufferData(i));
812}
813
814
815#if 0
[6582]816void ElementBufferObject::compileBuffer(State& state) const
[6555]817{
[6559]818    unsigned int contextID = state.getContextID();
[6565]819
[6574]820    _compiledList[contextID] = 1;
821
[6582]822    // osg::notify(osg::NOTICE)<<"ElementBufferObject::compile"<<std::endl;
[8530]823
[6559]824    Extensions* extensions = getExtensions(contextID,true);
825
826    unsigned int totalSizeRequired = 0;
[7375]827//    unsigned int numModified = 0;
828//    unsigned int numNotModified = 0;
[6559]829    for(BufferEntryDrawElementsPairs::const_iterator itr = _bufferEntryDrawElementsPairs.begin();
830        itr != _bufferEntryDrawElementsPairs.end();
831        ++itr)
832    {
[7101]833        const BufferEntryDrawElementsPair& bep = *itr;
[6559]834        if (bep.second)
835        {
836            totalSizeRequired += bep.second->getTotalDataSize();
837        }
838    }
839
840    bool copyAll = false;
841    GLuint& ebo = buffer(contextID);
842    if (ebo==0)
843    {
844        // building for the first time.
845
846        _totalSize = totalSizeRequired;
847
[8530]848        // don't generate buffer if size is zero.
[6559]849        if (_totalSize==0) return;
850
851        extensions->glGenBuffers(1, &ebo);
852        extensions->glBindBuffer(_target, ebo);
853        extensions->glBufferData(_target, _totalSize, NULL, _usage);
[8530]854
855        copyAll = true;
[6559]856    }
857    else
858    {
859        extensions->glBindBuffer(_target, ebo);
860
861        if (_totalSize != totalSizeRequired)
862        {
863            // resize EBO.
864            _totalSize = totalSizeRequired;
865            extensions->glBufferData(_target, _totalSize, NULL, _usage);
[8530]866
867            copyAll = true;
[6559]868        }
869    }
870
871//    osg::Timer_t start_tick = osg::Timer::instance()->tick();
872
873
[8530]874    void* eboMemory = 0;
[6559]875
876#if 0
877    eboMemory = extensions->glMapBuffer(_target, GL_WRITE_ONLY_ARB);
878#endif
879
[8531]880    size_t offset = 0;
[6559]881    for(BufferEntryDrawElementsPairs::const_iterator itr = _bufferEntryDrawElementsPairs.begin();
882        itr != _bufferEntryDrawElementsPairs.end();
883        ++itr)
884    {
[7101]885        const BufferEntryDrawElementsPair& bep = *itr;
[6559]886        const DrawElements* de = bep.second;
887        if (de)
888        {
[8530]889            if (copyAll ||
[6559]890                bep.first.modifiedCount[contextID] != bep.second->getModifiedCount() ||
891                bep.first.dataSize != bep.second->getTotalDataSize())
892            {
893                // copy data across
894                bep.first.dataSize = bep.second->getTotalDataSize();
[6565]895                bep.first.modifiedCount[contextID] = de->getModifiedCount();
[8530]896                if (copyAll)
[6559]897                {
898                    bep.first.offset = offset;
[6582]899                    de->setElementBufferObjectOffset((GLvoid*)offset);
[6559]900                    offset += bep.first.dataSize;
901                }
[8530]902
[6559]903                if (eboMemory)
904                    memcpy((char*)eboMemory + bep.first.offset, de->getDataPointer(), bep.first.dataSize);
905                else
906                    extensions->glBufferSubData(_target, bep.first.offset, bep.first.dataSize, de->getDataPointer());
907
908            }
909        }
910    }
911
[8530]912
[6559]913    // Unmap the texture image buffer
914    if (eboMemory) extensions->glUnmapBuffer(_target);
915
916//    osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
917//    osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
[6555]918}
[10600]919#endif
[6555]920
921//////////////////////////////////////////////////////////////////////////////////
922//
923//  PixelBufferObject
924//
[3819]925PixelBufferObject::PixelBufferObject(osg::Image* image):
926    BufferObject()
927{
928    _target = GL_PIXEL_UNPACK_BUFFER_ARB;
929    _usage = GL_STREAM_DRAW_ARB;
[10600]930
931    osg::notify(osg::NOTICE)<<"Constructing PixelBufferObject for image="<<image<<std::endl;
932
933    setBufferData(0, image);
[3819]934}
935
936PixelBufferObject::PixelBufferObject(const PixelBufferObject& buffer,const CopyOp& copyop):
[10600]937    BufferObject(buffer,copyop)
[3819]938{
939}
940
941PixelBufferObject::~PixelBufferObject()
942{
943}
944
945void PixelBufferObject::setImage(osg::Image* image)
946{
[10600]947    setBufferData(0, image);
948}
[8530]949
[10600]950Image* PixelBufferObject::getImage()
951{
952    return dynamic_cast<Image*>(getBufferData(0));
953}
[8530]954
[10600]955const Image* PixelBufferObject::getImage() const
956{
957    return dynamic_cast<const Image*>(getBufferData(0));
[3819]958}
[10600]959
960#if 0
[6582]961void PixelBufferObject::compileBuffer(State& state) const
[3819]962{
963    unsigned int contextID = state.getContextID();
[8530]964
[6574]965    _compiledList[contextID] = 1;
966
[4080]967    osg::Image* image = _bufferEntryImagePair.second;
968
969    _bufferEntryImagePair.first.modifiedCount[contextID] = image->getModifiedCount();
970    if (!image->valid()) return;
971
[3819]972    Extensions* extensions = getExtensions(contextID,true);
973
974    GLuint& pbo = buffer(contextID);
975    if (pbo==0)
976    {
977        // building for the first time.
978
979        _totalSize = image->getTotalSizeInBytes();
980
[8530]981        // don't generate buffer if size is zero.
[4080]982        if (_totalSize==0) return;
983
984        extensions->glGenBuffers(1, &pbo);
985        extensions->glBindBuffer(_target, pbo);
[6559]986        extensions->glBufferData(_target, _totalSize, NULL, _usage);
[8530]987
[3819]988    }
989    else
990    {
991        extensions->glBindBuffer(_target, pbo);
992
993        if (_totalSize != image->getTotalSizeInBytes())
994        {
[6559]995            // resize PBO.
[3819]996            _totalSize = image->getTotalSizeInBytes();
[6559]997            extensions->glBufferData(_target, _totalSize, NULL, _usage);
[3819]998        }
999    }
1000
1001//    osg::Timer_t start_tick = osg::Timer::instance()->tick();
1002
1003    void* pboMemory = extensions->glMapBuffer(_target,
1004                 GL_WRITE_ONLY_ARB);
1005
[6559]1006    // copy data across
[3819]1007    memcpy(pboMemory, image->data(), _totalSize);
[8530]1008
[3819]1009    // Unmap the texture image buffer
1010    extensions->glUnmapBuffer(_target);
1011
1012    _bufferEntryImagePair.first.modifiedCount[contextID] = image->getModifiedCount();
1013
1014//    osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
1015//    osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
1016}
[10600]1017#endif
[6582]1018
[9302]1019//////////////////////////////////////////////////////////////////////////////////
1020//
1021//  PixelDataBufferObject
1022//
1023//--------------------------------------------------------------------------------
1024PixelDataBufferObject::PixelDataBufferObject()
1025{
[9306]1026    _target = GL_ARRAY_BUFFER_ARB;
[9302]1027    _usage = GL_DYNAMIC_DRAW_ARB;
1028}
1029
1030//--------------------------------------------------------------------------------
1031PixelDataBufferObject::PixelDataBufferObject(const PixelDataBufferObject& buffer,const CopyOp& copyop):
[10600]1032    BufferObject(buffer,copyop)
[9302]1033{
1034}
1035
1036//--------------------------------------------------------------------------------
1037PixelDataBufferObject::~PixelDataBufferObject()
1038{
1039}
1040
1041//--------------------------------------------------------------------------------
1042void PixelDataBufferObject::compileBuffer(State& state) const
1043{
1044    unsigned int contextID = state.getContextID();   
[10600]1045    if ( _dataSize == 0) return;
[9302]1046
[10600]1047    GLBufferObject* bo = getOrCreateGLBufferObject(contextID);
1048    if (!bo || !bo->isDirty()) return;
[9302]1049
[10600]1050    bo->_extensions->glBindBuffer(_target, bo->getGLObjectID());
1051    bo->_extensions->glBufferData(_target, _dataSize, NULL, _usage);
1052    bo->_extensions->glBindBuffer(_target, 0);
[9302]1053}
1054
1055//--------------------------------------------------------------------------------
1056void PixelDataBufferObject::bindBufferInReadMode(State& state)
1057{
1058    unsigned int contextID = state.getContextID();   
1059
[10600]1060    GLBufferObject* bo = getOrCreateGLBufferObject(contextID);
1061    if (!bo) return;
[9302]1062
[10600]1063    if (bo->isDirty()) compileBuffer(state);
1064
1065    bo->_extensions->glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bo->getGLObjectID());
1066
[9302]1067    _mode[contextID] = READ;
1068}
1069
1070//--------------------------------------------------------------------------------
1071void PixelDataBufferObject::bindBufferInWriteMode(State& state)
1072{
1073    unsigned int contextID = state.getContextID();   
1074
[10600]1075    GLBufferObject* bo = getOrCreateGLBufferObject(contextID);
1076    if (!bo) return;
[9302]1077
[10600]1078    if (bo->isDirty()) compileBuffer(state);
1079
1080    bo->_extensions->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, bo->getGLObjectID());
1081
[9302]1082    _mode[contextID] = WRITE;
1083}
1084
1085//--------------------------------------------------------------------------------
1086void PixelDataBufferObject::unbindBuffer(unsigned int contextID) const
1087{
[10600]1088    GLBufferObject::Extensions* extensions = GLBufferObject::getExtensions(contextID,true);
[9302]1089
1090    switch(_mode[contextID])
1091    {
1092        case READ:
1093            extensions->glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
1094            break;
1095        case WRITE:
1096            extensions->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB,0);
1097            break;
1098        default:
1099            extensions->glBindBuffer(_target,0);
1100            break;
1101    }
1102
1103    _mode[contextID] = NONE;
1104}
1105
1106//--------------------------------------------------------------------------------
1107void PixelDataBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
1108{
1109    BufferObject::resizeGLObjectBuffers(maxSize);
1110
1111    _mode.resize(maxSize);
1112}
1113
[10600]1114
1115#endif
Note: See TracBrowser for help on using the browser.