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, ×tamp);
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