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

Revision 10621, 70.8 kB (checked in by robert, 5 years ago)

Introduced new uniforms for tracking the modelview and project matrices in shaders using non built-ins.

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