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

Revision 9447, 69.9 kB (checked in by robert, 6 years ago)

Added support for primitive instancing

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