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

Revision 10601, 69.9 kB (checked in by robert, 5 years ago)

Introduced new GLBufferObject pool for managing the memory footprint taken up by VertexBufferObejct?, ElementBufferObject? and PixelBufferObject?.

  • 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();
[10601]414            else vbo->bindBuffer();
[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();
[10601]432            else ebo->bindBuffer();
[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();
[10601]451            else pbo->bindBuffer();
[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
[10601]1043        void setMaxBufferObjectPoolSize(unsigned int size);
1044        unsigned int getMaxBufferObjectPoolSize() const { return _maxBufferObjectPoolSize; }
[6069]1045
[10588]1046
[4127]1047        enum CheckForGLErrors
1048        {
[10588]1049            /** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
[4127]1050                is the fastest option since checking for errors does incurr a small overhead.*/
1051            NEVER_CHECK_GL_ERRORS,
1052            /** ONCE_PER_FRAME means that OpenGl errors will be checked for once per
1053                frame, the overhead is still small, but at least OpenGL errors that are occurring
1054                will be caught, the reporting isn't fine grained enough for debugging purposes.*/
1055            ONCE_PER_FRAME,
1056            /** ONCE_PER_ATTRIBUTE means that OpenGL errors will be checked for after
1057                every attribute is applied, allow errors to be directly associated with
1058                particular operations which makes debugging much easier.*/
1059            ONCE_PER_ATTRIBUTE
1060        };
[455]1061
[4127]1062        /** Set whether and how often OpenGL errors should be checked for.*/
1063        void setCheckForGLErrors(CheckForGLErrors check) { _checkGLErrors = check; }
1064
1065        /** Get whether and how often OpenGL errors should be checked for.*/
1066        CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
1067
[1529]1068        bool checkGLErrors(const char* str) const;
1069        bool checkGLErrors(StateAttribute::GLMode mode) const;
1070        bool checkGLErrors(const StateAttribute* attribute) const;
1071
[6578]1072
1073        /** Initialize extension used by osg:::State.*/
1074        void initializeExtensionProcs();
1075
[9549]1076        virtual void objectDeleted(void* object);
1077
[1463]1078    protected:
[455]1079
[1463]1080        virtual ~State();
1081
[4400]1082        GraphicsContext*            _graphicsContext;
[225]1083        unsigned int                _contextID;
1084        ref_ptr<FrameStamp>         _frameStamp;
[3807]1085
[1463]1086        ref_ptr<const RefMatrix>    _identity;
[2073]1087        ref_ptr<const RefMatrix>    _initialViewMatrix;
[1463]1088        ref_ptr<const RefMatrix>    _projection;
1089        ref_ptr<const RefMatrix>    _modelView;
[3807]1090
[2176]1091        Matrix                      _initialInverseViewMatrix;
1092
[235]1093        ref_ptr<DisplaySettings>    _displaySettings;
[3807]1094
[1677]1095        bool*                       _abortRenderingPtr;
[4127]1096        CheckForGLErrors            _checkGLErrors;
[1529]1097
[8]1098        struct ModeStack
1099        {
[4027]1100            typedef std::vector<StateAttribute::GLModeValue> ValueVec;
1101
[8]1102            ModeStack()
1103            {
[5001]1104                valid = true;
[8]1105                changed = false;
1106                last_applied_value = false;
[97]1107                global_default_value = false;
[8]1108            }
[3807]1109
[5001]1110            bool        valid;
[8]1111            bool        changed;
1112            bool        last_applied_value;
[97]1113            bool        global_default_value;
[8]1114            ValueVec    valueVec;
1115        };
1116
1117        struct AttributeStack
1118        {
1119            AttributeStack()
1120            {
1121                changed = false;
1122                last_applied_attribute = 0L;
[97]1123                global_default_attribute = 0L;
[8]1124            }
1125
[97]1126            /** apply an attribute if required, passing in attribute and appropriate attribute stack */
[8]1127            bool                    changed;
1128            const StateAttribute*   last_applied_attribute;
[3252]1129            ref_ptr<const StateAttribute> global_default_attribute;
[8]1130            AttributeVec            attributeVec;
1131        };
1132
[3807]1133
[4027]1134        struct UniformStack
1135        {
1136            typedef std::pair<const Uniform*,StateAttribute::OverrideValue>         UniformPair;
1137            typedef std::vector<UniformPair>                                        UniformVec;
1138
[4180]1139            UniformStack() {}
[4027]1140
1141            UniformVec              uniformVec;
1142        };
1143
1144
[3807]1145        /** Apply an OpenGL mode if required, passing in mode, enable flag and
[10588]1146        * appropriate mode stack. This is a wrapper around \c glEnable() and
1147        * \c glDisable(), that just actually calls these functions if the
1148        * \c enabled flag is different than the current state.
1149        * @return \c true if the state was actually changed. \c false
1150        *         otherwise. Notice that a \c false return does not indicate
1151        *         an error, it just means that the mode was already set to the
1152        *         same value as the \c enabled parameter.
[3807]1153        */
[1133]1154        inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
[8]1155        {
[5001]1156            if (ms.valid && ms.last_applied_value != enabled)
[8]1157            {
1158                ms.last_applied_value = enabled;
1159
1160                if (enabled) glEnable(mode);
1161                else glDisable(mode);
1162
[4127]1163                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
[1529]1164
[8]1165                return true;
1166            }
1167            else
1168                return false;
1169        }
1170
[1529]1171
[8]1172        /** apply an attribute if required, passing in attribute and appropriate attribute stack */
[1133]1173        inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
[8]1174        {
1175            if (as.last_applied_attribute != attribute)
1176            {
[327]1177                if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
[97]1178
[8]1179                as.last_applied_attribute = attribute;
1180                attribute->apply(*this);
[3807]1181
[4127]1182                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
[3807]1183
[8]1184                return true;
1185            }
1186            else
1187                return false;
1188        }
1189
[1133]1190        inline bool applyGlobalDefaultAttribute(AttributeStack& as)
[97]1191        {
[98]1192            if (as.last_applied_attribute != as.global_default_attribute.get())
[97]1193            {
[98]1194                as.last_applied_attribute = as.global_default_attribute.get();
[1529]1195                if (as.global_default_attribute.valid())
1196                {
1197                    as.global_default_attribute->apply(*this);
[4127]1198                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
[1529]1199                }
[97]1200                return true;
1201            }
1202            else
1203                return false;
1204        }
1205
[3807]1206
[3488]1207        typedef std::map<StateAttribute::GLMode,ModeStack>              ModeMap;
1208        typedef std::vector<ModeMap>                                    TextureModeMapList;
[828]1209
[3488]1210        typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
1211        typedef std::vector<AttributeMap>                               TextureAttributeMapList;
[828]1212
[4027]1213        typedef std::map<std::string,UniformStack>                      UniformMap;
1214
[3488]1215        typedef std::vector<ref_ptr<const Matrix> >                     MatrixStack;
[10588]1216
[9549]1217        typedef std::set<const Program::PerContextProgram* >            AppliedProgramObjectSet;
[8]1218
[3488]1219        ModeMap                                                         _modeMap;
1220        AttributeMap                                                    _attributeMap;
[4027]1221        UniformMap                                                      _uniformMap;
[836]1222
[3488]1223        TextureModeMapList                                              _textureModeMapList;
1224        TextureAttributeMapList                                         _textureAttributeMapList;
[3807]1225
[4149]1226        AppliedProgramObjectSet                                         _appliedProgramObjectSet;
[4027]1227        const Program::PerContextProgram*                               _lastAppliedProgramObject;
[3958]1228
[4027]1229        StateSetStack                                                   _stateStateStack;
[3807]1230
[10588]1231        unsigned int                                                    _maxTexturePoolSize;
[10601]1232        unsigned int                                                    _maxBufferObjectPoolSize;
[10588]1233
1234
[828]1235        struct EnabledArrayPair
1236        {
[1940]1237            EnabledArrayPair():_dirty(true),_enabled(false),_normalized(0),_pointer(0) {}
1238            EnabledArrayPair(const EnabledArrayPair& eap):_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {}
1239            EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; }
[3807]1240
[1152]1241            bool            _dirty;
1242            bool            _enabled;
[1940]1243            GLboolean       _normalized;
[1152]1244            const GLvoid*   _pointer;
[828]1245        };
[3807]1246
[828]1247        typedef std::vector<EnabledArrayPair>                   EnabledTexCoordArrayList;
[1940]1248        typedef std::vector<EnabledArrayPair>                   EnabledVertexAttribArrayList;
[828]1249
[1940]1250        EnabledArrayPair                _vertexArray;
1251        EnabledArrayPair                _normalArray;
1252        EnabledArrayPair                _colorArray;
1253        EnabledArrayPair                _secondaryColorArray;
1254        EnabledArrayPair                _indexArray;
1255        EnabledArrayPair                _fogArray;
1256        EnabledTexCoordArrayList        _texCoordArrayList;
1257        EnabledVertexAttribArrayList    _vertexAttribArrayList;
1258
1259        unsigned int                    _currentActiveTextureUnit;
1260        unsigned int                    _currentClientActiveTextureUnit;
[10600]1261        GLBufferObject*                 _currentVBO;
1262        GLBufferObject*                 _currentEBO;
1263        GLBufferObject*                 _currentPBO;
[3807]1264
[6578]1265
[836]1266        inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
[3807]1267        {
[836]1268            if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
1269            return _textureModeMapList[unit];
1270        }
1271
1272
1273        inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
[3807]1274        {
[836]1275            if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
1276            return _textureAttributeMapList[unit];
1277        }
[3807]1278
[836]1279        inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1280        inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
[4180]1281        inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
[3807]1282
[836]1283        inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1284        inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
[4180]1285        inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
[836]1286
1287        inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1288        inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
[4180]1289        inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
[3807]1290
[836]1291        inline void applyModeMap(ModeMap& modeMap);
1292        inline void applyAttributeMap(AttributeMap& attributeMap);
[4180]1293        inline void applyUniformMap(UniformMap& uniformMap);
[836]1294
[1133]1295        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
1296        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
[836]1297        void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
[3488]1298        void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member);
[1133]1299        bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
[3488]1300        const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const;
[836]1301
[1313]1302
[2000]1303        mutable bool _isSecondaryColorSupportResolved;
1304        mutable bool _isSecondaryColorSupported;
[1313]1305        bool computeSecondaryColorSupported() const;
1306
1307        mutable bool _isFogCoordSupportResolved;
1308        mutable bool _isFogCoordSupported;
1309        bool computeFogCoordSupported() const;
[2000]1310
1311        mutable bool _isVertexBufferObjectSupportResolved;
1312        mutable bool _isVertexBufferObjectSupported;
1313        bool computeVertexBufferObjectSupported() const;
1314
[5380]1315        typedef void (APIENTRY * ActiveTextureProc) (GLenum texture);
1316        typedef void (APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer);
1317        typedef void (APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
1318        typedef void (APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
1319        typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int);
1320        typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int);
[6578]1321        typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
[10588]1322
[9447]1323        typedef void (APIENTRY * DrawArraysInstancedProc)( GLenum mode, GLint first, GLsizei count, GLsizei primcount );
1324        typedef void (APIENTRY * DrawElementsInstancedProc)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount );
[5380]1325
1326        bool                        _extensionProcsInitialized;
[6671]1327        GLint                       _glMaxTextureCoords;
1328        GLint                       _glMaxTextureUnits;
[5380]1329        ActiveTextureProc           _glClientActiveTexture;
1330        ActiveTextureProc           _glActiveTexture;
1331        FogCoordPointerProc         _glFogCoordPointer;
1332        SecondaryColorPointerProc   _glSecondaryColorPointer;
1333        VertexAttribPointerProc     _glVertexAttribPointer;
1334        EnableVertexAttribProc      _glEnableVertexAttribArray;
1335        DisableVertexAttribProc     _glDisableVertexAttribArray;
[6578]1336        BindBufferProc              _glBindBuffer;
[9447]1337        DrawArraysInstancedProc     _glDrawArraysInstanced;
1338        DrawElementsInstancedProc   _glDrawElementsInstanced;
[5380]1339
[6069]1340        unsigned int                                            _dynamicObjectCount;
1341        osg::ref_ptr<DynamicObjectRenderingCompletedCallback>   _completeDynamicObjectRenderingCallback;
[10588]1342
[2]1343};
1344
[836]1345inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1346{
1347    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1348        mitr!=modeList.end();
1349        ++mitr)
1350    {
[3375]1351        // get the mode stack for incoming GLmode {mitr->first}.
[836]1352        ModeStack& ms = modeMap[mitr->first];
1353        if (ms.valueVec.empty())
1354        {
[3375]1355            // first pair so simply push incoming pair to back.
[836]1356            ms.valueVec.push_back(mitr->second);
1357        }
[3807]1358        else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
[836]1359        {
[3375]1360            // push existing back since override keeps the previous value.
[836]1361            ms.valueVec.push_back(ms.valueVec.back());
1362        }
[3807]1363        else
[836]1364        {
[3375]1365            // no override on so simply push incoming pair to back.
[836]1366            ms.valueVec.push_back(mitr->second);
1367        }
1368        ms.changed = true;
1369    }
[349]1370}
[2]1371
[836]1372inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1373{
1374    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1375        aitr!=attributeList.end();
1376        ++aitr)
1377    {
[3375]1378        // get the attribute stack for incoming type {aitr->first}.
[836]1379        AttributeStack& as = attributeMap[aitr->first];
1380        if (as.attributeVec.empty())
1381        {
[3375]1382            // first pair so simply push incoming pair to back.
[836]1383            as.attributeVec.push_back(
[10179]1384                AttributePair(aitr->second.first.get(),aitr->second.second));
[836]1385        }
[3807]1386        else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
[836]1387        {
[3375]1388            // push existing back since override keeps the previous value.
[836]1389            as.attributeVec.push_back(as.attributeVec.back());
1390        }
[3807]1391        else
[836]1392        {
[3375]1393            // no override on so simply push incoming pair to back.
[836]1394            as.attributeVec.push_back(
[10179]1395                AttributePair(aitr->second.first.get(),aitr->second.second));
[836]1396        }
1397        as.changed = true;
1398    }
1399}
1400
[4180]1401
1402inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1403{
1404    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1405        aitr!=uniformList.end();
1406        ++aitr)
1407    {
1408        // get the attribute stack for incoming type {aitr->first}.
1409        UniformStack& us = uniformMap[aitr->first];
1410        if (us.uniformVec.empty())
1411        {
1412            // first pair so simply push incoming pair to back.
1413            us.uniformVec.push_back(
1414                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1415        }
1416        else if ((us.uniformVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1417        {
1418            // push existing back since override keeps the previous value.
1419            us.uniformVec.push_back(us.uniformVec.back());
1420        }
1421        else
1422        {
1423            // no override on so simply push incoming pair to back.
1424            us.uniformVec.push_back(
1425                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1426        }
1427    }
1428}
1429
[836]1430inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1431{
1432    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1433        mitr!=modeList.end();
1434        ++mitr)
1435    {
[3375]1436        // get the mode stack for incoming GLmode {mitr->first}.
[836]1437        ModeStack& ms = modeMap[mitr->first];
1438        if (!ms.valueVec.empty())
1439        {
1440            ms.valueVec.pop_back();
1441        }
1442        ms.changed = true;
1443    }
1444}
1445
1446inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1447{
1448    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1449        aitr!=attributeList.end();
1450        ++aitr)
1451    {
[3375]1452        // get the attribute stack for incoming type {aitr->first}.
[836]1453        AttributeStack& as = attributeMap[aitr->first];
1454        if (!as.attributeVec.empty())
1455        {
1456            as.attributeVec.pop_back();
1457        }
1458        as.changed = true;
1459    }
1460}
1461
[4180]1462inline void State::popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1463{
1464    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1465        aitr!=uniformList.end();
1466        ++aitr)
1467    {
1468        // get the attribute stack for incoming type {aitr->first}.
1469        UniformStack& us = uniformMap[aitr->first];
1470        if (!us.uniformVec.empty())
1471        {
1472            us.uniformVec.pop_back();
1473        }
1474    }
1475}
1476
[836]1477inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1478{
1479    StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
1480    ModeMap::iterator this_mitr=modeMap.begin();
1481
1482    while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
1483    {
1484        if (this_mitr->first<ds_mitr->first)
1485        {
1486
1487            // note GLMode = this_mitr->first
1488            ModeStack& ms = this_mitr->second;
1489            if (ms.changed)
1490            {
1491                ms.changed = false;
1492                if (!ms.valueVec.empty())
1493                {
1494                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1495                    applyMode(this_mitr->first,new_value,ms);
1496                }
1497                else
1498                {
1499                    // assume default of disabled.
1500                    applyMode(this_mitr->first,ms.global_default_value,ms);
1501
1502                }
1503
1504            }
1505
1506            ++this_mitr;
1507
1508        }
1509        else if (ds_mitr->first<this_mitr->first)
1510        {
1511
[3807]1512            // ds_mitr->first is a new mode, therefore
[836]1513            // need to insert a new mode entry for ds_mistr->first.
1514            ModeStack& ms = modeMap[ds_mitr->first];
1515
1516            bool new_value = ds_mitr->second & StateAttribute::ON;
1517            applyMode(ds_mitr->first,new_value,ms);
1518
1519            // will need to disable this mode on next apply so set it to changed.
1520            ms.changed = true;
1521
1522            ++ds_mitr;
1523
1524        }
1525        else
1526        {
[3375]1527            // this_mitr & ds_mitr refer to the same mode, check the override
1528            // if any otherwise just apply the incoming mode.
[836]1529
1530            ModeStack& ms = this_mitr->second;
1531
[1008]1532            if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
[836]1533            {
[3408]1534                // override is on, just treat as a normal apply on modes.
[836]1535
1536                if (ms.changed)
1537                {
1538                    ms.changed = false;
1539                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1540                    applyMode(this_mitr->first,new_value,ms);
1541
1542                }
1543            }
1544            else
1545            {
[3375]1546                // no override on or no previous entry, therefore consider incoming mode.
[836]1547                bool new_value = ds_mitr->second & StateAttribute::ON;
1548                if (applyMode(ds_mitr->first,new_value,ms))
1549                {
1550                    ms.changed = true;
1551                }
1552            }
1553
1554            ++this_mitr;
1555            ++ds_mitr;
1556        }
1557    }
1558
1559    // iterator over the remaining state modes to apply any previous changes.
1560    for(;
1561        this_mitr!=modeMap.end();
1562        ++this_mitr)
1563    {
1564        // note GLMode = this_mitr->first
1565        ModeStack& ms = this_mitr->second;
1566        if (ms.changed)
1567        {
1568            ms.changed = false;
1569            if (!ms.valueVec.empty())
1570            {
1571                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1572                applyMode(this_mitr->first,new_value,ms);
1573            }
1574            else
1575            {
1576                // assume default of disabled.
1577                applyMode(this_mitr->first,ms.global_default_value,ms);
1578
1579            }
1580
1581        }
[3807]1582    }
[836]1583
[3375]1584    // iterator over the remaining incoming modes to apply any new mode.
[836]1585    for(;
1586        ds_mitr!=modeList.end();
1587        ++ds_mitr)
1588    {
1589        ModeStack& ms = modeMap[ds_mitr->first];
1590
1591        bool new_value = ds_mitr->second & StateAttribute::ON;
1592        applyMode(ds_mitr->first,new_value,ms);
1593
1594        // will need to disable this mode on next apply so set it to changed.
1595        ms.changed = true;
1596    }
1597}
1598
1599inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1600{
1601    StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
1602
1603    AttributeMap::iterator this_aitr=attributeMap.begin();
1604
1605    while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
1606    {
1607        if (this_aitr->first<ds_aitr->first)
1608        {
1609
1610            // note attribute type = this_aitr->first
1611            AttributeStack& as = this_aitr->second;
1612            if (as.changed)
1613            {
1614                as.changed = false;
1615                if (!as.attributeVec.empty())
1616                {
1617                    const StateAttribute* new_attr = as.attributeVec.back().first;
1618                    applyAttribute(new_attr,as);
1619                }
1620                else
1621                {
1622                    applyGlobalDefaultAttribute(as);
1623                }
1624            }
1625
1626            ++this_aitr;
1627
1628        }
1629        else if (ds_aitr->first<this_aitr->first)
1630        {
1631
[3807]1632            // ds_aitr->first is a new attribute, therefore
[3408]1633            // need to insert a new attribute entry for ds_aitr->first.
[836]1634            AttributeStack& as = attributeMap[ds_aitr->first];
1635
1636            const StateAttribute* new_attr = ds_aitr->second.first.get();
1637            applyAttribute(new_attr,as);
1638
1639            as.changed = true;
1640
1641            ++ds_aitr;
1642
1643        }
1644        else
1645        {
[3375]1646            // this_mitr & ds_mitr refer to the same attribute, check the override
1647            // if any otherwise just apply the incoming attribute
[836]1648
1649            AttributeStack& as = this_aitr->second;
1650
[1008]1651            if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
[836]1652            {
[4027]1653                // override is on, just treat as a normal apply on attribute.
[836]1654
1655                if (as.changed)
1656                {
1657                    as.changed = false;
1658                    const StateAttribute* new_attr = as.attributeVec.back().first;
1659                    applyAttribute(new_attr,as);
1660                }
1661            }
1662            else
1663            {
[4027]1664                // no override on or no previous entry, therefore consider incoming attribute.
[836]1665                const StateAttribute* new_attr = ds_aitr->second.first.get();
1666                if (applyAttribute(new_attr,as))
1667                {
1668                    as.changed = true;
1669                }
1670            }
1671
1672            ++this_aitr;
1673            ++ds_aitr;
1674        }
1675    }
1676
[4027]1677    // iterator over the remaining state attributes to apply any previous changes.
[836]1678    for(;
1679        this_aitr!=attributeMap.end();
1680        ++this_aitr)
1681    {
1682        // note attribute type = this_aitr->first
1683        AttributeStack& as = this_aitr->second;
1684        if (as.changed)
1685        {
1686            as.changed = false;
1687            if (!as.attributeVec.empty())
1688            {
1689                const StateAttribute* new_attr = as.attributeVec.back().first;
1690                applyAttribute(new_attr,as);
1691            }
1692            else
1693            {
1694                applyGlobalDefaultAttribute(as);
1695            }
1696        }
[3807]1697    }
[836]1698
[4027]1699    // iterator over the remaining incoming attribute to apply any new attribute.
[836]1700    for(;
1701        ds_aitr!=attributeList.end();
1702        ++ds_aitr)
1703    {
[3807]1704        // ds_aitr->first is a new attribute, therefore
[3408]1705        // need to insert a new attribute entry for ds_aitr->first.
[836]1706        AttributeStack& as = attributeMap[ds_aitr->first];
1707
1708        const StateAttribute* new_attr = ds_aitr->second.first.get();
1709        applyAttribute(new_attr,as);
1710
1711        // will need to update this attribute on next apply so set it to changed.
1712        as.changed = true;
1713    }
1714
1715}
1716
[4180]1717inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1718{
1719    if (!_lastAppliedProgramObject) return;
1720
1721    StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
1722
1723    UniformMap::iterator this_aitr=uniformMap.begin();
1724
1725    while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
1726    {
1727        if (this_aitr->first<ds_aitr->first)
1728        {
1729            // note attribute type = this_aitr->first
1730            UniformStack& as = this_aitr->second;
1731            if (!as.uniformVec.empty())
1732            {
1733                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1734            }
1735
1736            ++this_aitr;
1737
1738        }
1739        else if (ds_aitr->first<this_aitr->first)
1740        {
1741            _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1742
1743            ++ds_aitr;
1744        }
1745        else
1746        {
1747            // this_mitr & ds_mitr refer to the same attribute, check the override
1748            // if any otherwise just apply the incoming attribute
1749
1750            UniformStack& as = this_aitr->second;
1751
1752            if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
1753            {
1754                // override is on, just treat as a normal apply on uniform.
1755                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1756            }
1757            else
1758            {
1759                // no override on or no previous entry, therefore consider incoming attribute.
1760                _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1761            }
1762
1763            ++this_aitr;
1764            ++ds_aitr;
1765        }
1766    }
1767
1768    // iterator over the remaining state attributes to apply any previous changes.
1769    for(;
1770        this_aitr!=uniformMap.end();
1771        ++this_aitr)
1772    {
1773        // note attribute type = this_aitr->first
1774        UniformStack& as = this_aitr->second;
1775        if (!as.uniformVec.empty())
1776        {
1777            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1778        }
1779    }
1780
1781    // iterator over the remaining incoming attribute to apply any new attribute.
1782    for(;
1783        ds_aitr!=uniformList.end();
1784        ++ds_aitr)
1785    {
1786        _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1787    }
1788
1789}
1790
[836]1791inline void State::applyModeMap(ModeMap& modeMap)
1792{
1793    for(ModeMap::iterator mitr=modeMap.begin();
1794        mitr!=modeMap.end();
1795        ++mitr)
1796    {
1797        // note GLMode = mitr->first
1798        ModeStack& ms = mitr->second;
1799        if (ms.changed)
1800        {
1801            ms.changed = false;
1802            if (!ms.valueVec.empty())
1803            {
1804                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1805                applyMode(mitr->first,new_value,ms);
1806            }
1807            else
1808            {
1809                // assume default of disabled.
1810                applyMode(mitr->first,ms.global_default_value,ms);
1811            }
[3807]1812
[836]1813        }
[3807]1814    }
[836]1815}
1816
1817inline void State::applyAttributeMap(AttributeMap& attributeMap)
1818{
1819    for(AttributeMap::iterator aitr=attributeMap.begin();
1820        aitr!=attributeMap.end();
1821        ++aitr)
1822    {
1823        AttributeStack& as = aitr->second;
1824        if (as.changed)
1825        {
1826            as.changed = false;
1827            if (!as.attributeVec.empty())
1828            {
1829                const StateAttribute* new_attr = as.attributeVec.back().first;
1830                applyAttribute(new_attr,as);
1831            }
1832            else
1833            {
1834                applyGlobalDefaultAttribute(as);
1835            }
[3807]1836
[836]1837        }
[3807]1838    }
[836]1839}
1840
[4180]1841inline void State::applyUniformMap(UniformMap& uniformMap)
1842{
1843    if (!_lastAppliedProgramObject) return;
1844
1845    for(UniformMap::iterator aitr=uniformMap.begin();
1846        aitr!=uniformMap.end();
1847        ++aitr)
1848    {
1849        UniformStack& as = aitr->second;
1850        if (!as.uniformVec.empty())
1851        {
1852            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1853        }
1854    }
[836]1855}
1856
[5573]1857
[4180]1858}
1859
[2]1860#endif
Note: See TracBrowser for help on using the browser.