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 #include <osg/State>
14 #include <osg/Texture>
15 #include <osg/Notify>
16 #include <osg/GLU>
17 #include <osg/GLExtensions>
18 #include <osg/Drawable>
19 #include <osg/ApplicationUsage>
20 #include <osg/ContextData>
21 #include <osg/PointSprite>
22 #include <osg/os_utils>
23 
24 #include <sstream>
25 #include <algorithm>
26 
27 #ifndef GL_MAX_TEXTURE_COORDS
28 #define GL_MAX_TEXTURE_COORDS 0x8871
29 #endif
30 
31 #ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
32 #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
33 #endif
34 
35 #ifndef GL_MAX_TEXTURE_UNITS
36 #define GL_MAX_TEXTURE_UNITS 0x84E2
37 #endif
38 
39 using namespace std;
40 using namespace osg;
41 
42 static ApplicationUsageProxy State_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_ERROR_CHECKING <type>","ONCE_PER_ATTRIBUTE | ON | on enables fine grained checking,  ONCE_PER_FRAME enables coarse grained checking");
43 
State()44 State::State():
45     Referenced(true)
46 {
47     _graphicsContext = 0;
48     _contextID = 0;
49 
50     _shaderCompositionEnabled = false;
51     _shaderCompositionDirty = true;
52     _shaderComposer = new ShaderComposer;
53     _currentShaderCompositionProgram = 0L;
54 
55     _drawBuffer = GL_INVALID_ENUM; // avoid the lazy state mechanism from ignoreing the first call to State::glDrawBuffer() to make sure it's always passed to OpenGL
56     _readBuffer = GL_INVALID_ENUM; // avoid the lazy state mechanism from ignoreing the first call to State::glReadBuffer() to make sure it's always passed to OpenGL
57 
58     _identity = new osg::RefMatrix(); // default RefMatrix constructs to identity.
59     _initialViewMatrix = _identity;
60     _projection = _identity;
61     _modelView = _identity;
62     _modelViewCache = new osg::RefMatrix;
63 
64     #if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
65         _useModelViewAndProjectionUniforms = true;
66         _useVertexAttributeAliasing = true;
67     #else
68         _useModelViewAndProjectionUniforms = false;
69         _useVertexAttributeAliasing = false;
70     #endif
71 
72     _modelViewMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ModelViewMatrix");
73     _projectionMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ProjectionMatrix");
74     _modelViewProjectionMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ModelViewProjectionMatrix");
75     _normalMatrixUniform = new Uniform(Uniform::FLOAT_MAT3,"osg_NormalMatrix");
76 
77     resetVertexAttributeAlias();
78 
79     _abortRenderingPtr = NULL;
80 
81     _checkGLErrors = ONCE_PER_FRAME;
82 
83     std::string str;
84     if (getEnvVar("OSG_GL_ERROR_CHECKING", str))
85     {
86         if (str=="ONCE_PER_ATTRIBUTE" || str=="ON" || str=="on")
87         {
88             _checkGLErrors = ONCE_PER_ATTRIBUTE;
89         }
90         else if (str=="OFF" || str=="off")
91         {
92             _checkGLErrors = NEVER_CHECK_GL_ERRORS;
93         }
94     }
95 
96     _currentActiveTextureUnit=0;
97     _currentClientActiveTextureUnit=0;
98 
99     _currentPBO = 0;
100     _currentDIBO = 0;
101     _currentVAO = 0;
102 
103     _isSecondaryColorSupported = false;
104     _isFogCoordSupported = false;
105     _isVertexBufferObjectSupported = false;
106     _isVertexArrayObjectSupported = false;
107 
108 #if OSG_GL3_FEATURES
109     _forceVertexBufferObject = true;
110     _forceVertexArrayObject = true;
111 #else
112     _forceVertexBufferObject = false;
113     _forceVertexArrayObject = false;
114 #endif
115 
116 
117     _lastAppliedProgramObject = 0;
118 
119     _extensionProcsInitialized = false;
120     _glClientActiveTexture = 0;
121     _glActiveTexture = 0;
122     _glFogCoordPointer = 0;
123     _glSecondaryColorPointer = 0;
124     _glVertexAttribPointer = 0;
125     _glVertexAttribIPointer = 0;
126     _glVertexAttribLPointer = 0;
127     _glEnableVertexAttribArray = 0;
128     _glDisableVertexAttribArray = 0;
129     _glDrawArraysInstanced = 0;
130     _glDrawElementsInstanced = 0;
131     _glMultiTexCoord4f = 0;
132     _glVertexAttrib4fv = 0;
133     _glVertexAttrib4f = 0;
134     _glBindBuffer = 0;
135 
136     _dynamicObjectCount  = 0;
137 
138     _glMaxTextureCoords = 1;
139     _glMaxTextureUnits = 1;
140 
141     _maxTexturePoolSize = 0;
142     _maxBufferObjectPoolSize = 0;
143 
144     _arrayDispatchers.setState(this);
145 
146     _graphicsCostEstimator = new GraphicsCostEstimator;
147 
148     _startTick = 0;
149     _gpuTick = 0;
150     _gpuTimestamp = 0;
151     _timestampBits = 0;
152 
153     _vas = 0;
154 }
155 
~State()156 State::~State()
157 {
158     // delete the GLExtensions object associated with this osg::State.
159     if (_glExtensions)
160     {
161         _glExtensions = 0;
162         GLExtensions* glExtensions = GLExtensions::Get(_contextID, false);
163         if (glExtensions && glExtensions->referenceCount() == 1) {
164             // the only reference left to the extension is in the static map itself, so we clean it up now
165             GLExtensions::Set(_contextID, 0);
166         }
167     }
168 
169     //_texCoordArrayList.clear();
170 
171     //_vertexAttribArrayList.clear();
172 }
173 
setUseVertexAttributeAliasing(bool flag)174 void State::setUseVertexAttributeAliasing(bool flag)
175 {
176     _useVertexAttributeAliasing = flag;
177     if (_globalVertexArrayState.valid()) _globalVertexArrayState->assignAllDispatchers();
178 }
179 
initializeExtensionProcs()180 void State::initializeExtensionProcs()
181 {
182     if (_extensionProcsInitialized) return;
183 
184     const char* vendor = (const char*) glGetString( GL_VENDOR );
185     if (vendor)
186     {
187         std::string str_vendor(vendor);
188         std::replace(str_vendor.begin(), str_vendor.end(), ' ', '_');
189         OSG_INFO<<"GL_VENDOR = ["<<str_vendor<<"]"<<std::endl;
190         _defineMap.map[str_vendor].defineVec.push_back(osg::StateSet::DefinePair("1",osg::StateAttribute::ON));
191         _defineMap.map[str_vendor].changed = true;
192         _defineMap.changed = true;
193     }
194 
195     _glExtensions = GLExtensions::Get(_contextID, true);
196 
197     _isSecondaryColorSupported = osg::isGLExtensionSupported(_contextID,"GL_EXT_secondary_color");
198     _isFogCoordSupported = osg::isGLExtensionSupported(_contextID,"GL_EXT_fog_coord");
199     _isVertexBufferObjectSupported = OSG_GLES2_FEATURES || OSG_GLES3_FEATURES || OSG_GL3_FEATURES || osg::isGLExtensionSupported(_contextID,"GL_ARB_vertex_buffer_object");
200     _isVertexArrayObjectSupported = _glExtensions->isVAOSupported;
201 
202     const DisplaySettings* ds = getDisplaySettings() ? getDisplaySettings() : osg::DisplaySettings::instance().get();
203 
204     if (ds->getVertexBufferHint()==DisplaySettings::VERTEX_BUFFER_OBJECT)
205     {
206         _forceVertexBufferObject = true;
207         _forceVertexArrayObject = false;
208     }
209     else if (ds->getVertexBufferHint()==DisplaySettings::VERTEX_ARRAY_OBJECT)
210     {
211         _forceVertexBufferObject = true;
212         _forceVertexArrayObject = true;
213     }
214 
215     OSG_INFO<<"osg::State::initializeExtensionProcs() _forceVertexArrayObject = "<<_forceVertexArrayObject<<std::endl;
216     OSG_INFO<<"                                       _forceVertexBufferObject = "<<_forceVertexBufferObject<<std::endl;
217 
218 
219     // Set up up global VertexArrayState object
220     _globalVertexArrayState = new VertexArrayState(this);
221     _globalVertexArrayState->assignAllDispatchers();
222     // if (_useVertexArrayObject) _globalVertexArrayState->generateVertexArrayObject();
223 
224     setCurrentToGlobalVertexArrayState();
225 
226 
227     setGLExtensionFuncPtr(_glClientActiveTexture,"glClientActiveTexture","glClientActiveTextureARB");
228     setGLExtensionFuncPtr(_glActiveTexture, "glActiveTexture","glActiveTextureARB");
229     setGLExtensionFuncPtr(_glFogCoordPointer, "glFogCoordPointer","glFogCoordPointerEXT");
230     setGLExtensionFuncPtr(_glSecondaryColorPointer, "glSecondaryColorPointer","glSecondaryColorPointerEXT");
231     setGLExtensionFuncPtr(_glVertexAttribPointer, "glVertexAttribPointer","glVertexAttribPointerARB");
232     setGLExtensionFuncPtr(_glVertexAttribIPointer, "glVertexAttribIPointer");
233     setGLExtensionFuncPtr(_glVertexAttribLPointer, "glVertexAttribLPointer","glVertexAttribPointerARB");
234     setGLExtensionFuncPtr(_glEnableVertexAttribArray, "glEnableVertexAttribArray","glEnableVertexAttribArrayARB");
235     setGLExtensionFuncPtr(_glMultiTexCoord4f, "glMultiTexCoord4f","glMultiTexCoord4fARB");
236     setGLExtensionFuncPtr(_glVertexAttrib4f, "glVertexAttrib4f");
237     setGLExtensionFuncPtr(_glVertexAttrib4fv, "glVertexAttrib4fv");
238     setGLExtensionFuncPtr(_glDisableVertexAttribArray, "glDisableVertexAttribArray","glDisableVertexAttribArrayARB");
239     setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
240 
241     setGLExtensionFuncPtr(_glDrawArraysInstanced, "glDrawArraysInstanced","glDrawArraysInstancedARB","glDrawArraysInstancedEXT");
242     setGLExtensionFuncPtr(_glDrawElementsInstanced, "glDrawElementsInstanced","glDrawElementsInstancedARB","glDrawElementsInstancedEXT");
243 
244     if (osg::getGLVersionNumber() >= 2.0 || osg::isGLExtensionSupported(_contextID, "GL_ARB_vertex_shader") || OSG_GLES2_FEATURES || OSG_GLES3_FEATURES || OSG_GL3_FEATURES)
245     {
246         glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&_glMaxTextureUnits);
247         #ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
248             glGetIntegerv(GL_MAX_TEXTURE_COORDS, &_glMaxTextureCoords);
249         #else
250             _glMaxTextureCoords = _glMaxTextureUnits;
251         #endif
252     }
253     else if ( osg::getGLVersionNumber() >= 1.3 ||
254                                  osg::isGLExtensionSupported(_contextID,"GL_ARB_multitexture") ||
255                                  osg::isGLExtensionSupported(_contextID,"GL_EXT_multitexture") ||
256                                  OSG_GLES1_FEATURES)
257     {
258         GLint maxTextureUnits = 0;
259         glGetIntegerv(GL_MAX_TEXTURE_UNITS,&maxTextureUnits);
260         _glMaxTextureUnits = maxTextureUnits;
261         _glMaxTextureCoords = maxTextureUnits;
262     }
263     else
264     {
265         _glMaxTextureUnits = 1;
266         _glMaxTextureCoords = 1;
267     }
268 
269     if (_glExtensions->isARBTimerQuerySupported)
270     {
271         const GLubyte* renderer = glGetString(GL_RENDERER);
272         std::string rendererString = renderer ? (const char*)renderer : "";
273         if (rendererString.find("Radeon")!=std::string::npos || rendererString.find("RADEON")!=std::string::npos || rendererString.find("FirePro")!=std::string::npos)
274         {
275             // AMD/ATI drivers are producing an invalid enumerate error on the
276             // glGetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS_ARB, &bits);
277             // call so work around it by assuming 64 bits for counter.
278             setTimestampBits(64);
279             //setTimestampBits(0);
280         }
281         else
282         {
283             GLint bits = 0;
284             _glExtensions->glGetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS_ARB, &bits);
285             setTimestampBits(bits);
286         }
287     }
288 
289     // set the validity of Modes
290     {
291         bool pointSpriteModeValid = _glExtensions->isPointSpriteModeSupported;
292 
293     #if defined( OSG_GLES1_AVAILABLE ) //point sprites don't exist on es 2.0
294         setModeValidity(GL_POINT_SPRITE_OES, pointSpriteModeValid);
295     #else
296         setModeValidity(GL_POINT_SPRITE_ARB, pointSpriteModeValid);
297     #endif
298     }
299 
300 
301     _extensionProcsInitialized = true;
302 
303     if (_graphicsCostEstimator.valid())
304     {
305         RenderInfo renderInfo(this,0);
306         _graphicsCostEstimator->calibrate(renderInfo);
307     }
308 }
309 
releaseGLObjects()310 void State::releaseGLObjects()
311 {
312     // release any GL objects held by the shader composer
313     _shaderComposer->releaseGLObjects(this);
314 
315     // release any StateSet's on the stack
316     for(StateSetStack::iterator itr = _stateStateStack.begin();
317         itr != _stateStateStack.end();
318         ++itr)
319     {
320         (*itr)->releaseGLObjects(this);
321     }
322 
323     _modeMap.clear();
324     _textureModeMapList.clear();
325 
326     // release any cached attributes
327     for(AttributeMap::iterator aitr = _attributeMap.begin();
328         aitr != _attributeMap.end();
329         ++aitr)
330     {
331         AttributeStack& as = aitr->second;
332         if (as.global_default_attribute.valid())
333         {
334             as.global_default_attribute->releaseGLObjects(this);
335         }
336     }
337     _attributeMap.clear();
338 
339     // release any cached texture attributes
340     for(TextureAttributeMapList::iterator itr = _textureAttributeMapList.begin();
341         itr != _textureAttributeMapList.end();
342         ++itr)
343     {
344         AttributeMap& attributeMap = *itr;
345         for(AttributeMap::iterator aitr = attributeMap.begin();
346             aitr != attributeMap.end();
347             ++aitr)
348         {
349             AttributeStack& as = aitr->second;
350             if (as.global_default_attribute.valid())
351             {
352                 as.global_default_attribute->releaseGLObjects(this);
353             }
354         }
355     }
356 
357     _textureAttributeMapList.clear();
358 }
359 
reset()360 void State::reset()
361 {
362     OSG_NOTICE<<std::endl<<"State::reset() *************************** "<<std::endl;
363 
364 #if 1
365     for(ModeMap::iterator mitr=_modeMap.begin();
366         mitr!=_modeMap.end();
367         ++mitr)
368     {
369         ModeStack& ms = mitr->second;
370         ms.valueVec.clear();
371         ms.last_applied_value = !ms.global_default_value;
372         ms.changed = true;
373     }
374 #else
375     _modeMap.clear();
376 #endif
377 
378     _modeMap[GL_DEPTH_TEST].global_default_value = true;
379     _modeMap[GL_DEPTH_TEST].changed = true;
380 
381     // go through all active StateAttribute's, setting to change to force update,
382     // the idea is to leave only the global defaults left.
383     for(AttributeMap::iterator aitr=_attributeMap.begin();
384         aitr!=_attributeMap.end();
385         ++aitr)
386     {
387         AttributeStack& as = aitr->second;
388         as.attributeVec.clear();
389         as.last_applied_attribute = NULL;
390         as.last_applied_shadercomponent = NULL;
391         as.changed = true;
392     }
393 
394     // we can do a straight clear, we aren't interested in GL_DEPTH_TEST defaults in texture modes.
395     for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin();
396         tmmItr!=_textureModeMapList.end();
397         ++tmmItr)
398     {
399         tmmItr->clear();
400     }
401 
402     // empty all the texture attributes as per normal attributes, leaving only the global defaults left.
403     for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin();
404         tamItr!=_textureAttributeMapList.end();
405         ++tamItr)
406     {
407         AttributeMap& attributeMap = *tamItr;
408         // go through all active StateAttribute's, setting to change to force update.
409         for(AttributeMap::iterator aitr=attributeMap.begin();
410             aitr!=attributeMap.end();
411             ++aitr)
412         {
413             AttributeStack& as = aitr->second;
414             as.attributeVec.clear();
415             as.last_applied_attribute = NULL;
416             as.last_applied_shadercomponent = NULL;
417             as.changed = true;
418         }
419     }
420 
421     _stateStateStack.clear();
422 
423     _modelView = _identity;
424     _projection = _identity;
425 
426     dirtyAllVertexArrays();
427 
428 #if 1
429     // reset active texture unit values and call OpenGL
430     // note, this OpenGL op precludes the use of State::reset() without a
431     // valid graphics context, therefore the new implementation below
432     // is preferred.
433     setActiveTextureUnit(0);
434 #else
435     // reset active texture unit values without calling OpenGL
436     _currentActiveTextureUnit = 0;
437     _currentClientActiveTextureUnit = 0;
438 #endif
439 
440     _shaderCompositionDirty = true;
441     _currentShaderCompositionUniformList.clear();
442 
443     _lastAppliedProgramObject = 0;
444 
445     // what about uniforms??? need to clear them too...
446     // go through all active Uniform's, setting to change to force update,
447     // the idea is to leave only the global defaults left.
448     for(UniformMap::iterator uitr=_uniformMap.begin();
449         uitr!=_uniformMap.end();
450         ++uitr)
451     {
452         UniformStack& us = uitr->second;
453         us.uniformVec.clear();
454     }
455 
456 }
457 
glDrawBuffer(GLenum buffer)458 void State::glDrawBuffer(GLenum buffer)
459 {
460     if (_drawBuffer!=buffer)
461     {
462         #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)
463         ::glDrawBuffer(buffer);
464         #endif
465         _drawBuffer=buffer;
466     }
467 }
468 
glReadBuffer(GLenum buffer)469 void State::glReadBuffer(GLenum buffer)
470 {
471     if (_readBuffer!=buffer)
472     {
473         #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)
474         ::glReadBuffer(buffer);
475         #endif
476         _readBuffer=buffer;
477     }
478 }
479 
setInitialViewMatrix(const osg::RefMatrix * matrix)480 void State::setInitialViewMatrix(const osg::RefMatrix* matrix)
481 {
482     if (matrix) _initialViewMatrix = matrix;
483     else _initialViewMatrix = _identity;
484 
485     _initialInverseViewMatrix.invert(*_initialViewMatrix);
486 }
487 
setMaxTexturePoolSize(unsigned int size)488 void State::setMaxTexturePoolSize(unsigned int size)
489 {
490     _maxTexturePoolSize = size;
491     osg::get<TextureObjectManager>(_contextID)->setMaxTexturePoolSize(size);
492     OSG_INFO<<"osg::State::_maxTexturePoolSize="<<_maxTexturePoolSize<<std::endl;
493 }
494 
setMaxBufferObjectPoolSize(unsigned int size)495 void State::setMaxBufferObjectPoolSize(unsigned int size)
496 {
497     _maxBufferObjectPoolSize = size;
498     osg::get<GLBufferObjectManager>(_contextID)->setMaxGLBufferObjectPoolSize(_maxBufferObjectPoolSize);
499     OSG_INFO<<"osg::State::_maxBufferObjectPoolSize="<<_maxBufferObjectPoolSize<<std::endl;
500 }
501 
pushStateSet(const StateSet * dstate)502 void State::pushStateSet(const StateSet* dstate)
503 {
504 
505     _stateStateStack.push_back(dstate);
506     if (dstate)
507     {
508 
509         pushModeList(_modeMap,dstate->getModeList());
510 
511         // iterator through texture modes.
512         unsigned int unit;
513         const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
514         for(unit=0;unit<ds_textureModeList.size();++unit)
515         {
516             pushModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
517         }
518 
519         pushAttributeList(_attributeMap,dstate->getAttributeList());
520 
521         // iterator through texture attributes.
522         const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
523         for(unit=0;unit<ds_textureAttributeList.size();++unit)
524         {
525             pushAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
526         }
527 
528         pushUniformList(_uniformMap,dstate->getUniformList());
529 
530         pushDefineList(_defineMap,dstate->getDefineList());
531     }
532 
533     // OSG_NOTICE<<"State::pushStateSet()"<<_stateStateStack.size()<<std::endl;
534 }
535 
popAllStateSets()536 void State::popAllStateSets()
537 {
538     // OSG_NOTICE<<"State::popAllStateSets()"<<_stateStateStack.size()<<std::endl;
539 
540     while (!_stateStateStack.empty()) popStateSet();
541 
542     applyProjectionMatrix(0);
543     applyModelViewMatrix(0);
544 
545     _lastAppliedProgramObject = 0;
546 }
547 
popStateSet()548 void State::popStateSet()
549 {
550     // OSG_NOTICE<<"State::popStateSet()"<<_stateStateStack.size()<<std::endl;
551 
552     if (_stateStateStack.empty()) return;
553 
554 
555     const StateSet* dstate = _stateStateStack.back();
556 
557     if (dstate)
558     {
559 
560         popModeList(_modeMap,dstate->getModeList());
561 
562         // iterator through texture modes.
563         unsigned int unit;
564         const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
565         for(unit=0;unit<ds_textureModeList.size();++unit)
566         {
567             popModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
568         }
569 
570         popAttributeList(_attributeMap,dstate->getAttributeList());
571 
572         // iterator through texture attributes.
573         const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
574         for(unit=0;unit<ds_textureAttributeList.size();++unit)
575         {
576             popAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
577         }
578 
579         popUniformList(_uniformMap,dstate->getUniformList());
580 
581         popDefineList(_defineMap,dstate->getDefineList());
582 
583     }
584 
585     // remove the top draw state from the stack.
586     _stateStateStack.pop_back();
587 }
588 
insertStateSet(unsigned int pos,const StateSet * dstate)589 void State::insertStateSet(unsigned int pos,const StateSet* dstate)
590 {
591     StateSetStack tempStack;
592 
593     // first pop the StateSet above the position we need to insert at
594     while (_stateStateStack.size()>pos)
595     {
596         tempStack.push_back(_stateStateStack.back());
597         popStateSet();
598     }
599 
600     // push our new stateset
601     pushStateSet(dstate);
602 
603     // push back the original ones
604     for(StateSetStack::reverse_iterator itr = tempStack.rbegin();
605         itr != tempStack.rend();
606         ++itr)
607     {
608         pushStateSet(*itr);
609     }
610 
611 }
612 
removeStateSet(unsigned int pos)613 void State::removeStateSet(unsigned int pos)
614 {
615     if (pos >= _stateStateStack.size())
616     {
617         OSG_NOTICE<<"Warning: State::removeStateSet("<<pos<<") out of range"<<std::endl;
618         return;
619     }
620 
621     // record the StateSet above the one we intend to remove
622     StateSetStack tempStack;
623     while (_stateStateStack.size()-1>pos)
624     {
625         tempStack.push_back(_stateStateStack.back());
626         popStateSet();
627     }
628 
629     // remove the intended StateSet as well
630     popStateSet();
631 
632     // push back the original ones that were above the remove StateSet
633     for(StateSetStack::reverse_iterator itr = tempStack.rbegin();
634         itr != tempStack.rend();
635         ++itr)
636     {
637         pushStateSet(*itr);
638     }
639 }
640 
captureCurrentState(StateSet & stateset) const641 void State::captureCurrentState(StateSet& stateset) const
642 {
643     // empty the stateset first.
644     stateset.clear();
645 
646     for(ModeMap::const_iterator mitr=_modeMap.begin();
647         mitr!=_modeMap.end();
648         ++mitr)
649     {
650         // note GLMode = mitr->first
651         const ModeStack& ms = mitr->second;
652         if (!ms.valueVec.empty())
653         {
654             stateset.setMode(mitr->first,ms.valueVec.back());
655         }
656     }
657 
658     for(AttributeMap::const_iterator aitr=_attributeMap.begin();
659         aitr!=_attributeMap.end();
660         ++aitr)
661     {
662         const AttributeStack& as = aitr->second;
663         if (!as.attributeVec.empty())
664         {
665             stateset.setAttribute(const_cast<StateAttribute*>(as.attributeVec.back().first));
666         }
667     }
668 
669 }
670 
apply(const StateSet * dstate)671 void State::apply(const StateSet* dstate)
672 {
673     if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply(StateSet*)");
674 
675     // equivalent to:
676     //pushStateSet(dstate);
677     //apply();
678     //popStateSet();
679     //return;
680 
681     if (dstate)
682     {
683         // push the stateset on the stack so it can be querried from within StateAttribute
684         _stateStateStack.push_back(dstate);
685 
686         _currentShaderCompositionUniformList.clear();
687 
688         // apply all texture state and modes
689         const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
690         const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
691 
692         unsigned int unit;
693         unsigned int unitMax = maximum(static_cast<unsigned int>(ds_textureModeList.size()),static_cast<unsigned int>(ds_textureAttributeList.size()));
694         unitMax = maximum(static_cast<unsigned int>(unitMax),static_cast<unsigned int>(_textureModeMapList.size()));
695         unitMax = maximum(static_cast<unsigned int>(unitMax),static_cast<unsigned int>(_textureAttributeMapList.size()));
696         for(unit=0;unit<unitMax;++unit)
697         {
698             if (unit<ds_textureModeList.size()) applyModeListOnTexUnit(unit,getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
699             else if (unit<_textureModeMapList.size()) applyModeMapOnTexUnit(unit,_textureModeMapList[unit]);
700 
701             if (unit<ds_textureAttributeList.size()) applyAttributeListOnTexUnit(unit,getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
702             else if (unit<_textureAttributeMapList.size()) applyAttributeMapOnTexUnit(unit,_textureAttributeMapList[unit]);
703         }
704 
705         const Program::PerContextProgram* previousLastAppliedProgramObject = _lastAppliedProgramObject;
706 
707         applyModeList(_modeMap,dstate->getModeList());
708 #if 1
709         pushDefineList(_defineMap, dstate->getDefineList());
710 #else
711         applyDefineList(_defineMap, dstate->getDefineList());
712 #endif
713 
714         applyAttributeList(_attributeMap,dstate->getAttributeList());
715 
716         if ((_lastAppliedProgramObject!=0) && (previousLastAppliedProgramObject==_lastAppliedProgramObject) && _defineMap.changed)
717         {
718             // OSG_NOTICE<<"State::apply(StateSet*) Program already applied ("<<(previousLastAppliedProgramObject==_lastAppliedProgramObject)<<") and _defineMap.changed= "<<_defineMap.changed<<std::endl;
719             _lastAppliedProgramObject->getProgram()->apply(*this);
720         }
721 
722         if (_shaderCompositionEnabled)
723         {
724             if (previousLastAppliedProgramObject == _lastAppliedProgramObject || _lastAppliedProgramObject==0)
725             {
726                 // No program has been applied by the StateSet stack so assume shader composition is required
727                 applyShaderComposition();
728             }
729         }
730 
731         if (dstate->getUniformList().empty())
732         {
733             if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap);
734             else applyUniformList(_uniformMap, _currentShaderCompositionUniformList);
735         }
736         else
737         {
738             if (_currentShaderCompositionUniformList.empty()) applyUniformList(_uniformMap, dstate->getUniformList());
739             else
740             {
741                 // need top merge uniforms lists, but cheat for now by just applying both.
742                 _currentShaderCompositionUniformList.insert(dstate->getUniformList().begin(), dstate->getUniformList().end());
743                 applyUniformList(_uniformMap, _currentShaderCompositionUniformList);
744             }
745         }
746 
747 #if 1
748         popDefineList(_defineMap, dstate->getDefineList());
749 #endif
750 
751         // pop the stateset from the stack
752         _stateStateStack.pop_back();
753     }
754     else
755     {
756         // no incoming stateset, so simply apply state.
757         apply();
758     }
759 
760     if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply(StateSet*)");
761 }
762 
apply()763 void State::apply()
764 {
765     if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply()");
766 
767     _currentShaderCompositionUniformList.clear();
768 
769     // apply all texture state and modes
770     unsigned int unit;
771     unsigned int unitMax = maximum(_textureModeMapList.size(),_textureAttributeMapList.size());
772     for(unit=0;unit<unitMax;++unit)
773     {
774         if (unit<_textureModeMapList.size()) applyModeMapOnTexUnit(unit,_textureModeMapList[unit]);
775         if (unit<_textureAttributeMapList.size()) applyAttributeMapOnTexUnit(unit,_textureAttributeMapList[unit]);
776     }
777 
778     // go through all active OpenGL modes, enabling/disable where
779     // appropriate.
780     applyModeMap(_modeMap);
781 
782     const Program::PerContextProgram* previousLastAppliedProgramObject = _lastAppliedProgramObject;
783 
784     // go through all active StateAttribute's, applying where appropriate.
785     applyAttributeMap(_attributeMap);
786 
787 
788     if ((_lastAppliedProgramObject!=0) && (previousLastAppliedProgramObject==_lastAppliedProgramObject) && _defineMap.changed)
789     {
790         //OSG_NOTICE<<"State::apply() Program already applied ("<<(previousLastAppliedProgramObject==_lastAppliedProgramObject)<<") and _defineMap.changed= "<<_defineMap.changed<<std::endl;
791         if (_lastAppliedProgramObject) _lastAppliedProgramObject->getProgram()->apply(*this);
792     }
793 
794 
795     if (_shaderCompositionEnabled)
796     {
797         applyShaderComposition();
798     }
799 
800     if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap);
801     else applyUniformList(_uniformMap, _currentShaderCompositionUniformList);
802 
803     if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()");
804 }
805 
applyShaderComposition()806 void State::applyShaderComposition()
807 {
808     if (_shaderCompositionEnabled)
809     {
810         if (_shaderCompositionDirty)
811         {
812             // if (isNotifyEnabled(osg::INFO)) print(notify(osg::INFO));
813 
814             // build lits of current ShaderComponents
815             ShaderComponents shaderComponents;
816 
817             // OSG_NOTICE<<"State::applyShaderComposition() : _attributeMap.size()=="<<_attributeMap.size()<<std::endl;
818 
819             for(AttributeMap::iterator itr = _attributeMap.begin();
820                 itr != _attributeMap.end();
821                 ++itr)
822             {
823                 // OSG_NOTICE<<"  itr->first="<<itr->first.first<<", "<<itr->first.second<<std::endl;
824 
825                 AttributeStack& as = itr->second;
826                 if (as.last_applied_shadercomponent)
827                 {
828                     shaderComponents.push_back(const_cast<ShaderComponent*>(as.last_applied_shadercomponent));
829                 }
830             }
831 
832             _currentShaderCompositionProgram = _shaderComposer->getOrCreateProgram(shaderComponents);
833         }
834 
835         if (_currentShaderCompositionProgram)
836         {
837             Program::PerContextProgram* pcp = _currentShaderCompositionProgram->getPCP(*this);
838             if (_lastAppliedProgramObject != pcp) applyAttribute(_currentShaderCompositionProgram);
839         }
840     }
841 }
842 
843 
haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value)844 void State::haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
845 {
846     haveAppliedMode(_modeMap,mode,value);
847 }
848 
haveAppliedMode(StateAttribute::GLMode mode)849 void State::haveAppliedMode(StateAttribute::GLMode mode)
850 {
851     haveAppliedMode(_modeMap,mode);
852 }
853 
haveAppliedAttribute(const StateAttribute * attribute)854 void State::haveAppliedAttribute(const StateAttribute* attribute)
855 {
856     haveAppliedAttribute(_attributeMap,attribute);
857 }
858 
haveAppliedAttribute(StateAttribute::Type type,unsigned int member)859 void State::haveAppliedAttribute(StateAttribute::Type type, unsigned int member)
860 {
861     haveAppliedAttribute(_attributeMap,type,member);
862 }
863 
getLastAppliedMode(StateAttribute::GLMode mode) const864 bool State::getLastAppliedMode(StateAttribute::GLMode mode) const
865 {
866     return getLastAppliedMode(_modeMap,mode);
867 }
868 
getLastAppliedAttribute(StateAttribute::Type type,unsigned int member) const869 const StateAttribute* State::getLastAppliedAttribute(StateAttribute::Type type, unsigned int member) const
870 {
871     return getLastAppliedAttribute(_attributeMap,type,member);
872 }
873 
874 
haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)875 void State::haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
876 {
877     haveAppliedMode(getOrCreateTextureModeMap(unit),mode,value);
878 }
879 
haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode)880 void State::haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode)
881 {
882     haveAppliedMode(getOrCreateTextureModeMap(unit),mode);
883 }
884 
haveAppliedTextureAttribute(unsigned int unit,const StateAttribute * attribute)885 void State::haveAppliedTextureAttribute(unsigned int unit,const StateAttribute* attribute)
886 {
887     haveAppliedAttribute(getOrCreateTextureAttributeMap(unit),attribute);
888 }
889 
haveAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type,unsigned int member)890 void State::haveAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type, unsigned int member)
891 {
892     haveAppliedAttribute(getOrCreateTextureAttributeMap(unit),type,member);
893 }
894 
getLastAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode) const895 bool State::getLastAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode) const
896 {
897     if (unit>=_textureModeMapList.size()) return false;
898     return getLastAppliedMode(_textureModeMapList[unit],mode);
899 }
900 
getLastAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type,unsigned int member) const901 const StateAttribute* State::getLastAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type, unsigned int member) const
902 {
903     if (unit>=_textureAttributeMapList.size()) return NULL;
904     return getLastAppliedAttribute(_textureAttributeMapList[unit],type,member);
905 }
906 
907 
haveAppliedMode(ModeMap & modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)908 void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
909 {
910     ModeStack& ms = modeMap[mode];
911 
912     ms.last_applied_value = value & StateAttribute::ON;
913 
914     // will need to disable this mode on next apply so set it to changed.
915     ms.changed = true;
916 }
917 
918 /** mode has been set externally, update state to reflect this setting.*/
haveAppliedMode(ModeMap & modeMap,StateAttribute::GLMode mode)919 void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode)
920 {
921     ModeStack& ms = modeMap[mode];
922 
923     // don't know what last applied value is can't apply it.
924     // assume that it has changed by toggle the value of last_applied_value.
925     ms.last_applied_value = !ms.last_applied_value;
926 
927     // will need to disable this mode on next apply so set it to changed.
928     ms.changed = true;
929 }
930 
931 /** attribute has been applied externally, update state to reflect this setting.*/
haveAppliedAttribute(AttributeMap & attributeMap,const StateAttribute * attribute)932 void State::haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute)
933 {
934     if (attribute)
935     {
936         AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
937 
938         as.last_applied_attribute = attribute;
939 
940         // will need to update this attribute on next apply so set it to changed.
941         as.changed = true;
942     }
943 }
944 
haveAppliedAttribute(AttributeMap & attributeMap,StateAttribute::Type type,unsigned int member)945 void State::haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member)
946 {
947 
948     AttributeMap::iterator itr = attributeMap.find(StateAttribute::TypeMemberPair(type,member));
949     if (itr!=attributeMap.end())
950     {
951         AttributeStack& as = itr->second;
952         as.last_applied_attribute = 0L;
953 
954         // will need to update this attribute on next apply so set it to changed.
955         as.changed = true;
956     }
957 }
958 
getLastAppliedMode(const ModeMap & modeMap,StateAttribute::GLMode mode) const959 bool State::getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const
960 {
961     ModeMap::const_iterator itr = modeMap.find(mode);
962     if (itr!=modeMap.end())
963     {
964         const ModeStack& ms = itr->second;
965         return ms.last_applied_value;
966     }
967     else
968     {
969         return false;
970     }
971 }
972 
getLastAppliedAttribute(const AttributeMap & attributeMap,StateAttribute::Type type,unsigned int member) const973 const StateAttribute* State::getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const
974 {
975     AttributeMap::const_iterator itr = attributeMap.find(StateAttribute::TypeMemberPair(type,member));
976     if (itr!=attributeMap.end())
977     {
978         const AttributeStack& as = itr->second;
979         return as.last_applied_attribute;
980     }
981     else
982     {
983         return NULL;
984     }
985 }
986 
dirtyAllModes()987 void State::dirtyAllModes()
988 {
989     for(ModeMap::iterator mitr=_modeMap.begin();
990         mitr!=_modeMap.end();
991         ++mitr)
992     {
993         ModeStack& ms = mitr->second;
994         ms.last_applied_value = !ms.last_applied_value;
995         ms.changed = true;
996 
997     }
998 
999     for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin();
1000         tmmItr!=_textureModeMapList.end();
1001         ++tmmItr)
1002     {
1003         for(ModeMap::iterator mitr=tmmItr->begin();
1004             mitr!=tmmItr->end();
1005             ++mitr)
1006         {
1007             ModeStack& ms = mitr->second;
1008             ms.last_applied_value = !ms.last_applied_value;
1009             ms.changed = true;
1010 
1011         }
1012     }
1013 }
1014 
dirtyAllAttributes()1015 void State::dirtyAllAttributes()
1016 {
1017     for(AttributeMap::iterator aitr=_attributeMap.begin();
1018         aitr!=_attributeMap.end();
1019         ++aitr)
1020     {
1021         AttributeStack& as = aitr->second;
1022         as.last_applied_attribute = 0;
1023         as.changed = true;
1024     }
1025 
1026 
1027     for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin();
1028         tamItr!=_textureAttributeMapList.end();
1029         ++tamItr)
1030     {
1031         AttributeMap& attributeMap = *tamItr;
1032         for(AttributeMap::iterator aitr=attributeMap.begin();
1033             aitr!=attributeMap.end();
1034             ++aitr)
1035         {
1036             AttributeStack& as = aitr->second;
1037             as.last_applied_attribute = 0;
1038             as.changed = true;
1039         }
1040     }
1041 
1042 }
1043 
1044 
getViewFrustum() const1045 Polytope State::getViewFrustum() const
1046 {
1047     Polytope cv;
1048     cv.setToUnitFrustum();
1049     cv.transformProvidingInverse((*_modelView)*(*_projection));
1050     return cv;
1051 }
1052 
1053 
resetVertexAttributeAlias(bool compactAliasing,unsigned int numTextureUnits)1054 void State::resetVertexAttributeAlias(bool compactAliasing, unsigned int numTextureUnits)
1055 {
1056     _texCoordAliasList.clear();
1057     _attributeBindingList.clear();
1058 
1059     if (compactAliasing)
1060     {
1061         unsigned int slot = 0;
1062         setUpVertexAttribAlias(_vertexAlias, slot++, "gl_Vertex","osg_Vertex","vec4 ");
1063         setUpVertexAttribAlias(_normalAlias, slot++, "gl_Normal","osg_Normal","vec3 ");
1064         setUpVertexAttribAlias(_colorAlias, slot++, "gl_Color","osg_Color","vec4 ");
1065 
1066         _texCoordAliasList.resize(numTextureUnits);
1067         for(unsigned int i=0; i<_texCoordAliasList.size(); i++)
1068         {
1069             std::stringstream gl_MultiTexCoord;
1070             std::stringstream osg_MultiTexCoord;
1071             gl_MultiTexCoord<<"gl_MultiTexCoord"<<i;
1072             osg_MultiTexCoord<<"osg_MultiTexCoord"<<i;
1073 
1074             setUpVertexAttribAlias(_texCoordAliasList[i], slot++, gl_MultiTexCoord.str(), osg_MultiTexCoord.str(), "vec4 ");
1075         }
1076 
1077         setUpVertexAttribAlias(_secondaryColorAlias, slot++, "gl_SecondaryColor","osg_SecondaryColor","vec4 ");
1078         setUpVertexAttribAlias(_fogCoordAlias, slot++, "gl_FogCoord","osg_FogCoord","float ");
1079 
1080     }
1081     else
1082     {
1083         setUpVertexAttribAlias(_vertexAlias,0, "gl_Vertex","osg_Vertex","vec4 ");
1084         setUpVertexAttribAlias(_normalAlias, 2, "gl_Normal","osg_Normal","vec3 ");
1085         setUpVertexAttribAlias(_colorAlias, 3, "gl_Color","osg_Color","vec4 ");
1086         setUpVertexAttribAlias(_secondaryColorAlias, 4, "gl_SecondaryColor","osg_SecondaryColor","vec4 ");
1087         setUpVertexAttribAlias(_fogCoordAlias, 5, "gl_FogCoord","osg_FogCoord","float ");
1088 
1089         unsigned int base = 8;
1090         _texCoordAliasList.resize(numTextureUnits);
1091         for(unsigned int i=0; i<_texCoordAliasList.size(); i++)
1092         {
1093             std::stringstream gl_MultiTexCoord;
1094             std::stringstream osg_MultiTexCoord;
1095             gl_MultiTexCoord<<"gl_MultiTexCoord"<<i;
1096             osg_MultiTexCoord<<"osg_MultiTexCoord"<<i;
1097 
1098             setUpVertexAttribAlias(_texCoordAliasList[i], base+i, gl_MultiTexCoord.str(), osg_MultiTexCoord.str(), "vec4 ");
1099         }
1100     }
1101 }
1102 
1103 
disableAllVertexArrays()1104 void State::disableAllVertexArrays()
1105 {
1106     disableVertexPointer();
1107     disableColorPointer();
1108     disableFogCoordPointer();
1109     disableNormalPointer();
1110     disableSecondaryColorPointer();
1111     disableTexCoordPointersAboveAndIncluding(0);
1112     disableVertexAttribPointersAboveAndIncluding(0);
1113 }
1114 
dirtyAllVertexArrays()1115 void State::dirtyAllVertexArrays()
1116 {
1117     OSG_INFO<<"State::dirtyAllVertexArrays()"<<std::endl;
1118 }
1119 
setClientActiveTextureUnit(unsigned int unit)1120 bool State::setClientActiveTextureUnit( unsigned int unit )
1121 {
1122     // if (true)
1123     if (_currentClientActiveTextureUnit!=unit)
1124     {
1125         // OSG_NOTICE<<"State::setClientActiveTextureUnit( "<<unit<<") done"<<std::endl;
1126 
1127         _glClientActiveTexture(GL_TEXTURE0+unit);
1128 
1129         _currentClientActiveTextureUnit = unit;
1130     }
1131     else
1132     {
1133         //OSG_NOTICE<<"State::setClientActiveTextureUnit( "<<unit<<") not required."<<std::endl;
1134     }
1135     return true;
1136 }
1137 
1138 
getClientActiveTextureUnit() const1139 unsigned int State::getClientActiveTextureUnit() const
1140 {
1141     return _currentClientActiveTextureUnit;
1142 }
1143 
1144 
checkGLErrors(const char * str1,const char * str2) const1145 bool State::checkGLErrors(const char* str1, const char* str2) const
1146 {
1147     GLenum errorNo = glGetError();
1148     if (errorNo!=GL_NO_ERROR)
1149     {
1150         osg::NotifySeverity notifyLevel = NOTICE; // WARN;
1151         const char* error = (char*)gluErrorString(errorNo);
1152         if (error)
1153         {
1154             OSG_NOTIFY(notifyLevel)<<"Warning: detected OpenGL error '" << error<<"'";
1155         }
1156         else
1157         {
1158             OSG_NOTIFY(notifyLevel)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
1159         }
1160 
1161         if (str1 || str2)
1162         {
1163             OSG_NOTIFY(notifyLevel)<<" at";
1164             if (str1) { OSG_NOTIFY(notifyLevel)<<" "<<str1; }
1165             if (str2) { OSG_NOTIFY(notifyLevel)<<" "<<str2; }
1166         }
1167         else
1168         {
1169             OSG_NOTIFY(notifyLevel)<<" in osg::State.";
1170         }
1171 
1172         OSG_NOTIFY(notifyLevel)<< std::endl;
1173 
1174         return true;
1175     }
1176     return false;
1177 }
1178 
checkGLErrors(StateAttribute::GLMode mode) const1179 bool State::checkGLErrors(StateAttribute::GLMode mode) const
1180 {
1181     GLenum errorNo = glGetError();
1182     if (errorNo!=GL_NO_ERROR)
1183     {
1184         const char* error = (char*)gluErrorString(errorNo);
1185         if (error)
1186         {
1187             OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error '"<< error <<"' after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1188         }
1189         else
1190         {
1191             OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1192         }
1193         return true;
1194     }
1195     return false;
1196 }
1197 
checkGLErrors(const StateAttribute * attribute) const1198 bool State::checkGLErrors(const StateAttribute* attribute) const
1199 {
1200     GLenum errorNo = glGetError();
1201     if (errorNo!=GL_NO_ERROR)
1202     {
1203         const char* error = (char*)gluErrorString(errorNo);
1204         if (error)
1205         {
1206             OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error '"<< error <<"' after applying attribute "<<attribute->className()<<" "<<attribute<< std::endl;
1207         }
1208         else
1209         {
1210             OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1211         }
1212 
1213         return true;
1214     }
1215     return false;
1216 }
1217 
1218 
applyModelViewAndProjectionUniformsIfRequired()1219 void State::applyModelViewAndProjectionUniformsIfRequired()
1220 {
1221     if (!_lastAppliedProgramObject) return;
1222 
1223     if (_modelViewMatrixUniform.valid()) _lastAppliedProgramObject->apply(*_modelViewMatrixUniform);
1224     if (_projectionMatrixUniform) _lastAppliedProgramObject->apply(*_projectionMatrixUniform);
1225     if (_modelViewProjectionMatrixUniform) _lastAppliedProgramObject->apply(*_modelViewProjectionMatrixUniform);
1226     if (_normalMatrixUniform) _lastAppliedProgramObject->apply(*_normalMatrixUniform);
1227 }
1228 
1229 namespace State_Utils
1230 {
replace(std::string & str,const std::string & original_phrase,const std::string & new_phrase)1231     bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
1232     {
1233         // Prevent infinite loop : if original_phrase is empty, do nothing and return false
1234         if (original_phrase.empty()) return false;
1235 
1236         bool replacedStr = false;
1237         std::string::size_type pos = 0;
1238         while((pos=str.find(original_phrase, pos))!=std::string::npos)
1239         {
1240             std::string::size_type endOfPhrasePos = pos+original_phrase.size();
1241             if (endOfPhrasePos<str.size())
1242             {
1243                 char c = str[endOfPhrasePos];
1244                 if ((c>='0' && c<='9') ||
1245                     (c>='a' && c<='z') ||
1246                     (c>='A' && c<='Z'))
1247                 {
1248                     pos = endOfPhrasePos;
1249                     continue;
1250                 }
1251             }
1252 
1253             replacedStr = true;
1254             str.replace(pos, original_phrase.size(), new_phrase);
1255         }
1256         return replacedStr;
1257     }
1258 
replaceAndInsertDeclaration(std::string & source,std::string::size_type declPos,const std::string & originalStr,const std::string & newStr,const std::string & qualifier,const std::string & declarationPrefix)1259     void replaceAndInsertDeclaration(std::string& source, std::string::size_type declPos, const std::string& originalStr, const std::string& newStr, const std::string& qualifier, const std::string& declarationPrefix)
1260     {
1261         if (replace(source, originalStr, newStr))
1262         {
1263             source.insert(declPos, qualifier + declarationPrefix + newStr + std::string(";\n"));
1264         }
1265     }
1266 
replaceVar(const osg::State & state,std::string & str,std::string::size_type start_pos,std::string::size_type num_chars)1267     void replaceVar(const osg::State& state, std::string& str, std::string::size_type start_pos,  std::string::size_type num_chars)
1268     {
1269         std::string var_str(str.substr(start_pos+1, num_chars-1));
1270         std::string value;
1271         if (state.getActiveDisplaySettings()->getValue(var_str, value))
1272         {
1273             str.replace(start_pos, num_chars, value);
1274         }
1275         else
1276         {
1277             str.erase(start_pos, num_chars);
1278         }
1279     }
1280 
1281 
substitudeEnvVars(const osg::State & state,std::string & str)1282     void substitudeEnvVars(const osg::State& state, std::string& str)
1283     {
1284         std::string::size_type pos = 0;
1285         while (pos<str.size() && ((pos=str.find_first_of("$'\"", pos)) != std::string::npos))
1286         {
1287             if (pos==str.size())
1288             {
1289                 break;
1290             }
1291 
1292             if (str[pos]=='"' || str[pos]=='\'')
1293             {
1294                 std::string::size_type start_quote = pos;
1295                 ++pos; // skip over first quote
1296                 pos = str.find(str[start_quote], pos);
1297 
1298                 if (pos!=std::string::npos)
1299                 {
1300                     ++pos; // skip over second quote
1301                 }
1302             }
1303             else
1304             {
1305                 std::string::size_type start_var = pos;
1306                 ++pos;
1307                 pos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRTSUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", pos);
1308                 if (pos != std::string::npos)
1309                 {
1310 
1311                     replaceVar(state, str, start_var, pos-start_var);
1312                     pos = start_var;
1313                 }
1314                 else
1315                 {
1316                     replaceVar(state, str, start_var, str.size()-start_var);
1317                     pos = start_var;
1318                 }
1319             }
1320         }
1321     }
1322 }
1323 
convertVertexShaderSourceToOsgBuiltIns(std::string & source) const1324 bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
1325 {
1326     OSG_DEBUG<<"State::convertShaderSourceToOsgBuiltIns()"<<std::endl;
1327 
1328     OSG_DEBUG<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
1329 
1330 
1331     State_Utils::substitudeEnvVars(*this, source);
1332 
1333 
1334     std::string attributeQualifier("attribute ");
1335 
1336     // find the first legal insertion point for replacement declarations. GLSL requires that nothing
1337     // precede a "#version" compiler directive, so we must insert new declarations after it.
1338     std::string::size_type declPos = source.rfind( "#version " );
1339     if ( declPos != std::string::npos )
1340     {
1341         declPos = source.find(" ", declPos); // move to the first space after "#version"
1342         declPos = source.find_first_not_of(std::string(" "), declPos); // skip all the spaces until you reach the version number
1343         std::string versionNumber(source, declPos, 3);
1344         int glslVersion = atoi(versionNumber.c_str());
1345         OSG_INFO<<"shader version found: "<< glslVersion <<std::endl;
1346         if (glslVersion >= 130) attributeQualifier = "in ";
1347         // found the string, now find the next linefeed and set the insertion point after it.
1348         declPos = source.find( '\n', declPos );
1349         declPos = declPos != std::string::npos ? declPos+1 : source.length();
1350     }
1351     else
1352     {
1353         declPos = 0;
1354     }
1355 
1356     std::string::size_type extPos = source.rfind( "#extension " );
1357     if ( extPos != std::string::npos )
1358     {
1359         // found the string, now find the next linefeed and set the insertion point after it.
1360         declPos = source.find( '\n', extPos );
1361         declPos = declPos != std::string::npos ? declPos+1 : source.length();
1362     }
1363     if (_useModelViewAndProjectionUniforms)
1364     {
1365         // replace ftransform as it only works with built-ins
1366         State_Utils::replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex");
1367 
1368         // replace built in uniform
1369         State_Utils::replaceAndInsertDeclaration(source, declPos, "gl_ModelViewMatrix", "osg_ModelViewMatrix", "uniform ", "mat4 ");
1370         State_Utils::replaceAndInsertDeclaration(source, declPos, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix", "uniform ", "mat4 ");
1371         State_Utils::replaceAndInsertDeclaration(source, declPos, "gl_ProjectionMatrix", "osg_ProjectionMatrix", "uniform ", "mat4 ");
1372         State_Utils::replaceAndInsertDeclaration(source, declPos, "gl_NormalMatrix", "osg_NormalMatrix", "uniform ", "mat3 ");
1373     }
1374 
1375     if (_useVertexAttributeAliasing)
1376     {
1377         State_Utils::replaceAndInsertDeclaration(source, declPos, _vertexAlias._glName,         _vertexAlias._osgName,         attributeQualifier, _vertexAlias._declaration);
1378         State_Utils::replaceAndInsertDeclaration(source, declPos, _normalAlias._glName,         _normalAlias._osgName,         attributeQualifier, _normalAlias._declaration);
1379         State_Utils::replaceAndInsertDeclaration(source, declPos, _colorAlias._glName,          _colorAlias._osgName,          attributeQualifier, _colorAlias._declaration);
1380         State_Utils::replaceAndInsertDeclaration(source, declPos, _secondaryColorAlias._glName, _secondaryColorAlias._osgName, attributeQualifier, _secondaryColorAlias._declaration);
1381         State_Utils::replaceAndInsertDeclaration(source, declPos, _fogCoordAlias._glName,       _fogCoordAlias._osgName,       attributeQualifier, _fogCoordAlias._declaration);
1382         for (size_t i=0; i<_texCoordAliasList.size(); i++)
1383         {
1384             const VertexAttribAlias& texCoordAlias = _texCoordAliasList[i];
1385             State_Utils::replaceAndInsertDeclaration(source, declPos, texCoordAlias._glName, texCoordAlias._osgName, attributeQualifier, texCoordAlias._declaration);
1386         }
1387     }
1388 
1389     OSG_DEBUG<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
1390 
1391     return true;
1392 }
1393 
setUpVertexAttribAlias(VertexAttribAlias & alias,GLuint location,const std::string glName,const std::string osgName,const std::string & declaration)1394 void State::setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration)
1395 {
1396     alias = VertexAttribAlias(location, glName, osgName, declaration);
1397     _attributeBindingList[osgName] = location;
1398     // OSG_NOTICE<<"State::setUpVertexAttribAlias("<<location<<" "<<glName<<" "<<osgName<<")"<<std::endl;
1399 }
1400 
applyProjectionMatrix(const osg::RefMatrix * matrix)1401 void State::applyProjectionMatrix(const osg::RefMatrix* matrix)
1402 {
1403     if (_projection!=matrix)
1404     {
1405         if (matrix)
1406         {
1407             _projection=matrix;
1408         }
1409         else
1410         {
1411             _projection=_identity;
1412         }
1413 
1414         if (_useModelViewAndProjectionUniforms)
1415         {
1416             if (_projectionMatrixUniform.valid()) _projectionMatrixUniform->set(*_projection);
1417             updateModelViewAndProjectionMatrixUniforms();
1418         }
1419 #ifdef OSG_GL_MATRICES_AVAILABLE
1420         glMatrixMode( GL_PROJECTION );
1421             glLoadMatrix(_projection->ptr());
1422         glMatrixMode( GL_MODELVIEW );
1423 #endif
1424     }
1425 }
1426 
loadModelViewMatrix()1427 void State::loadModelViewMatrix()
1428 {
1429     if (_useModelViewAndProjectionUniforms)
1430     {
1431         if (_modelViewMatrixUniform.valid()) _modelViewMatrixUniform->set(*_modelView);
1432         updateModelViewAndProjectionMatrixUniforms();
1433     }
1434 
1435 #ifdef OSG_GL_MATRICES_AVAILABLE
1436     glLoadMatrix(_modelView->ptr());
1437 #endif
1438 }
1439 
applyModelViewMatrix(const osg::RefMatrix * matrix)1440 void State::applyModelViewMatrix(const osg::RefMatrix* matrix)
1441 {
1442     if (_modelView!=matrix)
1443     {
1444         if (matrix)
1445         {
1446             _modelView=matrix;
1447         }
1448         else
1449         {
1450             _modelView=_identity;
1451         }
1452 
1453         loadModelViewMatrix();
1454     }
1455 }
1456 
applyModelViewMatrix(const osg::Matrix & matrix)1457 void State::applyModelViewMatrix(const osg::Matrix& matrix)
1458 {
1459     _modelViewCache->set(matrix);
1460     _modelView = _modelViewCache;
1461 
1462     loadModelViewMatrix();
1463 }
1464 
1465 #include <osg/io_utils>
1466 
updateModelViewAndProjectionMatrixUniforms()1467 void State::updateModelViewAndProjectionMatrixUniforms()
1468 {
1469     if (_modelViewProjectionMatrixUniform.valid()) _modelViewProjectionMatrixUniform->set((*_modelView) * (*_projection));
1470     if (_normalMatrixUniform.valid())
1471     {
1472         Matrix mv(*_modelView);
1473         mv.setTrans(0.0, 0.0, 0.0);
1474 
1475         Matrix matrix;
1476         matrix.invert(mv);
1477 
1478         Matrix3 normalMatrix(matrix(0,0), matrix(1,0), matrix(2,0),
1479                              matrix(0,1), matrix(1,1), matrix(2,1),
1480                              matrix(0,2), matrix(1,2), matrix(2,2));
1481 
1482         _normalMatrixUniform->set(normalMatrix);
1483     }
1484 }
1485 
drawQuads(GLint first,GLsizei count,GLsizei primCount)1486 void State::drawQuads(GLint first, GLsizei count, GLsizei primCount)
1487 {
1488     // OSG_NOTICE<<"State::drawQuads("<<first<<", "<<count<<")"<<std::endl;
1489 
1490     unsigned int array = first % 4;
1491     unsigned int offsetFirst = ((first-array) / 4) * 6;
1492     unsigned int numQuads = (count/4);
1493     unsigned int numIndices = numQuads * 6;
1494     unsigned int endOfIndices = offsetFirst+numIndices;
1495 
1496     if (endOfIndices<65536)
1497     {
1498         IndicesGLushort& indices = _quadIndicesGLushort[array];
1499 
1500         if (endOfIndices >= indices.size())
1501         {
1502             // we need to expand the _indexArray to be big enough to cope with all the quads required.
1503             unsigned int numExistingQuads = indices.size()/6;
1504             unsigned int numRequiredQuads = endOfIndices/6;
1505             indices.reserve(endOfIndices);
1506             for(unsigned int i=numExistingQuads; i<numRequiredQuads; ++i)
1507             {
1508                 unsigned int base = i*4 + array;
1509                 indices.push_back(base);
1510                 indices.push_back(base+1);
1511                 indices.push_back(base+3);
1512 
1513                 indices.push_back(base+1);
1514                 indices.push_back(base+2);
1515                 indices.push_back(base+3);
1516 
1517                 // OSG_NOTICE<<"   adding quad indices ("<<base<<")"<<std::endl;
1518             }
1519         }
1520 
1521         // if (array!=0) return;
1522 
1523         // OSG_NOTICE<<"  glDrawElements(GL_TRIANGLES, "<<numIndices<<", GL_UNSIGNED_SHORT, "<<&(indices[base])<<")"<<std::endl;
1524         glDrawElementsInstanced(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, &(indices[offsetFirst]), primCount);
1525     }
1526     else
1527     {
1528         IndicesGLuint& indices = _quadIndicesGLuint[array];
1529 
1530         if (endOfIndices >= indices.size())
1531         {
1532             // we need to expand the _indexArray to be big enough to cope with all the quads required.
1533             unsigned int numExistingQuads = indices.size()/6;
1534             unsigned int numRequiredQuads = endOfIndices/6;
1535             indices.reserve(endOfIndices);
1536             for(unsigned int i=numExistingQuads; i<numRequiredQuads; ++i)
1537             {
1538                 unsigned int base = i*4 + array;
1539                 indices.push_back(base);
1540                 indices.push_back(base+1);
1541                 indices.push_back(base+3);
1542 
1543                 indices.push_back(base+1);
1544                 indices.push_back(base+2);
1545                 indices.push_back(base+3);
1546 
1547                 // OSG_NOTICE<<"   adding quad indices ("<<base<<")"<<std::endl;
1548             }
1549         }
1550 
1551         // if (array!=0) return;
1552 
1553         // OSG_NOTICE<<"  glDrawElements(GL_TRIANGLES, "<<numIndices<<", GL_UNSIGNED_SHORT, "<<&(indices[base])<<")"<<std::endl;
1554         glDrawElementsInstanced(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, &(indices[offsetFirst]), primCount);
1555     }
1556 }
1557 
print(std::ostream & fout) const1558 void State::ModeStack::print(std::ostream& fout) const
1559 {
1560     fout<<"    valid = "<<valid<<std::endl;
1561     fout<<"    changed = "<<changed<<std::endl;
1562     fout<<"    last_applied_value = "<<last_applied_value<<std::endl;
1563     fout<<"    global_default_value = "<<global_default_value<<std::endl;
1564     fout<<"    valueVec { "<<std::endl;
1565     for(ModeStack::ValueVec::const_iterator itr = valueVec.begin();
1566         itr != valueVec.end();
1567         ++itr)
1568     {
1569         if (itr!=valueVec.begin()) fout<<", ";
1570         fout<<*itr;
1571     }
1572     fout<<" }"<<std::endl;
1573 }
1574 
print(std::ostream & fout) const1575 void State::AttributeStack::print(std::ostream& fout) const
1576 {
1577     fout<<"    changed = "<<changed<<std::endl;
1578     fout<<"    last_applied_attribute = "<<last_applied_attribute;
1579     if (last_applied_attribute) fout<<", "<<last_applied_attribute->className()<<", "<<last_applied_attribute->getName()<<std::endl;
1580     fout<<"    last_applied_shadercomponent = "<<last_applied_shadercomponent<<std::endl;
1581     if (last_applied_shadercomponent)  fout<<", "<<last_applied_shadercomponent->className()<<", "<<last_applied_shadercomponent->getName()<<std::endl;
1582     fout<<"    global_default_attribute = "<<global_default_attribute.get()<<std::endl;
1583     fout<<"    attributeVec { ";
1584     for(AttributeVec::const_iterator itr = attributeVec.begin();
1585         itr != attributeVec.end();
1586         ++itr)
1587     {
1588         if (itr!=attributeVec.begin()) fout<<", ";
1589         fout<<"("<<itr->first<<", "<<itr->second<<")";
1590     }
1591     fout<<" }"<<std::endl;
1592 }
1593 
1594 
print(std::ostream & fout) const1595 void State::UniformStack::print(std::ostream& fout) const
1596 {
1597     fout<<"    UniformVec { ";
1598     for(UniformVec::const_iterator itr = uniformVec.begin();
1599         itr != uniformVec.end();
1600         ++itr)
1601     {
1602         if (itr!=uniformVec.begin()) fout<<", ";
1603         fout<<"("<<itr->first<<", "<<itr->second<<")";
1604     }
1605     fout<<" }"<<std::endl;
1606 }
1607 
1608 
1609 
1610 
1611 
print(std::ostream & fout) const1612 void State::print(std::ostream& fout) const
1613 {
1614 #if 0
1615         GraphicsContext*            _graphicsContext;
1616         unsigned int                _contextID;
1617         bool                            _shaderCompositionEnabled;
1618         bool                            _shaderCompositionDirty;
1619         osg::ref_ptr<ShaderComposer>    _shaderComposer;
1620 #endif
1621 
1622 #if 0
1623         osg::Program*                   _currentShaderCompositionProgram;
1624         StateSet::UniformList           _currentShaderCompositionUniformList;
1625 #endif
1626 
1627 #if 0
1628         ref_ptr<FrameStamp>         _frameStamp;
1629 
1630         ref_ptr<const RefMatrix>    _identity;
1631         ref_ptr<const RefMatrix>    _initialViewMatrix;
1632         ref_ptr<const RefMatrix>    _projection;
1633         ref_ptr<const RefMatrix>    _modelView;
1634         ref_ptr<RefMatrix>          _modelViewCache;
1635 
1636         bool                        _useModelViewAndProjectionUniforms;
1637         ref_ptr<Uniform>            _modelViewMatrixUniform;
1638         ref_ptr<Uniform>            _projectionMatrixUniform;
1639         ref_ptr<Uniform>            _modelViewProjectionMatrixUniform;
1640         ref_ptr<Uniform>            _normalMatrixUniform;
1641 
1642         Matrix                      _initialInverseViewMatrix;
1643 
1644         ref_ptr<DisplaySettings>    _displaySettings;
1645 
1646         bool*                       _abortRenderingPtr;
1647         CheckForGLErrors            _checkGLErrors;
1648 
1649 
1650         bool                        _useVertexAttributeAliasing;
1651         VertexAttribAlias           _vertexAlias;
1652         VertexAttribAlias           _normalAlias;
1653         VertexAttribAlias           _colorAlias;
1654         VertexAttribAlias           _secondaryColorAlias;
1655         VertexAttribAlias           _fogCoordAlias;
1656         VertexAttribAliasList       _texCoordAliasList;
1657 
1658         Program::AttribBindingList  _attributeBindingList;
1659 #endif
1660         fout<<"ModeMap _modeMap {"<<std::endl;
1661         for(ModeMap::const_iterator itr = _modeMap.begin();
1662             itr != _modeMap.end();
1663             ++itr)
1664         {
1665             fout<<"  GLMode="<<itr->first<<", ModeStack {"<<std::endl;
1666             itr->second.print(fout);
1667             fout<<"  }"<<std::endl;
1668         }
1669         fout<<"}"<<std::endl;
1670 
1671         fout<<"AttributeMap _attributeMap {"<<std::endl;
1672         for(AttributeMap::const_iterator itr = _attributeMap.begin();
1673             itr != _attributeMap.end();
1674             ++itr)
1675         {
1676             fout<<"  TypeMemberPaid=("<<itr->first.first<<", "<<itr->first.second<<") AttributeStack {"<<std::endl;
1677             itr->second.print(fout);
1678             fout<<"  }"<<std::endl;
1679         }
1680         fout<<"}"<<std::endl;
1681 
1682         fout<<"UniformMap _uniformMap {"<<std::endl;
1683         for(UniformMap::const_iterator itr = _uniformMap.begin();
1684             itr != _uniformMap.end();
1685             ++itr)
1686         {
1687             fout<<"  name="<<itr->first<<", UniformStack {"<<std::endl;
1688             itr->second.print(fout);
1689             fout<<"  }"<<std::endl;
1690         }
1691         fout<<"}"<<std::endl;
1692 
1693 
1694         fout<<"StateSetStack _stateSetStack {"<<std::endl;
1695         for(StateSetStack::const_iterator itr = _stateStateStack.begin();
1696             itr != _stateStateStack.end();
1697             ++itr)
1698         {
1699             fout<<(*itr)->getName()<<"  "<<*itr<<std::endl;
1700         }
1701         fout<<"}"<<std::endl;
1702 }
1703 
frameCompleted()1704 void State::frameCompleted()
1705 {
1706     if (getTimestampBits())
1707     {
1708         GLint64 timestamp;
1709         _glExtensions->glGetInteger64v(GL_TIMESTAMP, &timestamp);
1710         setGpuTimestamp(osg::Timer::instance()->tick(), timestamp);
1711         //OSG_NOTICE<<"State::frameCompleted() setting time stamp. timestamp="<<timestamp<<std::endl;
1712     }
1713 }
1714 
updateCurrentDefines()1715 bool State::DefineMap::updateCurrentDefines()
1716 {
1717     currentDefines.clear();
1718     for(DefineStackMap::const_iterator itr = map.begin();
1719         itr != map.end();
1720         ++itr)
1721     {
1722         const DefineStack::DefineVec& dv = itr->second.defineVec;
1723         if (!dv.empty())
1724         {
1725             const StateSet::DefinePair& dp = dv.back();
1726             if (dp.second & osg::StateAttribute::ON)
1727             {
1728                 currentDefines[itr->first] = dp;
1729             }
1730         }
1731     }
1732     changed = false;
1733     return true;
1734 }
1735 
getDefineString(const osg::ShaderDefines & shaderDefines)1736 std::string State::getDefineString(const osg::ShaderDefines& shaderDefines)
1737 {
1738     if (_defineMap.changed) _defineMap.updateCurrentDefines();
1739 
1740     const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
1741 
1742     ShaderDefines::const_iterator sd_itr = shaderDefines.begin();
1743     StateSet::DefineList::const_iterator cd_itr = currentDefines.begin();
1744 
1745     std::string shaderDefineStr;
1746 
1747     while(sd_itr != shaderDefines.end() && cd_itr != currentDefines.end())
1748     {
1749         if ((*sd_itr) < cd_itr->first) ++sd_itr;
1750         else if (cd_itr->first < (*sd_itr)) ++cd_itr;
1751         else
1752         {
1753             const StateSet::DefinePair& dp = cd_itr->second;
1754             shaderDefineStr += "#define ";
1755             shaderDefineStr += cd_itr->first;
1756             if (!dp.first.empty())
1757             {
1758                 if (dp.first[0]!='(') shaderDefineStr += " ";
1759                 shaderDefineStr += dp.first;
1760             }
1761 #ifdef WIN32
1762             shaderDefineStr += "\r\n";
1763 #else
1764             shaderDefineStr += "\n";
1765 #endif
1766 
1767             ++sd_itr;
1768             ++cd_itr;
1769         }
1770     }
1771     return shaderDefineStr;
1772 }
1773 
supportsShaderRequirements(const osg::ShaderDefines & shaderRequirements)1774 bool State::supportsShaderRequirements(const osg::ShaderDefines& shaderRequirements)
1775 {
1776     if (shaderRequirements.empty()) return true;
1777 
1778     if (_defineMap.changed) _defineMap.updateCurrentDefines();
1779 
1780     const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
1781     for(ShaderDefines::const_iterator sr_itr = shaderRequirements.begin();
1782         sr_itr != shaderRequirements.end();
1783         ++sr_itr)
1784     {
1785         if (currentDefines.find(*sr_itr)==currentDefines.end()) return false;
1786     }
1787     return true;
1788 }
1789 
supportsShaderRequirement(const std::string & shaderRequirement)1790 bool State::supportsShaderRequirement(const std::string& shaderRequirement)
1791 {
1792     if (_defineMap.changed) _defineMap.updateCurrentDefines();
1793     const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
1794     return (currentDefines.find(shaderRequirement)!=currentDefines.end());
1795 }
1796