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

Revision 10600, 70.2 kB (checked in by robert, 5 years ago)

Introduced new BufferObject? design + implementation in preperation of implementing a pool system for buffer objects

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