root/OpenSceneGraph/trunk/include/osg/State @ 7648

Revision 7648, 68.9 kB (checked in by robert, 10 years ago)

From Roland Smeenk, "Attached you will find a large set of small typo fixes (mainly in the comments)."

  • 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
14#ifndef OSG_STATE
15#define OSG_STATE 1
16
17#include <osg/Export>
18#include <osg/StateSet>
19#include <osg/Matrix>
20#include <osg/Uniform>
21#include <osg/BufferObject>
22
23#include <osg/FrameStamp>
24#include <osg/DisplaySettings>
25#include <osg/Polytope>
26#include <osg/Viewport>
27
28#include <vector>
29#include <map>
30#include <set>
31#include <string>
32
33#ifndef GL_TEXTURE0
34#define GL_TEXTURE0 0x84C0
35#endif
36
37#ifndef GL_FOG_COORDINATE_ARRAY
38    #ifdef GL_FOG_COORDINATE_ARRAY_EXT
39        #define GL_FOG_COORDINATE_ARRAY GL_FOG_COORDINATE_ARRAY_EXT
40    #else
41         #define GL_FOG_COORDINATE_ARRAY 0x8457
42    #endif
43#endif
44
45#ifndef GL_SECONDARY_COLOR_ARRAY
46    #ifdef GL_SECONDARY_COLOR_ARRAY_EXT
47        #define GL_SECONDARY_COLOR_ARRAY GL_SECONDARY_COLOR_ARRAY_EXT
48    #else
49         #define GL_SECONDARY_COLOR_ARRAY 0x845E
50    #endif
51#endif
52
53namespace osg {
54
55/** macro for use with osg::StateAttribute::apply methods for detecting and
56  * reporting OpenGL error messages.*/
57#define OSG_GL_DEBUG(message) \
58    if (state.getFineGrainedErrorDetection()) \
59    { \
60        GLenum errorNo = glGetError(); \
61        if (errorNo!=GL_NO_ERROR) \
62        { \
63            osg::notify(WARN)<<"Warning: detected OpenGL error '"<<gluErrorString(errorNo)<<" "<<message<<endl; \
64        }\
65    }
66
67
68// forward declare GraphicsContext, View and State
69class GraphicsContext;
70
71/** Encapsulates the current applied OpenGL modes, attributes and vertex arrays settings,
72  * implements lazy state updating and provides accessors for querying the current state.
73  * The venerable Red Book says that "OpenGL is a state machine", and this class
74  * represents the OpenGL state in OSG. Furthermore, \c State also has other
75  * important features:
76  * - It works as a stack of states (see \c pushStateSet() and
77  *   \c popStateSet()). Manipulating this stack of OpenGL states manually is
78  *   seldom needed, since OSG does this in the most common situations.
79  * - It implements lazy state updating. This means that, if one requests a
80  *   state change and that particular state is already in the requested state,
81  *   no OpenGL call will be made. This ensures that the OpenGL pipeline is not
82  *   stalled by unnecessary state changes.
83  * - It allows to query the current OpenGL state without calls to \c glGet*(),
84  *   which typically stall the graphics pipeline (see, for instance,
85  *   \c captureCurrentState() and \c getModelViewMatrix()).
86  */
87class OSG_EXPORT State : public Referenced
88{
89    public :
90
91        State();
92       
93
94        /** Set the graphics context associated with that owns this State object.*/       
95        void setGraphicsContext(GraphicsContext* context) { _graphicsContext = context; }
96
97        /** Get the graphics context associated with that owns this State object.*/       
98        GraphicsContext* getGraphicsContext() { return _graphicsContext; }
99
100        /** Get the const graphics context associated with that owns this State object.*/       
101        const GraphicsContext* getGraphicsContext() const { return _graphicsContext; }
102       
103
104        /** Set the current OpenGL context uniqueID.
105            Note, it is the application developers responsibility to
106            set up unique ID for each OpenGL context.  This value is
107            then used by osg::StateAttribute's and osg::Drawable's to
108            help manage OpenGL display list and texture binds appropriate
109            for each context, the contextID simply acts as an index in local
110            arrays that they maintain for the purpose.
111            Typical settings for contextID are 0,1,2,3... up to the maximum
112            number of graphics contexts you have set up.
113            By default contextID is 0.*/
114        inline void setContextID(unsigned int contextID) { _contextID=contextID; }
115
116        /** Get the current OpenGL context unique ID.*/
117        inline unsigned int getContextID() const { return _contextID; }
118
119        /** Push stateset onto state stack.*/
120        void pushStateSet(const StateSet* dstate);
121
122        /** Pop stateset off state stack.*/
123        void popStateSet();
124       
125        /** pop all statesets off state stack, ensuring it is empty ready for the next frame.
126          * Note, to return OpenGL to default state, one should do any state.popAllStatSets(); state.apply().*/
127        void popAllStateSets();
128
129        /** Insert stateset onto state stack.*/
130        void insertStateSet(unsigned int pos,const StateSet* dstate);
131
132        /** Pop stateset off state stack.*/
133        void removeStateSet(unsigned int pos);
134       
135        /** Get the number of StateSet's on the StateSet stack.*/
136        unsigned int getStateSetStackSize() { return _stateStateStack.size(); }
137       
138        /** Pop StateSet's for the StateSet stack till its size equals the specified size.*/
139        void popStateSetStackToSize(unsigned int size) { while (_stateStateStack.size()>size) popStateSet(); }
140
141        typedef std::vector<const StateSet*> StateSetStack;
142
143        /** Get the StateSet stack.*/
144        StateSetStack& getStateSetStack() { return _stateStateStack; }
145       
146
147        /** Copy the modes and attributes which capture the current state.*/
148        void captureCurrentState(StateSet& stateset) const;
149
150        /** reset the state object to an empty stack.*/
151        void reset();
152
153        inline const Viewport* getCurrentViewport() const
154        {
155            return static_cast<const Viewport*>(getLastAppliedAttribute(osg::StateAttribute::VIEWPORT));
156        }
157
158
159        void setInitialViewMatrix(const osg::RefMatrix* matrix);
160
161        inline const osg::Matrix& getInitialViewMatrix() const { return *_initialViewMatrix; }
162        inline const osg::Matrix& getInitialInverseViewMatrix() const { return _initialInverseViewMatrix; }
163
164        inline void applyProjectionMatrix(const osg::RefMatrix* matrix)
165        {
166            if (_projection!=matrix)
167            {
168                glMatrixMode( GL_PROJECTION );
169                if (matrix)
170                {
171                    _projection=matrix;
172                    glLoadMatrix(matrix->ptr());
173                }
174                else
175                {
176                    _projection=_identity;
177                    glLoadIdentity();
178                }
179                glMatrixMode( GL_MODELVIEW );
180            }
181        }
182
183        inline const osg::Matrix& getProjectionMatrix() const
184        {
185            return *_projection;
186        }
187
188        inline void applyModelViewMatrix(const osg::RefMatrix* matrix)
189        {
190            if (_modelView!=matrix)
191            {
192                if (matrix)
193                {
194                    _modelView=matrix;
195                    glLoadMatrix(matrix->ptr());
196                }
197                else
198                {
199                    _modelView=_identity;
200                    glLoadIdentity();
201                }
202            }
203        }
204
205        const osg::Matrix& getModelViewMatrix() const
206        {
207            return *_modelView;
208        }
209
210
211        Polytope getViewFrustum() const;
212
213
214        /** Apply stateset.*/
215        void apply(const StateSet* dstate);
216
217        /** Updates the OpenGL state so that it matches the \c StateSet at the
218          * top of the stack of <tt>StateSet</tt>s maintained internally by a
219          * \c State.
220         */
221        void apply();
222
223
224        /** Set whether a particular OpenGL mode is valid in the current graphics context.
225          * Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
226        inline void setModeValidity(StateAttribute::GLMode mode,bool valid)
227        {
228            ModeStack& ms = _modeMap[mode];
229            ms.valid = valid;
230        }
231
232        /** Get whether a particular OpenGL mode is valid in the current graphics context.
233          * Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
234        inline bool getModeValidity(StateAttribute::GLMode mode)
235        {
236            ModeStack& ms = _modeMap[mode];
237            return ms.valid;
238        }
239
240        inline void setGlobalDefaultModeValue(StateAttribute::GLMode mode,bool enabled)
241        {
242            ModeStack& ms = _modeMap[mode];
243            ms.global_default_value = enabled;
244        }
245
246        inline bool getGlobalDefaultModeValue(StateAttribute::GLMode mode)
247        {
248            return _modeMap[mode].global_default_value;
249        }
250
251
252        /** Apply an OpenGL mode if required. This is a wrapper around
253          * \c glEnable() and \c glDisable(), that just actually calls these
254          * functions if the \c enabled flag is different than the current
255          * state.
256          * @return \c true if the state was actually changed. \c false
257          *         otherwise. Notice that a \c false return does not indicate
258          *         an error, it just means that the mode was already set to the
259          *         same value as the \c enabled parameter.
260        */
261        inline bool applyMode(StateAttribute::GLMode mode,bool enabled)
262        {
263            ModeStack& ms = _modeMap[mode];
264            ms.changed = true;
265            return applyMode(mode,enabled,ms);
266        }
267
268        inline void setGlobalDefaultTextureModeValue(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
269        {
270            ModeMap& modeMap = getOrCreateTextureModeMap(unit);
271            ModeStack& ms = modeMap[mode];
272            ms.global_default_value = enabled;
273        }
274
275        inline bool getGlobalDefaultTextureModeValue(unsigned int unit, StateAttribute::GLMode mode)
276        {
277            ModeMap& modeMap = getOrCreateTextureModeMap(unit);
278            ModeStack& ms = modeMap[mode];
279            return ms.global_default_value;
280        }
281
282        inline bool applyTextureMode(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
283        {
284            if (setActiveTextureUnit(unit))
285            {
286                ModeMap& modeMap = getOrCreateTextureModeMap(unit);
287                ModeStack& ms = modeMap[mode];
288                ms.changed = true;
289                return applyMode(mode,enabled,ms);
290            }
291            else
292                return false;
293        }
294
295        inline void setGlobalDefaultAttribute(const StateAttribute* attribute)
296        {
297            AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
298            as.global_default_attribute = attribute;
299        }
300
301        inline const StateAttribute* getGlobalDefaultAttribute(StateAttribute::Type type, unsigned int member=0)
302        {
303            AttributeStack& as = _attributeMap[StateAttribute::TypeMemberPair(type,member)];
304            return as.global_default_attribute.get();
305        }
306
307        /** Apply an attribute if required. */
308        inline bool applyAttribute(const StateAttribute* attribute)
309        {
310            AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
311            as.changed = true;
312            return applyAttribute(attribute,as);
313        }
314
315        inline void setGlobalDefaultTextureAttribute(unsigned int unit, const StateAttribute* attribute)
316        {
317            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
318            AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
319            as.global_default_attribute = attribute;
320        }
321
322        inline const StateAttribute* getGlobalDefaultTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member = 0)
323        {
324            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
325            AttributeStack& as = attributeMap[StateAttribute::TypeMemberPair(type,member)];
326            return as.global_default_attribute.get();
327        }
328
329
330        inline bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
331        {
332            if (setActiveTextureUnit(unit))
333            {
334                AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
335                AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
336                as.changed = true;
337                return applyAttribute(attribute,as);
338            }
339            else
340                return false;
341        }
342
343        /** Mode has been set externally, update state to reflect this setting.*/
344        void haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
345
346        /** Mode has been set externally, therefore dirty the associated mode in osg::State
347          * so it is applied on next call to osg::State::apply(..)*/
348        void haveAppliedMode(StateAttribute::GLMode mode);
349
350        /** Attribute has been applied externally, update state to reflect this setting.*/
351        void haveAppliedAttribute(const StateAttribute* attribute);
352
353        /** Attribute has been applied externally,
354          * and therefore this attribute type has been dirtied
355          * and will need to be re-applied on next osg::State.apply(..).
356          * note, if you have an osg::StateAttribute which you have applied externally
357          * then use the have_applied(attribute) method as this will cause the osg::State to
358          * track the current state more accurately and enable lazy state updating such
359          * that only changed state will be applied.*/
360        void haveAppliedAttribute(StateAttribute::Type type, unsigned int member=0);
361
362        /** Get whether the current specified mode is enabled (true) or disabled (false).*/
363        bool getLastAppliedMode(StateAttribute::GLMode mode) const;
364
365        /** Get the current specified attribute, return NULL if one has not yet been applied.*/
366        const StateAttribute* getLastAppliedAttribute(StateAttribute::Type type, unsigned int member=0) const;
367
368        /** texture Mode has been set externally, update state to reflect this setting.*/
369        void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
370
371        /** texture Mode has been set externally, therefore dirty the associated mode in osg::State
372          * so it is applied on next call to osg::State::apply(..)*/
373        void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode);
374
375        /** texture Attribute has been applied externally, update state to reflect this setting.*/
376        void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute* attribute);
377
378        /** texture Attribute has been applied externally,
379          * and therefore this attribute type has been dirtied
380          * and will need to be re-applied on next osg::State.apply(..).
381          * note, if you have an osg::StateAttribute which you have applied externally
382          * then use the have_applied(attribute) method as this will the osg::State to
383          * track the current state more accurately and enable lazy state updating such
384          * that only changed state will be applied.*/
385        void haveAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0);
386
387        /** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
388        bool getLastAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode) const;
389
390        /** Get the current specified texture attribute, return NULL if one has not yet been applied.*/
391        const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0) const;
392
393
394        /** Dirty the modes previously applied in osg::State.*/
395        void dirtyAllModes();
396
397        /** Dirty the modes attributes previously applied in osg::State.*/
398        void dirtyAllAttributes();
399
400        /** disable the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
401        void disableAllVertexArrays();
402
403        /** dirty the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
404        void dirtyAllVertexArrays();
405
406
407        void setCurrentVertexBufferObject(osg::VertexBufferObject* vbo) { _currentVBO = vbo; }
408        const VertexBufferObject* getCurrentVertexBufferObject() { return _currentVBO; }
409        inline void bindVertexBufferObject(const osg::VertexBufferObject* vbo)
410        {
411            if (vbo == _currentVBO) return;
412            if (vbo->isDirty(_contextID)) vbo->compileBuffer(*this);
413            else _glBindBuffer(GL_ARRAY_BUFFER_ARB,vbo->buffer(_contextID));
414            _currentVBO = vbo;
415        }
416
417        inline void unbindVertexBufferObject()
418        {
419            if (!_currentVBO) return;
420            _glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
421            _currentVBO = 0;
422        }
423
424        void setCurrentElementBufferObject(osg::ElementBufferObject* ebo) { _currentEBO = ebo; }
425        const ElementBufferObject* getCurrentElementBufferObject() { return _currentEBO; }
426
427        inline void bindElementBufferObject(const osg::ElementBufferObject* ebo)
428        {
429            if (ebo == _currentEBO) return;
430            if (ebo->isDirty(_contextID)) ebo->compileBuffer(*this);
431            else _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,ebo->buffer(_contextID));
432            _currentEBO = ebo;
433        }
434
435        inline void unbindElementBufferObject()
436        {
437            if (!_currentEBO) return;
438            _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
439            _currentEBO = 0;
440        }
441
442        void setCurrentPixelBufferObject(osg::PixelBufferObject* pbo) { _currentPBO = pbo; }
443        const PixelBufferObject* getCurrentPixelBufferObject() { return _currentPBO; }
444
445        inline void bindPixelBufferObject(const osg::PixelBufferObject* pbo)
446        {
447            if (pbo == _currentPBO) return;
448
449            if (pbo->isDirty(_contextID)) pbo->compileBuffer(*this);
450            else _glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,pbo->buffer(_contextID));
451
452            _currentPBO = pbo;
453        }
454
455        inline void unbindPixelBufferObject()
456        {
457            if (!_currentPBO) return;
458           
459            _glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
460            _currentPBO = 0;
461        }
462
463        /** Wrapper around glInterleavedArrays(..).
464          * also resets the internal array points and modes within osg::State to keep the other
465          * vertex array operations consistent. */
466        void setInterleavedArrays( GLenum format, GLsizei stride, const GLvoid* pointer);
467
468        /** Set the vertex pointer using an osg::Array, and manage any VBO that are required.*/
469        inline void setVertexPointer(const Array* array)
470        {
471            if (array)
472            {
473                const VertexBufferObject* vbo = array->getVertexBufferObject();
474                if (vbo)
475                {
476                    bindVertexBufferObject(vbo);
477                    setVertexPointer(array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
478                }
479                else
480                {
481                    unbindVertexBufferObject();
482                    setVertexPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
483                }
484            }
485            else disableVertexPointer();
486        }
487
488        /** wrapper around glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(..);
489          * note, only updates values that change.*/
490        inline void setVertexPointer( GLint size, GLenum type,
491                                      GLsizei stride, const GLvoid *ptr )
492        {
493            if (!_vertexArray._enabled || _vertexArray._dirty)
494            {
495                _vertexArray._enabled = true;
496                glEnableClientState(GL_VERTEX_ARRAY);
497            }
498            //if (_vertexArray._pointer!=ptr || _vertexArray._dirty)
499            {
500                _vertexArray._pointer=ptr;
501                glVertexPointer( size, type, stride, ptr );
502            }
503            _vertexArray._dirty = false;
504        }
505
506        /** wrapper around glDisableClientState(GL_VERTEX_ARRAY).
507          * note, only updates values that change.*/
508        inline void disableVertexPointer()
509        {
510            if (_vertexArray._enabled || _vertexArray._dirty)
511            {
512                _vertexArray._enabled = false;
513                _vertexArray._dirty = false;
514                glDisableClientState(GL_VERTEX_ARRAY);
515            }
516        }
517
518        inline void dirtyVertexPointer()
519        {
520            _vertexArray._pointer = 0;
521            _vertexArray._dirty = true;
522        }
523
524
525        /** Set the normal pointer using an osg::Array, and manage any VBO that are required.*/
526        inline void setNormalPointer(const Array* array)
527        {
528            if (array)
529            {
530                const VertexBufferObject* vbo = array->getVertexBufferObject();
531                if (vbo)
532                {
533                    bindVertexBufferObject(vbo);
534                   setNormalPointer(array->getDataType(),0,array->getVertexBufferObjectOffset());
535                }
536                else
537                {
538                    unbindVertexBufferObject();
539                    setNormalPointer(array->getDataType(),0,array->getDataPointer());
540                }
541            }
542            else disableNormalPointer();
543        }
544
545        /** wrapper around glEnableClientState(GL_NORMAL_ARRAY);glNormalPointer(..);
546          * note, only updates values that change.*/
547        inline void setNormalPointer( GLenum type, GLsizei stride,
548                                      const GLvoid *ptr )
549        {
550            if (!_normalArray._enabled || _normalArray._dirty)
551            {
552                _normalArray._enabled = true;
553                glEnableClientState(GL_NORMAL_ARRAY);
554            }
555            //if (_normalArray._pointer!=ptr || _normalArray._dirty)
556            {
557                _normalArray._pointer=ptr;
558                glNormalPointer( type, stride, ptr );
559            }
560            _normalArray._dirty = false;
561        }
562
563        /** wrapper around glDisableClientState(GL_NORMAL_ARRAY);
564          * note, only updates values that change.*/
565        inline void disableNormalPointer()
566        {
567            if (_normalArray._enabled || _normalArray._dirty)
568            {
569                _normalArray._enabled = false;
570                _normalArray._dirty = false;
571                glDisableClientState(GL_NORMAL_ARRAY);
572            }
573        }
574
575        inline void dirtyNormalPointer()
576        {
577            _normalArray._pointer = 0;
578            _normalArray._dirty = true;
579        }
580
581        /** Set the color pointer using an osg::Array, and manage any VBO that are required.*/
582        inline void setColorPointer(const Array* array)
583        {
584            if (array)
585            {
586                const VertexBufferObject* vbo = array->getVertexBufferObject();
587                if (vbo)
588                {
589                    bindVertexBufferObject(vbo);
590                    setColorPointer(array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
591                }
592                else
593                {
594                    unbindVertexBufferObject();
595                    setColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
596                }
597            }
598            else disableColorPointer();
599        }
600
601
602        /** wrapper around glEnableClientState(GL_COLOR_ARRAY);glColorPointer(..);
603          * note, only updates values that change.*/
604        inline void setColorPointer( GLint size, GLenum type,
605                                     GLsizei stride, const GLvoid *ptr )
606        {
607            if (!_colorArray._enabled || _colorArray._dirty)
608            {
609                _colorArray._enabled = true;
610                glEnableClientState(GL_COLOR_ARRAY);
611            }
612            //if (_colorArray._pointer!=ptr || _colorArray._dirty)
613            {
614                _colorArray._pointer=ptr;
615                glColorPointer( size, type, stride, ptr );
616            }
617            _colorArray._dirty = false;
618        }
619
620        /** wrapper around glDisableClientState(GL_COLOR_ARRAY);
621          * note, only updates values that change.*/
622        inline void disableColorPointer()
623        {
624            if (_colorArray._enabled || _colorArray._dirty)
625            {
626                _colorArray._enabled = false;
627                _colorArray._dirty = false;
628                glDisableClientState(GL_COLOR_ARRAY);
629            }
630        }
631
632        inline void dirtyColorPointer()
633        {
634            _colorArray._pointer = 0;
635            _colorArray._dirty = true;
636        }
637
638
639        inline bool isSecondaryColorSupported() const { return _isSecondaryColorSupportResolved?_isSecondaryColorSupported:computeSecondaryColorSupported(); }
640
641
642        /** Set the secondary color pointer using an osg::Array, and manage any VBO that are required.*/
643        inline void setSecondaryColorPointer(const Array* array)
644        {
645            if (array)
646            {
647                const VertexBufferObject* vbo = array->getVertexBufferObject();
648                if (vbo)
649                {
650                    bindVertexBufferObject(vbo);
651#if 0                   
652                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,vbo->getOffset(array->getVertexBufferObjectIndex()));
653#else
654                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
655#endif
656                }
657                else
658                {
659                    unbindVertexBufferObject();
660                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
661                }
662            }
663            else disableSecondaryColorPointer();
664        }
665
666        /** wrapper around glEnableClientState(GL_SECONDARY_COLOR_ARRAY);glSecondayColorPointer(..);
667          * note, only updates values that change.*/
668        void setSecondaryColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr );
669
670        /** wrapper around glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
671          * note, only updates values that change.*/
672        inline void disableSecondaryColorPointer()
673        {
674            if (_secondaryColorArray._enabled || _secondaryColorArray._dirty)
675            {
676                _secondaryColorArray._enabled = false;
677                _secondaryColorArray._dirty = false;
678                if (isSecondaryColorSupported()) glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
679            }
680        }
681
682        inline void dirtySecondaryColorPointer()
683        {
684            _secondaryColorArray._pointer = 0;
685            _secondaryColorArray._dirty = true;
686        }
687
688        /** wrapper around glEnableClientState(GL_INDEX_ARRAY);glIndexPointer(..);
689          * note, only updates values that change.*/
690        inline void setIndexPointer( GLenum type, GLsizei stride,
691                              const GLvoid *ptr )
692        {
693            if (!_indexArray._enabled || _indexArray._dirty)
694            {
695                _indexArray._enabled = true;
696                glEnableClientState(GL_INDEX_ARRAY);
697            }
698            //if (_indexArray._pointer!=ptr || _indexArray._dirty)
699            {
700                _indexArray._pointer=ptr;
701                glIndexPointer( type, stride, ptr );
702            }
703            _indexArray._dirty = false;
704        }
705
706        /** wrapper around glDisableClientState(GL_INDEX_ARRAY);
707          * note, only updates values that change.*/
708        inline void disableIndexPointer()
709        {
710            if (_indexArray._enabled || _indexArray._dirty)
711            {
712                _indexArray._enabled = false;
713                _indexArray._dirty = false;
714                glDisableClientState(GL_INDEX_ARRAY);
715            }
716        }
717
718        inline void dirtyIndexPointer()
719        {
720            _indexArray._pointer = 0;
721            _indexArray._dirty = true;
722        }
723
724
725        inline bool isFogCoordSupported() const { return _isFogCoordSupportResolved?_isFogCoordSupported:computeFogCoordSupported(); }
726
727
728        /** Set the fog coord pointer using an osg::Array, and manage any VBO that are required.*/
729        inline void setFogCoordPointer(const Array* array)
730        {
731            if (array)
732            {
733                const VertexBufferObject* vbo = array->getVertexBufferObject();
734                if (vbo)
735                {
736                    bindVertexBufferObject(vbo);
737#if 0
738                    setFogCoordPointer(array->getDataType(),0,vbo->getOffset(array->getVertexBufferObjectIndex()));
739#else
740                    setFogCoordPointer(array->getDataType(),0,array->getVertexBufferObjectOffset());
741#endif
742                }
743                else
744                {
745                    unbindVertexBufferObject();
746                    setFogCoordPointer(array->getDataType(),0,array->getDataPointer());
747                }
748            }
749            else disableFogCoordPointer();
750        }
751
752
753        /** wrapper around glEnableClientState(GL_FOG_COORDINATE_ARRAY);glFogCoordPointer(..);
754          * note, only updates values that change.*/
755        void setFogCoordPointer( GLenum type, GLsizei stride, const GLvoid *ptr );
756
757        /** wrapper around glDisableClientState(GL_FOG_COORDINATE_ARRAY);
758          * note, only updates values that change.*/
759        inline void disableFogCoordPointer()
760        {
761            if (_fogArray._enabled || _fogArray._dirty)
762            {
763                _fogArray._enabled = false;
764                _fogArray._dirty = false;
765                if (isFogCoordSupported()) glDisableClientState(GL_FOG_COORDINATE_ARRAY);
766            }
767        }
768
769        inline void dirtyFogCoordPointer()
770        {
771            _fogArray._pointer = 0;
772            _fogArray._dirty = true;
773        }
774
775
776
777        /** Set the tex coord pointer using an osg::Array, and manage any VBO that are required.*/
778        inline void setTexCoordPointer(unsigned int unit, const Array* array)
779        {
780            if (array)
781            {
782                const VertexBufferObject* vbo = array->getVertexBufferObject();
783                if (vbo)
784                {
785                    bindVertexBufferObject(vbo);
786#if 0
787                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,vbo->getOffset(array->getVertexBufferObjectIndex()));
788#else
789                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
790#endif
791                }
792                else
793                {
794                    unbindVertexBufferObject();
795                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,array->getDataPointer());
796                }
797            }
798            else disableTexCoordPointer(unit);
799        }
800
801        /** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..);
802          * note, only updates values that change.*/
803        inline void setTexCoordPointer( unsigned int unit,
804                                        GLint size, GLenum type,
805                                        GLsizei stride, const GLvoid *ptr )
806        {
807            if (setClientActiveTextureUnit(unit))
808            {
809                if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
810                EnabledArrayPair& eap = _texCoordArrayList[unit];
811
812                if (!eap._enabled || eap._dirty)
813                {
814                    eap._enabled = true;
815                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
816                }
817                //if (eap._pointer!=ptr || eap._dirty)
818                {
819                    glTexCoordPointer( size, type, stride, ptr );
820                    eap._pointer = ptr;
821                }
822                eap._dirty = false;
823            }
824        }
825
826        /** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
827          * note, only updates values that change.*/
828        inline void disableTexCoordPointer( unsigned int unit )
829        {
830            if (setClientActiveTextureUnit(unit))
831            {
832                if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
833                EnabledArrayPair& eap = _texCoordArrayList[unit];
834
835                if (eap._enabled || eap._dirty)
836                {
837                    eap._enabled = false;
838                    eap._dirty = false;
839                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
840                }
841            }
842        }
843
844        inline void dirtyTexCoordPointer( unsigned int unit )
845        {
846            if ( unit >= _texCoordArrayList.size()) return; // _texCoordArrayList.resize(unit+1);
847            EnabledArrayPair& eap = _texCoordArrayList[unit];
848            eap._pointer = 0;
849            eap._dirty = true;
850        }
851
852
853        inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit )
854        {
855            while (unit<_texCoordArrayList.size())
856            {
857                EnabledArrayPair& eap = _texCoordArrayList[unit];
858                if (eap._enabled || eap._dirty)
859                {
860                    if (setClientActiveTextureUnit(unit))
861                    {
862                        eap._enabled = false;
863                        eap._dirty = false;
864                        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
865                    }
866                }
867                ++unit;
868            }
869        }
870
871        inline void dirtyTexCoordPointersAboveAndIncluding( unsigned int unit )
872        {
873            while (unit<_texCoordArrayList.size())
874            {
875                EnabledArrayPair& eap = _texCoordArrayList[unit];
876                eap._pointer = 0;
877                eap._dirty = true;
878                ++unit;
879            }
880        }
881
882
883        /** Set the current texture unit, return true if selected,
884          * false if selection failed such as when multi texturing is not supported.
885          * note, only updates values that change.*/
886        bool setActiveTextureUnit( unsigned int unit );
887       
888        /** Get the current texture unit.*/
889        unsigned int getActiveTextureUnit() const { return _currentActiveTextureUnit; }
890
891        /** Set the current tex coord array texture unit, return true if selected,
892          * false if selection failed such as when multi texturing is not supported.
893          * note, only updates values that change.*/
894        bool setClientActiveTextureUnit( unsigned int unit );
895
896        /** Get the current tex coord array texture unit.*/
897        unsigned int getClientActiveTextureUnit() const { return _currentClientActiveTextureUnit; }
898
899        /** Set the vertex attrib pointer using an osg::Array, and manage any VBO that are required.*/
900        inline void setVertexAttribPointer(unsigned int unit, const Array* array, GLboolean normalized)
901        {
902            if (array)
903            {
904                const VertexBufferObject* vbo = array->getVertexBufferObject();
905                if (vbo)
906                {
907                    bindVertexBufferObject(vbo);
908#if 0                   
909                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,vbo->getOffset(array->getVertexBufferObjectIndex()));
910#else
911                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,array->getVertexBufferObjectOffset());
912#endif
913                }
914                else
915                {
916                    unbindVertexBufferObject();
917                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,array->getDataPointer());
918                }
919            }
920            else disableVertexAttribPointer(unit);
921        }
922
923        /** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..);
924          * note, only updates values that change.*/
925        void setVertexAttribPointer( unsigned int index,
926                                     GLint size, GLenum type, GLboolean normalized,
927                                     GLsizei stride, const GLvoid *ptr );
928
929        /** wrapper around DisableVertexAttribArrayARB(index);
930          * note, only updates values that change.*/
931        void disableVertexAttribPointer( unsigned int index );
932
933        void disableVertexAttribPointersAboveAndIncluding( unsigned int index );
934
935        inline void dirtyVertexAttribPointersAboveAndIncluding( unsigned int index )
936        {
937            while (index<_vertexAttribArrayList.size())
938            {
939                EnabledArrayPair& eap = _vertexAttribArrayList[index];
940                eap._pointer = 0;
941                eap._dirty = true;
942                ++index;
943            }
944        }
945
946        bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); }
947
948
949        void setLastAppliedProgramObject(const Program::PerContextProgram* program) { if (_lastAppliedProgramObject!=program) { _lastAppliedProgramObject = program; if (program) _appliedProgramObjectSet.insert(program); } }
950        const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; }
951
952        inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; }
953        inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; }
954
955
956        /** Set the frame stamp for the current frame.*/
957        inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
958
959        /** Get the frame stamp for the current frame.*/
960        inline FrameStamp* getFrameStamp() { return _frameStamp.get(); }
961
962        /** Get the const frame stamp for the current frame.*/
963        inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
964
965
966        /** Set the DisplaySettings. Note, nothing is applied, the visual settings are just
967          * used in the State object to pass the current visual settings to Drawables
968          * during rendering. */
969        inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
970
971        /** Get the DisplaySettings */
972        inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
973
974
975
976        /** Set flag for early termination of the draw traversal.*/
977        void setAbortRenderingPtr(bool* abortPtr) { _abortRenderingPtr = abortPtr; }
978
979        /** Get flag for early termination of the draw traversal,
980          * if true steps should be taken to complete rendering early.*/
981        bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
982
983
984        struct DynamicObjectRenderingCompletedCallback : public osg::Referenced
985        {
986            virtual void completed(osg::State*) = 0;
987        };
988       
989        /** Set the callback to be called when the dynamic object count hits 0.*/
990        void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; }
991       
992        /** Get the callback to be called when the dynamic object count hits 0.*/
993        DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); }
994       
995        /** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/
996        void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false)
997        {
998            if (_dynamicObjectCount != count)
999            {
1000                _dynamicObjectCount = count;
1001                if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid())
1002                {
1003                    _completeDynamicObjectRenderingCallback->completed(this);
1004                }
1005            }
1006        }
1007
1008        /** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/
1009        unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; }
1010       
1011        /** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the
1012          * DynamicObjectRenderingCompletedCallback to inform of completion.*/
1013        inline void decrementDynamicObjectCount()
1014        {
1015            --_dynamicObjectCount;
1016            if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid())
1017            {
1018                _completeDynamicObjectRenderingCallback->completed(this);
1019            }
1020        }
1021
1022
1023
1024        enum CheckForGLErrors
1025        {
1026            /** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
1027                is the fastest option since checking for errors does incurr a small overhead.*/
1028            NEVER_CHECK_GL_ERRORS,
1029            /** ONCE_PER_FRAME means that OpenGl errors will be checked for once per
1030                frame, the overhead is still small, but at least OpenGL errors that are occurring
1031                will be caught, the reporting isn't fine grained enough for debugging purposes.*/
1032            ONCE_PER_FRAME,
1033            /** ONCE_PER_ATTRIBUTE means that OpenGL errors will be checked for after
1034                every attribute is applied, allow errors to be directly associated with
1035                particular operations which makes debugging much easier.*/
1036            ONCE_PER_ATTRIBUTE
1037        };
1038
1039        /** Set whether and how often OpenGL errors should be checked for.*/
1040        void setCheckForGLErrors(CheckForGLErrors check) { _checkGLErrors = check; }
1041
1042        /** Get whether and how often OpenGL errors should be checked for.*/
1043        CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
1044
1045        bool checkGLErrors(const char* str) const;
1046        bool checkGLErrors(StateAttribute::GLMode mode) const;
1047        bool checkGLErrors(const StateAttribute* attribute) const;
1048
1049
1050        /** Initialize extension used by osg:::State.*/
1051        void initializeExtensionProcs();
1052
1053    protected:
1054
1055        virtual ~State();
1056
1057        GraphicsContext*            _graphicsContext;
1058        unsigned int                _contextID;
1059        ref_ptr<FrameStamp>         _frameStamp;
1060
1061        ref_ptr<const RefMatrix>    _identity;
1062        ref_ptr<const RefMatrix>    _initialViewMatrix;
1063        ref_ptr<const RefMatrix>    _projection;
1064        ref_ptr<const RefMatrix>    _modelView;
1065
1066        Matrix                      _initialInverseViewMatrix;
1067
1068        ref_ptr<DisplaySettings>    _displaySettings;
1069
1070        bool*                       _abortRenderingPtr;
1071        CheckForGLErrors            _checkGLErrors;
1072
1073        struct ModeStack
1074        {
1075            typedef std::vector<StateAttribute::GLModeValue> ValueVec;
1076
1077            ModeStack()
1078            {
1079                valid = true;
1080                changed = false;
1081                last_applied_value = false;
1082                global_default_value = false;
1083            }
1084
1085            bool        valid;
1086            bool        changed;
1087            bool        last_applied_value;
1088            bool        global_default_value;
1089            ValueVec    valueVec;
1090        };
1091
1092        struct AttributeStack
1093        {
1094            typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue>  AttributePair;
1095            typedef std::vector<AttributePair>                                      AttributeVec;
1096
1097            AttributeStack()
1098            {
1099                changed = false;
1100                last_applied_attribute = 0L;
1101                global_default_attribute = 0L;
1102            }
1103
1104            /** apply an attribute if required, passing in attribute and appropriate attribute stack */
1105            bool                    changed;
1106            const StateAttribute*   last_applied_attribute;
1107            ref_ptr<const StateAttribute> global_default_attribute;
1108            AttributeVec            attributeVec;
1109        };
1110
1111
1112        struct UniformStack
1113        {
1114            typedef std::pair<const Uniform*,StateAttribute::OverrideValue>         UniformPair;
1115            typedef std::vector<UniformPair>                                        UniformVec;
1116
1117            UniformStack() {}
1118
1119            UniformVec              uniformVec;
1120        };
1121
1122
1123        /** Apply an OpenGL mode if required, passing in mode, enable flag and
1124          * appropriate mode stack. This is a wrapper around \c glEnable() and
1125          * \c glDisable(), that just actually calls these functions if the
1126          * \c enabled flag is different than the current state.
1127          * @return \c true if the state was actually changed. \c false
1128          *         otherwise. Notice that a \c false return does not indicate
1129          *         an error, it just means that the mode was already set to the
1130          *         same value as the \c enabled parameter.
1131        */
1132        inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
1133        {
1134            if (ms.valid && ms.last_applied_value != enabled)
1135            {
1136                ms.last_applied_value = enabled;
1137
1138                if (enabled) glEnable(mode);
1139                else glDisable(mode);
1140
1141                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
1142
1143                return true;
1144            }
1145            else
1146                return false;
1147        }
1148
1149
1150        /** apply an attribute if required, passing in attribute and appropriate attribute stack */
1151        inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
1152        {
1153            if (as.last_applied_attribute != attribute)
1154            {
1155                if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
1156
1157                as.last_applied_attribute = attribute;
1158                attribute->apply(*this);
1159
1160                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
1161
1162                return true;
1163            }
1164            else
1165                return false;
1166        }
1167
1168        inline bool applyGlobalDefaultAttribute(AttributeStack& as)
1169        {
1170            if (as.last_applied_attribute != as.global_default_attribute.get())
1171            {
1172                as.last_applied_attribute = as.global_default_attribute.get();
1173                if (as.global_default_attribute.valid())
1174                {
1175                    as.global_default_attribute->apply(*this);
1176                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
1177                }
1178                return true;
1179            }
1180            else
1181                return false;
1182        }
1183
1184
1185        typedef std::map<StateAttribute::GLMode,ModeStack>              ModeMap;
1186        typedef std::vector<ModeMap>                                    TextureModeMapList;
1187
1188        typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
1189        typedef std::vector<AttributeMap>                               TextureAttributeMapList;
1190
1191        typedef std::map<std::string,UniformStack>                      UniformMap;
1192
1193        typedef std::vector<ref_ptr<const Matrix> >                     MatrixStack;
1194       
1195        typedef std::set<osg::ref_ptr<const Program::PerContextProgram> > AppliedProgramObjectSet;
1196
1197        ModeMap                                                         _modeMap;
1198        AttributeMap                                                    _attributeMap;
1199        UniformMap                                                      _uniformMap;
1200
1201        TextureModeMapList                                              _textureModeMapList;
1202        TextureAttributeMapList                                         _textureAttributeMapList;
1203
1204        AppliedProgramObjectSet                                         _appliedProgramObjectSet;
1205        const Program::PerContextProgram*                               _lastAppliedProgramObject;
1206
1207        StateSetStack                                                   _stateStateStack;
1208
1209        struct EnabledArrayPair
1210        {
1211            EnabledArrayPair():_dirty(true),_enabled(false),_normalized(0),_pointer(0) {}
1212            EnabledArrayPair(const EnabledArrayPair& eap):_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {}
1213            EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; }
1214
1215            bool            _dirty;
1216            bool            _enabled;
1217            GLboolean       _normalized;
1218            const GLvoid*   _pointer;
1219        };
1220
1221        typedef std::vector<EnabledArrayPair>                   EnabledTexCoordArrayList;
1222        typedef std::vector<EnabledArrayPair>                   EnabledVertexAttribArrayList;
1223
1224        EnabledArrayPair                _vertexArray;
1225        EnabledArrayPair                _normalArray;
1226        EnabledArrayPair                _colorArray;
1227        EnabledArrayPair                _secondaryColorArray;
1228        EnabledArrayPair                _indexArray;
1229        EnabledArrayPair                _fogArray;
1230        EnabledTexCoordArrayList        _texCoordArrayList;
1231        EnabledVertexAttribArrayList    _vertexAttribArrayList;
1232
1233        unsigned int                    _currentActiveTextureUnit;
1234        unsigned int                    _currentClientActiveTextureUnit;
1235        const VertexBufferObject*       _currentVBO;
1236        const ElementBufferObject*      _currentEBO;
1237        const PixelBufferObject*        _currentPBO;
1238
1239
1240        inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
1241        {
1242            if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
1243            return _textureModeMapList[unit];
1244        }
1245
1246
1247        inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
1248        {
1249            if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
1250            return _textureAttributeMapList[unit];
1251        }
1252
1253        inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1254        inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1255        inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1256
1257        inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1258        inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1259        inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1260
1261        inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1262        inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1263        inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1264
1265        inline void applyModeMap(ModeMap& modeMap);
1266        inline void applyAttributeMap(AttributeMap& attributeMap);
1267        inline void applyUniformMap(UniformMap& uniformMap);
1268
1269        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
1270        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
1271        void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
1272        void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member);
1273        bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
1274        const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const;
1275
1276
1277        mutable bool _isSecondaryColorSupportResolved;
1278        mutable bool _isSecondaryColorSupported;
1279        bool computeSecondaryColorSupported() const;
1280
1281        mutable bool _isFogCoordSupportResolved;
1282        mutable bool _isFogCoordSupported;
1283        bool computeFogCoordSupported() const;
1284
1285        mutable bool _isVertexBufferObjectSupportResolved;
1286        mutable bool _isVertexBufferObjectSupported;
1287        bool computeVertexBufferObjectSupported() const;
1288
1289        typedef void (APIENTRY * ActiveTextureProc) (GLenum texture);
1290        typedef void (APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer);
1291        typedef void (APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
1292        typedef void (APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
1293        typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int);
1294        typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int);
1295        typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
1296
1297
1298        bool                        _extensionProcsInitialized;
1299        GLint                       _glMaxTextureCoords;
1300        GLint                       _glMaxTextureUnits;
1301        ActiveTextureProc           _glClientActiveTexture;
1302        ActiveTextureProc           _glActiveTexture;
1303        FogCoordPointerProc         _glFogCoordPointer;
1304        SecondaryColorPointerProc   _glSecondaryColorPointer;
1305        VertexAttribPointerProc     _glVertexAttribPointer;
1306        EnableVertexAttribProc      _glEnableVertexAttribArray;
1307        DisableVertexAttribProc     _glDisableVertexAttribArray;
1308        BindBufferProc              _glBindBuffer;
1309
1310
1311        unsigned int                                            _dynamicObjectCount;
1312        osg::ref_ptr<DynamicObjectRenderingCompletedCallback>   _completeDynamicObjectRenderingCallback;
1313       
1314};
1315
1316inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1317{
1318    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1319        mitr!=modeList.end();
1320        ++mitr)
1321    {
1322        // get the mode stack for incoming GLmode {mitr->first}.
1323        ModeStack& ms = modeMap[mitr->first];
1324        if (ms.valueVec.empty())
1325        {
1326            // first pair so simply push incoming pair to back.
1327            ms.valueVec.push_back(mitr->second);
1328        }
1329        else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
1330        {
1331            // push existing back since override keeps the previous value.
1332            ms.valueVec.push_back(ms.valueVec.back());
1333        }
1334        else
1335        {
1336            // no override on so simply push incoming pair to back.
1337            ms.valueVec.push_back(mitr->second);
1338        }
1339        ms.changed = true;
1340    }
1341}
1342
1343inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1344{
1345    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1346        aitr!=attributeList.end();
1347        ++aitr)
1348    {
1349        // get the attribute stack for incoming type {aitr->first}.
1350        AttributeStack& as = attributeMap[aitr->first];
1351        if (as.attributeVec.empty())
1352        {
1353            // first pair so simply push incoming pair to back.
1354            as.attributeVec.push_back(
1355                AttributeStack::AttributePair(aitr->second.first.get(),aitr->second.second));
1356        }
1357        else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1358        {
1359            // push existing back since override keeps the previous value.
1360            as.attributeVec.push_back(as.attributeVec.back());
1361        }
1362        else
1363        {
1364            // no override on so simply push incoming pair to back.
1365            as.attributeVec.push_back(
1366                AttributeStack::AttributePair(aitr->second.first.get(),aitr->second.second));
1367        }
1368        as.changed = true;
1369    }
1370}
1371
1372
1373inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1374{
1375    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1376        aitr!=uniformList.end();
1377        ++aitr)
1378    {
1379        // get the attribute stack for incoming type {aitr->first}.
1380        UniformStack& us = uniformMap[aitr->first];
1381        if (us.uniformVec.empty())
1382        {
1383            // first pair so simply push incoming pair to back.
1384            us.uniformVec.push_back(
1385                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1386        }
1387        else if ((us.uniformVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1388        {
1389            // push existing back since override keeps the previous value.
1390            us.uniformVec.push_back(us.uniformVec.back());
1391        }
1392        else
1393        {
1394            // no override on so simply push incoming pair to back.
1395            us.uniformVec.push_back(
1396                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1397        }
1398    }
1399}
1400
1401inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1402{
1403    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1404        mitr!=modeList.end();
1405        ++mitr)
1406    {
1407        // get the mode stack for incoming GLmode {mitr->first}.
1408        ModeStack& ms = modeMap[mitr->first];
1409        if (!ms.valueVec.empty())
1410        {
1411            ms.valueVec.pop_back();
1412        }
1413        ms.changed = true;
1414    }
1415}
1416
1417inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1418{
1419    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1420        aitr!=attributeList.end();
1421        ++aitr)
1422    {
1423        // get the attribute stack for incoming type {aitr->first}.
1424        AttributeStack& as = attributeMap[aitr->first];
1425        if (!as.attributeVec.empty())
1426        {
1427            as.attributeVec.pop_back();
1428        }
1429        as.changed = true;
1430    }
1431}
1432
1433inline void State::popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1434{
1435    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1436        aitr!=uniformList.end();
1437        ++aitr)
1438    {
1439        // get the attribute stack for incoming type {aitr->first}.
1440        UniformStack& us = uniformMap[aitr->first];
1441        if (!us.uniformVec.empty())
1442        {
1443            us.uniformVec.pop_back();
1444        }
1445    }
1446}
1447
1448inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1449{
1450    StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
1451    ModeMap::iterator this_mitr=modeMap.begin();
1452
1453    while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
1454    {
1455        if (this_mitr->first<ds_mitr->first)
1456        {
1457
1458            // note GLMode = this_mitr->first
1459            ModeStack& ms = this_mitr->second;
1460            if (ms.changed)
1461            {
1462                ms.changed = false;
1463                if (!ms.valueVec.empty())
1464                {
1465                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1466                    applyMode(this_mitr->first,new_value,ms);
1467                }
1468                else
1469                {
1470                    // assume default of disabled.
1471                    applyMode(this_mitr->first,ms.global_default_value,ms);
1472
1473                }
1474
1475            }
1476
1477            ++this_mitr;
1478
1479        }
1480        else if (ds_mitr->first<this_mitr->first)
1481        {
1482
1483            // ds_mitr->first is a new mode, therefore
1484            // need to insert a new mode entry for ds_mistr->first.
1485            ModeStack& ms = modeMap[ds_mitr->first];
1486
1487            bool new_value = ds_mitr->second & StateAttribute::ON;
1488            applyMode(ds_mitr->first,new_value,ms);
1489
1490            // will need to disable this mode on next apply so set it to changed.
1491            ms.changed = true;
1492
1493            ++ds_mitr;
1494
1495        }
1496        else
1497        {
1498            // this_mitr & ds_mitr refer to the same mode, check the override
1499            // if any otherwise just apply the incoming mode.
1500
1501            ModeStack& ms = this_mitr->second;
1502
1503            if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
1504            {
1505                // override is on, just treat as a normal apply on modes.
1506
1507                if (ms.changed)
1508                {
1509                    ms.changed = false;
1510                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1511                    applyMode(this_mitr->first,new_value,ms);
1512
1513                }
1514            }
1515            else
1516            {
1517                // no override on or no previous entry, therefore consider incoming mode.
1518                bool new_value = ds_mitr->second & StateAttribute::ON;
1519                if (applyMode(ds_mitr->first,new_value,ms))
1520                {
1521                    ms.changed = true;
1522                }
1523            }
1524
1525            ++this_mitr;
1526            ++ds_mitr;
1527        }
1528    }
1529
1530    // iterator over the remaining state modes to apply any previous changes.
1531    for(;
1532        this_mitr!=modeMap.end();
1533        ++this_mitr)
1534    {
1535        // note GLMode = this_mitr->first
1536        ModeStack& ms = this_mitr->second;
1537        if (ms.changed)
1538        {
1539            ms.changed = false;
1540            if (!ms.valueVec.empty())
1541            {
1542                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1543                applyMode(this_mitr->first,new_value,ms);
1544            }
1545            else
1546            {
1547                // assume default of disabled.
1548                applyMode(this_mitr->first,ms.global_default_value,ms);
1549
1550            }
1551
1552        }
1553    }
1554
1555    // iterator over the remaining incoming modes to apply any new mode.
1556    for(;
1557        ds_mitr!=modeList.end();
1558        ++ds_mitr)
1559    {
1560        ModeStack& ms = modeMap[ds_mitr->first];
1561
1562        bool new_value = ds_mitr->second & StateAttribute::ON;
1563        applyMode(ds_mitr->first,new_value,ms);
1564
1565        // will need to disable this mode on next apply so set it to changed.
1566        ms.changed = true;
1567    }
1568}
1569
1570inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1571{
1572    StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
1573
1574    AttributeMap::iterator this_aitr=attributeMap.begin();
1575
1576    while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
1577    {
1578        if (this_aitr->first<ds_aitr->first)
1579        {
1580
1581            // note attribute type = this_aitr->first
1582            AttributeStack& as = this_aitr->second;
1583            if (as.changed)
1584            {
1585                as.changed = false;
1586                if (!as.attributeVec.empty())
1587                {
1588                    const StateAttribute* new_attr = as.attributeVec.back().first;
1589                    applyAttribute(new_attr,as);
1590                }
1591                else
1592                {
1593                    applyGlobalDefaultAttribute(as);
1594                }
1595            }
1596
1597            ++this_aitr;
1598
1599        }
1600        else if (ds_aitr->first<this_aitr->first)
1601        {
1602
1603            // ds_aitr->first is a new attribute, therefore
1604            // need to insert a new attribute entry for ds_aitr->first.
1605            AttributeStack& as = attributeMap[ds_aitr->first];
1606
1607            const StateAttribute* new_attr = ds_aitr->second.first.get();
1608            applyAttribute(new_attr,as);
1609
1610            as.changed = true;
1611
1612            ++ds_aitr;
1613
1614        }
1615        else
1616        {
1617            // this_mitr & ds_mitr refer to the same attribute, check the override
1618            // if any otherwise just apply the incoming attribute
1619
1620            AttributeStack& as = this_aitr->second;
1621
1622            if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
1623            {
1624                // override is on, just treat as a normal apply on attribute.
1625
1626                if (as.changed)
1627                {
1628                    as.changed = false;
1629                    const StateAttribute* new_attr = as.attributeVec.back().first;
1630                    applyAttribute(new_attr,as);
1631                }
1632            }
1633            else
1634            {
1635                // no override on or no previous entry, therefore consider incoming attribute.
1636                const StateAttribute* new_attr = ds_aitr->second.first.get();
1637                if (applyAttribute(new_attr,as))
1638                {
1639                    as.changed = true;
1640                }
1641            }
1642
1643            ++this_aitr;
1644            ++ds_aitr;
1645        }
1646    }
1647
1648    // iterator over the remaining state attributes to apply any previous changes.
1649    for(;
1650        this_aitr!=attributeMap.end();
1651        ++this_aitr)
1652    {
1653        // note attribute type = this_aitr->first
1654        AttributeStack& as = this_aitr->second;
1655        if (as.changed)
1656        {
1657            as.changed = false;
1658            if (!as.attributeVec.empty())
1659            {
1660                const StateAttribute* new_attr = as.attributeVec.back().first;
1661                applyAttribute(new_attr,as);
1662            }
1663            else
1664            {
1665                applyGlobalDefaultAttribute(as);
1666            }
1667        }
1668    }
1669
1670    // iterator over the remaining incoming attribute to apply any new attribute.
1671    for(;
1672        ds_aitr!=attributeList.end();
1673        ++ds_aitr)
1674    {
1675        // ds_aitr->first is a new attribute, therefore
1676        // need to insert a new attribute entry for ds_aitr->first.
1677        AttributeStack& as = attributeMap[ds_aitr->first];
1678
1679        const StateAttribute* new_attr = ds_aitr->second.first.get();
1680        applyAttribute(new_attr,as);
1681
1682        // will need to update this attribute on next apply so set it to changed.
1683        as.changed = true;
1684    }
1685
1686}
1687
1688inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1689{
1690    if (!_lastAppliedProgramObject) return;
1691
1692    StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
1693
1694    UniformMap::iterator this_aitr=uniformMap.begin();
1695
1696    while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
1697    {
1698        if (this_aitr->first<ds_aitr->first)
1699        {
1700            // note attribute type = this_aitr->first
1701            UniformStack& as = this_aitr->second;
1702            if (!as.uniformVec.empty())
1703            {
1704                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1705            }
1706
1707            ++this_aitr;
1708
1709        }
1710        else if (ds_aitr->first<this_aitr->first)
1711        {
1712            _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1713
1714            ++ds_aitr;
1715        }
1716        else
1717        {
1718            // this_mitr & ds_mitr refer to the same attribute, check the override
1719            // if any otherwise just apply the incoming attribute
1720
1721            UniformStack& as = this_aitr->second;
1722
1723            if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
1724            {
1725                // override is on, just treat as a normal apply on uniform.
1726                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1727            }
1728            else
1729            {
1730                // no override on or no previous entry, therefore consider incoming attribute.
1731                _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1732            }
1733
1734            ++this_aitr;
1735            ++ds_aitr;
1736        }
1737    }
1738
1739    // iterator over the remaining state attributes to apply any previous changes.
1740    for(;
1741        this_aitr!=uniformMap.end();
1742        ++this_aitr)
1743    {
1744        // note attribute type = this_aitr->first
1745        UniformStack& as = this_aitr->second;
1746        if (!as.uniformVec.empty())
1747        {
1748            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1749        }
1750    }
1751
1752    // iterator over the remaining incoming attribute to apply any new attribute.
1753    for(;
1754        ds_aitr!=uniformList.end();
1755        ++ds_aitr)
1756    {
1757        _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1758    }
1759
1760}
1761
1762inline void State::applyModeMap(ModeMap& modeMap)
1763{
1764    for(ModeMap::iterator mitr=modeMap.begin();
1765        mitr!=modeMap.end();
1766        ++mitr)
1767    {
1768        // note GLMode = mitr->first
1769        ModeStack& ms = mitr->second;
1770        if (ms.changed)
1771        {
1772            ms.changed = false;
1773            if (!ms.valueVec.empty())
1774            {
1775                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1776                applyMode(mitr->first,new_value,ms);
1777            }
1778            else
1779            {
1780                // assume default of disabled.
1781                applyMode(mitr->first,ms.global_default_value,ms);
1782            }
1783
1784        }
1785    }
1786}
1787
1788inline void State::applyAttributeMap(AttributeMap& attributeMap)
1789{
1790    for(AttributeMap::iterator aitr=attributeMap.begin();
1791        aitr!=attributeMap.end();
1792        ++aitr)
1793    {
1794        AttributeStack& as = aitr->second;
1795        if (as.changed)
1796        {
1797            as.changed = false;
1798            if (!as.attributeVec.empty())
1799            {
1800                const StateAttribute* new_attr = as.attributeVec.back().first;
1801                applyAttribute(new_attr,as);
1802            }
1803            else
1804            {
1805                applyGlobalDefaultAttribute(as);
1806            }
1807
1808        }
1809    }
1810}
1811
1812inline void State::applyUniformMap(UniformMap& uniformMap)
1813{
1814    if (!_lastAppliedProgramObject) return;
1815
1816    for(UniformMap::iterator aitr=uniformMap.begin();
1817        aitr!=uniformMap.end();
1818        ++aitr)
1819    {
1820        UniformStack& as = aitr->second;
1821        if (!as.uniformVec.empty())
1822        {
1823            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1824        }
1825    }
1826}
1827
1828
1829}
1830
1831#endif
Note: See TracBrowser for help on using the browser.