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

Revision 9549, 70.2 kB (checked in by robert, 6 years ago)

Fixed effective leak in Program::PerContextProgram? caused by previously osg::State keeping a set of std::ref_ptr<Program::PerContextProgram?> without ever pruning this list.
The fix was to convert the osg::State to use C pointers for the set of applied PerContexProgram? objects, and use the osg::Oberver mechanism to avoid dangling pointers for being maintained in osg::State.

  • 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
[1940]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
[1940]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
[8]57  * reporting OpenGL error messages.*/
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,
[7648]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
[3807]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
[5166]79  *   seldom needed, since OSG does this in the most common situations.
[3807]80  * - It implements lazy state updating. This means that, if one requests a
[5166]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
[7648]83  *   stalled by unnecessary state changes.
[3807]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()).
[8]87  */
[9549]88class OSG_EXPORT State : public Referenced, public Observer
[2]89{
90    public :
[3807]91
[8]92        State();
[4400]93       
[2]94
[4400]95        /** Set the graphics context associated with that owns this State object.*/       
96        void setGraphicsContext(GraphicsContext* context) { _graphicsContext = context; }
97
98        /** Get the graphics context associated with that owns this State object.*/       
99        GraphicsContext* getGraphicsContext() { return _graphicsContext; }
100
101        /** Get the const graphics context associated with that owns this State object.*/       
102        const GraphicsContext* getGraphicsContext() const { return _graphicsContext; }
103       
104
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();
[6504]125       
[3375]126        /** pop all statesets off state stack, ensuring it is empty ready for the next frame.
[3408]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);
[6056]135       
136        /** Get the number of StateSet's on the StateSet stack.*/
137        unsigned int getStateSetStackSize() { return _stateStateStack.size(); }
138       
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       
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
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.
226          * Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
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.
234          * Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
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
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.
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
[464]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
[698]354        /** Attribute has been applied externally,
[464]355          * and therefore this attribute type has been dirtied
[3375]356          * and will need to be re-applied on next osg::State.apply(..).
[464]357          * note, if you have an osg::StateAttribute which you have applied externally
[3375]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
[464]360          * that only changed state will be applied.*/
[3488]361        void haveAppliedAttribute(StateAttribute::Type type, unsigned int member=0);
[464]362
[698]363        /** Get whether the current specified mode is enabled (true) or disabled (false).*/
[1133]364        bool getLastAppliedMode(StateAttribute::GLMode mode) const;
[3807]365
[3375]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
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,
380          * and therefore this attribute type has been dirtied
[7648]381          * and will need to be re-applied on next osg::State.apply(..).
[828]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
[3375]384          * track the current state more accurately and enable lazy state updating such
[828]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
[6578]408        void setCurrentVertexBufferObject(osg::VertexBufferObject* vbo) { _currentVBO = vbo; }
409        const VertexBufferObject* getCurrentVertexBufferObject() { return _currentVBO; }
410        inline void bindVertexBufferObject(const osg::VertexBufferObject* vbo)
411        {
412            if (vbo == _currentVBO) return;
[6582]413            if (vbo->isDirty(_contextID)) vbo->compileBuffer(*this);
[6578]414            else _glBindBuffer(GL_ARRAY_BUFFER_ARB,vbo->buffer(_contextID));
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
425        void setCurrentElementBufferObject(osg::ElementBufferObject* ebo) { _currentEBO = ebo; }
426        const ElementBufferObject* getCurrentElementBufferObject() { return _currentEBO; }
427
428        inline void bindElementBufferObject(const osg::ElementBufferObject* ebo)
429        {
430            if (ebo == _currentEBO) return;
[6582]431            if (ebo->isDirty(_contextID)) ebo->compileBuffer(*this);
[6578]432            else _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,ebo->buffer(_contextID));
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
443        void setCurrentPixelBufferObject(osg::PixelBufferObject* pbo) { _currentPBO = pbo; }
444        const PixelBufferObject* getCurrentPixelBufferObject() { return _currentPBO; }
445
446        inline void bindPixelBufferObject(const osg::PixelBufferObject* pbo)
447        {
448            if (pbo == _currentPBO) return;
449
[6582]450            if (pbo->isDirty(_contextID)) pbo->compileBuffer(*this);
[6578]451            else _glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,pbo->buffer(_contextID));
452
453            _currentPBO = pbo;
454        }
455
456        inline void unbindPixelBufferObject()
457        {
458            if (!_currentPBO) return;
459           
460            _glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
461            _currentPBO = 0;
462        }
[9447]463       
464       
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        }
470   
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(..).
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            {
488                const VertexBufferObject* vbo = array->getVertexBufferObject();
489                if (vbo)
490                {
491                    bindVertexBufferObject(vbo);
[6582]492                    setVertexPointer(array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
[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(..);
504          * note, only updates values that change.*/
505        inline void setVertexPointer( GLint size, GLenum type,
506                                      GLsizei stride, const GLvoid *ptr )
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).
[828]522          * note, only updates values that change.*/
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            {
545                const VertexBufferObject* vbo = array->getVertexBufferObject();
546                if (vbo)
547                {
548                    bindVertexBufferObject(vbo);
[6582]549                   setNormalPointer(array->getDataType(),0,array->getVertexBufferObjectOffset());
[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(..);
561          * note, only updates values that change.*/
562        inline void setNormalPointer( GLenum type, GLsizei stride,
563                                      const GLvoid *ptr )
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);
579          * note, only updates values that change.*/
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            {
601                const VertexBufferObject* vbo = array->getVertexBufferObject();
602                if (vbo)
603                {
604                    bindVertexBufferObject(vbo);
[6582]605                    setColorPointer(array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
[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(..);
618          * note, only updates values that change.*/
619        inline void setColorPointer( GLint size, GLenum type,
620                                     GLsizei stride, const GLvoid *ptr )
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);
636          * note, only updates values that change.*/
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            {
662                const VertexBufferObject* vbo = array->getVertexBufferObject();
663                if (vbo)
664                {
665                    bindVertexBufferObject(vbo);
[6582]666#if 0                   
[6578]667                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,vbo->getOffset(array->getVertexBufferObjectIndex()));
[6582]668#else
669                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
670#endif
[6578]671                }
672                else
673                {
674                    unbindVertexBufferObject();
675                    setSecondaryColorPointer(array->getDataSize(),array->getDataType(),0,array->getDataPointer());
676                }
677            }
678            else disableSecondaryColorPointer();
679        }
680
[1045]681        /** wrapper around glEnableClientState(GL_SECONDARY_COLOR_ARRAY);glSecondayColorPointer(..);
682          * note, only updates values that change.*/
683        void setSecondaryColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr );
684
685        /** wrapper around glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
686          * note, only updates values that change.*/
687        inline void disableSecondaryColorPointer()
688        {
[1152]689            if (_secondaryColorArray._enabled || _secondaryColorArray._dirty)
[1045]690            {
691                _secondaryColorArray._enabled = false;
[1152]692                _secondaryColorArray._dirty = false;
[1313]693                if (isSecondaryColorSupported()) glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
[1045]694            }
695        }
696
[1152]697        inline void dirtySecondaryColorPointer()
698        {
[1771]699            _secondaryColorArray._pointer = 0;
[1152]700            _secondaryColorArray._dirty = true;
701        }
702
[828]703        /** wrapper around glEnableClientState(GL_INDEX_ARRAY);glIndexPointer(..);
704          * note, only updates values that change.*/
705        inline void setIndexPointer( GLenum type, GLsizei stride,
706                              const GLvoid *ptr )
707        {
[1152]708            if (!_indexArray._enabled || _indexArray._dirty)
[828]709            {
710                _indexArray._enabled = true;
711                glEnableClientState(GL_INDEX_ARRAY);
712            }
[2000]713            //if (_indexArray._pointer!=ptr || _indexArray._dirty)
[828]714            {
715                _indexArray._pointer=ptr;
716                glIndexPointer( type, stride, ptr );
717            }
[1152]718            _indexArray._dirty = false;
[828]719        }
720
721        /** wrapper around glDisableClientState(GL_INDEX_ARRAY);
722          * note, only updates values that change.*/
723        inline void disableIndexPointer()
724        {
[1152]725            if (_indexArray._enabled || _indexArray._dirty)
[828]726            {
727                _indexArray._enabled = false;
[1152]728                _indexArray._dirty = false;
[828]729                glDisableClientState(GL_INDEX_ARRAY);
730            }
731        }
732
[1152]733        inline void dirtyIndexPointer()
734        {
[1771]735            _indexArray._pointer = 0;
[1152]736            _indexArray._dirty = true;
737        }
738
739
[1313]740        inline bool isFogCoordSupported() const { return _isFogCoordSupportResolved?_isFogCoordSupported:computeFogCoordSupported(); }
741
[6578]742
743        /** Set the fog coord pointer using an osg::Array, and manage any VBO that are required.*/
744        inline void setFogCoordPointer(const Array* array)
745        {
746            if (array)
747            {
748                const VertexBufferObject* vbo = array->getVertexBufferObject();
749                if (vbo)
750                {
751                    bindVertexBufferObject(vbo);
[6582]752#if 0
[6578]753                    setFogCoordPointer(array->getDataType(),0,vbo->getOffset(array->getVertexBufferObjectIndex()));
[6582]754#else
755                    setFogCoordPointer(array->getDataType(),0,array->getVertexBufferObjectOffset());
756#endif
[6578]757                }
758                else
759                {
760                    unbindVertexBufferObject();
761                    setFogCoordPointer(array->getDataType(),0,array->getDataPointer());
762                }
763            }
764            else disableFogCoordPointer();
765        }
766
767
[1045]768        /** wrapper around glEnableClientState(GL_FOG_COORDINATE_ARRAY);glFogCoordPointer(..);
769          * note, only updates values that change.*/
770        void setFogCoordPointer( GLenum type, GLsizei stride, const GLvoid *ptr );
771
772        /** wrapper around glDisableClientState(GL_FOG_COORDINATE_ARRAY);
773          * note, only updates values that change.*/
774        inline void disableFogCoordPointer()
775        {
[1152]776            if (_fogArray._enabled || _fogArray._dirty)
[1045]777            {
778                _fogArray._enabled = false;
[1152]779                _fogArray._dirty = false;
[1313]780                if (isFogCoordSupported()) glDisableClientState(GL_FOG_COORDINATE_ARRAY);
[1045]781            }
782        }
783
[1152]784        inline void dirtyFogCoordPointer()
785        {
[1771]786            _fogArray._pointer = 0;
[1152]787            _fogArray._dirty = true;
788        }
[1045]789
[1152]790
[6578]791
792        /** Set the tex coord pointer using an osg::Array, and manage any VBO that are required.*/
793        inline void setTexCoordPointer(unsigned int unit, const Array* array)
794        {
795            if (array)
796            {
797                const VertexBufferObject* vbo = array->getVertexBufferObject();
798                if (vbo)
799                {
800                    bindVertexBufferObject(vbo);
[6582]801#if 0
[6578]802                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,vbo->getOffset(array->getVertexBufferObjectIndex()));
[6582]803#else
804                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,array->getVertexBufferObjectOffset());
805#endif
[6578]806                }
807                else
808                {
809                    unbindVertexBufferObject();
810                    setTexCoordPointer(unit, array->getDataSize(),array->getDataType(),0,array->getDataPointer());
811                }
812            }
813            else disableTexCoordPointer(unit);
814        }
815
[828]816        /** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..);
817          * note, only updates values that change.*/
818        inline void setTexCoordPointer( unsigned int unit,
[1940]819                                        GLint size, GLenum type,
820                                        GLsizei stride, const GLvoid *ptr )
[828]821        {
822            if (setClientActiveTextureUnit(unit))
823            {
824                if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
825                EnabledArrayPair& eap = _texCoordArrayList[unit];
826
[1152]827                if (!eap._enabled || eap._dirty)
[828]828                {
829                    eap._enabled = true;
830                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
831                }
[2000]832                //if (eap._pointer!=ptr || eap._dirty)
[828]833                {
834                    glTexCoordPointer( size, type, stride, ptr );
835                    eap._pointer = ptr;
836                }
[1152]837                eap._dirty = false;
[828]838            }
839        }
[1940]840
[828]841        /** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
842          * note, only updates values that change.*/
843        inline void disableTexCoordPointer( unsigned int unit )
844        {
845            if (setClientActiveTextureUnit(unit))
846            {
[854]847                if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
[828]848                EnabledArrayPair& eap = _texCoordArrayList[unit];
849
[1152]850                if (eap._enabled || eap._dirty)
[828]851                {
852                    eap._enabled = false;
[1152]853                    eap._dirty = false;
[828]854                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
855                }
856            }
857        }
858
[1152]859        inline void dirtyTexCoordPointer( unsigned int unit )
860        {
861            if ( unit >= _texCoordArrayList.size()) return; // _texCoordArrayList.resize(unit+1);
862            EnabledArrayPair& eap = _texCoordArrayList[unit];
[1771]863            eap._pointer = 0;
[1152]864            eap._dirty = true;
865        }
866
867
[887]868        inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit )
869        {
870            while (unit<_texCoordArrayList.size())
871            {
872                EnabledArrayPair& eap = _texCoordArrayList[unit];
[1152]873                if (eap._enabled || eap._dirty)
[887]874                {
875                    if (setClientActiveTextureUnit(unit))
876                    {
877                        eap._enabled = false;
[1152]878                        eap._dirty = false;
[887]879                        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
880                    }
881                }
882                ++unit;
883            }
884        }
[828]885
[1152]886        inline void dirtyTexCoordPointersAboveAndIncluding( unsigned int unit )
887        {
888            while (unit<_texCoordArrayList.size())
889            {
890                EnabledArrayPair& eap = _texCoordArrayList[unit];
[1771]891                eap._pointer = 0;
[1152]892                eap._dirty = true;
893                ++unit;
894            }
895        }
896
[3951]897
898        /** Set the current texture unit, return true if selected,
[7648]899          * false if selection failed such as when multi texturing is not supported.
[3951]900          * note, only updates values that change.*/
901        bool setActiveTextureUnit( unsigned int unit );
902       
903        /** Get the current texture unit.*/
904        unsigned int getActiveTextureUnit() const { return _currentActiveTextureUnit; }
905
[3807]906        /** Set the current tex coord array texture unit, return true if selected,
[7648]907          * false if selection failed such as when multi texturing is not supported.
[828]908          * note, only updates values that change.*/
[861]909        bool setClientActiveTextureUnit( unsigned int unit );
[858]910
[3951]911        /** Get the current tex coord array texture unit.*/
912        unsigned int getClientActiveTextureUnit() const { return _currentClientActiveTextureUnit; }
[828]913
[6578]914        /** Set the vertex attrib pointer using an osg::Array, and manage any VBO that are required.*/
915        inline void setVertexAttribPointer(unsigned int unit, const Array* array, GLboolean normalized)
916        {
917            if (array)
918            {
919                const VertexBufferObject* vbo = array->getVertexBufferObject();
920                if (vbo)
921                {
922                    bindVertexBufferObject(vbo);
[6582]923#if 0                   
[6578]924                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,vbo->getOffset(array->getVertexBufferObjectIndex()));
[6582]925#else
926                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,array->getVertexBufferObjectOffset());
927#endif
[6578]928                }
929                else
930                {
931                    unbindVertexBufferObject();
932                    setVertexAttribPointer(unit, array->getDataSize(),array->getDataType(),normalized,0,array->getDataPointer());
933                }
934            }
935            else disableVertexAttribPointer(unit);
936        }
937
[1940]938        /** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..);
939          * note, only updates values that change.*/
[1944]940        void setVertexAttribPointer( unsigned int index,
[3807]941                                     GLint size, GLenum type, GLboolean normalized,
[1944]942                                     GLsizei stride, const GLvoid *ptr );
[3807]943
[1940]944        /** wrapper around DisableVertexAttribArrayARB(index);
945          * note, only updates values that change.*/
[1944]946        void disableVertexAttribPointer( unsigned int index );
[3807]947
[1944]948        void disableVertexAttribPointersAboveAndIncluding( unsigned int index );
[3807]949
[1940]950        inline void dirtyVertexAttribPointersAboveAndIncluding( unsigned int index )
951        {
952            while (index<_vertexAttribArrayList.size())
953            {
954                EnabledArrayPair& eap = _vertexAttribArrayList[index];
955                eap._pointer = 0;
956                eap._dirty = true;
957                ++index;
958            }
959        }
960
[2000]961        bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); }
[1940]962
[2000]963
[9549]964        inline void setLastAppliedProgramObject(const Program::PerContextProgram* program)
965        {
966            if (_lastAppliedProgramObject!=program)
967            {
968                _lastAppliedProgramObject = program;
969                if (program && _appliedProgramObjectSet.count(program)==0)
970                {
971                    _appliedProgramObjectSet.insert(program);
972                    program->addObserver(this);
973                }
974            }
975        }
976        inline const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; }
[4027]977
[4210]978        inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; }
979        inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; }
[4027]980
[8]981
[26]982        /** Set the frame stamp for the current frame.*/
983        inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
984
[3408]985        /** Get the frame stamp for the current frame.*/
[7178]986        inline FrameStamp* getFrameStamp() { return _frameStamp.get(); }
987
988        /** Get the const frame stamp for the current frame.*/
[26]989        inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
[3807]990
991
[3375]992        /** Set the DisplaySettings. Note, nothing is applied, the visual settings are just
[225]993          * used in the State object to pass the current visual settings to Drawables
994          * during rendering. */
[235]995        inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
[3807]996
[235]997        /** Get the DisplaySettings */
998        inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
[225]999
[3807]1000
1001
[1677]1002        /** Set flag for early termination of the draw traversal.*/
1003        void setAbortRenderingPtr(bool* abortPtr) { _abortRenderingPtr = abortPtr; }
1004
[3807]1005        /** Get flag for early termination of the draw traversal,
[1677]1006          * if true steps should be taken to complete rendering early.*/
1007        bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
1008
[6069]1009
1010        struct DynamicObjectRenderingCompletedCallback : public osg::Referenced
1011        {
1012            virtual void completed(osg::State*) = 0;
1013        };
1014       
1015        /** Set the callback to be called when the dynamic object count hits 0.*/
1016        void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; }
1017       
1018        /** Get the callback to be called when the dynamic object count hits 0.*/
1019        DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); }
1020       
1021        /** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/
1022        void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false)
1023        {
1024            if (_dynamicObjectCount != count)
1025            {
1026                _dynamicObjectCount = count;
1027                if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid())
1028                {
1029                    _completeDynamicObjectRenderingCallback->completed(this);
1030                }
1031            }
1032        }
1033
1034        /** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/
1035        unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; }
1036       
1037        /** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the
1038          * DynamicObjectRenderingCompletedCallback to inform of completion.*/
1039        inline void decrementDynamicObjectCount()
1040        {
1041            --_dynamicObjectCount;
1042            if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid())
1043            {
1044                _completeDynamicObjectRenderingCallback->completed(this);
1045            }
1046        }
1047
1048
1049
[4127]1050        enum CheckForGLErrors
1051        {
1052            /** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
1053                is the fastest option since checking for errors does incurr a small overhead.*/
1054            NEVER_CHECK_GL_ERRORS,
1055            /** ONCE_PER_FRAME means that OpenGl errors will be checked for once per
1056                frame, the overhead is still small, but at least OpenGL errors that are occurring
1057                will be caught, the reporting isn't fine grained enough for debugging purposes.*/
1058            ONCE_PER_FRAME,
1059            /** ONCE_PER_ATTRIBUTE means that OpenGL errors will be checked for after
1060                every attribute is applied, allow errors to be directly associated with
1061                particular operations which makes debugging much easier.*/
1062            ONCE_PER_ATTRIBUTE
1063        };
[455]1064
[4127]1065        /** Set whether and how often OpenGL errors should be checked for.*/
1066        void setCheckForGLErrors(CheckForGLErrors check) { _checkGLErrors = check; }
1067
1068        /** Get whether and how often OpenGL errors should be checked for.*/
1069        CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
1070
[1529]1071        bool checkGLErrors(const char* str) const;
1072        bool checkGLErrors(StateAttribute::GLMode mode) const;
1073        bool checkGLErrors(const StateAttribute* attribute) const;
1074
[6578]1075
1076        /** Initialize extension used by osg:::State.*/
1077        void initializeExtensionProcs();
1078
[9549]1079        virtual void objectDeleted(void* object);
1080
[1463]1081    protected:
[455]1082
[1463]1083        virtual ~State();
1084
[4400]1085        GraphicsContext*            _graphicsContext;
[225]1086        unsigned int                _contextID;
1087        ref_ptr<FrameStamp>         _frameStamp;
[3807]1088
[1463]1089        ref_ptr<const RefMatrix>    _identity;
[2073]1090        ref_ptr<const RefMatrix>    _initialViewMatrix;
[1463]1091        ref_ptr<const RefMatrix>    _projection;
1092        ref_ptr<const RefMatrix>    _modelView;
[3807]1093
[2176]1094        Matrix                      _initialInverseViewMatrix;
1095
[235]1096        ref_ptr<DisplaySettings>    _displaySettings;
[3807]1097
[1677]1098        bool*                       _abortRenderingPtr;
[4127]1099        CheckForGLErrors            _checkGLErrors;
[1529]1100
[8]1101        struct ModeStack
1102        {
[4027]1103            typedef std::vector<StateAttribute::GLModeValue> ValueVec;
1104
[8]1105            ModeStack()
1106            {
[5001]1107                valid = true;
[8]1108                changed = false;
1109                last_applied_value = false;
[97]1110                global_default_value = false;
[8]1111            }
[3807]1112
[5001]1113            bool        valid;
[8]1114            bool        changed;
1115            bool        last_applied_value;
[97]1116            bool        global_default_value;
[8]1117            ValueVec    valueVec;
1118        };
1119
1120        struct AttributeStack
1121        {
[4210]1122            typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue>  AttributePair;
[4053]1123            typedef std::vector<AttributePair>                                      AttributeVec;
[4027]1124
[8]1125            AttributeStack()
1126            {
1127                changed = false;
1128                last_applied_attribute = 0L;
[97]1129                global_default_attribute = 0L;
[8]1130            }
1131
[97]1132            /** apply an attribute if required, passing in attribute and appropriate attribute stack */
[8]1133            bool                    changed;
1134            const StateAttribute*   last_applied_attribute;
[3252]1135            ref_ptr<const StateAttribute> global_default_attribute;
[8]1136            AttributeVec            attributeVec;
1137        };
1138
[3807]1139
[4027]1140        struct UniformStack
1141        {
1142            typedef std::pair<const Uniform*,StateAttribute::OverrideValue>         UniformPair;
1143            typedef std::vector<UniformPair>                                        UniformVec;
1144
[4180]1145            UniformStack() {}
[4027]1146
1147            UniformVec              uniformVec;
1148        };
1149
1150
[3807]1151        /** Apply an OpenGL mode if required, passing in mode, enable flag and
1152          * appropriate mode stack. This is a wrapper around \c glEnable() and
1153          * \c glDisable(), that just actually calls these functions if the
1154          * \c enabled flag is different than the current state.
1155          * @return \c true if the state was actually changed. \c false
1156          *         otherwise. Notice that a \c false return does not indicate
1157          *         an error, it just means that the mode was already set to the
1158          *         same value as the \c enabled parameter.
1159        */
[1133]1160        inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
[8]1161        {
[5001]1162            if (ms.valid && ms.last_applied_value != enabled)
[8]1163            {
1164                ms.last_applied_value = enabled;
1165
1166                if (enabled) glEnable(mode);
1167                else glDisable(mode);
1168
[4127]1169                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
[1529]1170
[8]1171                return true;
1172            }
1173            else
1174                return false;
1175        }
1176
[1529]1177
[8]1178        /** apply an attribute if required, passing in attribute and appropriate attribute stack */
[1133]1179        inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
[8]1180        {
1181            if (as.last_applied_attribute != attribute)
1182            {
[327]1183                if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
[97]1184
[8]1185                as.last_applied_attribute = attribute;
1186                attribute->apply(*this);
[3807]1187
[4127]1188                if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
[3807]1189
[8]1190                return true;
1191            }
1192            else
1193                return false;
1194        }
1195
[1133]1196        inline bool applyGlobalDefaultAttribute(AttributeStack& as)
[97]1197        {
[98]1198            if (as.last_applied_attribute != as.global_default_attribute.get())
[97]1199            {
[98]1200                as.last_applied_attribute = as.global_default_attribute.get();
[1529]1201                if (as.global_default_attribute.valid())
1202                {
1203                    as.global_default_attribute->apply(*this);
[4127]1204                    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
[1529]1205                }
[97]1206                return true;
1207            }
1208            else
1209                return false;
1210        }
1211
[3807]1212
[3488]1213        typedef std::map<StateAttribute::GLMode,ModeStack>              ModeMap;
1214        typedef std::vector<ModeMap>                                    TextureModeMapList;
[828]1215
[3488]1216        typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
1217        typedef std::vector<AttributeMap>                               TextureAttributeMapList;
[828]1218
[4027]1219        typedef std::map<std::string,UniformStack>                      UniformMap;
1220
[3488]1221        typedef std::vector<ref_ptr<const Matrix> >                     MatrixStack;
[4149]1222       
[9549]1223        typedef std::set<const Program::PerContextProgram* >            AppliedProgramObjectSet;
[8]1224
[3488]1225        ModeMap                                                         _modeMap;
1226        AttributeMap                                                    _attributeMap;
[4027]1227        UniformMap                                                      _uniformMap;
[836]1228
[3488]1229        TextureModeMapList                                              _textureModeMapList;
1230        TextureAttributeMapList                                         _textureAttributeMapList;
[3807]1231
[4149]1232        AppliedProgramObjectSet                                         _appliedProgramObjectSet;
[4027]1233        const Program::PerContextProgram*                               _lastAppliedProgramObject;
[3958]1234
[4027]1235        StateSetStack                                                   _stateStateStack;
[3807]1236
[828]1237        struct EnabledArrayPair
1238        {
[1940]1239            EnabledArrayPair():_dirty(true),_enabled(false),_normalized(0),_pointer(0) {}
1240            EnabledArrayPair(const EnabledArrayPair& eap):_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {}
1241            EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; }
[3807]1242
[1152]1243            bool            _dirty;
1244            bool            _enabled;
[1940]1245            GLboolean       _normalized;
[1152]1246            const GLvoid*   _pointer;
[828]1247        };
[3807]1248
[828]1249        typedef std::vector<EnabledArrayPair>                   EnabledTexCoordArrayList;
[1940]1250        typedef std::vector<EnabledArrayPair>                   EnabledVertexAttribArrayList;
[828]1251
[1940]1252        EnabledArrayPair                _vertexArray;
1253        EnabledArrayPair                _normalArray;
1254        EnabledArrayPair                _colorArray;
1255        EnabledArrayPair                _secondaryColorArray;
1256        EnabledArrayPair                _indexArray;
1257        EnabledArrayPair                _fogArray;
1258        EnabledTexCoordArrayList        _texCoordArrayList;
1259        EnabledVertexAttribArrayList    _vertexAttribArrayList;
1260
1261        unsigned int                    _currentActiveTextureUnit;
1262        unsigned int                    _currentClientActiveTextureUnit;
[6578]1263        const VertexBufferObject*       _currentVBO;
1264        const ElementBufferObject*      _currentEBO;
1265        const PixelBufferObject*        _currentPBO;
[3807]1266
[6578]1267
[836]1268        inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
[3807]1269        {
[836]1270            if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
1271            return _textureModeMapList[unit];
1272        }
1273
1274
1275        inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
[3807]1276        {
[836]1277            if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
1278            return _textureAttributeMapList[unit];
1279        }
[3807]1280
[836]1281        inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1282        inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
[4180]1283        inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
[3807]1284
[836]1285        inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1286        inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
[4180]1287        inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
[836]1288
1289        inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
1290        inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
[4180]1291        inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
[3807]1292
[836]1293        inline void applyModeMap(ModeMap& modeMap);
1294        inline void applyAttributeMap(AttributeMap& attributeMap);
[4180]1295        inline void applyUniformMap(UniformMap& uniformMap);
[836]1296
[1133]1297        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
1298        void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
[836]1299        void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
[3488]1300        void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member);
[1133]1301        bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
[3488]1302        const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const;
[836]1303
[1313]1304
[2000]1305        mutable bool _isSecondaryColorSupportResolved;
1306        mutable bool _isSecondaryColorSupported;
[1313]1307        bool computeSecondaryColorSupported() const;
1308
1309        mutable bool _isFogCoordSupportResolved;
1310        mutable bool _isFogCoordSupported;
1311        bool computeFogCoordSupported() const;
[2000]1312
1313        mutable bool _isVertexBufferObjectSupportResolved;
1314        mutable bool _isVertexBufferObjectSupported;
1315        bool computeVertexBufferObjectSupported() const;
1316
[5380]1317        typedef void (APIENTRY * ActiveTextureProc) (GLenum texture);
1318        typedef void (APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer);
1319        typedef void (APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
1320        typedef void (APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
1321        typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int);
1322        typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int);
[6578]1323        typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
[9447]1324       
1325        typedef void (APIENTRY * DrawArraysInstancedProc)( GLenum mode, GLint first, GLsizei count, GLsizei primcount );
1326        typedef void (APIENTRY * DrawElementsInstancedProc)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount );
[5380]1327
1328        bool                        _extensionProcsInitialized;
[6671]1329        GLint                       _glMaxTextureCoords;
1330        GLint                       _glMaxTextureUnits;
[5380]1331        ActiveTextureProc           _glClientActiveTexture;
1332        ActiveTextureProc           _glActiveTexture;
1333        FogCoordPointerProc         _glFogCoordPointer;
1334        SecondaryColorPointerProc   _glSecondaryColorPointer;
1335        VertexAttribPointerProc     _glVertexAttribPointer;
1336        EnableVertexAttribProc      _glEnableVertexAttribArray;
1337        DisableVertexAttribProc     _glDisableVertexAttribArray;
[6578]1338        BindBufferProc              _glBindBuffer;
[9447]1339        DrawArraysInstancedProc     _glDrawArraysInstanced;
1340        DrawElementsInstancedProc   _glDrawElementsInstanced;
[5380]1341
[6069]1342        unsigned int                                            _dynamicObjectCount;
1343        osg::ref_ptr<DynamicObjectRenderingCompletedCallback>   _completeDynamicObjectRenderingCallback;
1344       
[2]1345};
1346
[836]1347inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1348{
1349    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1350        mitr!=modeList.end();
1351        ++mitr)
1352    {
[3375]1353        // get the mode stack for incoming GLmode {mitr->first}.
[836]1354        ModeStack& ms = modeMap[mitr->first];
1355        if (ms.valueVec.empty())
1356        {
[3375]1357            // first pair so simply push incoming pair to back.
[836]1358            ms.valueVec.push_back(mitr->second);
1359        }
[3807]1360        else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
[836]1361        {
[3375]1362            // push existing back since override keeps the previous value.
[836]1363            ms.valueVec.push_back(ms.valueVec.back());
1364        }
[3807]1365        else
[836]1366        {
[3375]1367            // no override on so simply push incoming pair to back.
[836]1368            ms.valueVec.push_back(mitr->second);
1369        }
1370        ms.changed = true;
1371    }
[349]1372}
[2]1373
[836]1374inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1375{
1376    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1377        aitr!=attributeList.end();
1378        ++aitr)
1379    {
[3375]1380        // get the attribute stack for incoming type {aitr->first}.
[836]1381        AttributeStack& as = attributeMap[aitr->first];
1382        if (as.attributeVec.empty())
1383        {
[3375]1384            // first pair so simply push incoming pair to back.
[836]1385            as.attributeVec.push_back(
[4027]1386                AttributeStack::AttributePair(aitr->second.first.get(),aitr->second.second));
[836]1387        }
[3807]1388        else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
[836]1389        {
[3375]1390            // push existing back since override keeps the previous value.
[836]1391            as.attributeVec.push_back(as.attributeVec.back());
1392        }
[3807]1393        else
[836]1394        {
[3375]1395            // no override on so simply push incoming pair to back.
[836]1396            as.attributeVec.push_back(
[4027]1397                AttributeStack::AttributePair(aitr->second.first.get(),aitr->second.second));
[836]1398        }
1399        as.changed = true;
1400    }
1401}
1402
[4180]1403
1404inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1405{
1406    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1407        aitr!=uniformList.end();
1408        ++aitr)
1409    {
1410        // get the attribute stack for incoming type {aitr->first}.
1411        UniformStack& us = uniformMap[aitr->first];
1412        if (us.uniformVec.empty())
1413        {
1414            // first pair so simply push incoming pair to back.
1415            us.uniformVec.push_back(
1416                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1417        }
1418        else if ((us.uniformVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
1419        {
1420            // push existing back since override keeps the previous value.
1421            us.uniformVec.push_back(us.uniformVec.back());
1422        }
1423        else
1424        {
1425            // no override on so simply push incoming pair to back.
1426            us.uniformVec.push_back(
1427                UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
1428        }
1429    }
1430}
1431
[836]1432inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1433{
1434    for(StateSet::ModeList::const_iterator mitr=modeList.begin();
1435        mitr!=modeList.end();
1436        ++mitr)
1437    {
[3375]1438        // get the mode stack for incoming GLmode {mitr->first}.
[836]1439        ModeStack& ms = modeMap[mitr->first];
1440        if (!ms.valueVec.empty())
1441        {
1442            ms.valueVec.pop_back();
1443        }
1444        ms.changed = true;
1445    }
1446}
1447
1448inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1449{
1450    for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
1451        aitr!=attributeList.end();
1452        ++aitr)
1453    {
[3375]1454        // get the attribute stack for incoming type {aitr->first}.
[836]1455        AttributeStack& as = attributeMap[aitr->first];
1456        if (!as.attributeVec.empty())
1457        {
1458            as.attributeVec.pop_back();
1459        }
1460        as.changed = true;
1461    }
1462}
1463
[4180]1464inline void State::popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1465{
1466    for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
1467        aitr!=uniformList.end();
1468        ++aitr)
1469    {
1470        // get the attribute stack for incoming type {aitr->first}.
1471        UniformStack& us = uniformMap[aitr->first];
1472        if (!us.uniformVec.empty())
1473        {
1474            us.uniformVec.pop_back();
1475        }
1476    }
1477}
1478
[836]1479inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
1480{
1481    StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
1482    ModeMap::iterator this_mitr=modeMap.begin();
1483
1484    while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
1485    {
1486        if (this_mitr->first<ds_mitr->first)
1487        {
1488
1489            // note GLMode = this_mitr->first
1490            ModeStack& ms = this_mitr->second;
1491            if (ms.changed)
1492            {
1493                ms.changed = false;
1494                if (!ms.valueVec.empty())
1495                {
1496                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1497                    applyMode(this_mitr->first,new_value,ms);
1498                }
1499                else
1500                {
1501                    // assume default of disabled.
1502                    applyMode(this_mitr->first,ms.global_default_value,ms);
1503
1504                }
1505
1506            }
1507
1508            ++this_mitr;
1509
1510        }
1511        else if (ds_mitr->first<this_mitr->first)
1512        {
1513
[3807]1514            // ds_mitr->first is a new mode, therefore
[836]1515            // need to insert a new mode entry for ds_mistr->first.
1516            ModeStack& ms = modeMap[ds_mitr->first];
1517
1518            bool new_value = ds_mitr->second & StateAttribute::ON;
1519            applyMode(ds_mitr->first,new_value,ms);
1520
1521            // will need to disable this mode on next apply so set it to changed.
1522            ms.changed = true;
1523
1524            ++ds_mitr;
1525
1526        }
1527        else
1528        {
[3375]1529            // this_mitr & ds_mitr refer to the same mode, check the override
1530            // if any otherwise just apply the incoming mode.
[836]1531
1532            ModeStack& ms = this_mitr->second;
1533
[1008]1534            if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
[836]1535            {
[3408]1536                // override is on, just treat as a normal apply on modes.
[836]1537
1538                if (ms.changed)
1539                {
1540                    ms.changed = false;
1541                    bool new_value = ms.valueVec.back() & StateAttribute::ON;
1542                    applyMode(this_mitr->first,new_value,ms);
1543
1544                }
1545            }
1546            else
1547            {
[3375]1548                // no override on or no previous entry, therefore consider incoming mode.
[836]1549                bool new_value = ds_mitr->second & StateAttribute::ON;
1550                if (applyMode(ds_mitr->first,new_value,ms))
1551                {
1552                    ms.changed = true;
1553                }
1554            }
1555
1556            ++this_mitr;
1557            ++ds_mitr;
1558        }
1559    }
1560
1561    // iterator over the remaining state modes to apply any previous changes.
1562    for(;
1563        this_mitr!=modeMap.end();
1564        ++this_mitr)
1565    {
1566        // note GLMode = this_mitr->first
1567        ModeStack& ms = this_mitr->second;
1568        if (ms.changed)
1569        {
1570            ms.changed = false;
1571            if (!ms.valueVec.empty())
1572            {
1573                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1574                applyMode(this_mitr->first,new_value,ms);
1575            }
1576            else
1577            {
1578                // assume default of disabled.
1579                applyMode(this_mitr->first,ms.global_default_value,ms);
1580
1581            }
1582
1583        }
[3807]1584    }
[836]1585
[3375]1586    // iterator over the remaining incoming modes to apply any new mode.
[836]1587    for(;
1588        ds_mitr!=modeList.end();
1589        ++ds_mitr)
1590    {
1591        ModeStack& ms = modeMap[ds_mitr->first];
1592
1593        bool new_value = ds_mitr->second & StateAttribute::ON;
1594        applyMode(ds_mitr->first,new_value,ms);
1595
1596        // will need to disable this mode on next apply so set it to changed.
1597        ms.changed = true;
1598    }
1599}
1600
1601inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
1602{
1603    StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
1604
1605    AttributeMap::iterator this_aitr=attributeMap.begin();
1606
1607    while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
1608    {
1609        if (this_aitr->first<ds_aitr->first)
1610        {
1611
1612            // note attribute type = this_aitr->first
1613            AttributeStack& as = this_aitr->second;
1614            if (as.changed)
1615            {
1616                as.changed = false;
1617                if (!as.attributeVec.empty())
1618                {
1619                    const StateAttribute* new_attr = as.attributeVec.back().first;
1620                    applyAttribute(new_attr,as);
1621                }
1622                else
1623                {
1624                    applyGlobalDefaultAttribute(as);
1625                }
1626            }
1627
1628            ++this_aitr;
1629
1630        }
1631        else if (ds_aitr->first<this_aitr->first)
1632        {
1633
[3807]1634            // ds_aitr->first is a new attribute, therefore
[3408]1635            // need to insert a new attribute entry for ds_aitr->first.
[836]1636            AttributeStack& as = attributeMap[ds_aitr->first];
1637
1638            const StateAttribute* new_attr = ds_aitr->second.first.get();
1639            applyAttribute(new_attr,as);
1640
1641            as.changed = true;
1642
1643            ++ds_aitr;
1644
1645        }
1646        else
1647        {
[3375]1648            // this_mitr & ds_mitr refer to the same attribute, check the override
1649            // if any otherwise just apply the incoming attribute
[836]1650
1651            AttributeStack& as = this_aitr->second;
1652
[1008]1653            if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
[836]1654            {
[4027]1655                // override is on, just treat as a normal apply on attribute.
[836]1656
1657                if (as.changed)
1658                {
1659                    as.changed = false;
1660                    const StateAttribute* new_attr = as.attributeVec.back().first;
1661                    applyAttribute(new_attr,as);
1662                }
1663            }
1664            else
1665            {
[4027]1666                // no override on or no previous entry, therefore consider incoming attribute.
[836]1667                const StateAttribute* new_attr = ds_aitr->second.first.get();
1668                if (applyAttribute(new_attr,as))
1669                {
1670                    as.changed = true;
1671                }
1672            }
1673
1674            ++this_aitr;
1675            ++ds_aitr;
1676        }
1677    }
1678
[4027]1679    // iterator over the remaining state attributes to apply any previous changes.
[836]1680    for(;
1681        this_aitr!=attributeMap.end();
1682        ++this_aitr)
1683    {
1684        // note attribute type = this_aitr->first
1685        AttributeStack& as = this_aitr->second;
1686        if (as.changed)
1687        {
1688            as.changed = false;
1689            if (!as.attributeVec.empty())
1690            {
1691                const StateAttribute* new_attr = as.attributeVec.back().first;
1692                applyAttribute(new_attr,as);
1693            }
1694            else
1695            {
1696                applyGlobalDefaultAttribute(as);
1697            }
1698        }
[3807]1699    }
[836]1700
[4027]1701    // iterator over the remaining incoming attribute to apply any new attribute.
[836]1702    for(;
1703        ds_aitr!=attributeList.end();
1704        ++ds_aitr)
1705    {
[3807]1706        // ds_aitr->first is a new attribute, therefore
[3408]1707        // need to insert a new attribute entry for ds_aitr->first.
[836]1708        AttributeStack& as = attributeMap[ds_aitr->first];
1709
1710        const StateAttribute* new_attr = ds_aitr->second.first.get();
1711        applyAttribute(new_attr,as);
1712
1713        // will need to update this attribute on next apply so set it to changed.
1714        as.changed = true;
1715    }
1716
1717}
1718
[4180]1719inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
1720{
1721    if (!_lastAppliedProgramObject) return;
1722
1723    StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
1724
1725    UniformMap::iterator this_aitr=uniformMap.begin();
1726
1727    while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
1728    {
1729        if (this_aitr->first<ds_aitr->first)
1730        {
1731            // note attribute type = this_aitr->first
1732            UniformStack& as = this_aitr->second;
1733            if (!as.uniformVec.empty())
1734            {
1735                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1736            }
1737
1738            ++this_aitr;
1739
1740        }
1741        else if (ds_aitr->first<this_aitr->first)
1742        {
1743            _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1744
1745            ++ds_aitr;
1746        }
1747        else
1748        {
1749            // this_mitr & ds_mitr refer to the same attribute, check the override
1750            // if any otherwise just apply the incoming attribute
1751
1752            UniformStack& as = this_aitr->second;
1753
1754            if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
1755            {
1756                // override is on, just treat as a normal apply on uniform.
1757                _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1758            }
1759            else
1760            {
1761                // no override on or no previous entry, therefore consider incoming attribute.
1762                _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1763            }
1764
1765            ++this_aitr;
1766            ++ds_aitr;
1767        }
1768    }
1769
1770    // iterator over the remaining state attributes to apply any previous changes.
1771    for(;
1772        this_aitr!=uniformMap.end();
1773        ++this_aitr)
1774    {
1775        // note attribute type = this_aitr->first
1776        UniformStack& as = this_aitr->second;
1777        if (!as.uniformVec.empty())
1778        {
1779            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1780        }
1781    }
1782
1783    // iterator over the remaining incoming attribute to apply any new attribute.
1784    for(;
1785        ds_aitr!=uniformList.end();
1786        ++ds_aitr)
1787    {
1788        _lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
1789    }
1790
1791}
1792
[836]1793inline void State::applyModeMap(ModeMap& modeMap)
1794{
1795    for(ModeMap::iterator mitr=modeMap.begin();
1796        mitr!=modeMap.end();
1797        ++mitr)
1798    {
1799        // note GLMode = mitr->first
1800        ModeStack& ms = mitr->second;
1801        if (ms.changed)
1802        {
1803            ms.changed = false;
1804            if (!ms.valueVec.empty())
1805            {
1806                bool new_value = ms.valueVec.back() & StateAttribute::ON;
1807                applyMode(mitr->first,new_value,ms);
1808            }
1809            else
1810            {
1811                // assume default of disabled.
1812                applyMode(mitr->first,ms.global_default_value,ms);
1813            }
[3807]1814
[836]1815        }
[3807]1816    }
[836]1817}
1818
1819inline void State::applyAttributeMap(AttributeMap& attributeMap)
1820{
1821    for(AttributeMap::iterator aitr=attributeMap.begin();
1822        aitr!=attributeMap.end();
1823        ++aitr)
1824    {
1825        AttributeStack& as = aitr->second;
1826        if (as.changed)
1827        {
1828            as.changed = false;
1829            if (!as.attributeVec.empty())
1830            {
1831                const StateAttribute* new_attr = as.attributeVec.back().first;
1832                applyAttribute(new_attr,as);
1833            }
1834            else
1835            {
1836                applyGlobalDefaultAttribute(as);
1837            }
[3807]1838
[836]1839        }
[3807]1840    }
[836]1841}
1842
[4180]1843inline void State::applyUniformMap(UniformMap& uniformMap)
1844{
1845    if (!_lastAppliedProgramObject) return;
1846
1847    for(UniformMap::iterator aitr=uniformMap.begin();
1848        aitr!=uniformMap.end();
1849        ++aitr)
1850    {
1851        UniformStack& as = aitr->second;
1852        if (!as.uniformVec.empty())
1853        {
1854            _lastAppliedProgramObject->apply(*as.uniformVec.back().first);
1855        }
1856    }
[836]1857}
1858
[5573]1859
[4180]1860}
1861
[2]1862#endif
Note: See TracBrowser for help on using the browser.