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

Revision 10769, 82.0 kB (checked in by robert, 4 years ago)

Fixed primCount default value

  • 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            if (setActiveTextureUnit(unit))
302            {
303                ModeMap& modeMap = getOrCreateTextureModeMap(unit);
304                ModeStack& ms = modeMap[mode];
305                ms.changed = true;
306                return applyMode(mode,enabled,ms);
307            }
308            else
309                return false;
310        }
311
312        inline void setGlobalDefaultAttribute(const StateAttribute* attribute)
313        {
314            AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
315            as.global_default_attribute = attribute;
316        }
317
318        inline const StateAttribute* getGlobalDefaultAttribute(StateAttribute::Type type, unsigned int member=0)
319        {
320            AttributeStack& as = _attributeMap[StateAttribute::TypeMemberPair(type,member)];
321            return as.global_default_attribute.get();
322        }
323
324        /** Apply an attribute if required. */
325        inline bool applyAttribute(const StateAttribute* attribute)
326        {
327            AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
328            as.changed = true;
329            return applyAttribute(attribute,as);
330        }
331
332        inline void setGlobalDefaultTextureAttribute(unsigned int unit, const StateAttribute* attribute)
333        {
334            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
335            AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
336            as.global_default_attribute = attribute;
337        }
338
339        inline const StateAttribute* getGlobalDefaultTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member = 0)
340        {
341            AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
342            AttributeStack& as = attributeMap[StateAttribute::TypeMemberPair(type,member)];
343            return as.global_default_attribute.get();
344        }
345
346
347        inline bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
348        {
349            if (setActiveTextureUnit(unit))
350            {
351                AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
352                AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
353                as.changed = true;
354                return applyAttribute(attribute,as);
355            }
356            else
357                return false;
358        }
359
360        /** Mode has been set externally, update state to reflect this setting.*/
361        void haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
362
363        /** Mode has been set externally, therefore dirty the associated mode in osg::State
364        * so it is applied on next call to osg::State::apply(..)*/
365        void haveAppliedMode(StateAttribute::GLMode mode);
366
367        /** Attribute has been applied externally, update state to reflect this setting.*/
368        void haveAppliedAttribute(const StateAttribute* attribute);
369
370        /** Attribute has been applied externally,
371        * and therefore this attribute type has been dirtied
372        * and will need to be re-applied on next osg::State.apply(..).
373        * note, if you have an osg::StateAttribute which you have applied externally
374        * then use the have_applied(attribute) method as this will cause the osg::State to
375        * track the current state more accurately and enable lazy state updating such
376        * that only changed state will be applied.*/
377        void haveAppliedAttribute(StateAttribute::Type type, unsigned int member=0);
378
379        /** Get whether the current specified mode is enabled (true) or disabled (false).*/
380        bool getLastAppliedMode(StateAttribute::GLMode mode) const;
381
382        /** Get the current specified attribute, return NULL if one has not yet been applied.*/
383        const StateAttribute* getLastAppliedAttribute(StateAttribute::Type type, unsigned int member=0) const;
384
385        /** texture Mode has been set externally, update state to reflect this setting.*/
386        void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
387
388        /** texture Mode has been set externally, therefore dirty the associated mode in osg::State
389        * so it is applied on next call to osg::State::apply(..)*/
390        void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode);
391
392        /** texture Attribute has been applied externally, update state to reflect this setting.*/
393        void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute* attribute);
394
395        /** texture Attribute has been applied externally,
396        * and therefore this attribute type has been dirtied
397        * and will need to be re-applied on next osg::State.apply(..).
398        * note, if you have an osg::StateAttribute which you have applied externally
399        * then use the have_applied(attribute) method as this will the osg::State to
400        * track the current state more accurately and enable lazy state updating such
401        * that only changed state will be applied.*/
402        void haveAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0);
403
404        /** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
405        bool getLastAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode) const;
406
407        /** Get the current specified texture attribute, return NULL if one has not yet been applied.*/
408        const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0) const;
409
410
411        /** Dirty the modes previously applied in osg::State.*/
412        void dirtyAllModes();
413
414        /** Dirty the modes attributes previously applied in osg::State.*/
415        void dirtyAllAttributes();
416
417        /** disable the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
418        void disableAllVertexArrays();
419
420        /** dirty the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
421        void dirtyAllVertexArrays();
422
423
424        void setCurrentVertexBufferObject(osg::GLBufferObject* vbo) { _currentVBO = vbo; }
425        const GLBufferObject* getCurrentVertexBufferObject() { return _currentVBO; }
426        inline void bindVertexBufferObject(osg::GLBufferObject* vbo)
427        {
428            if (vbo == _currentVBO) return;
429            if (vbo->isDirty()) vbo->compileBuffer();
430            else vbo->bindBuffer();
431            _currentVBO = vbo;
432        }
433
434        inline void unbindVertexBufferObject()
435        {
436            if (!_currentVBO) return;
437            _glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
438            _currentVBO = 0;
439        }
440
441        void setCurrentElementBufferObject(osg::GLBufferObject* ebo) { _currentEBO = ebo; }
442        const GLBufferObject* getCurrentElementBufferObject() { return _currentEBO; }
443
444        inline void bindElementBufferObject(osg::GLBufferObject* ebo)
445        {
446            if (ebo == _currentEBO) return;
447            if (ebo->isDirty()) ebo->compileBuffer();
448            else ebo->bindBuffer();
449            _currentEBO = ebo;
450        }
451
452        inline void unbindElementBufferObject()
453        {
454            if (!_currentEBO) return;
455            _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
456            _currentEBO = 0;
457        }
458
459        void setCurrentPixelBufferObject(osg::GLBufferObject* pbo) { _currentPBO = pbo; }
460        const GLBufferObject* getCurrentPixelBufferObject() { return _currentPBO; }
461
462        inline void bindPixelBufferObject(osg::GLBufferObject* pbo)
463        {
464            if (pbo == _currentPBO) return;
465
466            if (pbo->isDirty()) pbo->compileBuffer();
467            else pbo->bindBuffer();
468
469            _currentPBO = pbo;
470        }
471
472        inline void unbindPixelBufferObject()
473        {
474            if (!_currentPBO) return;
475
476            _glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
477            _currentPBO = 0;
478        }
479
480        typedef std::vector<GLushort> Indices;
481        Indices _quadIndices[6];
482
483        void drawQuads(GLint first, GLsizei count, GLsizei primCount=0);
484
485        inline void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
486        {
487            if (primcount>=1 && _glDrawArraysInstanced!=0) _glDrawArraysInstanced(mode, first, count, primcount);
488            else glDrawArrays(mode, first, count);
489        }
490
491        inline void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount )
492        {
493            if (primcount>=1 && _glDrawElementsInstanced!=0) _glDrawElementsInstanced(mode, count, type, indices, primcount);
494            else glDrawElements(mode, count, type, indices);
495        }
496
497
498        inline void Vertex(float x, float y, float z, float w=1.0f)
499        {
500        #if defined(OSG_GL_VERTEX_FUNCS_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE)
501            if (_useVertexAttributeAliasing) _glVertexAttrib4f( _vertexAlias._location, x,y,z,w);
502            else glVertex4f(x,y,z,w);
503        #else
504            _glVertexAttrib4f( _vertexAlias._location, x,y,z,w);
505        #endif
506        }
507
508        inline void Color(float r, float g, float b, float a=1.0f)
509        {
510        #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
511            if (_useVertexAttributeAliasing) _glVertexAttrib4f( _colorAlias._location, r,g,b,a);
512            else glColor4f(r,g,b,a);
513        #else
514            _glVertexAttrib4f( _colorAlias._location, r,g,b,a);
515        #endif
516        }
517
518        void Normal(float x, float y, float z)
519        {
520        #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
521            if (_useVertexAttributeAliasing) _glVertexAttrib4f( _normalAlias._location, x,y,z,0.0);
522            else glNormal3f(x,y,z);
523        #else
524            _glVertexAttrib4f( _normalAlias._location, x,y,z,0.0);
525        #endif
526        }
527
528        void TexCoord(float x, float y=0.0f, float z=0.0f, float w=1.0f)
529        {
530        #if !defined(OSG_GLES1_AVAILABLE)
531            #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
532                if (_useVertexAttributeAliasing) _glVertexAttrib4f( _texCoordAliasList[0]._location, x,y,z,w);
533                else glTexCoord4f(x,y,z,w);
534            #else
535                _glVertexAttrib4f( _texCoordAliasList[0]._location, x,y,z,w);
536            #endif
537        #endif
538        }
539
540        void MultiTexCoord(unsigned int unit, float x, float y=0.0f, float z=0.0f, float w=1.0f)
541        {
542        #if !defined(OSG_GLES1_AVAILABLE)
543            #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
544                if (_useVertexAttributeAliasing) _glVertexAttrib4f( _texCoordAliasList[unit]._location, x,y,z,w);
545                else _glMultiTexCoord4f(GL_TEXTURE0+unit,x,y,z,w);
546            #else
547                _glVertexAttrib4f( _texCoordAliasList[unit]._location, x,y,z,w);
548            #endif
549        #endif
550        }
551
552        void VerteAttrib(unsigned int location, float x, float y=0.0f, float z=0.0f, float w=0.0f)
553        {
554            _glVertexAttrib4f( location, x,y,z,w);
555        }
556
557
558        /** Mark all the vertex attributes as being disabled but leave the disabling till a later call to applyDisablingOfVertexAttributes.*/
559        void lazyDisablingOfVertexAttributes();
560
561        /** Disable all the vertex attributes that have been marked as to be disabled.*/
562        void applyDisablingOfVertexAttributes();
563
564        /** Wrapper around glInterleavedArrays(..).
565          * also resets the internal array points and modes within osg::State to keep the other
566          * vertex array operations consistent. */
567        void setInterleavedArrays( GLenum format, GLsizei stride, const GLvoid* pointer);
568
569        /** Set the vertex pointer using an osg::Array, and manage any VBO that are required.*/
570        inline void setVertexPointer(const Array* array)
571        {
572            if (array)
573            {
574                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
575                if (vbo)
576                {
577                    bindVertexBufferObject(vbo);
578                    setVertexPointer(array->getDataSize(),array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
579                }
580                else
581                {
582                    unbindVertexBufferObject();
583                    setVertexPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
584                }
585            }
586        }
587
588        /** wrapper around glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(..);
589        * note, only updates values that change.*/
590        inline void setVertexPointer( GLint size, GLenum type,
591                                    GLsizei stride, const GLvoid *ptr )
592        {
593        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
594            if (_useVertexAttributeAliasing)
595            {
596                setVertexAttribPointer(_vertexAlias._location, size, type, GL_FALSE, stride, ptr);
597            }
598            else
599            {
600                if (!_vertexArray._enabled || _vertexArray._dirty)
601                {
602                    _vertexArray._enabled = true;
603                    glEnableClientState(GL_VERTEX_ARRAY);
604                }
605                //if (_vertexArray._pointer!=ptr || _vertexArray._dirty)
606                {
607                    _vertexArray._pointer=ptr;
608                    glVertexPointer( size, type, stride, ptr );
609                }
610                _vertexArray._lazy_disable = false;
611                _vertexArray._dirty = false;
612            }
613        #else
614            setVertexAttribPointer(_vertexAlias._location, size, type, GL_FALSE, stride, ptr);
615        #endif
616        }
617
618        /** wrapper around glDisableClientState(GL_VERTEX_ARRAY).
619        * note, only updates values that change.*/
620        inline void disableVertexPointer()
621        {
622        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
623            if (_useVertexAttributeAliasing)
624            {
625                disableVertexAttribPointer(_vertexAlias._location);
626            }
627            else
628            {
629                if (_vertexArray._enabled || _vertexArray._dirty)
630                {
631                    _vertexArray._lazy_disable = false;
632                    _vertexArray._enabled = false;
633                    _vertexArray._dirty = false;
634                    glDisableClientState(GL_VERTEX_ARRAY);
635                }
636            }
637        #else
638                disableVertexAttribPointer(_vertexAlias._location);
639        #endif
640        }
641
642        inline void dirtyVertexPointer()
643        {
644        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
645            if (_useVertexAttributeAliasing)
646            {
647                dirtyVertexAttribPointer(_vertexAlias._location);
648            }
649            else
650            {
651                _vertexArray._pointer = 0;
652                _vertexArray._dirty = true;
653            }
654        #else
655            dirtyVertexAttribPointer(_vertexAlias._location);
656        #endif
657        }
658
659
660        /** Set the normal pointer using an osg::Array, and manage any VBO that are required.*/
661        inline void setNormalPointer(const Array* array)
662        {
663            if (array)
664            {
665                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
666                if (vbo)
667                {
668                    bindVertexBufferObject(vbo);
669                    setNormalPointer(array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
670                }
671                else
672                {
673                    unbindVertexBufferObject();
674                    setNormalPointer(array->getDataType(),0,array->getDataPointer());
675                }
676            }
677        }
678
679        /** wrapper around glEnableClientState(GL_NORMAL_ARRAY);glNormalPointer(..);
680        * note, only updates values that change.*/
681        inline void setNormalPointer( GLenum type, GLsizei stride,
682                                    const GLvoid *ptr )
683        {
684        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
685            if (_useVertexAttributeAliasing)
686            {
687                setVertexAttribPointer(_normalAlias._location, 3, type, GL_FALSE, stride, ptr);
688            }
689            else
690            {
691                if (!_normalArray._enabled || _normalArray._dirty)
692                {
693                    _normalArray._enabled = true;
694                    glEnableClientState(GL_NORMAL_ARRAY);
695                }
696                //if (_normalArray._pointer!=ptr || _normalArray._dirty)
697                {
698                    _normalArray._pointer=ptr;
699                    glNormalPointer( type, stride, ptr );
700                }
701                _normalArray._lazy_disable = false;
702                _normalArray._dirty = false;
703            }
704        #else
705            setVertexAttribPointer(_normalAlias._location, 3, type, GL_FALSE, stride, ptr);
706        #endif
707        }
708
709        /** wrapper around glDisableClientState(GL_NORMAL_ARRAY);
710        * note, only updates values that change.*/
711        inline void disableNormalPointer()
712        {
713        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
714            if (_useVertexAttributeAliasing)
715            {
716                disableVertexAttribPointer(_normalAlias._location);
717            }
718            else
719            {
720                if (_normalArray._enabled || _normalArray._dirty)
721                {
722                    _normalArray._lazy_disable = false;
723                    _normalArray._enabled = false;
724                    _normalArray._dirty = false;
725                    glDisableClientState(GL_NORMAL_ARRAY);
726                }
727            }
728        #else
729            disableVertexAttribPointer(_normalAlias._location);
730        #endif
731        }
732
733        inline void dirtyNormalPointer()
734        {
735        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
736            if (_useVertexAttributeAliasing)
737            {
738                dirtyVertexAttribPointer(_normalAlias._location);
739            }
740            else
741            {
742                _normalArray._pointer = 0;
743                _normalArray._dirty = true;
744            }
745        #else
746            dirtyVertexAttribPointer(_normalAlias._location);
747        #endif
748        }
749
750        /** Set the color pointer using an osg::Array, and manage any VBO that are required.*/
751        inline void setColorPointer(const Array* array)
752        {
753            if (array)
754            {
755                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
756                if (vbo)
757                {
758                    bindVertexBufferObject(vbo);
759                    setColorPointer(array->getDataSize(),array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
760                }
761                else
762                {
763                    unbindVertexBufferObject();
764                    setColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
765                }
766            }
767        }
768
769
770        /** wrapper around glEnableClientState(GL_COLOR_ARRAY);glColorPointer(..);
771        * note, only updates values that change.*/
772        inline void setColorPointer( GLint size, GLenum type,
773                                    GLsizei stride, const GLvoid *ptr )
774        {
775        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
776            if (_useVertexAttributeAliasing)
777            {
778                setVertexAttribPointer(_colorAlias._location, size, type, GL_FALSE, stride, ptr);
779            }
780            else
781            {
782                if (!_colorArray._enabled || _colorArray._dirty)
783                {
784                    _colorArray._enabled = true;
785                    glEnableClientState(GL_COLOR_ARRAY);
786                }
787                //if (_colorArray._pointer!=ptr || _colorArray._dirty)
788                {
789                    _colorArray._pointer=ptr;
790                    glColorPointer( size, type, stride, ptr );
791                }
792                _colorArray._lazy_disable = false;
793                _colorArray._dirty = false;
794            }
795        #else
796            setVertexAttribPointer(_colorAlias._location, size, type, GL_FALSE, stride, ptr);
797        #endif
798        }
799
800        /** wrapper around glDisableClientState(GL_COLOR_ARRAY);
801        * note, only updates values that change.*/
802        inline void disableColorPointer()
803        {
804        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
805            if (_useVertexAttributeAliasing)
806            {
807                disableVertexAttribPointer(_colorAlias._location);
808            }
809            else
810            {
811                if (_colorArray._enabled || _colorArray._dirty)
812                {
813                    _colorArray._lazy_disable = false;
814                    _colorArray._enabled = false;
815                    _colorArray._dirty = false;
816                    glDisableClientState(GL_COLOR_ARRAY);
817                }
818            }
819        #else
820            disableVertexAttribPointer(_colorAlias._location);
821        #endif
822        }
823
824        inline void dirtyColorPointer()
825        {
826        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
827            if (_useVertexAttributeAliasing)
828            {
829                dirtyVertexAttribPointer(_colorAlias._location);
830            }
831            else
832            {
833                _colorArray._pointer = 0;
834                _colorArray._dirty = true;
835            }
836        #else
837            dirtyVertexAttribPointer(_colorAlias._location);
838        #endif
839        }
840
841
842        inline bool isSecondaryColorSupported() const { return _isSecondaryColorSupportResolved?_isSecondaryColorSupported:computeSecondaryColorSupported(); }
843
844
845        /** Set the secondary color pointer using an osg::Array, and manage any VBO that are required.*/
846        inline void setSecondaryColorPointer(const Array* array)
847        {
848            if (array)
849            {
850                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
851                if (vbo)
852                {
853                    bindVertexBufferObject(vbo);
854                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
855                }
856                else
857                {
858                    unbindVertexBufferObject();
859                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
860                }
861            }
862        }
863
864        /** wrapper around glEnableClientState(GL_SECONDARY_COLOR_ARRAY);glSecondayColorPointer(..);
865        * note, only updates values that change.*/
866        void setSecondaryColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr );
867
868        /** wrapper around glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
869        * note, only updates values that change.*/
870        inline void disableSecondaryColorPointer()
871        {
872        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
873            if (_useVertexAttributeAliasing)
874            {
875                disableVertexAttribPointer(_secondaryColorAlias._location);
876            }
877            else
878            {
879                if (_secondaryColorArray._enabled || _secondaryColorArray._dirty)
880                {
881                    _secondaryColorArray._lazy_disable = false;
882                    _secondaryColorArray._enabled = false;
883                    _secondaryColorArray._dirty = false;
884                    if (isSecondaryColorSupported()) glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
885                }
886            }
887        #else
888            disableVertexAttribPointer(_secondaryColorAlias._location);
889        #endif
890        }
891
892        inline void dirtySecondaryColorPointer()
893        {
894        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
895            if (_useVertexAttributeAliasing)
896            {
897                dirtyVertexAttribPointer(_secondaryColorAlias._location);
898            }
899            else
900            {
901                _secondaryColorArray._pointer = 0;
902                _secondaryColorArray._dirty = true;
903            }
904        #else
905            dirtyVertexAttribPointer(_secondaryColorAlias._location);
906        #endif
907        }
908
909        inline bool isFogCoordSupported() const { return _isFogCoordSupportResolved?_isFogCoordSupported:computeFogCoordSupported(); }
910
911
912        /** Set the fog coord pointer using an osg::Array, and manage any VBO that are required.*/
913        inline void setFogCoordPointer(const Array* array)
914        {
915            if (array)
916            {
917                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
918                if (vbo)
919                {
920                    bindVertexBufferObject(vbo);
921                    setFogCoordPointer(array->getDataType(),0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
922                }
923                else
924                {
925                    unbindVertexBufferObject();
926                    setFogCoordPointer(array->getDataType(),0,array->getDataPointer());
927                }
928            }
929        }
930
931
932        /** wrapper around glEnableClientState(GL_FOG_COORDINATE_ARRAY);glFogCoordPointer(..);
933        * note, only updates values that change.*/
934        void setFogCoordPointer( GLenum type, GLsizei stride, const GLvoid *ptr );
935
936        /** wrapper around glDisableClientState(GL_FOG_COORDINATE_ARRAY);
937        * note, only updates values that change.*/
938        inline void disableFogCoordPointer()
939        {
940        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
941            if (_useVertexAttributeAliasing)
942            {
943                disableVertexAttribPointer(_fogCoordAlias._location);
944            }
945            else
946            {
947                if (_fogArray._enabled || _fogArray._dirty)
948                {
949                    _fogArray._lazy_disable = false;
950                    _fogArray._enabled = false;
951                    _fogArray._dirty = false;
952                    if (isFogCoordSupported()) glDisableClientState(GL_FOG_COORDINATE_ARRAY);
953                }
954            }
955        #else
956            disableVertexAttribPointer(_fogCoordAlias._location);
957        #endif
958        }
959
960        inline void dirtyFogCoordPointer()
961        {
962        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
963            if (_useVertexAttributeAliasing)
964            {
965                dirtyVertexAttribPointer(_fogCoordAlias._location);
966            }
967            else
968            {
969                _fogArray._pointer = 0;
970                _fogArray._dirty = true;
971            }
972        #else
973            dirtyVertexAttribPointer(_fogCoordAlias._location);
974        #endif
975        }
976
977
978
979        /** Set the tex coord pointer using an osg::Array, and manage any VBO that are required.*/
980        inline void setTexCoordPointer(unsigned int unit, const Array* array)
981        {
982            if (array)
983            {
984                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
985                if (vbo)
986                {
987                    bindVertexBufferObject(vbo);
988                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
989                }
990                else
991                {
992                    unbindVertexBufferObject();
993                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,array->getDataPointer());
994                }
995            }
996        }
997
998        /** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..);
999        * note, only updates values that change.*/
1000        inline void setTexCoordPointer( unsigned int unit,
1001                                        GLint size, GLenum type,
1002                                        GLsizei stride, const GLvoid *ptr )
1003        {
1004        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1005            if (_useVertexAttributeAliasing)
1006            {
1007                setVertexAttribPointer(_texCoordAliasList[unit]._location, size, type, GL_FALSE, stride, ptr);
1008            }
1009            else
1010            {
1011                if (setClientActiveTextureUnit(unit))
1012                {
1013                    if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
1014                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1015
1016                    if (!eap._enabled || eap._dirty)
1017                    {
1018                        eap._enabled = true;
1019                        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1020                    }
1021                    //if (eap._pointer!=ptr || eap._dirty)
1022                    {
1023                        glTexCoordPointer( size, type, stride, ptr );
1024                        eap._pointer = ptr;
1025                    }
1026                    eap._lazy_disable = false;
1027                    eap._dirty = false;
1028                }
1029            }
1030        #else
1031            setVertexAttribPointer(_texCoordAliasList[unit]._location, size, type, GL_FALSE, stride, ptr);
1032        #endif
1033        }
1034
1035        /** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1036        * note, only updates values that change.*/
1037        inline void disableTexCoordPointer( unsigned int unit )
1038        {
1039        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1040            if (_useVertexAttributeAliasing)
1041            {
1042                disableVertexAttribPointer(_texCoordAliasList[unit]._location);
1043            }
1044            else
1045            {
1046                if (setClientActiveTextureUnit(unit))
1047                {
1048                    if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
1049                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1050
1051                    if (eap._enabled || eap._dirty)
1052                    {
1053                        eap._lazy_disable = false;
1054                        eap._enabled = false;
1055                        eap._dirty = false;
1056                        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1057                    }
1058                }
1059            }
1060        #else
1061            disableVertexAttribPointer(_texCoordAliasList[unit]._location);
1062        #endif
1063        }
1064
1065        inline void dirtyTexCoordPointer( unsigned int unit )
1066        {
1067        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1068            if (_useVertexAttributeAliasing)
1069            {
1070                dirtyVertexAttribPointer(_texCoordAliasList[unit]._location);
1071            }
1072            else
1073            {
1074                if ( unit >= _texCoordArrayList.size()) return; // _texCoordArrayList.resize(unit+1);
1075                EnabledArrayPair& eap = _texCoordArrayList[unit];
1076                eap._pointer = 0;
1077                eap._dirty = true;
1078            }
1079        #else
1080            dirtyVertexAttribPointer(_texCoordAliasList[unit]._location);
1081        #endif
1082        }
1083
1084
1085        inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit )
1086        {
1087        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1088            if (_useVertexAttributeAliasing)
1089            {
1090                disableVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1091            }
1092            else
1093            {
1094                while (unit<_texCoordArrayList.size())
1095                {
1096                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1097                    if (eap._enabled || eap._dirty)
1098                    {
1099                        if (setClientActiveTextureUnit(unit))
1100                        {
1101                            eap._lazy_disable = false;
1102                            eap._enabled = false;
1103                            eap._dirty = false;
1104                            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1105                        }
1106                    }
1107                    ++unit;
1108                }
1109            }
1110        #else
1111            disableVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1112        #endif
1113        }
1114
1115        inline void dirtyTexCoordPointersAboveAndIncluding( unsigned int unit )
1116        {
1117        #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
1118            if (_useVertexAttributeAliasing)
1119            {
1120                dirtyVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1121            }
1122            else
1123            {
1124                while (unit<_texCoordArrayList.size())
1125                {
1126                    EnabledArrayPair& eap = _texCoordArrayList[unit];
1127                    eap._pointer = 0;
1128                    eap._dirty = true;
1129                    ++unit;
1130                }
1131            }
1132        #else
1133            dirtyVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
1134        #endif
1135        }
1136
1137
1138        /** Set the current texture unit, return true if selected,
1139        * false if selection failed such as when multi texturing is not supported.
1140        * note, only updates values that change.*/
1141        bool setActiveTextureUnit( unsigned int unit );
1142
1143        /** Get the current texture unit.*/
1144        unsigned int getActiveTextureUnit() const { return _currentActiveTextureUnit; }
1145
1146        /** Set the current tex coord array texture unit, return true if selected,
1147        * false if selection failed such as when multi texturing is not supported.
1148        * note, only updates values that change.*/
1149        bool setClientActiveTextureUnit( unsigned int unit );
1150
1151        /** Get the current tex coord array texture unit.*/
1152        unsigned int getClientActiveTextureUnit() const { return _currentClientActiveTextureUnit; }
1153
1154        /** Set the vertex attrib pointer using an osg::Array, and manage any VBO that are required.*/
1155        inline void setVertexAttribPointer(unsigned int unit, const Array* array, GLboolean normalized)
1156        {
1157            if (array)
1158            {
1159                GLBufferObject* vbo = array->getOrCreateGLBufferObject(_contextID);
1160                if (vbo)
1161                {
1162                    bindVertexBufferObject(vbo);
1163                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,(const GLvoid *)(vbo->getOffset(array->getBufferIndex())));
1164                }
1165                else
1166                {
1167                    unbindVertexBufferObject();
1168                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,array->getDataPointer());
1169                }
1170            }
1171        }
1172
1173        /** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..);
1174        * note, only updates values that change.*/
1175        void setVertexAttribPointer( unsigned int index,
1176                                    GLint size, GLenum type, GLboolean normalized,
1177                                    GLsizei stride, const GLvoid *ptr );
1178
1179        /** wrapper around DisableVertexAttribArrayARB(index);
1180        * note, only updates values that change.*/
1181        void disableVertexAttribPointer( unsigned int index );
1182
1183        void disableVertexAttribPointersAboveAndIncluding( unsigned int index );
1184
1185        inline void dirtyVertexAttribPointer( unsigned int index )
1186        {
1187            if (index<_vertexAttribArrayList.size())
1188            {
1189                EnabledArrayPair& eap = _vertexAttribArrayList[index];
1190                eap._pointer = 0;
1191                eap._dirty = true;
1192            }
1193        }
1194
1195        inline void dirtyVertexAttribPointersAboveAndIncluding( unsigned int index )
1196        {
1197            while (index<_vertexAttribArrayList.size())
1198            {
1199                EnabledArrayPair& eap = _vertexAttribArrayList[index];
1200                eap._pointer = 0;
1201                eap._dirty = true;
1202                ++index;
1203            }
1204        }
1205
1206        bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); }
1207
1208
1209        inline void setLastAppliedProgramObject(const Program::PerContextProgram* program)
1210        {
1211            if (_lastAppliedProgramObject!=program)
1212            {
1213                _lastAppliedProgramObject = program;
1214                if (program && _appliedProgramObjectSet.count(program)==0)
1215                {
1216                    _appliedProgramObjectSet.insert(program);
1217                    program->addObserver(this);
1218                }
1219            }
1220        }
1221        inline const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; }
1222
1223        inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; }
1224        inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; }
1225
1226        typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue>  AttributePair;
1227        typedef std::vector<AttributePair>                                      AttributeVec;
1228
1229        AttributeVec& getAttributeVec( const osg::StateAttribute* attribute )
1230        {
1231                AttributeStack& as = _attributeMap[ attribute->getTypeMemberPair() ];
1232                return as.attributeVec;
1233        }
1234
1235        /** Set the frame stamp for the current frame.*/
1236        inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
1237
1238        /** Get the frame stamp for the current frame.*/
1239        inline FrameStamp* getFrameStamp() { return _frameStamp.get(); }
1240
1241        /** Get the const frame stamp for the current frame.*/
1242        inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
1243
1244
1245        /** Set the DisplaySettings. Note, nothing is applied, the visual settings are just
1246        * used in the State object to pass the current visual settings to Drawables
1247        * during rendering. */
1248        inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
1249
1250        /** Get the DisplaySettings */
1251        inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
1252
1253
1254
1255        /** Set flag for early termination of the draw traversal.*/
1256        void setAbortRenderingPtr(bool* abortPtr) { _abortRenderingPtr = abortPtr; }
1257
1258        /** Get flag for early termination of the draw traversal,
1259        * if true steps should be taken to complete rendering early.*/
1260        bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
1261
1262
1263        struct DynamicObjectRenderingCompletedCallback : public osg::Referenced
1264        {
1265            virtual void completed(osg::State*) = 0;
1266        };
1267
1268        /** Set the callback to be called when the dynamic object count hits 0.*/
1269        void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; }
1270
1271        /** Get the callback to be called when the dynamic object count hits 0.*/
1272        DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); }
1273
1274        /** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/
1275        void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false)
1276        {
1277            if (_dynamicObjectCount != count)
1278            {
1279                _dynamicObjectCount = count;
1280                if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid())
1281                {
1282                    _completeDynamicObjectRenderingCallback->completed(this);
1283                }
1284            }
1285        }
1286
1287        /** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/
1288        unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; }
1289
1290        /** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the
1291        * DynamicObjectRenderingCompletedCallback to inform of completion.*/
1292        inline void decrementDynamicObjectCount()
1293        {
1294            --_dynamicObjectCount;
1295            if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid())
1296            {
1297                _completeDynamicObjectRenderingCallback->completed(this);
1298            }
1299        }
1300
1301        void setMaxTexturePoolSize(unsigned int size);
1302        unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; }
1303
1304        void setMaxBufferObjectPoolSize(unsigned int size);
1305        unsigned int getMaxBufferObjectPoolSize() const { return _maxBufferObjectPoolSize; }
1306
1307
1308        enum CheckForGLErrors
1309        {
1310            /** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
1311                is the fastest option since checking for errors does incurr a small overhead.*/
1312            NEVER_CHECK_GL_ERRORS,
1313            /** ONCE_PER_FRAME means that OpenGl errors will be checked for once per
1314                frame, the overhead is still small, but at least OpenGL errors that are occurring
1315                will be caught, the reporting isn't fine grained enough for debugging purposes.*/
1316            ONCE_PER_FRAME,
1317            /** ONCE_PER_ATTRIBUTE means that OpenGL errors will be checked for after
1318                every attribute is applied, allow errors to be directly associated with
1319                particular operations which makes debugging much easier.*/
1320            ONCE_PER_ATTRIBUTE
1321        };
1322
1323        /** Set whether and how often OpenGL errors should be checked for.*/
1324        void setCheckForGLErrors(CheckForGLErrors check) { _checkGLErrors = check; }
1325
1326        /** Get whether and how often OpenGL errors should be checked for.*/
1327        CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
1328
1329        bool checkGLErrors(const char* str) const;
1330        bool checkGLErrors(StateAttribute::GLMode mode) const;
1331        bool checkGLErrors(const StateAttribute* attribute) const;
1332
1333
1334        /** Initialize extension used by osg:::State.*/
1335        void initializeExtensionProcs();
1336
1337        virtual void objectDeleted(void* object);
1338
1339        /** get the GL adapter object used to map OpenGL 1.0 glBegin/glEnd usage to vertex arrays.*/
1340        inline GLBeginEndAdapter& getGLBeginEndAdapter() { return _glBeginEndAdapter; }
1341
1342        /** get the helper class for dispatching osg::Arrays as OpenGL attribute data.*/
1343        inline ArrayDispatchers& getArrayDispatchers() { return _arrayDispatchers; }
1344
1345    protected:
1346
1347        virtual ~State();
1348
1349        GraphicsContext*            _graphicsContext;
1350        unsigned int                _contextID;
1351        ref_ptr<FrameStamp>         _frameStamp;
1352
1353        ref_ptr<const RefMatrix>    _identity;
1354        ref_ptr<const RefMatrix>    _initialViewMatrix;
1355        ref_ptr<const RefMatrix>    _projection;
1356        ref_ptr<const RefMatrix>    _modelView;
1357
1358        bool                        _useModelViewAndProjectionUniforms;
1359        ref_ptr<Uniform>            _modelViewMatrixUniform;
1360        ref_ptr<Uniform>            _projectionMatrixUniform;
1361        ref_ptr<Uniform>            _modelViewProjectionMatrixUniform;
1362        ref_ptr<Uniform>            _normalMatrixUniform;
1363
1364        Matrix                      _initialInverseViewMatrix;
1365
1366        ref_ptr<DisplaySettings>    _displaySettings;
1367
1368        bool*                       _abortRenderingPtr;
1369        CheckForGLErrors            _checkGLErrors;
1370
1371
1372        bool                        _useVertexAttributeAliasing;
1373        VertexAttribAlias           _vertexAlias;
1374        VertexAttribAlias           _normalAlias;
1375        VertexAttribAlias           _colorAlias;
1376        VertexAttribAlias           _secondaryColorAlias;
1377        VertexAttribAlias           _fogCoordAlias;
1378        VertexAttribAliasList       _texCoordAliasList;
1379
1380        Program::AttribBindingList  _attributeBindingList;
1381
1382        void setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration);
1383
1384
1385        struct ModeStack
1386        {
1387            typedef std::vector<StateAttribute::GLModeValue> ValueVec;
1388
1389            ModeStack()
1390            {
1391                valid = true;
1392                changed = false;
1393                last_applied_value = false;
1394                global_default_value = false;
1395            }
1396
1397            bool        valid;
1398            bool        changed;
1399            bool        last_applied_value;
1400            bool        global_default_value;
1401            ValueVec    valueVec;
1402        };
1403
1404        struct AttributeStack
1405        {
1406            AttributeStack()
1407            {
1408                changed = false;
1409                last_applied_attribute = 0L;
1410                global_default_attribute = 0L;
1411            }
1412
1413            /** apply an attribute if required, passing in attribute and appropriate attribute stack */
1414            bool                    changed;
1415            const StateAttribute*   last_applied_attribute;
1416            ref_ptr<const StateAttribute> global_default_attribute;
1417            AttributeVec            attributeVec;
1418        };
1419
1420
1421        struct UniformStack
1422        {
1423            typedef std::pair<const Uniform*,StateAttribute::OverrideValue>         UniformPair;
1424            typedef std::vector<UniformPair>                                        UniformVec;
1425
1426            UniformStack() {}
1427
1428            UniformVec              uniformVec;
1429        };
1430
1431
1432        /** Apply an OpenGL mode if required, passing in mode, enable flag and
1433        * appropriate mode stack. This is a wrapper around \c glEnable() and
1434        * \c glDisable(), that just actually calls these functions if the
1435        * \c enabled flag is different than the current state.
1436        * @return \c true if the state was actually changed. \c false
1437        *         otherwise. Notice that a \c false return does not indicate
1438        *         an error, it just means that the mode was already set to the
1439        *         same value as the \c enabled parameter.
1440        */
1441        inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
1442        {
1443            if (ms.valid && ms.last_applied_value != enabled)
1444            {
1445                ms.last_applied_value = enabled;
1446
1447                if (enabled) glEnable(mode);
1448                else glDisable(mode);
1449
1450                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
1451
1452                return true;
1453            }
1454            else
1455                return false;
1456        }
1457
1458
1459        /** apply an attribute if required, passing in attribute and appropriate attribute stack */
1460        inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
1461        {
1462            if (as.last_applied_attribute != attribute)
1463            {
1464                if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
1465
1466                as.last_applied_attribute = attribute;
1467                attribute->apply(*this);
1468
1469                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
1470
1471                return true;
1472            }
1473            else
1474                return false;
1475        }
1476
1477        inline bool applyGlobalDefaultAttribute(AttributeStack& as)
1478        {
1479            if (as.last_applied_attribute != as.global_default_attribute.get())
1480            {
1481                as.last_applied_attribute = as.global_default_attribute.get();
1482                if (as.global_default_attribute.valid())
1483                {
1484                    as.global_default_attribute->apply(*this);
1485                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
1486                }
1487                return true;
1488            }
1489            else
1490                return false;
1491        }
1492
1493
1494        typedef std::map<StateAttribute::GLMode,ModeStack>              ModeMap;
1495        typedef std::vector<ModeMap>                                    TextureModeMapList;
1496
1497        typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
1498        typedef std::vector<AttributeMap>                               TextureAttributeMapList;
1499
1500        typedef std::map<std::string,UniformStack>                      UniformMap;
1501
1502        typedef std::vector<ref_ptr<const Matrix> >                     MatrixStack;
1503
1504        typedef std::set<const Program::PerContextProgram* >            AppliedProgramObjectSet;
1505
1506        ModeMap                                                         _modeMap;
1507        AttributeMap                                                    _attributeMap;
1508        UniformMap                                                      _uniformMap;
1509
1510        TextureModeMapList                                              _textureModeMapList;
1511        TextureAttributeMapList                                         _textureAttributeMapList;
1512
1513        AppliedProgramObjectSet                                         _appliedProgramObjectSet;
1514        const Program::PerContextProgram*                               _lastAppliedProgramObject;
1515
1516        StateSetStack                                                   _stateStateStack;
1517
1518        unsigned int                                                    _maxTexturePoolSize;
1519        unsigned int                                                    _maxBufferObjectPoolSize;
1520
1521
1522        struct EnabledArrayPair
1523        {
1524            EnabledArrayPair():_lazy_disable(false),_dirty(true),_enabled(false),_normalized(0),_pointer(0) {}
1525            EnabledArrayPair(const EnabledArrayPair& eap):_lazy_disable(eap._lazy_disable),_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {}
1526            EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _lazy_disable = eap._lazy_disable;_dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; }
1527
1528            bool            _lazy_disable;
1529            bool            _dirty;
1530            bool            _enabled;
1531            GLboolean       _normalized;
1532            const GLvoid*   _pointer;
1533        };
1534
1535        typedef std::vector<EnabledArrayPair>                   EnabledTexCoordArrayList;
1536        typedef std::vector<EnabledArrayPair>                   EnabledVertexAttribArrayList;
1537
1538        EnabledArrayPair                _vertexArray;
1539        EnabledArrayPair                _normalArray;
1540        EnabledArrayPair                _colorArray;
1541        EnabledArrayPair                _secondaryColorArray;
1542        EnabledArrayPair                _fogArray;
1543        EnabledTexCoordArrayList        _texCoordArrayList;
1544        EnabledVertexAttribArrayList    _vertexAttribArrayList;
1545
1546        unsigned int                    _currentActiveTextureUnit;
1547        unsigned int                    _currentClientActiveTextureUnit;
1548        GLBufferObject*                 _currentVBO;
1549        GLBufferObject*                 _currentEBO;
1550        GLBufferObject*                 _currentPBO;
1551
1552
1553        inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
1554        {
1555            if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
1556            return _textureModeMapList[unit];
1557        }
1558
1559
1560        inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
1561        {
1562            if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
1563            return _textureAttributeMapList[unit];
1564        }
1565
1566        inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1567        inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1568        inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1569
1570        inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1571        inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1572        inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1573
1574        inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1575        inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
1576        inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
1577
1578        inline void applyModeMap(ModeMap& modeMap);
1579        inline void applyAttributeMap(AttributeMap& attributeMap);
1580        inline void applyUniformMap(UniformMap& uniformMap);
1581
1582        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
1583        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
1584        void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
1585        void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member);
1586        bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
1587        const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const;
1588
1589
1590        mutable bool _isSecondaryColorSupportResolved;
1591        mutable bool _isSecondaryColorSupported;
1592        bool computeSecondaryColorSupported() const;
1593
1594        mutable bool _isFogCoordSupportResolved;
1595        mutable bool _isFogCoordSupported;
1596        bool computeFogCoordSupported() const;
1597
1598        mutable bool _isVertexBufferObjectSupportResolved;
1599        mutable bool _isVertexBufferObjectSupported;
1600        bool computeVertexBufferObjectSupported() const;
1601
1602        typedef void (APIENTRY * ActiveTextureProc) (GLenum texture);
1603        typedef void (APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer);
1604        typedef void (APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
1605        typedef void (APIENTRY * MultiTexCoord4fProc) (GLenum target, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
1606        typedef void (APIENTRY * VertexAttrib4fProc)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
1607        typedef void (APIENTRY * VertexAttrib4fvProc)(GLuint index, const GLfloat *v);
1608        typedef void (APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
1609        typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int);
1610        typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int);
1611        typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
1612
1613        typedef void (APIENTRY * DrawArraysInstancedProc)( GLenum mode, GLint first, GLsizei count, GLsizei primcount );
1614        typedef void (APIENTRY * DrawElementsInstancedProc)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount );
1615
1616        bool                        _extensionProcsInitialized;
1617        GLint                       _glMaxTextureCoords;
1618        GLint                       _glMaxTextureUnits;
1619        ActiveTextureProc           _glClientActiveTexture;
1620        ActiveTextureProc           _glActiveTexture;
1621        MultiTexCoord4fProc         _glMultiTexCoord4f;
1622        VertexAttrib4fProc          _glVertexAttrib4f;
1623        VertexAttrib4fvProc         _glVertexAttrib4fv;
1624        FogCoordPointerProc         _glFogCoordPointer;
1625        SecondaryColorPointerProc   _glSecondaryColorPointer;
1626        VertexAttribPointerProc     _glVertexAttribPointer;
1627        EnableVertexAttribProc      _glEnableVertexAttribArray;
1628        DisableVertexAttribProc     _glDisableVertexAttribArray;
1629        BindBufferProc              _glBindBuffer;
1630        DrawArraysInstancedProc     _glDrawArraysInstanced;
1631        DrawElementsInstancedProc   _glDrawElementsInstanced;
1632
1633        unsigned int                                            _dynamicObjectCount;
1634        osg::ref_ptr<DynamicObjectRenderingCompletedCallback>   _completeDynamicObjectRenderingCallback;
1635
1636        GLBeginEndAdapter           _glBeginEndAdapter;
1637        ArrayDispatchers            _arrayDispatchers;
1638
1639};
1640
1641inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1642{
1643    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1644        mitr!=modeList.end();
1645        ++mitr)
1646    {
1647        // get the mode stack for incoming GLmode {mitr->first}.
1648        ModeStack& ms = modeMap[mitr->first];
1649        if (ms.valueVec.empty())
1650        {
1651            // first pair so simply push incoming pair to back.
1652            ms.valueVec.push_back(mitr->second);
1653        }
1654        else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
1655        {
1656            // push existing back since override keeps the previous value.
1657            ms.valueVec.push_back(ms.valueVec.back());
1658        }
1659        else
1660        {
1661            // no override on so simply push incoming pair to back.
1662            ms.valueVec.push_back(mitr->second);
1663        }
1664        ms.changed = true;
1665    }
1666}
1667
1668inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1669{
1670    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1671        aitr!=attributeList.end();
1672        ++aitr)
1673    {
1674        // get the attribute stack for incoming type {aitr->first}.
1675        AttributeStack& as = attributeMap[aitr->first];
1676        if (as.attributeVec.empty())
1677        {
1678            // first pair so simply push incoming pair to back.
1679            as.attributeVec.push_back(
1680                AttributePair(aitr->second.first.get(),aitr->second.second));
1681        }
1682        else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1683        {
1684            // push existing back since override keeps the previous value.
1685            as.attributeVec.push_back(as.attributeVec.back());
1686        }
1687        else
1688        {
1689            // no override on so simply push incoming pair to back.
1690            as.attributeVec.push_back(
1691                AttributePair(aitr->second.first.get(),aitr->second.second));
1692        }
1693        as.changed = true;
1694    }
1695}
1696
1697
1698inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1699{
1700    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1701        aitr!=uniformList.end();
1702        ++aitr)
1703    {
1704        // get the attribute stack for incoming type {aitr->first}.
1705        UniformStack& us = uniformMap[aitr->first];
1706        if (us.uniformVec.empty())
1707        {
1708            // first pair so simply push incoming pair to back.
1709            us.uniformVec.push_back(
1710                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1711        }
1712        else if ((us.uniformVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1713        {
1714            // push existing back since override keeps the previous value.
1715            us.uniformVec.push_back(us.uniformVec.back());
1716        }
1717        else
1718        {
1719            // no override on so simply push incoming pair to back.
1720            us.uniformVec.push_back(
1721                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1722        }
1723    }
1724}
1725
1726inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1727{
1728    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1729        mitr!=modeList.end();
1730        ++mitr)
1731    {
1732        // get the mode stack for incoming GLmode {mitr->first}.
1733        ModeStack& ms = modeMap[mitr->first];
1734        if (!ms.valueVec.empty())
1735        {
1736            ms.valueVec.pop_back();
1737        }
1738        ms.changed = true;
1739    }
1740}
1741
1742inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1743{
1744    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1745        aitr!=attributeList.end();
1746        ++aitr)
1747    {
1748        // get the attribute stack for incoming type {aitr->first}.
1749        AttributeStack& as = attributeMap[aitr->first];
1750        if (!as.attributeVec.empty())
1751        {
1752            as.attributeVec.pop_back();
1753        }
1754        as.changed = true;
1755    }
1756}
1757
1758inline void State::popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1759{
1760    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1761        aitr!=uniformList.end();
1762        ++aitr)
1763    {
1764        // get the attribute stack for incoming type {aitr->first}.
1765        UniformStack& us = uniformMap[aitr->first];
1766        if (!us.uniformVec.empty())
1767        {
1768            us.uniformVec.pop_back();
1769        }
1770    }
1771}
1772
1773inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1774{
1775    StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
1776    ModeMap::iterator this_mitr=modeMap.begin();
1777
1778    while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
1779    {
1780        if (this_mitr->first<ds_mitr->first)
1781        {
1782
1783            // note GLMode = this_mitr->first
1784            ModeStack& ms = this_mitr->second;
1785            if (ms.changed)
1786            {
1787                ms.changed = false;
1788                if (!ms.valueVec.empty())
1789                {
1790                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1791                    applyMode(this_mitr->first,new_value,ms);
1792                }
1793                else
1794                {
1795                    // assume default of disabled.
1796                    applyMode(this_mitr->first,ms.global_default_value,ms);
1797
1798                }
1799
1800            }
1801
1802            ++this_mitr;
1803
1804        }
1805        else if (ds_mitr->first<this_mitr->first)
1806        {
1807
1808            // ds_mitr->first is a new mode, therefore
1809            // need to insert a new mode entry for ds_mistr->first.
1810            ModeStack& ms = modeMap[ds_mitr->first];
1811
1812            bool new_value = ds_mitr->second & StateAttribute::ON;
1813            applyMode(ds_mitr->first,new_value,ms);
1814
1815            // will need to disable this mode on next apply so set it to changed.
1816            ms.changed = true;
1817
1818            ++ds_mitr;
1819
1820        }
1821        else
1822        {
1823            // this_mitr & ds_mitr refer to the same mode, check the override
1824            // if any otherwise just apply the incoming mode.
1825
1826            ModeStack& ms = this_mitr->second;
1827
1828            if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
1829            {
1830                // override is on, just treat as a normal apply on modes.
1831
1832                if (ms.changed)
1833                {
1834                    ms.changed = false;
1835                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1836                    applyMode(this_mitr->first,new_value,ms);
1837
1838                }
1839            }
1840            else
1841            {
1842                // no override on or no previous entry, therefore consider incoming mode.
1843                bool new_value = ds_mitr->second & StateAttribute::ON;
1844                if (applyMode(ds_mitr->first,new_value,ms))
1845                {
1846                    ms.changed = true;
1847                }
1848            }
1849
1850            ++this_mitr;
1851            ++ds_mitr;
1852        }
1853    }
1854
1855    // iterator over the remaining state modes to apply any previous changes.
1856    for(;
1857        this_mitr!=modeMap.end();
1858        ++this_mitr)
1859    {
1860        // note GLMode = this_mitr->first
1861        ModeStack& ms = this_mitr->second;
1862        if (ms.changed)
1863        {
1864            ms.changed = false;
1865            if (!ms.valueVec.empty())
1866            {
1867                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1868                applyMode(this_mitr->first,new_value,ms);
1869            }
1870            else
1871            {
1872                // assume default of disabled.
1873                applyMode(this_mitr->first,ms.global_default_value,ms);
1874
1875            }
1876
1877        }
1878    }
1879
1880    // iterator over the remaining incoming modes to apply any new mode.
1881    for(;
1882        ds_mitr!=modeList.end();
1883        ++ds_mitr)
1884    {
1885        ModeStack& ms = modeMap[ds_mitr->first];
1886
1887        bool new_value = ds_mitr->second & StateAttribute::ON;
1888        applyMode(ds_mitr->first,new_value,ms);
1889
1890        // will need to disable this mode on next apply so set it to changed.
1891        ms.changed = true;
1892    }
1893}
1894
1895inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1896{
1897    StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
1898
1899    AttributeMap::iterator this_aitr=attributeMap.begin();
1900
1901    while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
1902    {
1903        if (this_aitr->first<ds_aitr->first)
1904        {
1905
1906            // note attribute type = this_aitr->first
1907            AttributeStack& as = this_aitr->second;
1908            if (as.changed)
1909            {
1910                as.changed = false;
1911                if (!as.attributeVec.empty())
1912                {
1913                    const StateAttribute* new_attr = as.attributeVec.back().first;
1914                    applyAttribute(new_attr,as);
1915                }
1916                else
1917                {
1918                    applyGlobalDefaultAttribute(as);
1919                }
1920            }
1921
1922            ++this_aitr;
1923
1924        }
1925        else if (ds_aitr->first<this_aitr->first)
1926        {
1927
1928            // ds_aitr->first is a new attribute, therefore
1929            // need to insert a new attribute entry for ds_aitr->first.
1930            AttributeStack& as = attributeMap[ds_aitr->first];
1931
1932            const StateAttribute* new_attr = ds_aitr->second.first.get();
1933            applyAttribute(new_attr,as);
1934
1935            as.changed = true;
1936
1937            ++ds_aitr;
1938
1939        }
1940        else
1941        {
1942            // this_mitr & ds_mitr refer to the same attribute, check the override
1943            // if any otherwise just apply the incoming attribute
1944
1945            AttributeStack& as = this_aitr->second;
1946
1947            if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
1948            {
1949                // override is on, just treat as a normal apply on attribute.
1950
1951                if (as.changed)
1952                {
1953                    as.changed = false;
1954                    const StateAttribute* new_attr = as.attributeVec.back().first;
1955                    applyAttribute(new_attr,as);
1956                }
1957            }
1958            else
1959            {
1960                // no override on or no previous entry, therefore consider incoming attribute.
1961                const StateAttribute* new_attr = ds_aitr->second.first.get();
1962                if (applyAttribute(new_attr,as))
1963                {
1964                    as.changed = true;
1965                }
1966            }
1967
1968            ++this_aitr;
1969            ++ds_aitr;
1970        }
1971    }
1972
1973    // iterator over the remaining state attributes to apply any previous changes.
1974    for(;
1975        this_aitr!=attributeMap.end();
1976        ++this_aitr)
1977    {
1978        // note attribute type = this_aitr->first
1979        AttributeStack& as = this_aitr->second;
1980        if (as.changed)
1981        {
1982            as.changed = false;
1983            if (!as.attributeVec.empty())
1984            {
1985                const StateAttribute* new_attr = as.attributeVec.back().first;
1986                applyAttribute(new_attr,as);
1987            }
1988            else
1989            {
1990                applyGlobalDefaultAttribute(as);
1991            }
1992        }
1993    }
1994
1995    // iterator over the remaining incoming attribute to apply any new attribute.
1996    for(;
1997        ds_aitr!=attributeList.end();
1998        ++ds_aitr)
1999    {
2000        // ds_aitr->first is a new attribute, therefore
2001        // need to insert a new attribute entry for ds_aitr->first.
2002        AttributeStack& as = attributeMap[ds_aitr->first];
2003
2004        const StateAttribute* new_attr = ds_aitr->second.first.get();
2005        applyAttribute(new_attr,as);
2006
2007        // will need to update this attribute on next apply so set it to changed.
2008        as.changed = true;
2009    }
2010
2011}
2012
2013inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
2014{
2015    if (!_lastAppliedProgramObject) return;
2016
2017    StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
2018
2019    UniformMap::iterator this_aitr=uniformMap.begin();
2020
2021    while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
2022    {
2023        if (this_aitr->first<ds_aitr->first)
2024        {
2025            // note attribute type = this_aitr->first
2026            UniformStack& as = this_aitr->second;
2027            if (!as.uniformVec.empty())
2028            {
2029                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2030            }
2031
2032            ++this_aitr;
2033
2034        }
2035        else if (ds_aitr->first<this_aitr->first)
2036        {
2037            _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
2038
2039            ++ds_aitr;
2040        }
2041        else
2042        {
2043            // this_mitr & ds_mitr refer to the same attribute, check the override
2044            // if any otherwise just apply the incoming attribute
2045
2046            UniformStack& as = this_aitr->second;
2047
2048            if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
2049            {
2050                // override is on, just treat as a normal apply on uniform.
2051                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2052            }
2053            else
2054            {
2055                // no override on or no previous entry, therefore consider incoming attribute.
2056                _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
2057            }
2058
2059            ++this_aitr;
2060            ++ds_aitr;
2061        }
2062    }
2063
2064    // iterator over the remaining state attributes to apply any previous changes.
2065    for(;
2066        this_aitr!=uniformMap.end();
2067        ++this_aitr)
2068    {
2069        // note attribute type = this_aitr->first
2070        UniformStack& as = this_aitr->second;
2071        if (!as.uniformVec.empty())
2072        {
2073            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2074        }
2075    }
2076
2077    // iterator over the remaining incoming attribute to apply any new attribute.
2078    for(;
2079        ds_aitr!=uniformList.end();
2080        ++ds_aitr)
2081    {
2082        _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
2083    }
2084
2085}
2086
2087inline void State::applyModeMap(ModeMap& modeMap)
2088{
2089    for(ModeMap::iterator mitr=modeMap.begin();
2090        mitr!=modeMap.end();
2091        ++mitr)
2092    {
2093        // note GLMode = mitr->first
2094        ModeStack& ms = mitr->second;
2095        if (ms.changed)
2096        {
2097            ms.changed = false;
2098            if (!ms.valueVec.empty())
2099            {
2100                bool new_value = ms.valueVec.back() & StateAttribute::ON;
2101                applyMode(mitr->first,new_value,ms);
2102            }
2103            else
2104            {
2105                // assume default of disabled.
2106                applyMode(mitr->first,ms.global_default_value,ms);
2107            }
2108
2109        }
2110    }
2111}
2112
2113inline void State::applyAttributeMap(AttributeMap& attributeMap)
2114{
2115    for(AttributeMap::iterator aitr=attributeMap.begin();
2116        aitr!=attributeMap.end();
2117        ++aitr)
2118    {
2119        AttributeStack& as = aitr->second;
2120        if (as.changed)
2121        {
2122            as.changed = false;
2123            if (!as.attributeVec.empty())
2124            {
2125                const StateAttribute* new_attr = as.attributeVec.back().first;
2126                applyAttribute(new_attr,as);
2127            }
2128            else
2129            {
2130                applyGlobalDefaultAttribute(as);
2131            }
2132
2133        }
2134    }
2135}
2136
2137inline void State::applyUniformMap(UniformMap& uniformMap)
2138{
2139    if (!_lastAppliedProgramObject) return;
2140
2141    for(UniformMap::iterator aitr=uniformMap.begin();
2142        aitr!=uniformMap.end();
2143        ++aitr)
2144    {
2145        UniformStack& as = aitr->second;
2146        if (!as.uniformVec.empty())
2147        {
2148            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
2149        }
2150    }
2151}
2152
2153
2154}
2155
2156#endif
Note: See TracBrowser for help on using the browser.