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