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

Revision 9362, 28.2 kB (checked in by robert, 6 years ago)

From Peter Hrenka, "Fix counting number of new arrays and avoid
building free-list when not needed (saves
a handfull of mallocs/frees).
"

  • 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/Timer>
21#include <osg/Image>
22#include <osg/State>
23#include <osg/PrimitiveSet>
24#include <osg/Array>
25
26#include <OpenThreads/ScopedLock>
27#include <OpenThreads/Mutex>
28
29using namespace osg;
30
31// static cache of deleted buffer object lists which can only
32// by completely deleted once the appropriate OpenGL context
33// is set.  Used osg::BufferObject::deleteBufferObject(..) and flushDeletedBufferObjects(..) below.
34typedef std::multimap<unsigned int,GLuint> BufferObjectMap;
35typedef osg::buffered_object<BufferObjectMap> DeletedBufferObjectCache;
36
37static OpenThreads::Mutex s_mutex_deletedBufferObjectCache;
38static DeletedBufferObjectCache s_deletedBufferObjectCache;
39
40void BufferObject::deleteBufferObject(unsigned int contextID,GLuint globj)
41{
42    if (globj!=0)
43    {
44        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
45
46        // insert the globj into the cache for the appropriate context.
47        s_deletedBufferObjectCache[contextID].insert(BufferObjectMap::value_type(0,globj));
48    }
49}
50
51void BufferObject::flushDeletedBufferObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
52{
53    // if no time available don't try to flush objects.
54    if (availableTime<=0.0) return;
55
56    const osg::Timer& timer = *osg::Timer::instance();
57    osg::Timer_t start_tick = timer.tick();
58    double elapsedTime = 0.0;
59
60
61    {
62        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
63
64        const Extensions* extensions = getExtensions(contextID,true);
65
66        unsigned int noDeleted = 0;
67
68        BufferObjectMap& dll = s_deletedBufferObjectCache[contextID];
69
70        BufferObjectMap::iterator ditr=dll.begin();
71        for(;
72            ditr!=dll.end() && elapsedTime<availableTime;
73            ++ditr)
74        {
75            extensions->glDeleteBuffers(1,&(ditr->second));
76            elapsedTime = timer.delta_s(start_tick,timer.tick());
77            ++noDeleted;
78        }
79        if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr);
80
81        // if (noDeleted!=0) notify(osg::NOTICE)<<"Number VBOs deleted = "<<noDeleted<<" BO's left"<<dll.size()<<std::endl;
82    }
83
84    availableTime -= elapsedTime;
85}
86
87void BufferObject::discardDeletedBufferObjects(unsigned int contextID)
88{
89    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
90    BufferObjectMap& dll = s_deletedBufferObjectCache[contextID];
91    dll.clear();
92}
93
94
95BufferObject::BufferObject():
96    _target(0),
97    _usage(0),
98    _totalSize(0)
99{
100}
101
102BufferObject::BufferObject(const BufferObject& bo,const CopyOp& copyop):
103    Object(bo,copyop)
104{
105}
106
107BufferObject::~BufferObject()
108{
109    releaseGLObjects(0);
110}
111
112void BufferObject::resizeGLObjectBuffers(unsigned int maxSize)
113{
114    _bufferObjectList.resize(maxSize);
115}
116
117void BufferObject::releaseGLObjects(State* state) const
118{
119    if (state)
120    {
121        unsigned int contextID = state->getContextID();
122        if (_bufferObjectList[contextID])
123        {
124             deleteBufferObject(contextID,_bufferObjectList[contextID]);
125            _bufferObjectList[contextID] = 0;
126        }
127    }
128    else
129    {
130        for(unsigned int contextID=0;contextID<_bufferObjectList.size();++contextID)
131        {
132            if (_bufferObjectList[contextID])
133            {
134                 deleteBufferObject(contextID,_bufferObjectList[contextID]);
135                _bufferObjectList[contextID] = 0;
136            }
137        }
138    }
139}
140
141//////////////////////////////////////////////////////////////////////////////
142//
143//  Extension support
144//
145
146typedef buffered_value< ref_ptr<BufferObject::Extensions> > BufferedExtensions;
147static BufferedExtensions s_extensions;
148
149BufferObject::Extensions* BufferObject::getExtensions(unsigned int contextID,bool createIfNotInitalized)
150{
151    if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new BufferObject::Extensions(contextID);
152    return s_extensions[contextID].get();
153}
154
155void BufferObject::setExtensions(unsigned int contextID,Extensions* extensions)
156{
157    s_extensions[contextID] = extensions;
158}
159
160BufferObject::Extensions::Extensions(unsigned int contextID)
161{
162    setupGLExtensions(contextID);
163}
164
165BufferObject::Extensions::Extensions(const Extensions& rhs):
166    Referenced()
167{
168    _glGenBuffers = rhs._glGenBuffers;
169    _glBindBuffer = rhs._glBindBuffer;
170    _glBufferData = rhs._glBufferData;
171    _glBufferSubData = rhs._glBufferSubData;
172    _glDeleteBuffers = rhs._glDeleteBuffers;
173    _glIsBuffer = rhs._glIsBuffer;
174    _glGetBufferSubData = rhs._glGetBufferSubData;
175    _glMapBuffer = rhs._glMapBuffer;
176    _glUnmapBuffer = rhs._glUnmapBuffer;
177    _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
178    _glGetBufferPointerv = rhs._glGetBufferPointerv;
179}
180
181
182void BufferObject::Extensions::lowestCommonDenominator(const Extensions& rhs)
183{
184    if (!rhs._glGenBuffers) _glGenBuffers = rhs._glGenBuffers;
185    if (!rhs._glBindBuffer) _glBindBuffer = rhs._glBindBuffer;
186    if (!rhs._glBufferData) _glBufferData = rhs._glBufferData;
187    if (!rhs._glBufferSubData) _glBufferSubData = rhs._glBufferSubData;
188    if (!rhs._glDeleteBuffers) _glDeleteBuffers = rhs._glDeleteBuffers;
189    if (!rhs._glIsBuffer) _glIsBuffer = rhs._glIsBuffer;
190    if (!rhs._glGetBufferSubData) _glGetBufferSubData = rhs._glGetBufferSubData;
191    if (!rhs._glMapBuffer) _glMapBuffer = rhs._glMapBuffer;
192    if (!rhs._glUnmapBuffer) _glUnmapBuffer = rhs._glUnmapBuffer;
193    if (!rhs._glGetBufferParameteriv) _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
194    if (!rhs._glGetBufferParameteriv) _glGetBufferPointerv = rhs._glGetBufferPointerv;
195}
196
197void BufferObject::Extensions::setupGLExtensions(unsigned int contextID)
198{
199    setGLExtensionFuncPtr(_glGenBuffers, "glGenBuffers","glGenBuffersARB");
200    setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
201    setGLExtensionFuncPtr(_glBufferData, "glBufferData","glBufferDataARB");
202    setGLExtensionFuncPtr(_glBufferSubData, "glBufferSubData","glBufferSubDataARB");
203    setGLExtensionFuncPtr(_glDeleteBuffers, "glDeleteBuffers","glDeleteBuffersARB");
204    setGLExtensionFuncPtr(_glIsBuffer, "glIsBuffer","glIsBufferARB");
205    setGLExtensionFuncPtr(_glGetBufferSubData, "glGetBufferSubData","glGetBufferSubDataARB");
206    setGLExtensionFuncPtr(_glMapBuffer, "glMapBuffer","glMapBufferARB");
207    setGLExtensionFuncPtr(_glUnmapBuffer, "glUnmapBuffer","glUnmapBufferARB");
208    setGLExtensionFuncPtr(_glGetBufferParameteriv, "glGetBufferParameteriv","glGetBufferParameterivARB");
209    setGLExtensionFuncPtr(_glGetBufferPointerv, "glGetBufferPointerv","glGetBufferPointervARB");
210    _isPBOSupported = osg::isGLExtensionSupported(contextID,"GL_ARB_pixel_buffer_object");
211}
212
213void BufferObject::Extensions::glGenBuffers(GLsizei n, GLuint *buffers) const
214{
215    if (_glGenBuffers) _glGenBuffers(n, buffers);
216    else notify(WARN)<<"Error: glGenBuffers not supported by OpenGL driver"<<std::endl;
217}
218
219void BufferObject::Extensions::glBindBuffer(GLenum target, GLuint buffer) const
220{
221    if (_glBindBuffer) _glBindBuffer(target, buffer);
222    else notify(WARN)<<"Error: glBindBuffer not supported by OpenGL driver"<<std::endl;
223}
224
225void BufferObject::Extensions::glBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const
226{
227    if (_glBufferData) _glBufferData(target, size, data, usage);
228    else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
229}
230
231void BufferObject::Extensions::glBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const
232{
233    if (_glBufferSubData) _glBufferSubData(target, offset, size, data);
234    else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
235}
236
237void BufferObject::Extensions::glDeleteBuffers(GLsizei n, const GLuint *buffers) const
238{
239    if (_glDeleteBuffers) _glDeleteBuffers(n, buffers);
240    else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
241}
242
243GLboolean BufferObject::Extensions::glIsBuffer (GLuint buffer) const
244{
245    if (_glIsBuffer) return _glIsBuffer(buffer);
246    else
247    {
248        notify(WARN)<<"Error: glIsBuffer not supported by OpenGL driver"<<std::endl;
249        return GL_FALSE;
250    }
251}
252
253void BufferObject::Extensions::glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const
254{
255    if (_glGetBufferSubData) _glGetBufferSubData(target,offset,size,data);
256    else notify(WARN)<<"Error: glGetBufferSubData not supported by OpenGL driver"<<std::endl;
257}
258
259GLvoid* BufferObject::Extensions::glMapBuffer (GLenum target, GLenum access) const
260{
261    if (_glMapBuffer) return _glMapBuffer(target,access);
262    else
263    {
264        notify(WARN)<<"Error: glMapBuffer not supported by OpenGL driver"<<std::endl;
265        return 0;
266    }
267}
268
269GLboolean BufferObject::Extensions::glUnmapBuffer (GLenum target) const
270{
271    if (_glUnmapBuffer) return _glUnmapBuffer(target);
272    else
273    {
274        notify(WARN)<<"Error: glUnmapBuffer not supported by OpenGL driver"<<std::endl;
275        return GL_FALSE;
276    }
277}
278
279void BufferObject::Extensions::glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const
280{
281    if (_glGetBufferParameteriv) _glGetBufferParameteriv(target,pname,params);
282    else notify(WARN)<<"Error: glGetBufferParameteriv not supported by OpenGL driver"<<std::endl;
283}
284
285void BufferObject::Extensions::glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const
286{
287    if (_glGetBufferPointerv) _glGetBufferPointerv(target,pname,params);
288    else notify(WARN)<<"Error: glGetBufferPointerv not supported by OpenGL driver"<<std::endl;
289}
290
291//////////////////////////////////////////////////////////////////////////////////
292//
293//  VertexBufferObject
294//
295VertexBufferObject::VertexBufferObject()
296{
297    _target = GL_ARRAY_BUFFER_ARB;
298    _usage = GL_STATIC_DRAW_ARB;
299//    _usage = GL_DYNAMIC_DRAW_ARB;
300//    _usage = GL_STREAM_DRAW_ARB;
301}
302
303VertexBufferObject::VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop):
304    BufferObject(vbo,copyop)
305{
306}
307
308VertexBufferObject::~VertexBufferObject()
309{
310}
311
312unsigned int VertexBufferObject::addArray(osg::Array* array)
313{
314    unsigned int i = _bufferEntryArrayPairs.size();
315
316    _bufferEntryArrayPairs.resize(i+1);
317    _bufferEntryArrayPairs[i].second = array;
318    _bufferEntryArrayPairs[i].first.modifiedCount.setAllElementsTo(0xffffffff);
319    _bufferEntryArrayPairs[i].first.offset = 0;
320
321    dirty();
322
323    return i;
324}
325
326void VertexBufferObject::removeArray(osg::Array* array)
327{
328    BufferEntryArrayPairs::iterator itr;
329    for(itr = _bufferEntryArrayPairs.begin();
330        itr != _bufferEntryArrayPairs.end();
331        ++itr)
332    {
333        if (itr->second == array) break;
334    }
335    if (itr != _bufferEntryArrayPairs.end()) _bufferEntryArrayPairs.erase(itr);
336}
337
338void VertexBufferObject::setArray(unsigned int i, Array* array)
339{
340    if (i+1>=_bufferEntryArrayPairs.size()) _bufferEntryArrayPairs.resize(i+1);
341
342    _bufferEntryArrayPairs[i].second = array;
343    _bufferEntryArrayPairs[i].first.modifiedCount.setAllElementsTo(0xffffffff);
344    _bufferEntryArrayPairs[i].first.offset = 0;
345
346    dirty();
347}
348void VertexBufferObject::compileBuffer(State& state) const
349{
350    unsigned int contextID = state.getContextID();
351
352    _compiledList[contextID] = 1;
353
354    Extensions* extensions = getExtensions(contextID,true);
355
356    // osg::notify(osg::NOTICE)<<"VertexBufferObject::compileBuffer frameNumber="<<state.getFrameStamp()->getFrameNumber()<<std::endl;
357
358    unsigned int totalSizeRequired = 0;
359    unsigned int numNewArrays = 0;
360    for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
361        itr != _bufferEntryArrayPairs.end();
362        ++itr)
363    {
364        const BufferEntryArrayPair& bep = *itr;
365        if (bep.second)
366        {
367            totalSizeRequired += bep.second->getTotalDataSize();
368            if (bep.first.dataSize == 0) ++numNewArrays;
369        }
370    }
371
372    bool copyAll = false;
373    GLuint& vbo = buffer(contextID);
374    if (vbo==0)
375    {
376        // building for the first time.
377
378        _totalSize = totalSizeRequired;
379
380        // don't generate buffer if size is zero.
381        if (_totalSize==0) return;
382
383        extensions->glGenBuffers(1, &vbo);
384        extensions->glBindBuffer(_target, vbo);
385        extensions->glBufferData(_target, _totalSize, NULL, _usage);
386
387        copyAll = true;
388    }
389    else
390    {
391        extensions->glBindBuffer(_target, vbo);
392
393        if (_totalSize != totalSizeRequired)
394        {
395            // resize vbo.
396            _totalSize = totalSizeRequired;
397            extensions->glBufferData(_target, _totalSize, NULL, _usage);
398
399            copyAll = true;
400        }
401    }
402
403    typedef std::map<unsigned int,std::vector<unsigned int> > SizePosMap_t;
404    SizePosMap_t freeList;
405    if (copyAll == false && numNewArrays > 0)
406    {
407        std::map<unsigned int,unsigned int> usedList;
408        for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
409            itr != _bufferEntryArrayPairs.end();
410            ++itr)
411        {
412            const BufferEntryArrayPair& bep = *itr;
413            if (bep.second==NULL) continue;
414            if (bep.first.dataSize == 0) continue;
415            usedList[bep.first.offset] = bep.first.dataSize;
416        }
417        unsigned int numFreeBlocks = 0;
418        unsigned int pos=0;
419
420        for (std::map<unsigned int,unsigned int>::const_iterator it=usedList.begin(); it!=usedList.end(); ++it)
421        {
422            unsigned int start = it->first;
423            unsigned int length = it->second;
424            if (pos < start)
425            {
426                freeList[start-pos].push_back(pos);
427                ++numFreeBlocks;
428            }
429            pos = start+length;
430        }
431        if (pos < totalSizeRequired)
432        {
433            freeList[totalSizeRequired-pos].push_back(pos);
434            ++numFreeBlocks;
435        }
436        if (numNewArrays < numFreeBlocks)
437        {
438            copyAll = true;     // too fragmented, fallback to copyAll
439            freeList.clear();
440        }
441    }
442
443
444//    osg::Timer_t start_tick = osg::Timer::instance()->tick();
445
446
447    void* vboMemory = 0;
448
449#if 0
450    vboMemory = extensions->glMapBuffer(_target, GL_WRITE_ONLY_ARB);
451#endif
452
453    unsigned int offset = 0;
454    for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
455        itr != _bufferEntryArrayPairs.end();
456        ++itr)
457    {
458        const BufferEntryArrayPair& bep = *itr;
459        const Array* de = bep.second;
460        if (de)
461        {
462            const unsigned int arraySize = de->getTotalDataSize();
463            if (copyAll ||
464                bep.first.modifiedCount[contextID] != bep.second->getModifiedCount() ||
465                bep.first.dataSize != arraySize)
466            {
467                // copy data across
468                unsigned int newOffset = bep.first.offset;             
469                if (copyAll)
470                {
471                    newOffset = offset;
472                    offset += arraySize;
473                }
474                else if (bep.first.dataSize == 0)
475                {
476                    SizePosMap_t::iterator findIt = freeList.lower_bound(arraySize);
477                    if (findIt==freeList.end())
478                    {
479                        osg::notify(osg::FATAL)<<"No suitable Memory in VBO found!"<<std::endl;
480                        continue;
481                    }
482                    const unsigned int oldOffset = findIt->second.back();
483                    newOffset = oldOffset;
484                    if (findIt->first > arraySize) // using larger block
485                    {
486                        freeList[findIt->first-arraySize].push_back(oldOffset+arraySize);
487                    }
488                    findIt->second.pop_back();
489                    if (findIt->second.empty())
490                    {
491                        freeList.erase(findIt);
492                    }
493                }
494                bep.first.dataSize = arraySize;
495                bep.first.modifiedCount[contextID] = de->getModifiedCount();
496                bep.first.offset = newOffset;
497                de->setVertexBufferObjectOffset((GLvoid*)newOffset);
498
499                // osg::notify(osg::NOTICE)<<"   copying vertex buffer data "<<bep.first.dataSize<<" bytes"<<std::endl;
500
501                if (vboMemory)
502                    memcpy((char*)vboMemory + bep.first.offset, de->getDataPointer(), bep.first.dataSize);
503                else
504                    extensions->glBufferSubData(_target, bep.first.offset, bep.first.dataSize, de->getDataPointer());
505
506            }
507        }
508    }
509
510
511    // Unmap the texture image buffer
512    if (vboMemory) extensions->glUnmapBuffer(_target);
513
514//    osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
515//    osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
516}
517
518void VertexBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
519{
520    BufferObject::resizeGLObjectBuffers(maxSize);
521
522    for(BufferEntryArrayPairs::iterator itr = _bufferEntryArrayPairs.begin();
523        itr != _bufferEntryArrayPairs.end();
524        ++itr)
525    {
526        itr->first.modifiedCount.resize(maxSize);
527    }
528}
529
530//////////////////////////////////////////////////////////////////////////////////
531//
532//  ElementBufferObject
533//
534ElementBufferObject::ElementBufferObject()
535{
536    _target = GL_ELEMENT_ARRAY_BUFFER_ARB;
537    _usage = GL_STATIC_DRAW_ARB;
538}
539
540ElementBufferObject::ElementBufferObject(const ElementBufferObject& vbo,const CopyOp& copyop):
541    BufferObject(vbo,copyop)
542{
543}
544
545ElementBufferObject::~ElementBufferObject()
546{
547}
548
549unsigned int ElementBufferObject::addDrawElements(osg::DrawElements* drawElements)
550{
551    unsigned int i = _bufferEntryDrawElementsPairs.size();
552    _bufferEntryDrawElementsPairs.resize(i+1);
553    _bufferEntryDrawElementsPairs[i].second = drawElements;
554    _bufferEntryDrawElementsPairs[i].first.modifiedCount.setAllElementsTo(0xffffffff);
555    _bufferEntryDrawElementsPairs[i].first.dataSize = 0;
556
557    return i;
558}
559
560void ElementBufferObject::removeDrawElements(osg::DrawElements* drawElements)
561{
562    BufferEntryDrawElementsPairs::iterator itr;
563    for(itr = _bufferEntryDrawElementsPairs.begin();
564        itr != _bufferEntryDrawElementsPairs.end();
565        ++itr)
566    {
567        if (itr->second == drawElements) break;
568    }
569    if (itr != _bufferEntryDrawElementsPairs.end()) _bufferEntryDrawElementsPairs.erase(itr);
570}
571
572void ElementBufferObject::setDrawElements(unsigned int i, DrawElements* drawElements)
573{
574    if (i+1>=_bufferEntryDrawElementsPairs.size()) _bufferEntryDrawElementsPairs.resize(i+1);
575
576    _bufferEntryDrawElementsPairs[i].second = drawElements;
577    _bufferEntryDrawElementsPairs[i].first.modifiedCount.setAllElementsTo(0xffffffff);
578    _bufferEntryDrawElementsPairs[i].first.dataSize = 0;
579}
580
581void ElementBufferObject::compileBuffer(State& state) const
582{
583    unsigned int contextID = state.getContextID();
584
585    _compiledList[contextID] = 1;
586
587    // osg::notify(osg::NOTICE)<<"ElementBufferObject::compile"<<std::endl;
588
589    Extensions* extensions = getExtensions(contextID,true);
590
591    unsigned int totalSizeRequired = 0;
592//    unsigned int numModified = 0;
593//    unsigned int numNotModified = 0;
594    for(BufferEntryDrawElementsPairs::const_iterator itr = _bufferEntryDrawElementsPairs.begin();
595        itr != _bufferEntryDrawElementsPairs.end();
596        ++itr)
597    {
598        const BufferEntryDrawElementsPair& bep = *itr;
599        if (bep.second)
600        {
601            totalSizeRequired += bep.second->getTotalDataSize();
602        }
603    }
604
605    bool copyAll = false;
606    GLuint& ebo = buffer(contextID);
607    if (ebo==0)
608    {
609        // building for the first time.
610
611        _totalSize = totalSizeRequired;
612
613        // don't generate buffer if size is zero.
614        if (_totalSize==0) return;
615
616        extensions->glGenBuffers(1, &ebo);
617        extensions->glBindBuffer(_target, ebo);
618        extensions->glBufferData(_target, _totalSize, NULL, _usage);
619
620        copyAll = true;
621    }
622    else
623    {
624        extensions->glBindBuffer(_target, ebo);
625
626        if (_totalSize != totalSizeRequired)
627        {
628            // resize EBO.
629            _totalSize = totalSizeRequired;
630            extensions->glBufferData(_target, _totalSize, NULL, _usage);
631
632            copyAll = true;
633        }
634    }
635
636//    osg::Timer_t start_tick = osg::Timer::instance()->tick();
637
638
639    void* eboMemory = 0;
640
641#if 0
642    eboMemory = extensions->glMapBuffer(_target, GL_WRITE_ONLY_ARB);
643#endif
644
645    size_t offset = 0;
646    for(BufferEntryDrawElementsPairs::const_iterator itr = _bufferEntryDrawElementsPairs.begin();
647        itr != _bufferEntryDrawElementsPairs.end();
648        ++itr)
649    {
650        const BufferEntryDrawElementsPair& bep = *itr;
651        const DrawElements* de = bep.second;
652        if (de)
653        {
654            if (copyAll ||
655                bep.first.modifiedCount[contextID] != bep.second->getModifiedCount() ||
656                bep.first.dataSize != bep.second->getTotalDataSize())
657            {
658                // copy data across
659                bep.first.dataSize = bep.second->getTotalDataSize();
660                bep.first.modifiedCount[contextID] = de->getModifiedCount();
661                if (copyAll)
662                {
663                    bep.first.offset = offset;
664                    de->setElementBufferObjectOffset((GLvoid*)offset);
665                    offset += bep.first.dataSize;
666                }
667
668                if (eboMemory)
669                    memcpy((char*)eboMemory + bep.first.offset, de->getDataPointer(), bep.first.dataSize);
670                else
671                    extensions->glBufferSubData(_target, bep.first.offset, bep.first.dataSize, de->getDataPointer());
672
673            }
674        }
675    }
676
677
678    // Unmap the texture image buffer
679    if (eboMemory) extensions->glUnmapBuffer(_target);
680
681//    osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
682//    osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
683}
684
685void ElementBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
686{
687    BufferObject::resizeGLObjectBuffers(maxSize);
688
689    for(BufferEntryDrawElementsPairs::iterator itr = _bufferEntryDrawElementsPairs.begin();
690        itr != _bufferEntryDrawElementsPairs.end();
691        ++itr)
692    {
693        itr->first.modifiedCount.resize(maxSize);
694    }
695}
696
697//////////////////////////////////////////////////////////////////////////////////
698//
699//  PixelBufferObject
700//
701PixelBufferObject::PixelBufferObject(osg::Image* image):
702    BufferObject()
703{
704    _target = GL_PIXEL_UNPACK_BUFFER_ARB;
705    _usage = GL_STREAM_DRAW_ARB;
706    _bufferEntryImagePair.second = image;
707}
708
709/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
710PixelBufferObject::PixelBufferObject(const PixelBufferObject& buffer,const CopyOp& copyop):
711    BufferObject(buffer,copyop),
712    _bufferEntryImagePair(buffer._bufferEntryImagePair)
713{
714}
715
716PixelBufferObject::~PixelBufferObject()
717{
718}
719
720void PixelBufferObject::setImage(osg::Image* image)
721{
722    if (_bufferEntryImagePair.second == image) return;
723
724    _bufferEntryImagePair.second = image;
725
726    dirty();
727}
728void PixelBufferObject::compileBuffer(State& state) const
729{
730    unsigned int contextID = state.getContextID();
731
732    _compiledList[contextID] = 1;
733
734    osg::Image* image = _bufferEntryImagePair.second;
735
736    _bufferEntryImagePair.first.modifiedCount[contextID] = image->getModifiedCount();
737    if (!image->valid()) return;
738
739    Extensions* extensions = getExtensions(contextID,true);
740
741    GLuint& pbo = buffer(contextID);
742    if (pbo==0)
743    {
744        // building for the first time.
745
746        _totalSize = image->getTotalSizeInBytes();
747
748        // don't generate buffer if size is zero.
749        if (_totalSize==0) return;
750
751        extensions->glGenBuffers(1, &pbo);
752        extensions->glBindBuffer(_target, pbo);
753        extensions->glBufferData(_target, _totalSize, NULL, _usage);
754
755    }
756    else
757    {
758        extensions->glBindBuffer(_target, pbo);
759
760        if (_totalSize != image->getTotalSizeInBytes())
761        {
762            // resize PBO.
763            _totalSize = image->getTotalSizeInBytes();
764            extensions->glBufferData(_target, _totalSize, NULL, _usage);
765        }
766    }
767
768//    osg::Timer_t start_tick = osg::Timer::instance()->tick();
769
770    void* pboMemory = extensions->glMapBuffer(_target,
771                 GL_WRITE_ONLY_ARB);
772
773    // copy data across
774    memcpy(pboMemory, image->data(), _totalSize);
775
776    // Unmap the texture image buffer
777    extensions->glUnmapBuffer(_target);
778
779    _bufferEntryImagePair.first.modifiedCount[contextID] = image->getModifiedCount();
780
781//    osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
782//    osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
783}
784
785void PixelBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
786{
787    BufferObject::resizeGLObjectBuffers(maxSize);
788
789    _bufferEntryImagePair.first.modifiedCount.resize(maxSize);
790}
791
792
793//////////////////////////////////////////////////////////////////////////////////
794//
795//  PixelDataBufferObject
796//
797//--------------------------------------------------------------------------------
798PixelDataBufferObject::PixelDataBufferObject()
799{
800    _target = GL_ARRAY_BUFFER_ARB;
801    _usage = GL_DYNAMIC_DRAW_ARB;
802    _bufferData.dataSize = 0;
803}
804
805//--------------------------------------------------------------------------------
806PixelDataBufferObject::PixelDataBufferObject(const PixelDataBufferObject& buffer,const CopyOp& copyop):
807    BufferObject(buffer,copyop),
808    _bufferData(buffer._bufferData)
809{
810}
811
812//--------------------------------------------------------------------------------
813PixelDataBufferObject::~PixelDataBufferObject()
814{
815}
816
817//--------------------------------------------------------------------------------
818void PixelDataBufferObject::compileBuffer(State& state) const
819{
820    unsigned int contextID = state.getContextID();   
821    if (!isDirty(contextID) || _bufferData.dataSize == 0) return;
822
823    Extensions* extensions = getExtensions(contextID,true);
824
825    GLuint& pbo = buffer(contextID);
826    if (pbo == 0)
827    {
828        extensions->glGenBuffers(1, &pbo);
829    }
830
831    extensions->glBindBuffer(_target, pbo);
832    extensions->glBufferData(_target, _bufferData.dataSize, NULL, _usage);
833    extensions->glBindBuffer(_target, 0);
834
835    _compiledList[contextID] = 1;
836}
837
838//--------------------------------------------------------------------------------
839void PixelDataBufferObject::bindBufferInReadMode(State& state)
840{
841    unsigned int contextID = state.getContextID();   
842    if (isDirty(contextID)) compileBuffer(state);
843
844    Extensions* extensions = getExtensions(contextID,true);
845
846    extensions->glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, buffer(contextID));
847    _mode[contextID] = READ;
848}
849
850//--------------------------------------------------------------------------------
851void PixelDataBufferObject::bindBufferInWriteMode(State& state)
852{
853    unsigned int contextID = state.getContextID();   
854    if (isDirty(contextID)) compileBuffer(state);
855
856    Extensions* extensions = getExtensions(contextID,true);
857
858    extensions->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer(contextID));
859    _mode[contextID] = WRITE;
860}
861
862//--------------------------------------------------------------------------------
863void PixelDataBufferObject::unbindBuffer(unsigned int contextID) const
864{
865    Extensions* extensions = getExtensions(contextID,true);
866
867    switch(_mode[contextID])
868    {
869        case READ:
870            extensions->glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
871            break;
872        case WRITE:
873            extensions->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB,0);
874            break;
875        default:
876            extensions->glBindBuffer(_target,0);
877            break;
878    }
879
880    _mode[contextID] = NONE;
881}
882
883//--------------------------------------------------------------------------------
884void PixelDataBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
885{
886    BufferObject::resizeGLObjectBuffers(maxSize);
887
888    _mode.resize(maxSize);
889}
Note: See TracBrowser for help on using the browser.