root/OpenSceneGraph/trunk/src/osg/Drawable.cpp @ 13041

Revision 13041, 50.6 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • 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/Drawable>
18#include <osg/State>
19#include <osg/Notify>
20#include <osg/Node>
21#include <osg/GLExtensions>
22#include <osg/Timer>
23#include <osg/TriangleFunctor>
24#include <osg/io_utils>
25
26#include <algorithm>
27#include <map>
28#include <list>
29
30#include <OpenThreads/ScopedLock>
31#include <OpenThreads/Mutex>
32
33using namespace osg;
34
35unsigned int Drawable::s_numberDrawablesReusedLastInLastFrame = 0;
36unsigned int Drawable::s_numberNewDrawablesInLastFrame = 0;
37unsigned int Drawable::s_numberDeletedDrawablesInLastFrame = 0;
38
39// static cache of deleted display lists which can only
40// by completely deleted once the appropriate OpenGL context
41// is set.  Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
42typedef std::multimap<unsigned int,GLuint> DisplayListMap;
43typedef osg::buffered_object<DisplayListMap> DeletedDisplayListCache;
44
45static OpenThreads::Mutex s_mutex_deletedDisplayListCache;
46static DeletedDisplayListCache s_deletedDisplayListCache;
47
48GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint)
49{
50#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
51    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
52
53    DisplayListMap& dll = s_deletedDisplayListCache[contextID];
54    if (dll.empty())
55    {
56        ++s_numberNewDrawablesInLastFrame;
57        return  glGenLists( 1 );
58    }
59    else
60    {
61        DisplayListMap::iterator itr = dll.lower_bound(sizeHint);
62        if (itr!=dll.end())
63        {
64            // OSG_NOTICE<<"Reusing a display list of size = "<<itr->first<<" for requested size = "<<sizeHint<<std::endl;
65
66            ++s_numberDrawablesReusedLastInLastFrame;
67
68            GLuint globj = itr->second;
69            dll.erase(itr);
70
71            return globj;
72        }
73        else
74        {
75            // OSG_NOTICE<<"Creating a new display list of size = "<<sizeHint<<" although "<<dll.size()<<" are available"<<std::endl;
76            ++s_numberNewDrawablesInLastFrame;
77            return  glGenLists( 1 );
78        }
79    }
80#else
81    OSG_NOTICE<<"Warning: Drawable::generateDisplayList(..) - not supported."<<std::endl;
82    return 0;
83#endif
84}
85
86unsigned int s_minimumNumberOfDisplayListsToRetainInCache = 0;
87void Drawable::setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum)
88{
89    s_minimumNumberOfDisplayListsToRetainInCache = minimum;
90}
91
92unsigned int Drawable::getMinimumNumberOfDisplayListsToRetainInCache()
93{
94    return s_minimumNumberOfDisplayListsToRetainInCache;
95}
96
97void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint)
98{
99#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
100    if (globj!=0)
101    {
102        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
103
104        // insert the globj into the cache for the appropriate context.
105        s_deletedDisplayListCache[contextID].insert(DisplayListMap::value_type(sizeHint,globj));
106    }
107#else
108    OSG_NOTICE<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
109#endif
110}
111
112void Drawable::flushAllDeletedDisplayLists(unsigned int contextID)
113{
114#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
115    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
116
117    DisplayListMap& dll = s_deletedDisplayListCache[contextID];
118
119    for(DisplayListMap::iterator ditr=dll.begin();
120        ditr!=dll.end();
121        ++ditr)
122    {
123        glDeleteLists(ditr->second,1);
124    }
125
126    dll.clear();
127#else
128    OSG_NOTICE<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
129#endif
130}
131
132void Drawable::discardAllDeletedDisplayLists(unsigned int contextID)
133{
134    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
135
136    DisplayListMap& dll = s_deletedDisplayListCache[contextID];
137    dll.clear();
138}
139
140void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availableTime)
141{
142#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
143    // if no time available don't try to flush objects.
144    if (availableTime<=0.0) return;
145
146    const osg::Timer& timer = *osg::Timer::instance();
147    osg::Timer_t start_tick = timer.tick();
148    double elapsedTime = 0.0;
149
150    unsigned int noDeleted = 0;
151
152    {
153        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
154
155        DisplayListMap& dll = s_deletedDisplayListCache[contextID];
156
157        bool trimFromFront = true;
158        if (trimFromFront)
159        {
160            unsigned int prev_size = dll.size();
161
162            DisplayListMap::iterator ditr=dll.begin();
163            unsigned int maxNumToDelete = (dll.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
164            for(;
165                ditr!=dll.end() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
166                ++ditr)
167            {
168                glDeleteLists(ditr->second,1);
169
170                elapsedTime = timer.delta_s(start_tick,timer.tick());
171                ++noDeleted;
172
173                ++Drawable::s_numberDeletedDrawablesInLastFrame;
174             }
175
176             if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr);
177
178             if (noDeleted+dll.size() != prev_size)
179             {
180                OSG_WARN<<"Error in delete"<<std::endl;
181             }
182        }
183        else
184        {
185            unsigned int prev_size = dll.size();
186
187            DisplayListMap::reverse_iterator ditr=dll.rbegin();
188            unsigned int maxNumToDelete = (dll.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
189            for(;
190                ditr!=dll.rend() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
191                ++ditr)
192            {
193                glDeleteLists(ditr->second,1);
194
195                elapsedTime = timer.delta_s(start_tick,timer.tick());
196                ++noDeleted;
197
198                ++Drawable::s_numberDeletedDrawablesInLastFrame;
199             }
200
201             if (ditr!=dll.rbegin()) dll.erase(ditr.base(),dll.end());
202
203             if (noDeleted+dll.size() != prev_size)
204             {
205                OSG_WARN<<"Error in delete"<<std::endl;
206             }
207        }
208    }
209    elapsedTime = timer.delta_s(start_tick,timer.tick());
210
211    if (noDeleted!=0) OSG_INFO<<"Number display lists deleted = "<<noDeleted<<" elapsed time"<<elapsedTime<<std::endl;
212
213    availableTime -= elapsedTime;
214#else
215    OSG_NOTICE<<"Warning: Drawable::flushDeletedDisplayLists(..) - not supported."<<std::endl;
216#endif
217}
218
219Drawable::Drawable()
220    :Object(true)
221{
222    _boundingBoxComputed = false;
223
224    // Note, if your are defining a subclass from drawable which is
225    // dynamically updated then you should set both the following to
226    // to false in your constructor.  This will prevent any display
227    // lists from being automatically created and safeguard the
228    // dynamic updating of data.
229#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
230    _supportsDisplayList = true;
231    _useDisplayList = true;
232#else
233    _supportsDisplayList = false;
234    _useDisplayList = false;
235#endif
236
237    _supportsVertexBufferObjects = false;
238    _useVertexBufferObjects = false;
239    // _useVertexBufferObjects = true;
240
241    _numChildrenRequiringUpdateTraversal = 0;
242    _numChildrenRequiringEventTraversal = 0;
243}
244
245Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop):
246    Object(drawable,copyop),
247    _parents(), // leave empty as parentList is managed by Geode
248    _initialBound(drawable._initialBound),
249    _computeBoundCallback(drawable._computeBoundCallback),
250    _boundingBox(drawable._boundingBox),
251    _boundingBoxComputed(drawable._boundingBoxComputed),
252    _shape(copyop(drawable._shape.get())),
253    _supportsDisplayList(drawable._supportsDisplayList),
254    _useDisplayList(drawable._useDisplayList),
255    _supportsVertexBufferObjects(drawable._supportsVertexBufferObjects),
256    _useVertexBufferObjects(drawable._useVertexBufferObjects),
257    _updateCallback(drawable._updateCallback),
258    _numChildrenRequiringUpdateTraversal(drawable._numChildrenRequiringUpdateTraversal),
259    _eventCallback(drawable._eventCallback),
260    _numChildrenRequiringEventTraversal(drawable._numChildrenRequiringEventTraversal),
261    _cullCallback(drawable._cullCallback),
262    _drawCallback(drawable._drawCallback)
263{
264    setStateSet(copyop(drawable._stateset.get()));
265}
266
267Drawable::~Drawable()
268{
269    // cleanly detatch any associated stateset (include remove parent links)
270    setStateSet(0);
271
272    dirtyDisplayList();
273}
274
275osg::MatrixList Drawable::getWorldMatrices(const osg::Node* haltTraversalAtNode) const
276{
277    osg::MatrixList matrices;
278    for(ParentList::const_iterator itr = _parents.begin();
279        itr != _parents.end();
280        ++itr)
281    {
282        osg::MatrixList localMatrices = (*itr)->getWorldMatrices(haltTraversalAtNode);
283        matrices.insert(matrices.end(), localMatrices.begin(), localMatrices.end());
284    }
285    return matrices;
286}
287
288void Drawable::computeDataVariance()
289{
290    if (getDataVariance() != UNSPECIFIED) return;
291
292    bool dynamic = false;
293
294    if (getUpdateCallback() ||
295        getEventCallback() ||
296        getCullCallback())
297    {
298        dynamic = true;
299    }
300
301    setDataVariance(dynamic ? DYNAMIC : STATIC);
302}
303
304void Drawable::addParent(osg::Node* node)
305{
306    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
307
308    _parents.push_back(node);
309}
310
311void Drawable::removeParent(osg::Node* node)
312{
313    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
314
315    ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
316    if (pitr!=_parents.end()) _parents.erase(pitr);
317}
318
319
320void Drawable::setStateSet(osg::StateSet* stateset)
321{
322    // do nothing if nothing changed.
323    if (_stateset==stateset) return;
324
325    // track whether we need to account for the need to do a update or event traversal.
326    int delta_update = 0;
327    int delta_event = 0;
328
329    // remove this node from the current statesets parent list
330    if (_stateset.valid())
331    {
332        _stateset->removeParent(this);
333        if (_stateset->requiresUpdateTraversal()) --delta_update;
334        if (_stateset->requiresEventTraversal()) --delta_event;
335    }
336
337    // set the stateset.
338    _stateset = stateset;
339
340    // add this node to the new stateset to the parent list.
341    if (_stateset.valid())
342    {
343        _stateset->addParent(this);
344        if (_stateset->requiresUpdateTraversal()) ++delta_update;
345        if (_stateset->requiresEventTraversal()) ++delta_event;
346    }
347
348
349    // only inform parents if change occurs and drawable doesn't already have an update callback
350    if (delta_update!=0 && !_updateCallback)
351    {
352        for(ParentList::iterator itr=_parents.begin();
353            itr!=_parents.end();
354            ++itr)
355        {
356            (*itr)->setNumChildrenRequiringUpdateTraversal( (*itr)->getNumChildrenRequiringUpdateTraversal()+delta_update );
357        }
358    }
359
360    // only inform parents if change occurs and drawable doesn't already have an event callback
361    if (delta_event!=0 && !_eventCallback)
362    {
363        for(ParentList::iterator itr=_parents.begin();
364            itr!=_parents.end();
365            ++itr)
366        {
367            (*itr)->setNumChildrenRequiringEventTraversal( (*itr)->getNumChildrenRequiringEventTraversal()+delta_event );
368        }
369    }
370
371
372}
373
374void Drawable::setNumChildrenRequiringUpdateTraversal(unsigned int num)
375{
376    // if no changes just return.
377    if (_numChildrenRequiringUpdateTraversal==num) return;
378
379    // note, if _updateCallback is set then the
380    // parents won't be affected by any changes to
381    // _numChildrenRequiringUpdateTraversal so no need to inform them.
382    if (!_updateCallback && !_parents.empty())
383    {
384        // need to pass on changes to parents.
385        int delta = 0;
386        if (_numChildrenRequiringUpdateTraversal>0) --delta;
387        if (num>0) ++delta;
388        if (delta!=0)
389        {
390            // the number of callbacks has changed, need to pass this
391            // on to parents so they know whether app traversal is
392            // required on this subgraph.
393            for(ParentList::iterator itr =_parents.begin();
394                itr != _parents.end();
395                ++itr)
396            {
397                (*itr)->setNumChildrenRequiringUpdateTraversal( (*itr)->getNumChildrenRequiringUpdateTraversal()+delta );
398            }
399
400        }
401    }
402
403    // finally update this objects value.
404    _numChildrenRequiringUpdateTraversal=num;
405
406}
407
408
409void Drawable::setNumChildrenRequiringEventTraversal(unsigned int num)
410{
411    // if no changes just return.
412    if (_numChildrenRequiringEventTraversal==num) return;
413
414    // note, if _eventCallback is set then the
415    // parents won't be affected by any changes to
416    // _numChildrenRequiringEventTraversal so no need to inform them.
417    if (!_eventCallback && !_parents.empty())
418    {
419        // need to pass on changes to parents.
420        int delta = 0;
421        if (_numChildrenRequiringEventTraversal>0) --delta;
422        if (num>0) ++delta;
423        if (delta!=0)
424        {
425            // the number of callbacks has changed, need to pass this
426            // on to parents so they know whether app traversal is
427            // required on this subgraph.
428            for(ParentList::iterator itr =_parents.begin();
429                itr != _parents.end();
430                ++itr)
431            {
432                (*itr)->setNumChildrenRequiringEventTraversal( (*itr)->getNumChildrenRequiringEventTraversal()+delta );
433            }
434
435        }
436    }
437
438    // finally Event this objects value.
439    _numChildrenRequiringEventTraversal=num;
440
441}
442
443osg::StateSet* Drawable::getOrCreateStateSet()
444{
445    if (!_stateset) setStateSet(new StateSet);
446    return _stateset.get();
447}
448
449void Drawable::dirtyBound()
450{
451    if (_boundingBoxComputed)
452    {
453        _boundingBoxComputed = false;
454
455        // dirty parent bounding sphere's to ensure that all are valid.
456        for(ParentList::iterator itr=_parents.begin();
457            itr!=_parents.end();
458            ++itr)
459        {
460            (*itr)->dirtyBound();
461        }
462
463    }
464}
465
466void Drawable::compileGLObjects(RenderInfo& renderInfo) const
467{
468    if (!_useDisplayList) return;
469
470#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
471    // get the contextID (user defined ID of 0 upwards) for the
472    // current OpenGL context.
473    unsigned int contextID = renderInfo.getContextID();
474
475    // get the globj for the current contextID.
476    GLuint& globj = _globjList[contextID];
477
478    // call the globj if already set otherwise compile and execute.
479    if( globj != 0 )
480    {
481        glDeleteLists( globj, 1 );
482    }
483
484    globj = generateDisplayList(contextID, getGLObjectSizeHint());
485    glNewList( globj, GL_COMPILE );
486
487    if (_drawCallback.valid())
488        _drawCallback->drawImplementation(renderInfo,this);
489    else
490        drawImplementation(renderInfo);
491
492    glEndList();
493#else
494    OSG_NOTICE<<"Warning: Drawable::compileGLObjects(RenderInfo&) - not supported."<<std::endl;
495#endif
496}
497
498void Drawable::setThreadSafeRefUnref(bool threadSafe)
499{
500    Object::setThreadSafeRefUnref(threadSafe);
501
502    if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe);
503    if (_updateCallback.valid()) _updateCallback->setThreadSafeRefUnref(threadSafe);
504    if (_eventCallback.valid()) _eventCallback->setThreadSafeRefUnref(threadSafe);
505    if (_cullCallback.valid()) _cullCallback->setThreadSafeRefUnref(threadSafe);
506    if (_drawCallback.valid()) _drawCallback->setThreadSafeRefUnref(threadSafe);
507}
508
509void Drawable::resizeGLObjectBuffers(unsigned int maxSize)
510{
511    if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize);
512    if (_drawCallback.valid()) _drawCallback->resizeGLObjectBuffers(maxSize);
513
514    _globjList.resize(maxSize);
515}
516
517void Drawable::releaseGLObjects(State* state) const
518{
519    if (_stateset.valid()) _stateset->releaseGLObjects(state);
520
521    if (_drawCallback.valid()) _drawCallback->releaseGLObjects(state);
522
523    if (!_useDisplayList) return;
524
525    if (state)
526    {
527        // get the contextID (user defined ID of 0 upwards) for the
528        // current OpenGL context.
529        unsigned int contextID = state->getContextID();
530
531        // get the globj for the current contextID.
532        GLuint& globj = _globjList[contextID];
533
534        // call the globj if already set otherwise compile and execute.
535        if( globj != 0 )
536        {
537            Drawable::deleteDisplayList(contextID,globj, getGLObjectSizeHint());
538            globj = 0;
539        }
540    }
541    else
542    {
543        const_cast<Drawable*>(this)->dirtyDisplayList();
544    }
545}
546
547void Drawable::setSupportsDisplayList(bool flag)
548{
549    // if value unchanged simply return.
550    if (_supportsDisplayList==flag) return;
551
552#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
553    // if previously set to true then need to check about display lists.
554    if (_supportsDisplayList)
555    {
556        if (_useDisplayList)
557        {
558            // used to support display lists and display lists switched
559            // on so now delete them and turn useDisplayList off.
560            dirtyDisplayList();
561            _useDisplayList = false;
562        }
563    }
564
565    // set with new value.
566    _supportsDisplayList=flag;
567#else
568    _supportsDisplayList=false;
569#endif
570}
571
572void Drawable::setUseDisplayList(bool flag)
573{
574    // if value unchanged simply return.
575    if (_useDisplayList==flag) return;
576
577#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
578    // if was previously set to true, remove display list.
579    if (_useDisplayList)
580    {
581        dirtyDisplayList();
582    }
583
584    if (_supportsDisplayList)
585    {
586
587        // set with new value.
588        _useDisplayList = flag;
589
590    }
591    else // does not support display lists.
592    {
593        if (flag)
594        {
595            OSG_WARN<<"Warning: attempt to setUseDisplayList(true) on a drawable with does not support display lists."<<std::endl;
596        }
597        else
598        {
599            // set with new value.
600            _useDisplayList = false;
601        }
602    }
603#else
604   _useDisplayList = false;
605#endif
606}
607
608
609void Drawable::setUseVertexBufferObjects(bool flag)
610{
611    // _useVertexBufferObjects = true;
612
613    // OSG_NOTICE<<"Drawable::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
614
615    // if value unchanged simply return.
616    if (_useVertexBufferObjects==flag) return;
617
618    // if was previously set to true, remove display list.
619    if (_useVertexBufferObjects)
620    {
621        dirtyDisplayList();
622    }
623
624    _useVertexBufferObjects = flag;
625}
626
627void Drawable::dirtyDisplayList()
628{
629#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
630    unsigned int i;
631    for(i=0;i<_globjList.size();++i)
632    {
633        if (_globjList[i] != 0)
634        {
635            Drawable::deleteDisplayList(i,_globjList[i], getGLObjectSizeHint());
636            _globjList[i] = 0;
637        }
638    }
639#endif
640}
641
642
643void Drawable::setUpdateCallback(UpdateCallback* ac)
644{
645    if (_updateCallback==ac) return;
646
647    int delta = 0;
648    if (_updateCallback.valid()) --delta;
649    if (ac) ++delta;
650
651    _updateCallback = ac;
652
653    if (delta!=0 && !(_stateset.valid() && _stateset->requiresUpdateTraversal()))
654    {
655        for(ParentList::iterator itr=_parents.begin();
656            itr!=_parents.end();
657            ++itr)
658        {
659            (*itr)->setNumChildrenRequiringUpdateTraversal((*itr)->getNumChildrenRequiringUpdateTraversal()+delta);
660        }
661    }
662}
663
664void Drawable::setEventCallback(EventCallback* ac)
665{
666    if (_eventCallback==ac) return;
667
668    int delta = 0;
669    if (_eventCallback.valid()) --delta;
670    if (ac) ++delta;
671
672    _eventCallback = ac;
673
674    if (delta!=0 && !(_stateset.valid() && _stateset->requiresEventTraversal()))
675    {
676        for(ParentList::iterator itr=_parents.begin();
677            itr!=_parents.end();
678            ++itr)
679        {
680            (*itr)->setNumChildrenRequiringEventTraversal( (*itr)->getNumChildrenRequiringEventTraversal()+delta );
681        }
682    }
683}
684
685struct ComputeBound : public PrimitiveFunctor
686{
687        ComputeBound()
688        {
689            _vertices2f = 0;
690            _vertices3f = 0;
691            _vertices4f = 0;
692            _vertices2d = 0;
693            _vertices3d = 0;
694            _vertices4d = 0;
695        }
696
697        virtual void setVertexArray(unsigned int,const Vec2* vertices) { _vertices2f = vertices; }
698        virtual void setVertexArray(unsigned int,const Vec3* vertices) { _vertices3f = vertices; }
699        virtual void setVertexArray(unsigned int,const Vec4* vertices) { _vertices4f = vertices; }
700
701        virtual void setVertexArray(unsigned int,const Vec2d* vertices) { _vertices2d  = vertices; }
702        virtual void setVertexArray(unsigned int,const Vec3d* vertices) { _vertices3d  = vertices; }
703        virtual void setVertexArray(unsigned int,const Vec4d* vertices) { _vertices4d = vertices; }
704
705        template<typename T>
706        void _drawArrays(T* vert, T* end)
707        {
708            for(;vert<end;++vert)
709            {
710                vertex(*vert);
711            }
712        }
713
714
715        template<typename T, typename I>
716        void _drawElements(T* vert, I* indices, I* end)
717        {
718            for(;indices<end;++indices)
719            {
720                vertex(vert[*indices]);
721            }
722        }
723
724        virtual void drawArrays(GLenum,GLint first,GLsizei count)
725        {
726            if      (_vertices3f) _drawArrays(_vertices3f+first, _vertices3f+(first+count));
727            else if (_vertices2f) _drawArrays(_vertices2f+first, _vertices2f+(first+count));
728            else if (_vertices4f) _drawArrays(_vertices4f+first, _vertices4f+(first+count));
729            else if (_vertices2d) _drawArrays(_vertices2d+first, _vertices2d+(first+count));
730            else if (_vertices3d) _drawArrays(_vertices3d+first, _vertices3d+(first+count));
731            else if (_vertices4d) _drawArrays(_vertices4d+first, _vertices4d+(first+count));
732        }
733
734        virtual void drawElements(GLenum,GLsizei count,const GLubyte* indices)
735        {
736            if (_vertices3f) _drawElements(_vertices3f, indices, indices + count);
737            else if (_vertices2f) _drawElements(_vertices2f, indices, indices + count);
738            else if (_vertices4f) _drawElements(_vertices4f, indices, indices + count);
739            else if (_vertices2d) _drawElements(_vertices2d, indices, indices + count);
740            else if (_vertices3d) _drawElements(_vertices3d, indices, indices + count);
741            else if (_vertices4d) _drawElements(_vertices4d, indices, indices + count);
742        }
743
744        virtual void drawElements(GLenum,GLsizei count,const GLushort* indices)
745        {
746            if      (_vertices3f) _drawElements(_vertices3f, indices, indices + count);
747            else if (_vertices2f) _drawElements(_vertices2f, indices, indices + count);
748            else if (_vertices4f) _drawElements(_vertices4f, indices, indices + count);
749            else if (_vertices2d) _drawElements(_vertices2d, indices, indices + count);
750            else if (_vertices3d) _drawElements(_vertices3d, indices, indices + count);
751            else if (_vertices4d) _drawElements(_vertices4d, indices, indices + count);
752        }
753
754        virtual void drawElements(GLenum,GLsizei count,const GLuint* indices)
755        {
756            if      (_vertices3f) _drawElements(_vertices3f, indices, indices + count);
757            else if (_vertices2f) _drawElements(_vertices2f, indices, indices + count);
758            else if (_vertices4f) _drawElements(_vertices4f, indices, indices + count);
759            else if (_vertices2d) _drawElements(_vertices2d, indices, indices + count);
760            else if (_vertices3d) _drawElements(_vertices3d, indices, indices + count);
761            else if (_vertices4d) _drawElements(_vertices4d, indices, indices + count);
762        }
763
764        virtual void begin(GLenum) {}
765        virtual void vertex(const Vec2& vert) { _bb.expandBy(osg::Vec3(vert[0],vert[1],0.0f)); }
766        virtual void vertex(const Vec3& vert) { _bb.expandBy(vert); }
767        virtual void vertex(const Vec4& vert) { if (vert[3]!=0.0f) _bb.expandBy(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); }
768        virtual void vertex(const Vec2d& vert) { _bb.expandBy(osg::Vec3(vert[0],vert[1],0.0f)); }
769        virtual void vertex(const Vec3d& vert) { _bb.expandBy(vert); }
770        virtual void vertex(const Vec4d& vert) { if (vert[3]!=0.0f) _bb.expandBy(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); }
771        virtual void vertex(float x,float y)  { _bb.expandBy(x,y,1.0f); }
772        virtual void vertex(float x,float y,float z) { _bb.expandBy(x,y,z); }
773        virtual void vertex(float x,float y,float z,float w) { if (w!=0.0f) _bb.expandBy(x/w,y/w,z/w); }
774        virtual void vertex(double x,double y)  { _bb.expandBy(x,y,1.0f); }
775        virtual void vertex(double x,double y,double z) { _bb.expandBy(x,y,z); }
776        virtual void vertex(double x,double y,double z,double w) { if (w!=0.0f) _bb.expandBy(x/w,y/w,z/w); }
777        virtual void end() {}
778
779        const Vec2*     _vertices2f;
780        const Vec3*     _vertices3f;
781        const Vec4*     _vertices4f;
782        const Vec2d*    _vertices2d;
783        const Vec3d*    _vertices3d;
784        const Vec4d*    _vertices4d;
785        BoundingBox     _bb;
786};
787
788BoundingBox Drawable::computeBound() const
789{
790    ComputeBound cb;
791
792    Drawable* non_const_this = const_cast<Drawable*>(this);
793    non_const_this->accept(cb);
794
795#if 0
796    OSG_NOTICE<<"computeBound() "<<cb._bb.xMin()<<", "<<cb._bb.xMax()<<", "<<std::endl;
797    OSG_NOTICE<<"               "<<cb._bb.yMin()<<", "<<cb._bb.yMax()<<", "<<std::endl;
798    OSG_NOTICE<<"               "<<cb._bb.zMin()<<", "<<cb._bb.zMax()<<", "<<std::endl;
799#endif
800
801    return cb._bb;
802}
803
804void Drawable::setBound(const BoundingBox& bb) const
805{
806     _boundingBox = bb;
807     _boundingBoxComputed = true;
808}
809
810
811//////////////////////////////////////////////////////////////////////////////
812//
813//  Extension support
814//
815
816typedef buffered_value< ref_ptr<Drawable::Extensions> > BufferedExtensions;
817static BufferedExtensions s_extensions;
818
819Drawable::Extensions* Drawable::getExtensions(unsigned int contextID,bool createIfNotInitalized)
820{
821    if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Drawable::Extensions(contextID);
822    return s_extensions[contextID].get();
823}
824
825void Drawable::setExtensions(unsigned int contextID,Extensions* extensions)
826{
827    s_extensions[contextID] = extensions;
828}
829
830Drawable::Extensions::Extensions(unsigned int contextID)
831{
832    setupGLExtensions(contextID);
833}
834
835Drawable::Extensions::Extensions(const Extensions& rhs):
836    Referenced()
837{
838    _isVertexProgramSupported = rhs._isVertexProgramSupported;
839    _isSecondaryColorSupported = rhs._isSecondaryColorSupported;
840    _isFogCoordSupported = rhs._isFogCoordSupported;
841    _isMultiTexSupported = rhs._isMultiTexSupported;
842    _isOcclusionQuerySupported = rhs._isOcclusionQuerySupported;
843    _isARBOcclusionQuerySupported = rhs._isARBOcclusionQuerySupported;
844    _isTimerQuerySupported = rhs._isTimerQuerySupported;
845    _isARBTimerQuerySupported = rhs._isARBTimerQuerySupported;
846
847    _glFogCoordfv = rhs._glFogCoordfv;
848    _glSecondaryColor3ubv = rhs._glSecondaryColor3ubv;
849    _glSecondaryColor3fv = rhs._glSecondaryColor3fv;
850    _glMultiTexCoord1f = rhs._glMultiTexCoord1f;
851    _glMultiTexCoord2fv = rhs._glMultiTexCoord2fv;
852    _glMultiTexCoord3fv = rhs._glMultiTexCoord3fv;
853    _glMultiTexCoord4fv = rhs._glMultiTexCoord4fv;
854    _glVertexAttrib1s = rhs._glVertexAttrib1s;
855    _glVertexAttrib1f = rhs._glVertexAttrib1f;
856    _glVertexAttrib2fv = rhs._glVertexAttrib2fv;
857    _glVertexAttrib3fv = rhs._glVertexAttrib3fv;
858    _glVertexAttrib4fv = rhs._glVertexAttrib4fv;
859    _glVertexAttrib4ubv = rhs._glVertexAttrib4ubv;
860    _glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv;
861    _glGenBuffers = rhs._glGenBuffers;
862    _glBindBuffer = rhs._glBindBuffer;
863    _glBufferData = rhs._glBufferData;
864    _glBufferSubData = rhs._glBufferSubData;
865    _glDeleteBuffers = rhs._glDeleteBuffers;
866    _glGenOcclusionQueries = rhs._glGenOcclusionQueries;
867    _glDeleteOcclusionQueries = rhs._glDeleteOcclusionQueries;
868    _glIsOcclusionQuery = rhs._glIsOcclusionQuery;
869    _glBeginOcclusionQuery = rhs._glBeginOcclusionQuery;
870    _glEndOcclusionQuery = rhs._glEndOcclusionQuery;
871    _glGetOcclusionQueryiv = rhs._glGetOcclusionQueryiv;
872    _glGetOcclusionQueryuiv = rhs._glGetOcclusionQueryuiv;
873    _gl_gen_queries_arb = rhs._gl_gen_queries_arb;
874    _gl_delete_queries_arb = rhs._gl_delete_queries_arb;
875    _gl_is_query_arb = rhs._gl_is_query_arb;
876    _gl_begin_query_arb = rhs._gl_begin_query_arb;
877    _gl_end_query_arb = rhs._gl_end_query_arb;
878    _gl_get_queryiv_arb = rhs._gl_get_queryiv_arb;
879    _gl_get_query_objectiv_arb = rhs._gl_get_query_objectiv_arb;
880    _gl_get_query_objectuiv_arb = rhs._gl_get_query_objectuiv_arb;
881    _gl_get_query_objectui64v = rhs._gl_get_query_objectui64v;
882    _glGetInteger64v = rhs._glGetInteger64v;
883}
884
885
886void Drawable::Extensions::lowestCommonDenominator(const Extensions& rhs)
887{
888    if (!rhs._isVertexProgramSupported) _isVertexProgramSupported = false;
889    if (!rhs._isSecondaryColorSupported) _isSecondaryColorSupported = false;
890    if (!rhs._isFogCoordSupported) _isFogCoordSupported = false;
891    if (!rhs._isMultiTexSupported) _isMultiTexSupported = false;
892    if (!rhs._isOcclusionQuerySupported) _isOcclusionQuerySupported = false;
893    if (!rhs._isARBOcclusionQuerySupported) _isARBOcclusionQuerySupported = false;
894
895    if (!rhs._isTimerQuerySupported) _isTimerQuerySupported = false;
896    if (!rhs._isARBTimerQuerySupported) _isARBTimerQuerySupported = false;
897
898    if (!rhs._glFogCoordfv) _glFogCoordfv = 0;
899    if (!rhs._glSecondaryColor3ubv) _glSecondaryColor3ubv = 0;
900    if (!rhs._glSecondaryColor3fv) _glSecondaryColor3fv = 0;
901    if (!rhs._glMultiTexCoord1f) _glMultiTexCoord1f = 0;
902    if (!rhs._glMultiTexCoord2fv) _glMultiTexCoord2fv = 0;
903    if (!rhs._glMultiTexCoord3fv) _glMultiTexCoord3fv = 0;
904    if (!rhs._glMultiTexCoord4fv) _glMultiTexCoord4fv = 0;
905
906    if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0;
907    if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0;
908    if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0;
909    if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0;
910    if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0;
911    if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0;
912    if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0;
913
914    if (!rhs._glGenBuffers) _glGenBuffers = 0;
915    if (!rhs._glBindBuffer) _glBindBuffer = 0;
916    if (!rhs._glBufferData) _glBufferData = 0;
917    if (!rhs._glBufferSubData) _glBufferSubData = 0;
918    if (!rhs._glDeleteBuffers) _glDeleteBuffers = 0;
919    if (!rhs._glIsBuffer) _glIsBuffer = 0;
920    if (!rhs._glGetBufferSubData) _glGetBufferSubData = 0;
921    if (!rhs._glMapBuffer) _glMapBuffer = 0;
922    if (!rhs._glUnmapBuffer) _glUnmapBuffer = 0;
923    if (!rhs._glGetBufferParameteriv) _glGetBufferParameteriv = 0;
924    if (!rhs._glGetBufferPointerv) _glGetBufferPointerv = 0;
925
926    if (!rhs._glGenOcclusionQueries) _glGenOcclusionQueries = 0;
927    if (!rhs._glDeleteOcclusionQueries) _glDeleteOcclusionQueries = 0;
928    if (!rhs._glIsOcclusionQuery) _glIsOcclusionQuery = 0;
929    if (!rhs._glBeginOcclusionQuery) _glBeginOcclusionQuery = 0;
930    if (!rhs._glEndOcclusionQuery) _glEndOcclusionQuery = 0;
931    if (!rhs._glGetOcclusionQueryiv) _glGetOcclusionQueryiv = 0;
932    if (!rhs._glGetOcclusionQueryuiv) _glGetOcclusionQueryuiv = 0;
933
934    if (!rhs._gl_gen_queries_arb) _gl_gen_queries_arb = 0;
935    if (!rhs._gl_delete_queries_arb) _gl_delete_queries_arb = 0;
936    if (!rhs._gl_is_query_arb) _gl_is_query_arb = 0;
937    if (!rhs._gl_begin_query_arb) _gl_begin_query_arb = 0;
938    if (!rhs._gl_end_query_arb) _gl_end_query_arb = 0;
939    if (!rhs._gl_get_queryiv_arb) _gl_get_queryiv_arb = 0;
940    if (!rhs._gl_get_query_objectiv_arb) _gl_get_query_objectiv_arb = 0;
941    if (!rhs._gl_get_query_objectuiv_arb) _gl_get_query_objectuiv_arb = 0;
942    if (!rhs._gl_get_query_objectui64v) _gl_get_query_objectui64v = 0;
943    if (!rhs._glGetInteger64v) _glGetInteger64v = 0;
944}
945
946void Drawable::Extensions::setupGLExtensions(unsigned int contextID)
947{
948    _isVertexProgramSupported = isGLExtensionSupported(contextID,"GL_ARB_vertex_program");
949    _isSecondaryColorSupported = isGLExtensionSupported(contextID,"GL_EXT_secondary_color");
950    _isFogCoordSupported = isGLExtensionSupported(contextID,"GL_EXT_fog_coord");
951    _isMultiTexSupported = isGLExtensionSupported(contextID,"GL_ARB_multitexture");
952    _isOcclusionQuerySupported = osg::isGLExtensionSupported(contextID, "GL_NV_occlusion_query" );
953    _isARBOcclusionQuerySupported = OSG_GL3_FEATURES || osg::isGLExtensionSupported(contextID, "GL_ARB_occlusion_query" );
954
955    _isTimerQuerySupported = osg::isGLExtensionSupported(contextID, "GL_EXT_timer_query" );
956    _isARBTimerQuerySupported = osg::isGLExtensionSupported(contextID, "GL_ARB_timer_query");
957
958
959    setGLExtensionFuncPtr(_glFogCoordfv, "glFogCoordfv","glFogCoordfvEXT");
960    setGLExtensionFuncPtr(_glSecondaryColor3ubv, "glSecondaryColor3ubv","glSecondaryColor3ubvEXT");
961    setGLExtensionFuncPtr(_glSecondaryColor3fv, "glSecondaryColor3fv","glSecondaryColor3fvEXT");
962    setGLExtensionFuncPtr(_glMultiTexCoord1f, "glMultiTexCoord1f","glMultiTexCoord1fARB");
963    setGLExtensionFuncPtr(_glMultiTexCoord1fv, "glMultiTexCoord1fv","glMultiTexCoord1fvARB");
964    setGLExtensionFuncPtr(_glMultiTexCoord2fv, "glMultiTexCoord2fv","glMultiTexCoord2fvARB");
965    setGLExtensionFuncPtr(_glMultiTexCoord3fv, "glMultiTexCoord3fv","glMultiTexCoord3fvARB");
966    setGLExtensionFuncPtr(_glMultiTexCoord4fv, "glMultiTexCoord4fv","glMultiTexCoord4fvARB");
967    setGLExtensionFuncPtr(_glMultiTexCoord1d, "glMultiTexCoord1d","glMultiTexCoorddfARB");
968    setGLExtensionFuncPtr(_glMultiTexCoord2dv, "glMultiTexCoord2dv","glMultiTexCoord2dvARB");
969    setGLExtensionFuncPtr(_glMultiTexCoord3dv, "glMultiTexCoord3dv","glMultiTexCoord3dvARB");
970    setGLExtensionFuncPtr(_glMultiTexCoord4dv, "glMultiTexCoord4dv","glMultiTexCoord4dvARB");
971
972    setGLExtensionFuncPtr(_glVertexAttrib1s, "glVertexAttrib1s","glVertexAttrib1sARB");
973    setGLExtensionFuncPtr(_glVertexAttrib1f, "glVertexAttrib1f","glVertexAttrib1fARB");
974    setGLExtensionFuncPtr(_glVertexAttrib1d, "glVertexAttrib1d","glVertexAttrib1dARB");
975    setGLExtensionFuncPtr(_glVertexAttrib1fv, "glVertexAttrib1fv","glVertexAttrib1fvARB");
976    setGLExtensionFuncPtr(_glVertexAttrib2fv, "glVertexAttrib2fv","glVertexAttrib2fvARB");
977    setGLExtensionFuncPtr(_glVertexAttrib3fv, "glVertexAttrib3fv","glVertexAttrib3fvARB");
978    setGLExtensionFuncPtr(_glVertexAttrib4fv, "glVertexAttrib4fv","glVertexAttrib4fvARB");
979    setGLExtensionFuncPtr(_glVertexAttrib2dv, "glVertexAttrib2dv","glVertexAttrib2dvARB");
980    setGLExtensionFuncPtr(_glVertexAttrib3dv, "glVertexAttrib3dv","glVertexAttrib3dvARB");
981    setGLExtensionFuncPtr(_glVertexAttrib4dv, "glVertexAttrib4dv","glVertexAttrib4dvARB");
982    setGLExtensionFuncPtr(_glVertexAttrib4ubv, "glVertexAttrib4ubv","glVertexAttrib4ubvARB");
983    setGLExtensionFuncPtr(_glVertexAttrib4Nubv, "glVertexAttrib4Nubv","glVertexAttrib4NubvARB");
984
985    setGLExtensionFuncPtr(_glGenBuffers, "glGenBuffers","glGenBuffersARB");
986    setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
987    setGLExtensionFuncPtr(_glBufferData, "glBufferData","glBufferDataARB");
988    setGLExtensionFuncPtr(_glBufferSubData, "glBufferSubData","glBufferSubDataARB");
989    setGLExtensionFuncPtr(_glDeleteBuffers, "glDeleteBuffers","glDeleteBuffersARB");
990    setGLExtensionFuncPtr(_glIsBuffer, "glIsBuffer","glIsBufferARB");
991    setGLExtensionFuncPtr(_glGetBufferSubData, "glGetBufferSubData","glGetBufferSubDataARB");
992    setGLExtensionFuncPtr(_glMapBuffer, "glMapBuffer","glMapBufferARB");
993    setGLExtensionFuncPtr(_glUnmapBuffer, "glUnmapBuffer","glUnmapBufferARB");
994    setGLExtensionFuncPtr(_glGetBufferParameteriv, "glGetBufferParameteriv","glGetBufferParameterivARB");
995    setGLExtensionFuncPtr(_glGetBufferPointerv, "glGetBufferPointerv","glGetBufferPointervARB");
996
997    setGLExtensionFuncPtr(_glGenOcclusionQueries, "glGenOcclusionQueries","glGenOcclusionQueriesNV");
998    setGLExtensionFuncPtr(_glDeleteOcclusionQueries, "glDeleteOcclusionQueries","glDeleteOcclusionQueriesNV");
999    setGLExtensionFuncPtr(_glIsOcclusionQuery, "glIsOcclusionQuery","_glIsOcclusionQueryNV");
1000    setGLExtensionFuncPtr(_glBeginOcclusionQuery, "glBeginOcclusionQuery","glBeginOcclusionQueryNV");
1001    setGLExtensionFuncPtr(_glEndOcclusionQuery, "glEndOcclusionQuery","glEndOcclusionQueryNV");
1002    setGLExtensionFuncPtr(_glGetOcclusionQueryiv, "glGetOcclusionQueryiv","glGetOcclusionQueryivNV");
1003    setGLExtensionFuncPtr(_glGetOcclusionQueryuiv, "glGetOcclusionQueryuiv","glGetOcclusionQueryuivNV");
1004
1005    setGLExtensionFuncPtr(_gl_gen_queries_arb, "glGenQueries", "glGenQueriesARB");
1006    setGLExtensionFuncPtr(_gl_delete_queries_arb, "glDeleteQueries", "glDeleteQueriesARB");
1007    setGLExtensionFuncPtr(_gl_is_query_arb, "glIsQuery", "glIsQueryARB");
1008    setGLExtensionFuncPtr(_gl_begin_query_arb, "glBeginQuery", "glBeginQueryARB");
1009    setGLExtensionFuncPtr(_gl_end_query_arb, "glEndQuery", "glEndQueryARB");
1010    setGLExtensionFuncPtr(_gl_get_queryiv_arb, "glGetQueryiv", "glGetQueryivARB");
1011    setGLExtensionFuncPtr(_gl_get_query_objectiv_arb, "glGetQueryObjectiv","glGetQueryObjectivARB");
1012    setGLExtensionFuncPtr(_gl_get_query_objectuiv_arb, "glGetQueryObjectuiv","glGetQueryObjectuivARB");
1013    setGLExtensionFuncPtr(_gl_get_query_objectui64v, "glGetQueryObjectui64v","glGetQueryObjectui64vEXT");
1014    setGLExtensionFuncPtr(_glQueryCounter, "glQueryCounter");
1015    setGLExtensionFuncPtr(_glGetInteger64v, "glGetInteger64v");
1016}
1017
1018void Drawable::Extensions::glFogCoordfv(const GLfloat* coord) const
1019{
1020    if (_glFogCoordfv)
1021    {
1022        _glFogCoordfv(coord);
1023    }
1024    else
1025    {
1026        OSG_WARN<<"Error: glFogCoordfv not supported by OpenGL driver"<<std::endl;
1027    }
1028}
1029
1030void Drawable::Extensions::glSecondaryColor3ubv(const GLubyte* coord) const
1031{
1032    if (_glSecondaryColor3ubv)
1033    {
1034        _glSecondaryColor3ubv(coord);
1035    }
1036    else
1037    {
1038        OSG_WARN<<"Error: glSecondaryColor3ubv not supported by OpenGL driver"<<std::endl;
1039    }
1040}
1041
1042void Drawable::Extensions::glSecondaryColor3fv(const GLfloat* coord) const
1043{
1044    if (_glSecondaryColor3fv)
1045    {
1046        _glSecondaryColor3fv(coord);
1047    }
1048    else
1049    {
1050        OSG_WARN<<"Error: glSecondaryColor3fv not supported by OpenGL driver"<<std::endl;
1051    }
1052}
1053
1054void Drawable::Extensions::glMultiTexCoord1f(GLenum target,GLfloat coord) const
1055{
1056    if (_glMultiTexCoord1f)
1057    {
1058        _glMultiTexCoord1f(target,coord);
1059    }
1060    else
1061    {
1062        OSG_WARN<<"Error: glMultiTexCoord1f not supported by OpenGL driver"<<std::endl;
1063    }
1064}
1065
1066void Drawable::Extensions::glMultiTexCoord2fv(GLenum target,const GLfloat* coord) const
1067{
1068    if (_glMultiTexCoord2fv)
1069    {
1070        _glMultiTexCoord2fv(target,coord);
1071    }
1072    else
1073    {
1074        OSG_WARN<<"Error: glMultiTexCoord2fv not supported by OpenGL driver"<<std::endl;
1075    }
1076}
1077
1078void Drawable::Extensions::glMultiTexCoord3fv(GLenum target,const GLfloat* coord) const
1079{
1080    if (_glMultiTexCoord3fv)
1081    {
1082        _glMultiTexCoord3fv(target,coord);
1083    }
1084    else
1085    {
1086        OSG_WARN<<"Error: _glMultiTexCoord3fv not supported by OpenGL driver"<<std::endl;
1087    }
1088}
1089
1090void Drawable::Extensions::glMultiTexCoord4fv(GLenum target,const GLfloat* coord) const
1091{
1092    if (_glMultiTexCoord4fv)
1093    {
1094        _glMultiTexCoord4fv(target,coord);
1095    }
1096    else
1097    {
1098        OSG_WARN<<"Error: glMultiTexCoord4fv not supported by OpenGL driver"<<std::endl;
1099    }
1100}
1101
1102void Drawable::Extensions::glMultiTexCoord1d(GLenum target,GLdouble coord) const
1103{
1104    if (_glMultiTexCoord1d)
1105    {
1106        _glMultiTexCoord1d(target,coord);
1107    }
1108    else
1109    {
1110        OSG_WARN<<"Error: glMultiTexCoord1d not supported by OpenGL driver"<<std::endl;
1111    }
1112}
1113
1114void Drawable::Extensions::glMultiTexCoord2dv(GLenum target,const GLdouble* coord) const
1115{
1116    if (_glMultiTexCoord2dv)
1117    {
1118        _glMultiTexCoord2dv(target,coord);
1119    }
1120    else
1121    {
1122        OSG_WARN<<"Error: glMultiTexCoord2dv not supported by OpenGL driver"<<std::endl;
1123    }
1124}
1125
1126void Drawable::Extensions::glMultiTexCoord3dv(GLenum target,const GLdouble* coord) const
1127{
1128    if (_glMultiTexCoord3dv)
1129    {
1130        _glMultiTexCoord3dv(target,coord);
1131    }
1132    else
1133    {
1134        OSG_WARN<<"Error: _glMultiTexCoord3dv not supported by OpenGL driver"<<std::endl;
1135    }
1136}
1137
1138void Drawable::Extensions::glMultiTexCoord4dv(GLenum target,const GLdouble* coord) const
1139{
1140    if (_glMultiTexCoord4dv)
1141    {
1142        _glMultiTexCoord4dv(target,coord);
1143    }
1144    else
1145    {
1146        OSG_WARN<<"Error: glMultiTexCoord4dv not supported by OpenGL driver"<<std::endl;
1147    }
1148}
1149
1150void Drawable::Extensions::glVertexAttrib1s(unsigned int index, GLshort s) const
1151{
1152    if (_glVertexAttrib1s)
1153    {
1154        _glVertexAttrib1s(index,s);
1155    }
1156    else
1157    {
1158        OSG_WARN<<"Error: glVertexAttrib1s not supported by OpenGL driver"<<std::endl;
1159    }
1160}
1161
1162void Drawable::Extensions::glVertexAttrib1f(unsigned int index, GLfloat f) const
1163{
1164    if (_glVertexAttrib1f)
1165    {
1166        _glVertexAttrib1f(index,f);
1167    }
1168    else
1169    {
1170        OSG_WARN<<"Error: glVertexAttrib1f not supported by OpenGL driver"<<std::endl;
1171    }
1172}
1173
1174void Drawable::Extensions::glVertexAttrib1d(unsigned int index, GLdouble f) const
1175{
1176    if (_glVertexAttrib1d)
1177    {
1178        _glVertexAttrib1d(index,f);
1179    }
1180    else
1181    {
1182        OSG_WARN<<"Error: glVertexAttrib1d not supported by OpenGL driver"<<std::endl;
1183    }
1184}
1185
1186void Drawable::Extensions::glVertexAttrib2fv(unsigned int index, const GLfloat * v) const
1187{
1188    if (_glVertexAttrib2fv)
1189    {
1190        _glVertexAttrib2fv(index,v);
1191    }
1192    else
1193    {
1194        OSG_WARN<<"Error: glVertexAttrib2fv not supported by OpenGL driver"<<std::endl;
1195    }
1196}
1197
1198void Drawable::Extensions::glVertexAttrib3fv(unsigned int index, const GLfloat * v) const
1199{
1200    if (_glVertexAttrib3fv)
1201    {
1202        _glVertexAttrib3fv(index,v);
1203    }
1204    else
1205    {
1206        OSG_WARN<<"Error: glVertexAttrib3fv not supported by OpenGL driver"<<std::endl;
1207    }
1208}
1209
1210void Drawable::Extensions::glVertexAttrib4fv(unsigned int index, const GLfloat * v) const
1211{
1212    if (_glVertexAttrib4fv)
1213    {
1214        _glVertexAttrib4fv(index,v);
1215    }
1216    else
1217    {
1218        OSG_WARN<<"Error: glVertexAttrib4fv not supported by OpenGL driver"<<std::endl;
1219    }
1220}
1221
1222void Drawable::Extensions::glVertexAttrib2dv(unsigned int index, const GLdouble * v) const
1223{
1224    if (_glVertexAttrib2dv)
1225    {
1226        _glVertexAttrib2dv(index,v);
1227    }
1228    else
1229    {
1230        OSG_WARN<<"Error: glVertexAttrib2dv not supported by OpenGL driver"<<std::endl;
1231    }
1232}
1233
1234void Drawable::Extensions::glVertexAttrib3dv(unsigned int index, const GLdouble * v) const
1235{
1236    if (_glVertexAttrib3dv)
1237    {
1238        _glVertexAttrib3dv(index,v);
1239    }
1240    else
1241    {
1242        OSG_WARN<<"Error: glVertexAttrib3dv not supported by OpenGL driver"<<std::endl;
1243    }
1244}
1245
1246void Drawable::Extensions::glVertexAttrib4dv(unsigned int index, const GLdouble * v) const
1247{
1248    if (_glVertexAttrib4dv)
1249    {
1250        _glVertexAttrib4dv(index,v);
1251    }
1252    else
1253    {
1254        OSG_WARN<<"Error: glVertexAttrib4dv not supported by OpenGL driver"<<std::endl;
1255    }
1256}
1257
1258void Drawable::Extensions::glVertexAttrib4ubv(unsigned int index, const GLubyte * v) const
1259{
1260    if (_glVertexAttrib4ubv)
1261    {
1262        _glVertexAttrib4ubv(index,v);
1263    }
1264    else
1265    {
1266        OSG_WARN<<"Error: glVertexAttrib4ubv not supported by OpenGL driver"<<std::endl;
1267    }
1268}
1269
1270void Drawable::Extensions::glVertexAttrib4Nubv(unsigned int index, const GLubyte * v) const
1271{
1272    if (_glVertexAttrib4Nubv)
1273    {
1274        _glVertexAttrib4Nubv(index,v);
1275    }
1276    else
1277    {
1278        OSG_WARN<<"Error: glVertexAttrib4Nubv not supported by OpenGL driver"<<std::endl;
1279    }
1280}
1281
1282void Drawable::Extensions::glGenBuffers(GLsizei n, GLuint *buffers) const
1283{
1284    if (_glGenBuffers) _glGenBuffers(n, buffers);
1285    else OSG_WARN<<"Error: glGenBuffers not supported by OpenGL driver"<<std::endl;
1286}
1287
1288void Drawable::Extensions::glBindBuffer(GLenum target, GLuint buffer) const
1289{
1290    if (_glBindBuffer) _glBindBuffer(target, buffer);
1291    else OSG_WARN<<"Error: glBindBuffer not supported by OpenGL driver"<<std::endl;
1292}
1293
1294void Drawable::Extensions::glBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const
1295{
1296    if (_glBufferData) _glBufferData(target, size, data, usage);
1297    else OSG_WARN<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
1298}
1299
1300void Drawable::Extensions::glBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const
1301{
1302    if (_glBufferSubData) _glBufferSubData(target, offset, size, data);
1303    else OSG_WARN<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
1304}
1305
1306void Drawable::Extensions::glDeleteBuffers(GLsizei n, const GLuint *buffers) const
1307{
1308    if (_glDeleteBuffers) _glDeleteBuffers(n, buffers);
1309    else OSG_WARN<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
1310}
1311
1312GLboolean Drawable::Extensions::glIsBuffer (GLuint buffer) const
1313{
1314    if (_glIsBuffer) return _glIsBuffer(buffer);
1315    else
1316    {
1317        OSG_WARN<<"Error: glIsBuffer not supported by OpenGL driver"<<std::endl;
1318        return GL_FALSE;
1319    }
1320}
1321
1322void Drawable::Extensions::glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const
1323{
1324    if (_glGetBufferSubData) _glGetBufferSubData(target,offset,size,data);
1325    else OSG_WARN<<"Error: glGetBufferSubData not supported by OpenGL driver"<<std::endl;
1326}
1327
1328GLvoid* Drawable::Extensions::glMapBuffer (GLenum target, GLenum access) const
1329{
1330    if (_glMapBuffer) return _glMapBuffer(target,access);
1331    else
1332    {
1333        OSG_WARN<<"Error: glMapBuffer not supported by OpenGL driver"<<std::endl;
1334        return 0;
1335    }
1336}
1337
1338GLboolean Drawable::Extensions::glUnmapBuffer (GLenum target) const
1339{
1340    if (_glUnmapBuffer) return _glUnmapBuffer(target);
1341    else
1342    {
1343        OSG_WARN<<"Error: glUnmapBuffer not supported by OpenGL driver"<<std::endl;
1344        return GL_FALSE;
1345    }
1346}
1347
1348void Drawable::Extensions::glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const
1349{
1350    if (_glGetBufferParameteriv) _glGetBufferParameteriv(target,pname,params);
1351    else OSG_WARN<<"Error: glGetBufferParameteriv not supported by OpenGL driver"<<std::endl;
1352}
1353
1354void Drawable::Extensions::glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const
1355{
1356    if (_glGetBufferPointerv) _glGetBufferPointerv(target,pname,params);
1357    else OSG_WARN<<"Error: glGetBufferPointerv not supported by OpenGL driver"<<std::endl;
1358}
1359
1360
1361void Drawable::Extensions::glGenOcclusionQueries( GLsizei n, GLuint *ids ) const
1362{
1363    if (_glGenOcclusionQueries)
1364    {
1365        _glGenOcclusionQueries( n, ids );
1366    }
1367    else
1368    {
1369        OSG_WARN<<"Error: glGenOcclusionQueries not supported by OpenGL driver"<<std::endl;
1370    }
1371}
1372
1373void Drawable::Extensions::glDeleteOcclusionQueries( GLsizei n, const GLuint *ids ) const
1374{
1375    if (_glDeleteOcclusionQueries)
1376    {
1377        _glDeleteOcclusionQueries( n, ids );
1378    }
1379    else
1380    {
1381        OSG_WARN<<"Error: glDeleteOcclusionQueries not supported by OpenGL driver"<<std::endl;
1382    }
1383}
1384
1385GLboolean Drawable::Extensions::glIsOcclusionQuery( GLuint id ) const
1386{
1387    if (_glIsOcclusionQuery)
1388    {
1389        return _glIsOcclusionQuery( id );
1390    }
1391    else
1392    {
1393        OSG_WARN<<"Error: glIsOcclusionQuery not supported by OpenGL driver"<<std::endl;
1394    }
1395
1396    return GLboolean( 0 );
1397}
1398
1399void Drawable::Extensions::glBeginOcclusionQuery( GLuint id ) const
1400{
1401    if (_glBeginOcclusionQuery)
1402    {
1403        _glBeginOcclusionQuery( id );
1404    }
1405    else
1406    {
1407        OSG_WARN<<"Error: glBeginOcclusionQuery not supported by OpenGL driver"<<std::endl;
1408    }
1409}
1410
1411void Drawable::Extensions::glEndOcclusionQuery() const
1412{
1413    if (_glEndOcclusionQuery)
1414    {
1415        _glEndOcclusionQuery();
1416    }
1417    else
1418    {
1419        OSG_WARN<<"Error: glEndOcclusionQuery not supported by OpenGL driver"<<std::endl;
1420    }
1421}
1422
1423void Drawable::Extensions::glGetOcclusionQueryiv( GLuint id, GLenum pname, GLint *params ) const
1424{
1425    if (_glGetOcclusionQueryiv)
1426    {
1427        _glGetOcclusionQueryiv( id, pname, params );
1428    }
1429    else
1430    {
1431        OSG_WARN<<"Error: glGetOcclusionQueryiv not supported by OpenGL driver"<<std::endl;
1432    }
1433}
1434
1435void Drawable::Extensions::glGetOcclusionQueryuiv( GLuint id, GLenum pname, GLuint *params ) const
1436{
1437    if (_glGetOcclusionQueryuiv)
1438    {
1439        _glGetOcclusionQueryuiv( id, pname, params );
1440    }
1441    else
1442    {
1443        OSG_WARN<<"Error: glGetOcclusionQueryuiv not supported by OpenGL driver"<<std::endl;
1444    }
1445}
1446
1447void Drawable::Extensions::glGetQueryiv(GLenum target, GLenum pname, GLint *params) const
1448{
1449  if (_gl_get_queryiv_arb)
1450    _gl_get_queryiv_arb(target, pname, params);
1451  else
1452    OSG_WARN << "Error: glGetQueryiv not supported by OpenGL driver" << std::endl;
1453}
1454
1455void Drawable::Extensions::glGenQueries(GLsizei n, GLuint *ids) const
1456{
1457  if (_gl_gen_queries_arb)
1458    _gl_gen_queries_arb(n, ids);
1459  else
1460    OSG_WARN << "Error: glGenQueries not supported by OpenGL driver" << std::endl;
1461}
1462
1463void Drawable::Extensions::glBeginQuery(GLenum target, GLuint id) const
1464{
1465  if (_gl_begin_query_arb)
1466    _gl_begin_query_arb(target, id);
1467  else
1468    OSG_WARN << "Error: glBeginQuery not supported by OpenGL driver" << std::endl;
1469}
1470
1471void Drawable::Extensions::glEndQuery(GLenum target) const
1472{
1473  if (_gl_end_query_arb)
1474    _gl_end_query_arb(target);
1475  else
1476    OSG_WARN << "Error: glEndQuery not supported by OpenGL driver" << std::endl;
1477}
1478
1479void Drawable::Extensions::glQueryCounter(GLuint id, GLenum target) const
1480{
1481    if (_glQueryCounter)
1482        _glQueryCounter(id, target);
1483    else
1484        OSG_WARN << "Error: glQueryCounter not supported by OpenGL driver\n";
1485}
1486
1487GLboolean Drawable::Extensions::glIsQuery(GLuint id) const
1488{
1489  if (_gl_is_query_arb) return _gl_is_query_arb(id);
1490
1491  OSG_WARN << "Error: glIsQuery not supported by OpenGL driver" << std::endl;
1492  return false;
1493}
1494
1495void Drawable::Extensions::glDeleteQueries(GLsizei n, const GLuint *ids) const
1496{
1497    if (_gl_delete_queries_arb)
1498        _gl_delete_queries_arb(n, ids);
1499    else
1500        OSG_WARN << "Error: glIsQuery not supported by OpenGL driver" << std::endl;
1501}
1502
1503void Drawable::Extensions::glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params) const
1504{
1505  if (_gl_get_query_objectiv_arb)
1506    _gl_get_query_objectiv_arb(id, pname, params);
1507  else
1508    OSG_WARN << "Error: glGetQueryObjectiv not supported by OpenGL driver" << std::endl;
1509}
1510
1511void Drawable::Extensions::glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) const
1512{
1513  if (_gl_get_query_objectuiv_arb)
1514    _gl_get_query_objectuiv_arb(id, pname, params);
1515  else
1516    OSG_WARN << "Error: glGetQueryObjectuiv not supported by OpenGL driver" << std::endl;
1517}
1518
1519void Drawable::Extensions::glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) const
1520{
1521  if (_gl_get_query_objectui64v)
1522    _gl_get_query_objectui64v(id, pname, params);
1523  else
1524    OSG_WARN << "Error: glGetQueryObjectui64v not supported by OpenGL driver" << std::endl;
1525}
1526
1527void Drawable::Extensions::glGetInteger64v(GLenum pname, GLint64EXT *params)
1528    const
1529{
1530    if (_glGetInteger64v)
1531        _glGetInteger64v(pname, params);
1532    else
1533        OSG_WARN << "Error: glGetInteger64v not supported by OpenGL driver\n";
1534}
Note: See TracBrowser for help on using the browser.