root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osg/Drawable.cpp @ 11238

Revision 11238, 49.5 kB (checked in by paulmartz, 4 years ago)

2.8 branch: Minor bug fixes for ac and 3dc plugins. Merges these revisions from trunk: 10010, 10758, and 11175.

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