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

Revision 13041, 100.8 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

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