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

Revision 10588, 70.7 kB (checked in by robert, 5 years ago)

Preliminary work on support for a texture object pool that is designed to help manage resources down the GPU more tightly.

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