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

Revision 10926, 93.6 kB (checked in by robert, 4 years ago)

From Lilith Bryant, "As discussed previously on the users list. Fixes the redundant calls to
glActiveTexture on every State::apply after more than one texunits have been
used.

This is against 2.9.6 (I think SVN head is the same)

Quick Synopsis:

New functions:

State::applyModeOnTexUnit
State::applyAttributeOnTexUnit
State::applyModeMapOnTexUnit
State::applyAttributeMapOnTexUnit
State::applyModeListOnTexUnit
State::applyAttributeListOnTexUnit

All copies of the normal versions, but they also set the active tex unit if
absolutely necessary (i.e. only if they call something OpenGL).

State::apply (*2)
State::applyTextureAttribute

Changed to call the above functions and no longer call setActiveTextureUnit
themselves.

State::setActiveTextureUnit

Made inline, so the benefit of having applyModeOnTexUnit (etc) inline
is retained.
"

  • 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#include <osg/GLBeginEndAdapter>
29#include <osg/ArrayDispatchers>
30
31#include <vector>
32#include <map>
33#include <set>
34#include <string>
35
36#ifndef GL_FOG_COORDINATE_ARRAY
37    #ifdef GL_FOG_COORDINATE_ARRAY_EXT
38        #define GL_FOG_COORDINATE_ARRAY GL_FOG_COORDINATE_ARRAY_EXT
39    #else
40        #define GL_FOG_COORDINATE_ARRAY 0x8457
41    #endif
42#endif
43
44#ifndef GL_SECONDARY_COLOR_ARRAY
45    #ifdef GL_SECONDARY_COLOR_ARRAY_EXT
46        #define GL_SECONDARY_COLOR_ARRAY GL_SECONDARY_COLOR_ARRAY_EXT
47    #else
48        #define GL_SECONDARY_COLOR_ARRAY 0x845E
49    #endif
50#endif
51
52namespace osg {
53
54/** macro for use with osg::StateAttribute::apply methods for detecting and
55* reporting OpenGL error messages.*/
56#define OSG_GL_DEBUG(message) \
57    if (state.getFineGrainedErrorDetection()) \
58    { \
59        GLenum errorNo = glGetError(); \
60        if (errorNo!=GL_NO_ERROR) \
61        { \
62            osg::notify(WARN)<<"Warning: detected OpenGL error '"<<gluErrorString(errorNo)<<" "<<message<<endl; \
63        }\
64    }
65
66
67// forward declare GraphicsContext, View and State
68class GraphicsContext;
69
70class VertexAttribAlias
71{
72    public:
73        VertexAttribAlias():
74            _location(0) {}
75
76        VertexAttribAlias(const VertexAttribAlias& rhs):
77            _location(rhs._location),
78            _glName(rhs._glName),
79            _osgName(rhs._osgName),
80            _declaration(rhs._declaration) {}
81
82        VertexAttribAlias(GLuint location, const std::string glName, const std::string osgName, const std::string& declaration):
83            _location(location),
84            _glName(glName),
85            _osgName(osgName),
86            _declaration(declaration) {}
87
88        GLuint      _location;
89        std::string _glName;
90        std::string _osgName;
91        std::string _declaration;
92};
93
94
95/** Encapsulates the current applied OpenGL modes, attributes and vertex arrays settings,
96* implements lazy state updating and provides accessors for querying the current state.
97* The venerable Red Book says that "OpenGL is a state machine", and this class
98* represents the OpenGL state in OSG. Furthermore, \c State also has other
99* important features:
100* - It works as a stack of states (see \c pushStateSet() and
101*   \c popStateSet()). Manipulating this stack of OpenGL states manually is
102*   seldom needed, since OSG does this in the most common situations.
103* - It implements lazy state updating. This means that, if one requests a
104*   state change and that particular state is already in the requested state,
105*   no OpenGL call will be made. This ensures that the OpenGL pipeline is not
106*   stalled by unnecessary state changes.
107* - It allows to query the current OpenGL state without calls to \c glGet*(),
108*   which typically stall the graphics pipeline (see, for instance,
109*   \c captureCurrentState() and \c getModelViewMatrix()).
110*/
111class OSG_EXPORT State : public Referenced, public Observer
112{
113    public :
114
115        State();
116
117
118        /** Set the graphics context associated with that owns this State object.*/
119        void setGraphicsContext(GraphicsContext* context) { _graphicsContext = context; }
120
121        /** Get the graphics context associated with that owns this State object.*/
122        GraphicsContext* getGraphicsContext() { return _graphicsContext; }
123
124        /** Get the const graphics context associated with that owns this State object.*/
125        const GraphicsContext* getGraphicsContext() const { return _graphicsContext; }
126
127
128        /** Set the current OpenGL context uniqueID.
129            Note, it is the application developers responsibility to
130            set up unique ID for each OpenGL context.  This value is
131            then used by osg::StateAttribute's and osg::Drawable's to
132            help manage OpenGL display list and texture binds appropriate
133            for each context, the contextID simply acts as an index in local
134            arrays that they maintain for the purpose.
135            Typical settings for contextID are 0,1,2,3... up to the maximum
136            number of graphics contexts you have set up.
137            By default contextID is 0.*/
138        inline void setContextID(unsigned int contextID) { _contextID=contextID; }
139
140        /** Get the current OpenGL context unique ID.*/
141        inline unsigned int getContextID() const { return _contextID; }
142
143        /** Push stateset onto state stack.*/
144        void pushStateSet(const StateSet* dstate);
145
146        /** Pop stateset off state stack.*/
147        void popStateSet();
148
149        /** pop all statesets off state stack, ensuring it is empty ready for the next frame.
150        * Note, to return OpenGL to default state, one should do any state.popAllStatSets(); state.apply().*/
151        void popAllStateSets();
152
153        /** Insert stateset onto state stack.*/
154        void insertStateSet(unsigned int pos,const StateSet* dstate);
155
156        /** Pop stateset off state stack.*/
157        void removeStateSet(unsigned int pos);
158
159        /** Get the number of StateSet's on the StateSet stack.*/
160        unsigned int getStateSetStackSize() { return static_cast<unsigned int>(_stateStateStack.size()); }
161
162        /** Pop StateSet's for the StateSet stack till its size equals the specified size.*/
163        void popStateSetStackToSize(unsigned int size) { while (_stateStateStack.size()>size) popStateSet(); }
164
165        typedef std::vector<const StateSet*> StateSetStack;
166
167        /** Get the StateSet stack.*/
168        StateSetStack& getStateSetStack() { return _stateStateStack; }
169
170
171        /** Copy the modes and attributes which capture the current state.*/
172        void captureCurrentState(StateSet& stateset) const;
173
174        /** reset the state object to an empty stack.*/
175        void reset();
176
177
178        inline const Viewport* getCurrentViewport() const
179        {
180            return static_cast<const Viewport*>(getLastAppliedAttribute(osg::StateAttribute::VIEWPORT));
181        }
182
183
184        void setInitialViewMatrix(const osg::RefMatrix* matrix);
185
186        inline const osg::Matrix& getInitialViewMatrix() const { return *_initialViewMatrix; }
187        inline const osg::Matrix& getInitialInverseViewMatrix() const { return _initialInverseViewMatrix; }
188
189        void applyProjectionMatrix(const osg::RefMatrix* matrix);
190
191        inline const osg::Matrix& getProjectionMatrix() const { return *_projection; }
192
193        void applyModelViewMatrix(const osg::RefMatrix* matrix);
194
195        const osg::Matrix& getModelViewMatrix() const { return *_modelView; }
196
197        void setUseModelViewAndProjectionUniforms(bool flag) { _useModelViewAndProjectionUniforms = flag; }
198        bool getUseModelViewAndProjectionUniforms() const { return _useModelViewAndProjectionUniforms; }
199
200        void updateModelViewAndProjectionMatrixUniforms();
201
202        void applyModelViewAndProjectionUniformsIfRequired();
203
204        osg::Uniform* getModelViewMatrixUniform() { return _modelViewMatrixUniform.get(); }
205        osg::Uniform* getProjectionMatrixUniform() { return _projectionMatrixUniform.get(); }
206        osg::Uniform* getModelViewProjectionMatrixUniform() { return _modelViewProjectionMatrixUniform.get(); }
207        osg::Uniform* getNormalMatrixUniform() { return _normalMatrixUniform.get(); }
208
209
210        Polytope getViewFrustum() const;
211
212
213        void setUseVertexAttributeAliasing(bool flag) { _useVertexAttributeAliasing = flag; }
214        bool getUseVertexAttributeAliasing() const { return _useVertexAttributeAliasing ; }
215
216        typedef std::vector<VertexAttribAlias> VertexAttribAliasList;
217
218        const VertexAttribAlias& getVertexAlias() { return _vertexAlias; }
219        const VertexAttribAlias& getNormalAlias() { return _normalAlias; }
220        const VertexAttribAlias& getColorAlias() { return _colorAlias; }
221        const VertexAttribAlias& getSecondaryColorAlias() { return _secondaryColorAlias; }
222        const VertexAttribAlias& getFogCoordAlias() { return _fogCoordAlias; }
223        const VertexAttribAliasList& getTexCoordAliasList() { return _texCoordAliasList; }
224
225
226        const Program::AttribBindingList&  getAttributeBindingList() { return _attributeBindingList; }
227
228        bool convertVertexShaderSourceToOsgBuiltIns(std::string& source) const;
229
230
231        /** Apply stateset.*/
232        void apply(const StateSet* dstate);
233
234        /** Updates the OpenGL state so that it matches the \c StateSet at the
235        * top of the stack of <tt>StateSet</tt>s maintained internally by a
236        * \c State.
237        */
238        void apply();
239
240
241        /** Set whether a particular OpenGL mode is valid in the current graphics context.
242        * Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
243        inline void setModeValidity(StateAttribute::GLMode mode,bool valid)
244        {
245            ModeStack& ms = _modeMap[mode];
246            ms.valid = valid;
247        }
248
249        /** Get whether a particular OpenGL mode is valid in the current graphics context.
250        * Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
251        inline bool getModeValidity(StateAttribute::GLMode mode)
252        {
253            ModeStack& ms = _modeMap[mode];
254            return ms.valid;
255        }
256
257        inline void setGlobalDefaultModeValue(StateAttribute::GLMode mode,bool enabled)
258        {
259            ModeStack& ms = _modeMap[mode];
260            ms.global_default_value = enabled;
261        }
262
263        inline bool getGlobalDefaultModeValue(StateAttribute::GLMode mode)
264        {
265            return _modeMap[mode].global_default_value;
266        }
267
268
269        /** Apply an OpenGL mode if required. This is a wrapper around
270        * \c glEnable() and \c glDisable(), that just actually calls these
271        * functions if the \c enabled flag is different than the current
272        * state.
273        * @return \c true if the state was actually changed. \c false
274        *         otherwise. Notice that a \c false return does not indicate
275        *         an error, it just means that the mode was already set to the
276        *         same value as the \c enabled parameter.
277        */
278        inline bool applyMode(StateAttribute::GLMode mode,bool enabled)
279        {
280            ModeStack& ms = _modeMap[mode];
281            ms.changed = true;
282            return applyMode(mode,enabled,ms);
283        }
284
285        inline void setGlobalDefaultTextureModeValue(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
286        {
287            ModeMap& modeMap = getOrCreateTextureModeMap(unit);
288            ModeStack& ms = modeMap[mode];
289            ms.global_default_value = enabled;
290        }
291
292        inline bool getGlobalDefaultTextureModeValue(unsigned int unit, StateAttribute::GLMode mode)
293        {
294            ModeMap& modeMap = getOrCreateTextureModeMap(unit);
295            ModeStack& ms = modeMap[mode];
296            return ms.global_default_value;
297        }
298
299        inline bool applyTextureMode(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
300        {
301            ModeMap& modeMap = getOrCreateTextureModeMap(unit);
302            ModeStack& ms = modeMap[mode];
303            ms.changed = true;
304            return applyModeOnTexUnit(unit,mode,enabled,ms);
305        }
306
307        inline void setGlobalDefaultAttribute(const StateAttribute* attribute)
308        {
309            AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
310            as.global_default_attribute = attribute;
311        }
312
313        inline const StateAttribute* getGlobalDefaultAttribute(StateAttribute::Type type, unsigned int member=0)
314        {
315            AttributeStack& as = _attributeMap[StateAttribute::TypeMemberPair(type,member)];
316            return as.global_default_attribute.get();
317        }
318
319        /** Apply an attribute if required. */
320        inline bool applyAttribute(const StateAttribute* attribute)
321        {
322            AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
323            as.changed = true;
324            return applyAttribute(attribute,as);
325        }
326
327        inline void setGlobalDefaultTextureAttribute(unsigned int unit, const StateAttribute* attribute)
328        {
329            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
330            AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
331            as.global_default_attribute = attribute;
332        }
333
334        inline const StateAttribute* getGlobalDefaultTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member = 0)
335        {
336            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
337            AttributeStack& as = attributeMap[StateAttribute::TypeMemberPair(type,member)];
338            return as.global_default_attribute.get();
339        }
340
341
342        inline bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
343        {
344            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
345            AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
346            as.changed = true;
347            return applyAttributeOnTexUnit(unit,attribute,as);
348        }
349
350        /** Mode has been set externally, update state to reflect this setting.*/
351        void haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
352
353        /** Mode has been set externally, therefore dirty the associated mode in osg::State
354        * so it is applied on next call to osg::State::apply(..)*/
355        void haveAppliedMode(StateAttribute::GLMode mode);
356
357        /** Attribute has been applied externally, update state to reflect this setting.*/
358        void haveAppliedAttribute(const StateAttribute* attribute);
359
360        /** Attribute has been applied externally,
361        * and therefore this attribute type has been dirtied
362        * and will need to be re-applied on next osg::State.apply(..).
363        * note, if you have an osg::StateAttribute which you have applied externally
364        * then use the have_applied(attribute) method as this will cause the osg::State to
365        * track the current state more accurately and enable lazy state updating such
366        * that only changed state will be applied.*/
367        void haveAppliedAttribute(StateAttribute::Type type, unsigned int member=0);
368
369        /** Get whether the current specified mode is enabled (true) or disabled (false).*/
370        bool getLastAppliedMode(StateAttribute::GLMode mode) const;
371
372        /** Get the current specified attribute, return NULL if one has not yet been applied.*/
373        const StateAttribute* getLastAppliedAttribute(StateAttribute::Type type, unsigned int member=0) const;
374
375        /** texture Mode has been set externally, update state to reflect this setting.*/
376        void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
377
378        /** texture Mode has been set externally, therefore dirty the associated mode in osg::State
379        * so it is applied on next call to osg::State::apply(..)*/
380        void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode);
381
382        /** texture Attribute has been applied externally, update state to reflect this setting.*/
383        void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute* attribute);
384
385        /** texture Attribute has been applied externally,
386        * and therefore this attribute type has been dirtied
387        * and will need to be re-applied on next osg::State.apply(..).
388        * note, if you have an osg::StateAttribute which you have applied externally
389        * then use the have_applied(attribute) method as this will the osg::State to
390        * track the current state more accurately and enable lazy state updating such
391        * that only changed state will be applied.*/
392        void haveAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0);
393
394        /** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
395        bool getLastAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode) const;
396
397        /** Get the current specified texture attribute, return NULL if one has not yet been applied.*/
398        const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0) const;
399
400
401        /** Dirty the modes previously applied in osg::State.*/
402        void dirtyAllModes();
403
404        /** Dirty the modes attributes previously applied in osg::State.*/
405        void dirtyAllAttributes();
406
407        /** disable the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
408        void disableAllVertexArrays();
409
410        /** dirty the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
411        void dirtyAllVertexArrays();
412
413
414        void setCurrentVertexBufferObject(osg::GLBufferObject* vbo) { _currentVBO = vbo; }
415        const GLBufferObject* getCurrentVertexBufferObject() { return _currentVBO; }
416        inline void bindVertexBufferObject(osg::GLBufferObject* vbo)
417        {
418            if (vbo == _currentVBO) return;
419            if (vbo->isDirty()) vbo->compileBuffer();
420            else vbo->bindBuffer();
421            _currentVBO = vbo;
422        }
423
424        inline void unbindVertexBufferObject()
425        {
426            if (!_currentVBO) return;
427            _glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
428            _currentVBO = 0;
429        }
430
431        void setCurrentElementBufferObject(osg::GLBufferObject* ebo) { _currentEBO = ebo; }
432        const GLBufferObject* getCurrentElementBufferObject() { return _currentEBO; }
433
434        inline void bindElementBufferObject(osg::GLBufferObject* ebo)
435        {
436            if (ebo == _currentEBO) return;
437            if (ebo->isDirty()) ebo->compileBuffer();
438            else ebo->bindBuffer();
439            _currentEBO = ebo;
440        }
441
442        inline void unbindElementBufferObject()
443        {
444            if (!_currentEBO) return;
445            _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
446            _currentEBO = 0;
447        }
448
449        void setCurrentPixelBufferObject(osg::GLBufferObject* pbo) { _currentPBO = pbo; }
450        const GLBufferObject* getCurrentPixelBufferObject() { return _currentPBO; }
451
452        inline void bindPixelBufferObject(osg::GLBufferObject* pbo)
453        {
454            if (pbo == _currentPBO) return;
455
456            if (pbo->isDirty()) pbo->compileBuffer();
457            else pbo->bindBuffer();
458
459            _currentPBO = pbo;
460        }
461
462        inline void unbindPixelBufferObject()
463        {
464            if (!_currentPBO) return;
465
466            _glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
467            _currentPBO = 0;
468        }
469
470        typedef std::vector<GLushort> Indices;
471        Indices _quadIndices[6];
472
473        void drawQuads(GLint first, GLsizei count, GLsizei primCount=0);
474
475        inline void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
476        {
477            if (primcount>=1 && _glDrawArraysInstanced!=0) _glDrawArraysInstanced(mode, first, count, primcount);
478            else glDrawArrays(mode, first, count);
479        }
480
481        inline void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount )
482        {
483            if (primcount>=1 && _glDrawElementsInstanced!=0) _glDrawElementsInstanced(mode, count, type, indices, primcount);
484            else glDrawElements(mode, count, type, indices);
485        }
486
487
488        inline void Vertex(float x, float y, float z, float w=1.0f)
489        {
490        #if defined(OSG_GL_VERTEX_FUNCS_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE)
491            if (_useVertexAttributeAliasing) _glVertexAttrib4f( _vertexAlias._location, x,y,z,w);
492            else glVertex4f(x,y,z,w);
493        #else
494            _glVertexAttrib4f( _vertexAlias._location, x,y,z,w);
495        #endif
496        }
497
498        inline void Color(float r, float g, float b, float a=1.0f)
499        {
500        #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
501            if (_useVertexAttributeAliasing) _glVertexAttrib4f( _colorAlias._location, r,g,b,a);
502            else glColor4f(r,g,b,a);
503        #else
504            _glVertexAttrib4f( _colorAlias._location, r,g,b,a);
505        #endif
506        }
507
508        void Normal(float x, float y, float z)
509        {
510        #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
511            if (_useVertexAttributeAliasing) _glVertexAttrib4f( _normalAlias._location, x,y,z,0.0);
512            else glNormal3f(x,y,z);
513        #else
514            _glVertexAttrib4f( _normalAlias._location, x,y,z,0.0);
515        #endif
516        }
517
518        void TexCoord(float x, float y=0.0f, float z=0.0f, float w=1.0f)
519        {
520        #if !defined(OSG_GLES1_AVAILABLE)
521            #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
522                if (_useVertexAttributeAliasing) _glVertexAttrib4f( _texCoordAliasList[0]._location, x,y,z,w);
523                else glTexCoord4f(x,y,z,w);
524            #else
525                _glVertexAttrib4f( _texCoordAliasList[0]._location, x,y,z,w);
526            #endif
527        #endif
528        }
529
530        void MultiTexCoord(unsigned int unit, float x, float y=0.0f, float z=0.0f, float w=1.0f)
531        {
532        #if !defined(OSG_GLES1_AVAILABLE)
533            #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
534                if (_useVertexAttributeAliasing) _glVertexAttrib4f( _texCoordAliasList[unit]._location, x,y,z,w);
535                else _glMultiTexCoord4f(GL_TEXTURE0+unit,x,y,z,w);
536            #else
537                _glVertexAttrib4f( _texCoordAliasList[unit]._location, x,y,z,w);
538            #endif
539        #endif
540        }
541
542        void VerteAttrib(unsigned int location, float x, float y=0.0f, float z=0.0f, float w=0.0f)
543        {
544            _glVertexAttrib4f( location, x,y,z,w);
545        }
546
547
548        /** Mark all the vertex attributes as being disabled but leave the disabling till a later call to applyDisablingOfVertexAttributes.*/
549        void lazyDisablingOfVertexAttributes();
550
551        /** Disable all the vertex attributes that have been marked as to be disabled.*/
552        void applyDisablingOfVertexAttributes();
553
554        /** Wrapper around glInterleavedArrays(..).
555          * also resets the internal array points and modes within osg::State to keep the other
556          * vertex array operations consistent. */
557        void setInterleavedArrays( GLenum format, GLsizei stride, const GLvoid* pointer);
558
559        /** Set the vertex pointer using an osg::Array, and manage any VBO that are required.*/
560        inline void setVertexPointer(const Array* array)
561        {
562            if (array)
563            {
564                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
565                if (vbo)
566                {
567                    bindVertexBufferObject(vbo);
568                    setVertexPointer(array->getDataSize(),array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
569                }
570                else
571                {
572                    unbindVertexBufferObject();
573                    setVertexPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
574                }
575            }
576        }
577
578        /** wrapper around glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(..);
579        * note, only updates values that change.*/
580        inline void setVertexPointer( GLint size, GLenum type,
581                                    GLsizei stride, const GLvoid *ptr )
582        {
583        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
584            if (_useVertexAttributeAliasing)
585            {
586                setVertexAttribPointer(_vertexAlias._location, size, type, GL_FALSE, stride, ptr);
587            }
588            else
589            {
590                if (!_vertexArray._enabled || _vertexArray._dirty)
591                {
592                    _vertexArray._enabled = true;
593                    glEnableClientState(GL_VERTEX_ARRAY);
594                }
595                //if (_vertexArray._pointer!=ptr || _vertexArray._dirty)
596                {
597                    _vertexArray._pointer=ptr;
598                    glVertexPointer( size, type, stride, ptr );
599                }
600                _vertexArray._lazy_disable = false;
601                _vertexArray._dirty = false;
602            }
603        #else
604            setVertexAttribPointer(_vertexAlias._location, size, type, GL_FALSE, stride, ptr);
605        #endif
606        }
607
608        /** wrapper around glDisableClientState(GL_VERTEX_ARRAY).
609        * note, only updates values that change.*/
610        inline void disableVertexPointer()
611        {
612        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
613            if (_useVertexAttributeAliasing)
614            {
615                disableVertexAttribPointer(_vertexAlias._location);
616            }
617            else
618            {
619                if (_vertexArray._enabled || _vertexArray._dirty)
620                {
621                    _vertexArray._lazy_disable = false;
622                    _vertexArray._enabled = false;
623                    _vertexArray._dirty = false;
624                    glDisableClientState(GL_VERTEX_ARRAY);
625                }
626            }
627        #else
628                disableVertexAttribPointer(_vertexAlias._location);
629        #endif
630        }
631
632        inline void dirtyVertexPointer()
633        {
634        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
635            if (_useVertexAttributeAliasing)
636            {
637                dirtyVertexAttribPointer(_vertexAlias._location);
638            }
639            else
640            {
641                _vertexArray._pointer = 0;
642                _vertexArray._dirty = true;
643            }
644        #else
645            dirtyVertexAttribPointer(_vertexAlias._location);
646        #endif
647        }
648
649
650        /** Set the normal pointer using an osg::Array, and manage any VBO that are required.*/
651        inline void setNormalPointer(const Array* array)
652        {
653            if (array)
654            {
655                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
656                if (vbo)
657                {
658                    bindVertexBufferObject(vbo);
659                    setNormalPointer(array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
660                }
661                else
662                {
663                    unbindVertexBufferObject();
664                    setNormalPointer(array->getDataType(),0,array->getDataPointer());
665                }
666            }
667        }
668
669        /** wrapper around glEnableClientState(GL_NORMAL_ARRAY);glNormalPointer(..);
670        * note, only updates values that change.*/
671        inline void setNormalPointer( GLenum type, GLsizei stride,
672                                    const GLvoid *ptr )
673        {
674        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
675            if (_useVertexAttributeAliasing)
676            {
677                setVertexAttribPointer(_normalAlias._location, 3, type, GL_FALSE, stride, ptr);
678            }
679            else
680            {
681                if (!_normalArray._enabled || _normalArray._dirty)
682                {
683                    _normalArray._enabled = true;
684                    glEnableClientState(GL_NORMAL_ARRAY);
685                }
686                //if (_normalArray._pointer!=ptr || _normalArray._dirty)
687                {
688                    _normalArray._pointer=ptr;
689                    glNormalPointer( type, stride, ptr );
690                }
691                _normalArray._lazy_disable = false;
692                _normalArray._dirty = false;
693            }
694        #else
695            setVertexAttribPointer(_normalAlias._location, 3, type, GL_FALSE, stride, ptr);
696        #endif
697        }
698
699        /** wrapper around glDisableClientState(GL_NORMAL_ARRAY);
700        * note, only updates values that change.*/
701        inline void disableNormalPointer()
702        {
703        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
704            if (_useVertexAttributeAliasing)
705            {
706                disableVertexAttribPointer(_normalAlias._location);
707            }
708            else
709            {
710                if (_normalArray._enabled || _normalArray._dirty)
711                {
712                    _normalArray._lazy_disable = false;
713                    _normalArray._enabled = false;
714                    _normalArray._dirty = false;
715                    glDisableClientState(GL_NORMAL_ARRAY);
716                }
717            }
718        #else
719            disableVertexAttribPointer(_normalAlias._location);
720        #endif
721        }
722
723        inline void dirtyNormalPointer()
724        {
725        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
726            if (_useVertexAttributeAliasing)
727            {
728                dirtyVertexAttribPointer(_normalAlias._location);
729            }
730            else
731            {
732                _normalArray._pointer = 0;
733                _normalArray._dirty = true;
734            }
735        #else
736            dirtyVertexAttribPointer(_normalAlias._location);
737        #endif
738        }
739
740        /** Set the color pointer using an osg::Array, and manage any VBO that are required.*/
741        inline void setColorPointer(const Array* array)
742        {
743            if (array)
744            {
745                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
746                if (vbo)
747                {
748                    bindVertexBufferObject(vbo);
749                    setColorPointer(array->getDataSize(),array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
750                }
751                else
752                {
753                    unbindVertexBufferObject();
754                    setColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
755                }
756            }
757        }
758
759
760        /** wrapper around glEnableClientState(GL_COLOR_ARRAY);glColorPointer(..);
761        * note, only updates values that change.*/
762        inline void setColorPointer( GLint size, GLenum type,
763                                    GLsizei stride, const GLvoid *ptr )
764        {
765        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
766            if (_useVertexAttributeAliasing)
767            {
768                setVertexAttribPointer(_colorAlias._location, size, type, GL_FALSE, stride, ptr);
769            }
770            else
771            {
772                if (!_colorArray._enabled || _colorArray._dirty)
773                {
774                    _colorArray._enabled = true;
775                    glEnableClientState(GL_COLOR_ARRAY);
776                }
777                //if (_colorArray._pointer!=ptr || _colorArray._dirty)
778                {
779                    _colorArray._pointer=ptr;
780                    glColorPointer( size, type, stride, ptr );
781                }
782                _colorArray._lazy_disable = false;
783                _colorArray._dirty = false;
784            }
785        #else
786            setVertexAttribPointer(_colorAlias._location, size, type, GL_FALSE, stride, ptr);
787        #endif
788        }
789
790        /** wrapper around glDisableClientState(GL_COLOR_ARRAY);
791        * note, only updates values that change.*/
792        inline void disableColorPointer()
793        {
794        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
795            if (_useVertexAttributeAliasing)
796            {
797                disableVertexAttribPointer(_colorAlias._location);
798            }
799            else
800            {
801                if (_colorArray._enabled || _colorArray._dirty)
802                {
803                    _colorArray._lazy_disable = false;
804                    _colorArray._enabled = false;
805                    _colorArray._dirty = false;
806                    glDisableClientState(GL_COLOR_ARRAY);
807                }
808            }
809        #else
810            disableVertexAttribPointer(_colorAlias._location);
811        #endif
812        }
813
814        inline void dirtyColorPointer()
815        {
816        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
817            if (_useVertexAttributeAliasing)
818            {
819                dirtyVertexAttribPointer(_colorAlias._location);
820            }
821            else
822            {
823                _colorArray._pointer = 0;
824                _colorArray._dirty = true;
825            }
826        #else
827            dirtyVertexAttribPointer(_colorAlias._location);
828        #endif
829        }
830
831
832        inline bool isSecondaryColorSupported() const { return _isSecondaryColorSupportResolved?_isSecondaryColorSupported:computeSecondaryColorSupported(); }
833
834
835        /** Set the secondary color pointer using an osg::Array, and manage any VBO that are required.*/
836        inline void setSecondaryColorPointer(const Array* array)
837        {
838            if (array)
839            {
840                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
841                if (vbo)
842                {
843                    bindVertexBufferObject(vbo);
844                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
845                }
846                else
847                {
848                    unbindVertexBufferObject();
849                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
850                }
851            }
852        }
853
854        /** wrapper around glEnableClientState(GL_SECONDARY_COLOR_ARRAY);glSecondayColorPointer(..);
855        * note, only updates values that change.*/
856        void setSecondaryColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr );
857
858        /** wrapper around glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
859        * note, only updates values that change.*/
860        inline void disableSecondaryColorPointer()
861        {
862        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
863            if (_useVertexAttributeAliasing)
864            {
865                disableVertexAttribPointer(_secondaryColorAlias._location);
866            }
867            else
868            {
869                if (_secondaryColorArray._enabled || _secondaryColorArray._dirty)
870                {
871                    _secondaryColorArray._lazy_disable = false;
872                    _secondaryColorArray._enabled = false;
873                    _secondaryColorArray._dirty = false;
874                    if (isSecondaryColorSupported()) glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
875                }
876            }
877        #else
878            disableVertexAttribPointer(_secondaryColorAlias._location);
879        #endif
880        }
881
882        inline void dirtySecondaryColorPointer()
883        {
884        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
885            if (_useVertexAttributeAliasing)
886            {
887                dirtyVertexAttribPointer(_secondaryColorAlias._location);
888            }
889            else
890            {
891                _secondaryColorArray._pointer = 0;
892                _secondaryColorArray._dirty = true;
893            }
894        #else
895            dirtyVertexAttribPointer(_secondaryColorAlias._location);
896        #endif
897        }
898
899        inline bool isFogCoordSupported() const { return _isFogCoordSupportResolved?_isFogCoordSupported:computeFogCoordSupported(); }
900
901
902        /** Set the fog coord pointer using an osg::Array, and manage any VBO that are required.*/
903        inline void setFogCoordPointer(const Array* array)
904        {
905            if (array)
906            {
907                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
908                if (vbo)
909                {
910                    bindVertexBufferObject(vbo);
911                    setFogCoordPointer(array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
912                }
913                else
914                {
915                    unbindVertexBufferObject();
916                    setFogCoordPointer(array->getDataType(),0,array->getDataPointer());
917                }
918            }
919        }
920
921
922        /** wrapper around glEnableClientState(GL_FOG_COORDINATE_ARRAY);glFogCoordPointer(..);
923        * note, only updates values that change.*/
924        void setFogCoordPointer( GLenum type, GLsizei stride, const GLvoid *ptr );
925
926        /** wrapper around glDisableClientState(GL_FOG_COORDINATE_ARRAY);
927        * note, only updates values that change.*/
928        inline void disableFogCoordPointer()
929        {
930        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
931            if (_useVertexAttributeAliasing)
932            {
933                disableVertexAttribPointer(_fogCoordAlias._location);
934            }
935            else
936            {
937                if (_fogArray._enabled || _fogArray._dirty)
938                {
939                    _fogArray._lazy_disable = false;
940                    _fogArray._enabled = false;
941                    _fogArray._dirty = false;
942                    if (isFogCoordSupported()) glDisableClientState(GL_FOG_COORDINATE_ARRAY);
943                }
944            }
945        #else
946            disableVertexAttribPointer(_fogCoordAlias._location);
947        #endif
948        }
949
950        inline void dirtyFogCoordPointer()
951        {
952        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
953            if (_useVertexAttributeAliasing)
954            {
955                dirtyVertexAttribPointer(_fogCoordAlias._location);
956            }
957            else
958            {
959                _fogArray._pointer = 0;
960                _fogArray._dirty = true;
961            }
962        #else
963            dirtyVertexAttribPointer(_fogCoordAlias._location);
964        #endif
965        }
966
967
968
969        /** Set the tex coord pointer using an osg::Array, and manage any VBO that are required.*/
970        inline void setTexCoordPointer(unsigned int unit, const Array* array)
971        {
972            if (array)
973            {
974                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
975                if (vbo)
976                {
977                    bindVertexBufferObject(vbo);
978                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
979                }
980                else
981                {
982                    unbindVertexBufferObject();
983                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,array->getDataPointer());
984                }
985            }
986        }
987
988        /** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..);
989        * note, only updates values that change.*/
990        inline void setTexCoordPointer( unsigned int unit,
991                                        GLint size, GLenum type,
992                                        GLsizei stride, const GLvoid *ptr )
993        {
994        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
995            if (_useVertexAttributeAliasing)
996            {
997                setVertexAttribPointer(_texCoordAliasList[unit]._location, size, type, GL_FALSE, stride, ptr);
998            }
999            else
1000            {
1001                if (setClientActiveTextureUnit(unit))
1002                {
1003                    if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
1004                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1005
1006                    if (!eap._enabled || eap._dirty)
1007                    {
1008                        eap._enabled = true;
1009                        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1010                    }
1011                    //if (eap._pointer!=ptr || eap._dirty)
1012                    {
1013                        glTexCoordPointer( size, type, stride, ptr );
1014                        eap._pointer = ptr;
1015                    }
1016                    eap._lazy_disable = false;
1017                    eap._dirty = false;
1018                }
1019            }
1020        #else
1021            setVertexAttribPointer(_texCoordAliasList[unit]._location, size, type, GL_FALSE, stride, ptr);
1022        #endif
1023        }
1024
1025        /** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1026        * note, only updates values that change.*/
1027        inline void disableTexCoordPointer( unsigned int unit )
1028        {
1029        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1030            if (_useVertexAttributeAliasing)
1031            {
1032                disableVertexAttribPointer(_texCoordAliasList[unit]._location);
1033            }
1034            else
1035            {
1036                if (setClientActiveTextureUnit(unit))
1037                {
1038                    if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
1039                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1040
1041                    if (eap._enabled || eap._dirty)
1042                    {
1043                        eap._lazy_disable = false;
1044                        eap._enabled = false;
1045                        eap._dirty = false;
1046                        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1047                    }
1048                }
1049            }
1050        #else
1051            disableVertexAttribPointer(_texCoordAliasList[unit]._location);
1052        #endif
1053        }
1054
1055        inline void dirtyTexCoordPointer( unsigned int unit )
1056        {
1057        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1058            if (_useVertexAttributeAliasing)
1059            {
1060                dirtyVertexAttribPointer(_texCoordAliasList[unit]._location);
1061            }
1062            else
1063            {
1064                if ( unit >= _texCoordArrayList.size()) return; // _texCoordArrayList.resize(unit+1);
1065                EnabledArrayPair& eap = _texCoordArrayList[unit];
1066                eap._pointer = 0;
1067                eap._dirty = true;
1068            }
1069        #else
1070            dirtyVertexAttribPointer(_texCoordAliasList[unit]._location);
1071        #endif
1072        }
1073
1074
1075        inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit )
1076        {
1077        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1078            if (_useVertexAttributeAliasing)
1079            {
1080                disableVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1081            }
1082            else
1083            {
1084                while (unit<_texCoordArrayList.size())
1085                {
1086                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1087                    if (eap._enabled || eap._dirty)
1088                    {
1089                        if (setClientActiveTextureUnit(unit))
1090                        {
1091                            eap._lazy_disable = false;
1092                            eap._enabled = false;
1093                            eap._dirty = false;
1094                            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1095                        }
1096                    }
1097                    ++unit;
1098                }
1099            }
1100        #else
1101            disableVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1102        #endif
1103        }
1104
1105        inline void dirtyTexCoordPointersAboveAndIncluding( unsigned int unit )
1106        {
1107        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1108            if (_useVertexAttributeAliasing)
1109            {
1110                dirtyVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1111            }
1112            else
1113            {
1114                while (unit<_texCoordArrayList.size())
1115                {
1116                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1117                    eap._pointer = 0;
1118                    eap._dirty = true;
1119                    ++unit;
1120                }
1121            }
1122        #else
1123            dirtyVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1124        #endif
1125        }
1126
1127
1128        /** Set the current texture unit, return true if selected,
1129        * false if selection failed such as when multi texturing is not supported.
1130        * note, only updates values that change.*/
1131        inline bool setActiveTextureUnit( unsigned int unit );
1132
1133        /** Get the current texture unit.*/
1134        unsigned int getActiveTextureUnit() const { return _currentActiveTextureUnit; }
1135
1136        /** Set the current tex coord array texture unit, return true if selected,
1137        * false if selection failed such as when multi texturing is not supported.
1138        * note, only updates values that change.*/
1139        bool setClientActiveTextureUnit( unsigned int unit );
1140
1141        /** Get the current tex coord array texture unit.*/
1142        unsigned int getClientActiveTextureUnit() const { return _currentClientActiveTextureUnit; }
1143
1144        /** Set the vertex attrib pointer using an osg::Array, and manage any VBO that are required.*/
1145        inline void setVertexAttribPointer(unsigned int unit, const Array* array, GLboolean normalized)
1146        {
1147            if (array)
1148            {
1149                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
1150                if (vbo)
1151                {
1152                    bindVertexBufferObject(vbo);
1153                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
1154                }
1155                else
1156                {
1157                    unbindVertexBufferObject();
1158                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,array->getDataPointer());
1159                }
1160            }
1161        }
1162
1163        /** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..);
1164        * note, only updates values that change.*/
1165        void setVertexAttribPointer( unsigned int index,
1166                                    GLint size, GLenum type, GLboolean normalized,
1167                                    GLsizei stride, const GLvoid *ptr );
1168
1169        /** wrapper around DisableVertexAttribArrayARB(index);
1170        * note, only updates values that change.*/
1171        void disableVertexAttribPointer( unsigned int index );
1172
1173        void disableVertexAttribPointersAboveAndIncluding( unsigned int index );
1174
1175        inline void dirtyVertexAttribPointer( unsigned int index )
1176        {
1177            if (index<_vertexAttribArrayList.size())
1178            {
1179                EnabledArrayPair& eap = _vertexAttribArrayList[index];
1180                eap._pointer = 0;
1181                eap._dirty = true;
1182            }
1183        }
1184
1185        inline void dirtyVertexAttribPointersAboveAndIncluding( unsigned int index )
1186        {
1187            while (index<_vertexAttribArrayList.size())
1188            {
1189                EnabledArrayPair& eap = _vertexAttribArrayList[index];
1190                eap._pointer = 0;
1191                eap._dirty = true;
1192                ++index;
1193            }
1194        }
1195
1196        bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); }
1197
1198
1199        inline void setLastAppliedProgramObject(const Program::PerContextProgram* program)
1200        {
1201            if (_lastAppliedProgramObject!=program)
1202            {
1203                _lastAppliedProgramObject = program;
1204                if (program && _appliedProgramObjectSet.count(program)==0)
1205                {
1206                    _appliedProgramObjectSet.insert(program);
1207                    program->addObserver(this);
1208                }
1209            }
1210        }
1211        inline const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; }
1212
1213        inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; }
1214        inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; }
1215
1216        typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue>  AttributePair;
1217        typedef std::vector<AttributePair>                                      AttributeVec;
1218
1219        AttributeVec& getAttributeVec( const osg::StateAttribute* attribute )
1220        {
1221                AttributeStack& as = _attributeMap[ attribute->getTypeMemberPair() ];
1222                return as.attributeVec;
1223        }
1224
1225        /** Set the frame stamp for the current frame.*/
1226        inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
1227
1228        /** Get the frame stamp for the current frame.*/
1229        inline FrameStamp* getFrameStamp() { return _frameStamp.get(); }
1230
1231        /** Get the const frame stamp for the current frame.*/
1232        inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
1233
1234
1235        /** Set the DisplaySettings. Note, nothing is applied, the visual settings are just
1236        * used in the State object to pass the current visual settings to Drawables
1237        * during rendering. */
1238        inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
1239
1240        /** Get the DisplaySettings */
1241        inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
1242
1243
1244
1245        /** Set flag for early termination of the draw traversal.*/
1246        void setAbortRenderingPtr(bool* abortPtr) { _abortRenderingPtr = abortPtr; }
1247
1248        /** Get flag for early termination of the draw traversal,
1249        * if true steps should be taken to complete rendering early.*/
1250        bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
1251
1252
1253        struct DynamicObjectRenderingCompletedCallback : public osg::Referenced
1254        {
1255            virtual void completed(osg::State*) = 0;
1256        };
1257
1258        /** Set the callback to be called when the dynamic object count hits 0.*/
1259        void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; }
1260
1261        /** Get the callback to be called when the dynamic object count hits 0.*/
1262        DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); }
1263
1264        /** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/
1265        void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false)
1266        {
1267            if (_dynamicObjectCount != count)
1268            {
1269                _dynamicObjectCount = count;
1270                if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid())
1271                {
1272                    _completeDynamicObjectRenderingCallback->completed(this);
1273                }
1274            }
1275        }
1276
1277        /** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/
1278        unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; }
1279
1280        /** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the
1281        * DynamicObjectRenderingCompletedCallback to inform of completion.*/
1282        inline void decrementDynamicObjectCount()
1283        {
1284            --_dynamicObjectCount;
1285            if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid())
1286            {
1287                _completeDynamicObjectRenderingCallback->completed(this);
1288            }
1289        }
1290
1291        void setMaxTexturePoolSize(unsigned int size);
1292        unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; }
1293
1294        void setMaxBufferObjectPoolSize(unsigned int size);
1295        unsigned int getMaxBufferObjectPoolSize() const { return _maxBufferObjectPoolSize; }
1296
1297
1298        enum CheckForGLErrors
1299        {
1300            /** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
1301                is the fastest option since checking for errors does incurr a small overhead.*/
1302            NEVER_CHECK_GL_ERRORS,
1303            /** ONCE_PER_FRAME means that OpenGl errors will be checked for once per
1304                frame, the overhead is still small, but at least OpenGL errors that are occurring
1305                will be caught, the reporting isn't fine grained enough for debugging purposes.*/
1306            ONCE_PER_FRAME,
1307            /** ONCE_PER_ATTRIBUTE means that OpenGL errors will be checked for after
1308                every attribute is applied, allow errors to be directly associated with
1309                particular operations which makes debugging much easier.*/
1310            ONCE_PER_ATTRIBUTE
1311        };
1312
1313        /** Set whether and how often OpenGL errors should be checked for.*/
1314        void setCheckForGLErrors(CheckForGLErrors check) { _checkGLErrors = check; }
1315
1316        /** Get whether and how often OpenGL errors should be checked for.*/
1317        CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
1318
1319        bool checkGLErrors(const char* str) const;
1320        bool checkGLErrors(StateAttribute::GLMode mode) const;
1321        bool checkGLErrors(const StateAttribute* attribute) const;
1322
1323
1324        /** Initialize extension used by osg:::State.*/
1325        void initializeExtensionProcs();
1326
1327        virtual void objectDeleted(void* object);
1328
1329        /** get the GL adapter object used to map OpenGL 1.0 glBegin/glEnd usage to vertex arrays.*/
1330        inline GLBeginEndAdapter& getGLBeginEndAdapter() { return _glBeginEndAdapter; }
1331
1332        /** get the helper class for dispatching osg::Arrays as OpenGL attribute data.*/
1333        inline ArrayDispatchers& getArrayDispatchers() { return _arrayDispatchers; }
1334
1335    protected:
1336
1337        virtual ~State();
1338
1339        GraphicsContext*            _graphicsContext;
1340        unsigned int                _contextID;
1341        ref_ptr<FrameStamp>         _frameStamp;
1342
1343        ref_ptr<const RefMatrix>    _identity;
1344        ref_ptr<const RefMatrix>    _initialViewMatrix;
1345        ref_ptr<const RefMatrix>    _projection;
1346        ref_ptr<const RefMatrix>    _modelView;
1347
1348        bool                        _useModelViewAndProjectionUniforms;
1349        ref_ptr<Uniform>            _modelViewMatrixUniform;
1350        ref_ptr<Uniform>            _projectionMatrixUniform;
1351        ref_ptr<Uniform>            _modelViewProjectionMatrixUniform;
1352        ref_ptr<Uniform>            _normalMatrixUniform;
1353
1354        Matrix                      _initialInverseViewMatrix;
1355
1356        ref_ptr<DisplaySettings>    _displaySettings;
1357
1358        bool*                       _abortRenderingPtr;
1359        CheckForGLErrors            _checkGLErrors;
1360
1361
1362        bool                        _useVertexAttributeAliasing;
1363        VertexAttribAlias           _vertexAlias;
1364        VertexAttribAlias           _normalAlias;
1365        VertexAttribAlias           _colorAlias;
1366        VertexAttribAlias           _secondaryColorAlias;
1367        VertexAttribAlias           _fogCoordAlias;
1368        VertexAttribAliasList       _texCoordAliasList;
1369
1370        Program::AttribBindingList  _attributeBindingList;
1371
1372        void setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration);
1373
1374
1375        struct ModeStack
1376        {
1377            typedef std::vector<StateAttribute::GLModeValue> ValueVec;
1378
1379            ModeStack()
1380            {
1381                valid = true;
1382                changed = false;
1383                last_applied_value = false;
1384                global_default_value = false;
1385            }
1386
1387            bool        valid;
1388            bool        changed;
1389            bool        last_applied_value;
1390            bool        global_default_value;
1391            ValueVec    valueVec;
1392        };
1393
1394        struct AttributeStack
1395        {
1396            AttributeStack()
1397            {
1398                changed = false;
1399                last_applied_attribute = 0L;
1400                global_default_attribute = 0L;
1401            }
1402
1403            /** apply an attribute if required, passing in attribute and appropriate attribute stack */
1404            bool                    changed;
1405            const StateAttribute*   last_applied_attribute;
1406            ref_ptr<const StateAttribute> global_default_attribute;
1407            AttributeVec            attributeVec;
1408        };
1409
1410
1411        struct UniformStack
1412        {
1413            typedef std::pair<const Uniform*,StateAttribute::OverrideValue>         UniformPair;
1414            typedef std::vector<UniformPair>                                        UniformVec;
1415
1416            UniformStack() {}
1417
1418            UniformVec              uniformVec;
1419        };
1420
1421
1422        /** Apply an OpenGL mode if required, passing in mode, enable flag and
1423        * appropriate mode stack. This is a wrapper around \c glEnable() and
1424        * \c glDisable(), that just actually calls these functions if the
1425        * \c enabled flag is different than the current state.
1426        * @return \c true if the state was actually changed. \c false
1427        *         otherwise. Notice that a \c false return does not indicate
1428        *         an error, it just means that the mode was already set to the
1429        *         same value as the \c enabled parameter.
1430        */
1431        inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
1432        {
1433            if (ms.valid && ms.last_applied_value != enabled)
1434            {
1435                ms.last_applied_value = enabled;
1436
1437                if (enabled) glEnable(mode);
1438                else glDisable(mode);
1439
1440                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
1441
1442                return true;
1443            }
1444            else
1445                return false;
1446        }
1447
1448        inline bool applyModeOnTexUnit(unsigned int unit,StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
1449        {
1450            if (ms.valid && ms.last_applied_value != enabled)
1451            {
1452                if (setActiveTextureUnit(unit))
1453                {
1454                    ms.last_applied_value = enabled;
1455
1456                    if (enabled) glEnable(mode);
1457                    else glDisable(mode);
1458
1459                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
1460
1461                    return true;
1462                }
1463                else
1464                    return false;
1465            }
1466            else
1467                return false;
1468        }
1469
1470        /** apply an attribute if required, passing in attribute and appropriate attribute stack */
1471        inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
1472        {
1473            if (as.last_applied_attribute != attribute)
1474            {
1475                if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
1476
1477                as.last_applied_attribute = attribute;
1478                attribute->apply(*this);
1479
1480                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
1481
1482                return true;
1483            }
1484            else
1485                return false;
1486        }
1487
1488        inline bool applyAttributeOnTexUnit(unsigned int unit,const StateAttribute* attribute,AttributeStack& as)
1489        {
1490            if (as.last_applied_attribute != attribute)
1491            {
1492                if (setActiveTextureUnit(unit))
1493                {
1494                    if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
1495
1496                    as.last_applied_attribute = attribute;
1497                    attribute->apply(*this);
1498
1499                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
1500
1501                    return true;
1502                }
1503                else
1504                    return false;
1505            }
1506            else
1507                return false;
1508        }
1509
1510
1511        inline bool applyGlobalDefaultAttribute(AttributeStack& as)
1512        {
1513            if (as.last_applied_attribute != as.global_default_attribute.get())
1514            {
1515                as.last_applied_attribute = as.global_default_attribute.get();
1516                if (as.global_default_attribute.valid())
1517                {
1518                    as.global_default_attribute->apply(*this);
1519                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
1520                }
1521                return true;
1522            }
1523            else
1524                return false;
1525        }
1526
1527        inline bool applyGlobalDefaultAttributeOnTexUnit(unsigned int unit,AttributeStack& as)
1528        {
1529            if (as.last_applied_attribute != as.global_default_attribute.get())
1530            {
1531                if (setActiveTextureUnit(unit))
1532                {
1533                    as.last_applied_attribute = as.global_default_attribute.get();
1534                    if (as.global_default_attribute.valid())
1535                    {
1536                        as.global_default_attribute->apply(*this);
1537                        if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
1538                    }
1539                    return true;
1540                }
1541                else
1542                    return false;
1543            }
1544            else
1545                return false;
1546        }
1547
1548
1549        typedef std::map<StateAttribute::GLMode,ModeStack>              ModeMap;
1550        typedef std::vector<ModeMap>                                    TextureModeMapList;
1551
1552        typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
1553        typedef std::vector<AttributeMap>                               TextureAttributeMapList;
1554
1555        typedef std::map<std::string,UniformStack>                      UniformMap;
1556
1557        typedef std::vector<ref_ptr<const Matrix> >                     MatrixStack;
1558
1559        typedef std::set<const Program::PerContextProgram* >            AppliedProgramObjectSet;
1560
1561        ModeMap                                                         _modeMap;
1562        AttributeMap                                                    _attributeMap;
1563        UniformMap                                                      _uniformMap;
1564
1565        TextureModeMapList                                              _textureModeMapList;
1566        TextureAttributeMapList                                         _textureAttributeMapList;
1567
1568        AppliedProgramObjectSet                                         _appliedProgramObjectSet;
1569        const Program::PerContextProgram*                               _lastAppliedProgramObject;
1570
1571        StateSetStack                                                   _stateStateStack;
1572
1573        unsigned int                                                    _maxTexturePoolSize;
1574        unsigned int                                                    _maxBufferObjectPoolSize;
1575
1576
1577        struct EnabledArrayPair
1578        {
1579            EnabledArrayPair():_lazy_disable(false),_dirty(true),_enabled(false),_normalized(0),_pointer(0) {}
1580            EnabledArrayPair(const EnabledArrayPair& eap):_lazy_disable(eap._lazy_disable),_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {}
1581            EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _lazy_disable = eap._lazy_disable;_dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; }
1582
1583            bool            _lazy_disable;
1584            bool            _dirty;
1585            bool            _enabled;
1586            GLboolean       _normalized;
1587            const GLvoid*   _pointer;
1588        };
1589
1590        typedef std::vector<EnabledArrayPair>                   EnabledTexCoordArrayList;
1591        typedef std::vector<EnabledArrayPair>                   EnabledVertexAttribArrayList;
1592
1593        EnabledArrayPair                _vertexArray;
1594        EnabledArrayPair                _normalArray;
1595        EnabledArrayPair                _colorArray;
1596        EnabledArrayPair                _secondaryColorArray;
1597        EnabledArrayPair                _fogArray;
1598        EnabledTexCoordArrayList        _texCoordArrayList;
1599        EnabledVertexAttribArrayList    _vertexAttribArrayList;
1600
1601        unsigned int                    _currentActiveTextureUnit;
1602        unsigned int                    _currentClientActiveTextureUnit;
1603        GLBufferObject*                 _currentVBO;
1604        GLBufferObject*                 _currentEBO;
1605        GLBufferObject*                 _currentPBO;
1606
1607
1608        inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
1609        {
1610            if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
1611            return _textureModeMapList[unit];
1612        }
1613
1614
1615        inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
1616        {
1617            if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
1618            return _textureAttributeMapList[unit];
1619        }
1620
1621        inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1622        inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1623        inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1624
1625        inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1626        inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1627        inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1628
1629        inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1630        inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1631        inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1632
1633        inline void applyModeMap(ModeMap& modeMap);
1634        inline void applyAttributeMap(AttributeMap& attributeMap);
1635        inline void applyUniformMap(UniformMap& uniformMap);
1636
1637        inline void applyModeListOnTexUnit(unsigned int unit,ModeMap& modeMap,const StateSet::ModeList& modeList);
1638        inline void applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1639
1640        inline void applyModeMapOnTexUnit(unsigned int unit,ModeMap& modeMap);
1641        inline void applyAttributeMapOnTexUnit(unsigned int unit,AttributeMap& attributeMap);
1642
1643        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
1644        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
1645        void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
1646        void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member);
1647        bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
1648        const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const;
1649
1650
1651        mutable bool _isSecondaryColorSupportResolved;
1652        mutable bool _isSecondaryColorSupported;
1653        bool computeSecondaryColorSupported() const;
1654
1655        mutable bool _isFogCoordSupportResolved;
1656        mutable bool _isFogCoordSupported;
1657        bool computeFogCoordSupported() const;
1658
1659        mutable bool _isVertexBufferObjectSupportResolved;
1660        mutable bool _isVertexBufferObjectSupported;
1661        bool computeVertexBufferObjectSupported() const;
1662
1663        typedef void (APIENTRY * ActiveTextureProc) (GLenum texture);
1664        typedef void (APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer);
1665        typedef void (APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
1666        typedef void (APIENTRY * MultiTexCoord4fProc) (GLenum target, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
1667        typedef void (APIENTRY * VertexAttrib4fProc)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
1668        typedef void (APIENTRY * VertexAttrib4fvProc)(GLuint index, const GLfloat *v);
1669        typedef void (APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
1670        typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int);
1671        typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int);
1672        typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
1673
1674        typedef void (APIENTRY * DrawArraysInstancedProc)( GLenum mode, GLint first, GLsizei count, GLsizei primcount );
1675        typedef void (APIENTRY * DrawElementsInstancedProc)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount );
1676
1677        bool                        _extensionProcsInitialized;
1678        GLint                       _glMaxTextureCoords;
1679        GLint                       _glMaxTextureUnits;
1680        ActiveTextureProc           _glClientActiveTexture;
1681        ActiveTextureProc           _glActiveTexture;
1682        MultiTexCoord4fProc         _glMultiTexCoord4f;
1683        VertexAttrib4fProc          _glVertexAttrib4f;
1684        VertexAttrib4fvProc         _glVertexAttrib4fv;
1685        FogCoordPointerProc         _glFogCoordPointer;
1686        SecondaryColorPointerProc   _glSecondaryColorPointer;
1687        VertexAttribPointerProc     _glVertexAttribPointer;
1688        EnableVertexAttribProc      _glEnableVertexAttribArray;
1689        DisableVertexAttribProc     _glDisableVertexAttribArray;
1690        BindBufferProc              _glBindBuffer;
1691        DrawArraysInstancedProc     _glDrawArraysInstanced;
1692        DrawElementsInstancedProc   _glDrawElementsInstanced;
1693
1694        unsigned int                                            _dynamicObjectCount;
1695        osg::ref_ptr<DynamicObjectRenderingCompletedCallback>   _completeDynamicObjectRenderingCallback;
1696
1697        GLBeginEndAdapter           _glBeginEndAdapter;
1698        ArrayDispatchers            _arrayDispatchers;
1699
1700};
1701
1702inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1703{
1704    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1705        mitr!=modeList.end();
1706        ++mitr)
1707    {
1708        // get the mode stack for incoming GLmode {mitr->first}.
1709        ModeStack& ms = modeMap[mitr->first];
1710        if (ms.valueVec.empty())
1711        {
1712            // first pair so simply push incoming pair to back.
1713            ms.valueVec.push_back(mitr->second);
1714        }
1715        else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
1716        {
1717            // push existing back since override keeps the previous value.
1718            ms.valueVec.push_back(ms.valueVec.back());
1719        }
1720        else
1721        {
1722            // no override on so simply push incoming pair to back.
1723            ms.valueVec.push_back(mitr->second);
1724        }
1725        ms.changed = true;
1726    }
1727}
1728
1729inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1730{
1731    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1732        aitr!=attributeList.end();
1733        ++aitr)
1734    {
1735        // get the attribute stack for incoming type {aitr->first}.
1736        AttributeStack& as = attributeMap[aitr->first];
1737        if (as.attributeVec.empty())
1738        {
1739            // first pair so simply push incoming pair to back.
1740            as.attributeVec.push_back(
1741                AttributePair(aitr->second.first.get(),aitr->second.second));
1742        }
1743        else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1744        {
1745            // push existing back since override keeps the previous value.
1746            as.attributeVec.push_back(as.attributeVec.back());
1747        }
1748        else
1749        {
1750            // no override on so simply push incoming pair to back.
1751            as.attributeVec.push_back(
1752                AttributePair(aitr->second.first.get(),aitr->second.second));
1753        }
1754        as.changed = true;
1755    }
1756}
1757
1758
1759inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1760{
1761    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1762        aitr!=uniformList.end();
1763        ++aitr)
1764    {
1765        // get the attribute stack for incoming type {aitr->first}.
1766        UniformStack& us = uniformMap[aitr->first];
1767        if (us.uniformVec.empty())
1768        {
1769            // first pair so simply push incoming pair to back.
1770            us.uniformVec.push_back(
1771                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1772        }
1773        else if ((us.uniformVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1774        {
1775            // push existing back since override keeps the previous value.
1776            us.uniformVec.push_back(us.uniformVec.back());
1777        }
1778        else
1779        {
1780            // no override on so simply push incoming pair to back.
1781            us.uniformVec.push_back(
1782                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1783        }
1784    }
1785}
1786
1787inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1788{
1789    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1790        mitr!=modeList.end();
1791        ++mitr)
1792    {
1793        // get the mode stack for incoming GLmode {mitr->first}.
1794        ModeStack& ms = modeMap[mitr->first];
1795        if (!ms.valueVec.empty())
1796        {
1797            ms.valueVec.pop_back();
1798        }
1799        ms.changed = true;
1800    }
1801}
1802
1803inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1804{
1805    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1806        aitr!=attributeList.end();
1807        ++aitr)
1808    {
1809        // get the attribute stack for incoming type {aitr->first}.
1810        AttributeStack& as = attributeMap[aitr->first];
1811        if (!as.attributeVec.empty())
1812        {
1813            as.attributeVec.pop_back();
1814        }
1815        as.changed = true;
1816    }
1817}
1818
1819inline void State::popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1820{
1821    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1822        aitr!=uniformList.end();
1823        ++aitr)
1824    {
1825        // get the attribute stack for incoming type {aitr->first}.
1826        UniformStack& us = uniformMap[aitr->first];
1827        if (!us.uniformVec.empty())
1828        {
1829            us.uniformVec.pop_back();
1830        }
1831    }
1832}
1833
1834inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1835{
1836    StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
1837    ModeMap::iterator this_mitr=modeMap.begin();
1838
1839    while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
1840    {
1841        if (this_mitr->first<ds_mitr->first)
1842        {
1843
1844            // note GLMode = this_mitr->first
1845            ModeStack& ms = this_mitr->second;
1846            if (ms.changed)
1847            {
1848                ms.changed = false;
1849                if (!ms.valueVec.empty())
1850                {
1851                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1852                    applyMode(this_mitr->first,new_value,ms);
1853                }
1854                else
1855                {
1856                    // assume default of disabled.
1857                    applyMode(this_mitr->first,ms.global_default_value,ms);
1858
1859                }
1860
1861            }
1862
1863            ++this_mitr;
1864
1865        }
1866        else if (ds_mitr->first<this_mitr->first)
1867        {
1868
1869            // ds_mitr->first is a new mode, therefore
1870            // need to insert a new mode entry for ds_mistr->first.
1871            ModeStack& ms = modeMap[ds_mitr->first];
1872
1873            bool new_value = ds_mitr->second & StateAttribute::ON;
1874            applyMode(ds_mitr->first,new_value,ms);
1875
1876            // will need to disable this mode on next apply so set it to changed.
1877            ms.changed = true;
1878
1879            ++ds_mitr;
1880
1881        }
1882        else
1883        {
1884            // this_mitr & ds_mitr refer to the same mode, check the override
1885            // if any otherwise just apply the incoming mode.
1886
1887            ModeStack& ms = this_mitr->second;
1888
1889            if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
1890            {
1891                // override is on, just treat as a normal apply on modes.
1892
1893                if (ms.changed)
1894                {
1895                    ms.changed = false;
1896                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1897                    applyMode(this_mitr->first,new_value,ms);
1898
1899                }
1900            }
1901            else
1902            {
1903                // no override on or no previous entry, therefore consider incoming mode.
1904                bool new_value = ds_mitr->second & StateAttribute::ON;
1905                if (applyMode(ds_mitr->first,new_value,ms))
1906                {
1907                    ms.changed = true;
1908                }
1909            }
1910
1911            ++this_mitr;
1912            ++ds_mitr;
1913        }
1914    }
1915
1916    // iterator over the remaining state modes to apply any previous changes.
1917    for(;
1918        this_mitr!=modeMap.end();
1919        ++this_mitr)
1920    {
1921        // note GLMode = this_mitr->first
1922        ModeStack& ms = this_mitr->second;
1923        if (ms.changed)
1924        {
1925            ms.changed = false;
1926            if (!ms.valueVec.empty())
1927            {
1928                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1929                applyMode(this_mitr->first,new_value,ms);
1930            }
1931            else
1932            {
1933                // assume default of disabled.
1934                applyMode(this_mitr->first,ms.global_default_value,ms);
1935
1936            }
1937
1938        }
1939    }
1940
1941    // iterator over the remaining incoming modes to apply any new mode.
1942    for(;
1943        ds_mitr!=modeList.end();
1944        ++ds_mitr)
1945    {
1946        ModeStack& ms = modeMap[ds_mitr->first];
1947
1948        bool new_value = ds_mitr->second & StateAttribute::ON;
1949        applyMode(ds_mitr->first,new_value,ms);
1950
1951        // will need to disable this mode on next apply so set it to changed.
1952        ms.changed = true;
1953    }
1954}
1955
1956inline void State::applyModeListOnTexUnit(unsigned int unit,ModeMap& modeMap,const StateSet::ModeList& modeList)
1957{
1958    StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
1959    ModeMap::iterator this_mitr=modeMap.begin();
1960
1961    while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
1962    {
1963        if (this_mitr->first<ds_mitr->first)
1964        {
1965
1966            // note GLMode = this_mitr->first
1967            ModeStack& ms = this_mitr->second;
1968            if (ms.changed)
1969            {
1970                ms.changed = false;
1971                if (!ms.valueVec.empty())
1972                {
1973                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1974                    applyModeOnTexUnit(unit,this_mitr->first,new_value,ms);
1975                }
1976                else
1977                {
1978                    // assume default of disabled.
1979                    applyModeOnTexUnit(unit,this_mitr->first,ms.global_default_value,ms);
1980
1981                }
1982
1983            }
1984
1985            ++this_mitr;
1986
1987        }
1988        else if (ds_mitr->first<this_mitr->first)
1989        {
1990
1991            // ds_mitr->first is a new mode, therefore
1992            // need to insert a new mode entry for ds_mistr->first.
1993            ModeStack& ms = modeMap[ds_mitr->first];
1994
1995            bool new_value = ds_mitr->second & StateAttribute::ON;
1996            applyModeOnTexUnit(unit,ds_mitr->first,new_value,ms);
1997
1998            // will need to disable this mode on next apply so set it to changed.
1999            ms.changed = true;
2000
2001            ++ds_mitr;
2002
2003        }
2004        else
2005        {
2006            // this_mitr & ds_mitr refer to the same mode, check the override
2007            // if any otherwise just apply the incoming mode.
2008
2009            ModeStack& ms = this_mitr->second;
2010
2011            if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
2012            {
2013                // override is on, just treat as a normal apply on modes.
2014
2015                if (ms.changed)
2016                {
2017                    ms.changed = false;
2018                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
2019                    applyModeOnTexUnit(unit,this_mitr->first,new_value,ms);
2020
2021                }
2022            }
2023            else
2024            {
2025                // no override on or no previous entry, therefore consider incoming mode.
2026                bool new_value = ds_mitr->second & StateAttribute::ON;
2027                if (applyModeOnTexUnit(unit,ds_mitr->first,new_value,ms))
2028                {
2029                    ms.changed = true;
2030                }
2031            }
2032
2033            ++this_mitr;
2034            ++ds_mitr;
2035        }
2036    }
2037
2038    // iterator over the remaining state modes to apply any previous changes.
2039    for(;
2040        this_mitr!=modeMap.end();
2041        ++this_mitr)
2042    {
2043        // note GLMode = this_mitr->first
2044        ModeStack& ms = this_mitr->second;
2045        if (ms.changed)
2046        {
2047            ms.changed = false;
2048            if (!ms.valueVec.empty())
2049            {
2050                bool new_value = ms.valueVec.back() & StateAttribute::ON;
2051                applyModeOnTexUnit(unit,this_mitr->first,new_value,ms);
2052            }
2053            else
2054            {
2055                // assume default of disabled.
2056                applyModeOnTexUnit(unit,this_mitr->first,ms.global_default_value,ms);
2057
2058            }
2059
2060        }
2061    }
2062
2063    // iterator over the remaining incoming modes to apply any new mode.
2064    for(;
2065        ds_mitr!=modeList.end();
2066        ++ds_mitr)
2067    {
2068        ModeStack& ms = modeMap[ds_mitr->first];
2069
2070        bool new_value = ds_mitr->second & StateAttribute::ON;
2071        applyModeOnTexUnit(unit,ds_mitr->first,new_value,ms);
2072
2073        // will need to disable this mode on next apply so set it to changed.
2074        ms.changed = true;
2075    }
2076}
2077
2078inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
2079{
2080    StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
2081
2082    AttributeMap::iterator this_aitr=attributeMap.begin();
2083
2084    while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
2085    {
2086        if (this_aitr->first<ds_aitr->first)
2087        {
2088
2089            // note attribute type = this_aitr->first
2090            AttributeStack& as = this_aitr->second;
2091            if (as.changed)
2092            {
2093                as.changed = false;
2094                if (!as.attributeVec.empty())
2095                {
2096                    const StateAttribute* new_attr = as.attributeVec.back().first;
2097                    applyAttribute(new_attr,as);
2098                }
2099                else
2100                {
2101                    applyGlobalDefaultAttribute(as);
2102                }
2103            }
2104
2105            ++this_aitr;
2106
2107        }
2108        else if (ds_aitr->first<this_aitr->first)
2109        {
2110
2111            // ds_aitr->first is a new attribute, therefore
2112            // need to insert a new attribute entry for ds_aitr->first.
2113            AttributeStack& as = attributeMap[ds_aitr->first];
2114
2115            const StateAttribute* new_attr = ds_aitr->second.first.get();
2116            applyAttribute(new_attr,as);
2117
2118            as.changed = true;
2119
2120            ++ds_aitr;
2121
2122        }
2123        else
2124        {
2125            // this_mitr & ds_mitr refer to the same attribute, check the override
2126            // if any otherwise just apply the incoming attribute
2127
2128            AttributeStack& as = this_aitr->second;
2129
2130            if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
2131            {
2132                // override is on, just treat as a normal apply on attribute.
2133
2134                if (as.changed)
2135                {
2136                    as.changed = false;
2137                    const StateAttribute* new_attr = as.attributeVec.back().first;
2138                    applyAttribute(new_attr,as);
2139                }
2140            }
2141            else
2142            {
2143                // no override on or no previous entry, therefore consider incoming attribute.
2144                const StateAttribute* new_attr = ds_aitr->second.first.get();
2145                if (applyAttribute(new_attr,as))
2146                {
2147                    as.changed = true;
2148                }
2149            }
2150
2151            ++this_aitr;
2152            ++ds_aitr;
2153        }
2154    }
2155
2156    // iterator over the remaining state attributes to apply any previous changes.
2157    for(;
2158        this_aitr!=attributeMap.end();
2159        ++this_aitr)
2160    {
2161        // note attribute type = this_aitr->first
2162        AttributeStack& as = this_aitr->second;
2163        if (as.changed)
2164        {
2165            as.changed = false;
2166            if (!as.attributeVec.empty())
2167            {
2168                const StateAttribute* new_attr = as.attributeVec.back().first;
2169                applyAttribute(new_attr,as);
2170            }
2171            else
2172            {
2173                applyGlobalDefaultAttribute(as);
2174            }
2175        }
2176    }
2177
2178    // iterator over the remaining incoming attribute to apply any new attribute.
2179    for(;
2180        ds_aitr!=attributeList.end();
2181        ++ds_aitr)
2182    {
2183        // ds_aitr->first is a new attribute, therefore
2184        // need to insert a new attribute entry for ds_aitr->first.
2185        AttributeStack& as = attributeMap[ds_aitr->first];
2186
2187        const StateAttribute* new_attr = ds_aitr->second.first.get();
2188        applyAttribute(new_attr,as);
2189
2190        // will need to update this attribute on next apply so set it to changed.
2191        as.changed = true;
2192    }
2193
2194}
2195
2196inline void State::applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
2197{
2198    StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
2199
2200    AttributeMap::iterator this_aitr=attributeMap.begin();
2201
2202    while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
2203    {
2204        if (this_aitr->first<ds_aitr->first)
2205        {
2206
2207            // note attribute type = this_aitr->first
2208            AttributeStack& as = this_aitr->second;
2209            if (as.changed)
2210            {
2211                as.changed = false;
2212                if (!as.attributeVec.empty())
2213                {
2214                    const StateAttribute* new_attr = as.attributeVec.back().first;
2215                    applyAttributeOnTexUnit(unit,new_attr,as);
2216                }
2217                else
2218                {
2219                    applyGlobalDefaultAttributeOnTexUnit(unit,as);
2220                }
2221            }
2222
2223            ++this_aitr;
2224
2225        }
2226        else if (ds_aitr->first<this_aitr->first)
2227        {
2228
2229            // ds_aitr->first is a new attribute, therefore
2230            // need to insert a new attribute entry for ds_aitr->first.
2231            AttributeStack& as = attributeMap[ds_aitr->first];
2232
2233            const StateAttribute* new_attr = ds_aitr->second.first.get();
2234            applyAttributeOnTexUnit(unit,new_attr,as);
2235
2236            as.changed = true;
2237
2238            ++ds_aitr;
2239
2240        }
2241        else
2242        {
2243            // this_mitr & ds_mitr refer to the same attribute, check the override
2244            // if any otherwise just apply the incoming attribute
2245
2246            AttributeStack& as = this_aitr->second;
2247
2248            if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
2249            {
2250                // override is on, just treat as a normal apply on attribute.
2251
2252                if (as.changed)
2253                {
2254                    as.changed = false;
2255                    const StateAttribute* new_attr = as.attributeVec.back().first;
2256                    applyAttributeOnTexUnit(unit,new_attr,as);
2257                }
2258            }
2259            else
2260            {
2261                // no override on or no previous entry, therefore consider incoming attribute.
2262                const StateAttribute* new_attr = ds_aitr->second.first.get();
2263                if (applyAttributeOnTexUnit(unit,new_attr,as))
2264                {
2265                    as.changed = true;
2266                }
2267            }
2268
2269            ++this_aitr;
2270            ++ds_aitr;
2271        }
2272    }
2273
2274    // iterator over the remaining state attributes to apply any previous changes.
2275    for(;
2276        this_aitr!=attributeMap.end();
2277        ++this_aitr)
2278    {
2279        // note attribute type = this_aitr->first
2280        AttributeStack& as = this_aitr->second;
2281        if (as.changed)
2282        {
2283            as.changed = false;
2284            if (!as.attributeVec.empty())
2285            {
2286                const StateAttribute* new_attr = as.attributeVec.back().first;
2287                applyAttributeOnTexUnit(unit,new_attr,as);
2288            }
2289            else
2290            {
2291                applyGlobalDefaultAttributeOnTexUnit(unit,as);
2292            }
2293        }
2294    }
2295
2296    // iterator over the remaining incoming attribute to apply any new attribute.
2297    for(;
2298        ds_aitr!=attributeList.end();
2299        ++ds_aitr)
2300    {
2301        // ds_aitr->first is a new attribute, therefore
2302        // need to insert a new attribute entry for ds_aitr->first.
2303        AttributeStack& as = attributeMap[ds_aitr->first];
2304
2305        const StateAttribute* new_attr = ds_aitr->second.first.get();
2306        applyAttributeOnTexUnit(unit,new_attr,as);
2307
2308        // will need to update this attribute on next apply so set it to changed.
2309        as.changed = true;
2310    }
2311
2312}
2313
2314inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
2315{
2316    if (!_lastAppliedProgramObject) return;
2317
2318    StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
2319
2320    UniformMap::iterator this_aitr=uniformMap.begin();
2321
2322    while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
2323    {
2324        if (this_aitr->first<ds_aitr->first)
2325        {
2326            // note attribute type = this_aitr->first
2327            UniformStack& as = this_aitr->second;
2328            if (!as.uniformVec.empty())
2329            {
2330                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2331            }
2332
2333            ++this_aitr;
2334
2335        }
2336        else if (ds_aitr->first<this_aitr->first)
2337        {
2338            _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
2339
2340            ++ds_aitr;
2341        }
2342        else
2343        {
2344            // this_mitr & ds_mitr refer to the same attribute, check the override
2345            // if any otherwise just apply the incoming attribute
2346
2347            UniformStack& as = this_aitr->second;
2348
2349            if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
2350            {
2351                // override is on, just treat as a normal apply on uniform.
2352                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2353            }
2354            else
2355            {
2356                // no override on or no previous entry, therefore consider incoming attribute.
2357                _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
2358            }
2359
2360            ++this_aitr;
2361            ++ds_aitr;
2362        }
2363    }
2364
2365    // iterator over the remaining state attributes to apply any previous changes.
2366    for(;
2367        this_aitr!=uniformMap.end();
2368        ++this_aitr)
2369    {
2370        // note attribute type = this_aitr->first
2371        UniformStack& as = this_aitr->second;
2372        if (!as.uniformVec.empty())
2373        {
2374            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2375        }
2376    }
2377
2378    // iterator over the remaining incoming attribute to apply any new attribute.
2379    for(;
2380        ds_aitr!=uniformList.end();
2381        ++ds_aitr)
2382    {
2383        _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
2384    }
2385
2386}
2387
2388inline void State::applyModeMap(ModeMap& modeMap)
2389{
2390    for(ModeMap::iterator mitr=modeMap.begin();
2391        mitr!=modeMap.end();
2392        ++mitr)
2393    {
2394        // note GLMode = mitr->first
2395        ModeStack& ms = mitr->second;
2396        if (ms.changed)
2397        {
2398            ms.changed = false;
2399            if (!ms.valueVec.empty())
2400            {
2401                bool new_value = ms.valueVec.back() & StateAttribute::ON;
2402                applyMode(mitr->first,new_value,ms);
2403            }
2404            else
2405            {
2406                // assume default of disabled.
2407                applyMode(mitr->first,ms.global_default_value,ms);
2408            }
2409
2410        }
2411    }
2412}
2413
2414inline void State::applyModeMapOnTexUnit(unsigned int unit,ModeMap& modeMap)
2415{
2416    for(ModeMap::iterator mitr=modeMap.begin();
2417        mitr!=modeMap.end();
2418        ++mitr)
2419    {
2420        // note GLMode = mitr->first
2421        ModeStack& ms = mitr->second;
2422        if (ms.changed)
2423        {
2424            ms.changed = false;
2425            if (!ms.valueVec.empty())
2426            {
2427                bool new_value = ms.valueVec.back() & StateAttribute::ON;
2428                applyModeOnTexUnit(unit,mitr->first,new_value,ms);
2429            }
2430            else
2431            {
2432                // assume default of disabled.
2433                applyModeOnTexUnit(unit,mitr->first,ms.global_default_value,ms);
2434            }
2435
2436        }
2437    }
2438}
2439
2440inline void State::applyAttributeMap(AttributeMap& attributeMap)
2441{
2442    for(AttributeMap::iterator aitr=attributeMap.begin();
2443        aitr!=attributeMap.end();
2444        ++aitr)
2445    {
2446        AttributeStack& as = aitr->second;
2447        if (as.changed)
2448        {
2449            as.changed = false;
2450            if (!as.attributeVec.empty())
2451            {
2452                const StateAttribute* new_attr = as.attributeVec.back().first;
2453                applyAttribute(new_attr,as);
2454            }
2455            else
2456            {
2457                applyGlobalDefaultAttribute(as);
2458            }
2459
2460        }
2461    }
2462}
2463
2464inline void State::applyAttributeMapOnTexUnit(unsigned int unit,AttributeMap& attributeMap)
2465{
2466    for(AttributeMap::iterator aitr=attributeMap.begin();
2467        aitr!=attributeMap.end();
2468        ++aitr)
2469    {
2470        AttributeStack& as = aitr->second;
2471        if (as.changed)
2472        {
2473            as.changed = false;
2474            if (!as.attributeVec.empty())
2475            {
2476                const StateAttribute* new_attr = as.attributeVec.back().first;
2477                applyAttributeOnTexUnit(unit,new_attr,as);
2478            }
2479            else
2480            {
2481                applyGlobalDefaultAttributeOnTexUnit(unit,as);
2482            }
2483
2484        }
2485    }
2486}
2487
2488inline void State::applyUniformMap(UniformMap& uniformMap)
2489{
2490    if (!_lastAppliedProgramObject) return;
2491
2492    for(UniformMap::iterator aitr=uniformMap.begin();
2493        aitr!=uniformMap.end();
2494        ++aitr)
2495    {
2496        UniformStack& as = aitr->second;
2497        if (!as.uniformVec.empty())
2498        {
2499            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2500        }
2501    }
2502}
2503
2504inline bool State::setActiveTextureUnit( unsigned int unit )
2505{
2506    if (unit!=_currentActiveTextureUnit)
2507    {
2508        if (_glActiveTexture && unit < (unsigned int)(maximum(_glMaxTextureCoords,_glMaxTextureUnits)) )
2509        {
2510            _glActiveTexture(GL_TEXTURE0+unit);
2511            _currentActiveTextureUnit = unit;
2512        }
2513        else
2514        {
2515            return unit==0;
2516        }
2517    }
2518    return true;
2519}
2520
2521}
2522
2523#endif
Note: See TracBrowser for help on using the browser.