root/OpenSceneGraph/trunk/src/osg/State.cpp @ 10621

Revision 10621, 31.1 kB (checked in by robert, 5 years ago)

Introduced new uniforms for tracking the modelview and project matrices in shaders using non built-ins.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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/ApplicationUsage>
19
20#ifndef GL_MAX_TEXTURE_COORDS
21#define GL_MAX_TEXTURE_COORDS 0x8871
22#endif
23
24#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
25#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
26#endif
27
28#ifndef GL_MAX_TEXTURE_UNITS
29#define GL_MAX_TEXTURE_UNITS 0x84E2
30#endif
31
32using namespace std;
33using namespace osg;
34
35static 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");
36
37State::State():
38    Referenced(true)
39{
40    _graphicsContext = 0;
41    _contextID = 0;
42    _identity = new osg::RefMatrix(); // default RefMatrix constructs to identity.
43    _initialViewMatrix = _identity;
44    _projection = _identity;
45    _modelView = _identity;
46
47    _modelViewMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ModelViewMatrix");
48    _projectionMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ProjectionMatrix");
49    _modelViewProjectionMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ModelViewProjectionMatrix");
50
51    _abortRenderingPtr = false;   
52
53    _checkGLErrors = ONCE_PER_FRAME;
54
55    const char* str = getenv("OSG_GL_ERROR_CHECKING");
56    if (str && (strcmp(str,"ONCE_PER_ATTRIBUTE")==0 || strcmp(str,"ON")==0 || strcmp(str,"on")==0))
57    {
58        _checkGLErrors = ONCE_PER_ATTRIBUTE;
59    }
60
61    _currentActiveTextureUnit=0;
62    _currentClientActiveTextureUnit=0;
63
64    _currentVBO = 0;
65    _currentEBO = 0;
66    _currentPBO = 0;
67
68    _isSecondaryColorSupportResolved = false;
69    _isSecondaryColorSupported = false;
70
71    _isFogCoordSupportResolved = false;
72    _isFogCoordSupported = false;
73
74    _isVertexBufferObjectSupportResolved = false;
75    _isVertexBufferObjectSupported = false;
76   
77    _lastAppliedProgramObject = 0;
78
79    _extensionProcsInitialized = false;
80    _glClientActiveTexture = 0;
81    _glActiveTexture = 0;
82    _glFogCoordPointer = 0;
83    _glSecondaryColorPointer = 0;
84    _glVertexAttribPointer = 0;
85    _glEnableVertexAttribArray = 0;
86    _glDisableVertexAttribArray = 0;
87    _glDrawArraysInstanced = 0;
88    _glDrawElementsInstanced = 0;
89
90    _dynamicObjectCount  = 0;
91
92    _glMaxTextureCoords = 1;
93    _glMaxTextureUnits = 1;
94
95    _maxTexturePoolSize = 0;
96    _maxBufferObjectPoolSize = 0;
97
98
99}
100
101State::~State()
102{
103    for(AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.begin();
104        itr != _appliedProgramObjectSet.end();
105        ++itr)
106    {
107        (*itr)->removeObserver(this);
108    }
109}
110
111void State::objectDeleted(void* object)
112{
113    const Program::PerContextProgram* ppcp = reinterpret_cast<const Program::PerContextProgram*>(object);
114    AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.find(ppcp);
115    if (itr != _appliedProgramObjectSet.end())
116    {
117        // osg::notify(osg::NOTICE)<<"Removing _appliedProgramObjectSet entry "<<ppcp<<std::endl;
118        _appliedProgramObjectSet.erase(itr);
119    }
120}
121
122void State::reset()
123{
124
125#if 1
126    for(ModeMap::iterator mitr=_modeMap.begin();
127        mitr!=_modeMap.end();
128        ++mitr)
129    {
130        ModeStack& ms = mitr->second;
131        ms.valueVec.clear();
132        ms.last_applied_value = !ms.global_default_value;
133        ms.changed = true;
134    }       
135#else
136    _modeMap.clear();
137#endif
138
139    _modeMap[GL_DEPTH_TEST].global_default_value = true;
140    _modeMap[GL_DEPTH_TEST].changed = true;
141   
142    // go through all active StateAttribute's, setting to change to force update,
143    // the idea is to leave only the global defaults left.
144    for(AttributeMap::iterator aitr=_attributeMap.begin();
145        aitr!=_attributeMap.end();
146        ++aitr)
147    {
148        AttributeStack& as = aitr->second;
149        as.attributeVec.clear();
150        as.last_applied_attribute = NULL;
151        as.changed = true;
152    }
153   
154    // we can do a straight clear, we arn't interested in GL_DEPTH_TEST defaults in texture modes.
155    for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin();
156        tmmItr!=_textureModeMapList.end();
157        ++tmmItr)
158    {
159        tmmItr->clear();
160    }
161
162    // empty all the texture attributes as per normal attributes, leaving only the global defaults left.
163    for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin();
164        tamItr!=_textureAttributeMapList.end();
165        ++tamItr)
166    {
167        AttributeMap& attributeMap = *tamItr;
168        // go through all active StateAttribute's, setting to change to force update.
169        for(AttributeMap::iterator aitr=attributeMap.begin();
170            aitr!=attributeMap.end();
171            ++aitr)
172        {
173            AttributeStack& as = aitr->second;
174            as.attributeVec.clear();
175            as.last_applied_attribute = NULL;
176            as.changed = true;
177        }
178    }
179
180    _stateStateStack.clear();
181   
182    _modelView = _identity;
183    _projection = _identity;
184   
185    dirtyAllVertexArrays();
186   
187#if 0
188    // reset active texture unit values and call OpenGL
189    // note, this OpenGL op precludes the use of State::reset() without a
190    // valid graphics context, therefore the new implementation below
191    // is preferred.
192    setActiveTextureUnit(0);
193#else
194    // reset active texture unit values without calling OpenGL
195    _currentActiveTextureUnit = 0;
196    _currentClientActiveTextureUnit = 0;
197#endif
198   
199    _lastAppliedProgramObject = 0;
200
201    for(AppliedProgramObjectSet::iterator apitr=_appliedProgramObjectSet.begin();
202        apitr!=_appliedProgramObjectSet.end();
203        ++apitr)
204    {
205        (*apitr)->resetAppliedUniforms();
206        (*apitr)->removeObserver(this);
207    }
208   
209    _appliedProgramObjectSet.clear();
210   
211   
212    // what about uniforms??? need to clear them too...
213    // go through all active Unfirom's, setting to change to force update,
214    // the idea is to leave only the global defaults left.
215    for(UniformMap::iterator uitr=_uniformMap.begin();
216        uitr!=_uniformMap.end();
217        ++uitr)
218    {
219        UniformStack& us = uitr->second;
220        us.uniformVec.clear();
221    }
222
223}
224
225void State::setInitialViewMatrix(const osg::RefMatrix* matrix)
226{
227    if (matrix) _initialViewMatrix = matrix;
228    else _initialViewMatrix = _identity;
229
230    _initialInverseViewMatrix.invert(*_initialViewMatrix);
231}
232
233void State::setMaxTexturePoolSize(unsigned int size)
234{
235    _maxTexturePoolSize = size;
236    osg::Texture::getTextureObjectManager(getContextID())->setMaxTexturePoolSize(size);
237    osg::notify(osg::INFO)<<"osg::State::_maxTexturePoolSize="<<_maxTexturePoolSize<<std::endl;
238}
239
240void State::setMaxBufferObjectPoolSize(unsigned int size)
241{
242    _maxBufferObjectPoolSize = size;
243    osg::GLBufferObjectManager::getGLBufferObjectManager(getContextID())->setMaxGLBufferObjectPoolSize(_maxBufferObjectPoolSize);
244    osg::notify(osg::INFO)<<"osg::State::_maxBufferObjectPoolSize="<<_maxBufferObjectPoolSize<<std::endl;
245}
246
247void State::pushStateSet(const StateSet* dstate)
248{
249
250    _stateStateStack.push_back(dstate);
251    if (dstate)
252    {
253
254        pushModeList(_modeMap,dstate->getModeList());
255
256        // iterator through texture modes.       
257        unsigned int unit;
258        const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
259        for(unit=0;unit<ds_textureModeList.size();++unit)
260        {
261            pushModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
262        }
263
264        pushAttributeList(_attributeMap,dstate->getAttributeList());
265
266        // iterator through texture attributes.
267        const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
268        for(unit=0;unit<ds_textureAttributeList.size();++unit)
269        {
270            pushAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
271        }
272
273        pushUniformList(_uniformMap,dstate->getUniformList());
274    }
275
276    // osg::notify(osg::NOTICE)<<"State::pushStateSet()"<<_stateStateStack.size()<<std::endl;
277}
278
279void State::popAllStateSets()
280{
281    // osg::notify(osg::NOTICE)<<"State::popAllStateSets()"<<_stateStateStack.size()<<std::endl;
282
283    while (!_stateStateStack.empty()) popStateSet();
284   
285    applyProjectionMatrix(0);
286    applyModelViewMatrix(0);
287   
288    _lastAppliedProgramObject = 0;
289}
290
291void State::popStateSet()
292{
293    // osg::notify(osg::NOTICE)<<"State::popStateSet()"<<_stateStateStack.size()<<std::endl;
294
295    if (_stateStateStack.empty()) return;
296   
297   
298    const StateSet* dstate = _stateStateStack.back();
299
300    if (dstate)
301    {
302
303        popModeList(_modeMap,dstate->getModeList());
304
305        // iterator through texture modes.       
306        unsigned int unit;
307        const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
308        for(unit=0;unit<ds_textureModeList.size();++unit)
309        {
310            popModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
311        }
312
313        popAttributeList(_attributeMap,dstate->getAttributeList());
314
315        // iterator through texture attributes.
316        const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
317        for(unit=0;unit<ds_textureAttributeList.size();++unit)
318        {
319            popAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
320        }
321
322        popUniformList(_uniformMap,dstate->getUniformList());
323
324    }
325   
326    // remove the top draw state from the stack.
327    _stateStateStack.pop_back();
328}
329
330void State::insertStateSet(unsigned int pos,const StateSet* dstate)
331{
332    StateSetStack tempStack;
333   
334    // first pop the StateSet above the position we need to insert at
335    while (_stateStateStack.size()>pos)
336    {
337        tempStack.push_back(_stateStateStack.back());
338        popStateSet();
339    }
340
341    // push our new stateset
342    pushStateSet(dstate);
343   
344    // push back the original ones
345    for(StateSetStack::reverse_iterator itr = tempStack.rbegin();
346        itr != tempStack.rend();
347        ++itr)
348    {
349        pushStateSet(*itr);
350    }
351
352}
353
354void State::removeStateSet(unsigned int pos)
355{
356    if (pos >= _stateStateStack.size())
357    {
358        osg::notify(osg::NOTICE)<<"Warning: State::removeStateSet("<<pos<<") out of range"<<std::endl;
359        return;
360    }
361   
362    // record the StateSet above the one we intend to remove
363    StateSetStack tempStack;
364    while (_stateStateStack.size()-1>pos)
365    {
366        tempStack.push_back(_stateStateStack.back());
367        popStateSet();
368    }
369
370    // remove the intended StateSet as well   
371    popStateSet();
372
373    // push back the original ones that were above the remove StateSet
374    for(StateSetStack::reverse_iterator itr = tempStack.rbegin();
375        itr != tempStack.rend();
376        ++itr)
377    {
378        pushStateSet(*itr);
379    }
380}
381
382void State::captureCurrentState(StateSet& stateset) const
383{
384    // empty the stateset first.
385    stateset.clear();
386   
387    for(ModeMap::const_iterator mitr=_modeMap.begin();
388        mitr!=_modeMap.end();
389        ++mitr)
390    {
391        // note GLMode = mitr->first
392        const ModeStack& ms = mitr->second;
393        if (!ms.valueVec.empty())
394        {
395            stateset.setMode(mitr->first,ms.valueVec.back());
396        }
397    }       
398
399    for(AttributeMap::const_iterator aitr=_attributeMap.begin();
400        aitr!=_attributeMap.end();
401        ++aitr)
402    {
403        const AttributeStack& as = aitr->second;
404        if (!as.attributeVec.empty())
405        {
406            stateset.setAttribute(const_cast<StateAttribute*>(as.attributeVec.back().first));
407        }
408    }       
409
410}
411
412// revert to using maximum for consistency, maximum should be defined by STLport on VS.
413// // visual studio 6.0 doesn't appear to define maximum?!? So do our own here..
414// template<class T>
415// T mymax(const T& a,const T& b)
416// {
417//     return (((a) > (b)) ? (a) : (b));
418// }
419
420void State::apply(const StateSet* dstate)
421{
422    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply(StateSet*)");
423
424    // equivalent to:
425    //pushStateSet(dstate);
426    //apply();
427    //popStateSet();
428    //return;
429
430    if (dstate)
431    {
432
433        applyModeList(_modeMap,dstate->getModeList());
434        applyAttributeList(_attributeMap,dstate->getAttributeList());
435
436        const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
437        const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
438
439        unsigned int unit;
440        unsigned int unitMax = maximum(static_cast<unsigned int>(ds_textureModeList.size()),static_cast<unsigned int>(ds_textureAttributeList.size()));
441        unitMax = maximum(static_cast<unsigned int>(unitMax),static_cast<unsigned int>(_textureModeMapList.size()));
442        unitMax = maximum(static_cast<unsigned int>(unitMax),static_cast<unsigned int>(_textureAttributeMapList.size()));
443        for(unit=0;unit<unitMax;++unit)
444        {
445            if (setActiveTextureUnit(unit))
446            {
447                if (unit<ds_textureModeList.size()) applyModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
448                else if (unit<_textureModeMapList.size()) applyModeMap(_textureModeMapList[unit]);
449
450                if (unit<ds_textureAttributeList.size()) applyAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
451                else if (unit<_textureAttributeMapList.size()) applyAttributeMap(_textureAttributeMapList[unit]);
452            }
453        }
454
455        applyUniformList(_uniformMap,dstate->getUniformList());
456    }
457    else
458    {
459        // no incoming stateset, so simply apply state.
460        apply();
461    }
462
463    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply(StateSet*)");
464}
465
466void State::apply()
467{
468
469    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply()");
470
471    // go through all active OpenGL modes, enabling/disable where
472    // appropriate.
473    applyModeMap(_modeMap);
474
475    // go through all active StateAttribute's, applying where appropriate.
476    applyAttributeMap(_attributeMap);
477       
478    unsigned int unit;
479    unsigned int unitMax = maximum(_textureModeMapList.size(),_textureAttributeMapList.size());
480    for(unit=0;unit<unitMax;++unit)
481    {
482        if (setActiveTextureUnit(unit))
483        {
484            if (unit<_textureModeMapList.size()) applyModeMap(_textureModeMapList[unit]);
485            if (unit<_textureAttributeMapList.size()) applyAttributeMap(_textureAttributeMapList[unit]);
486        }
487    }
488
489    applyUniformMap(_uniformMap);
490
491    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()");
492}
493
494void State::haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
495{
496    haveAppliedMode(_modeMap,mode,value);
497}
498
499void State::haveAppliedMode(StateAttribute::GLMode mode)
500{
501    haveAppliedMode(_modeMap,mode);
502}
503
504void State::haveAppliedAttribute(const StateAttribute* attribute)
505{
506    haveAppliedAttribute(_attributeMap,attribute);
507}
508
509void State::haveAppliedAttribute(StateAttribute::Type type, unsigned int member)
510{
511    haveAppliedAttribute(_attributeMap,type,member);
512}
513
514bool State::getLastAppliedMode(StateAttribute::GLMode mode) const
515{
516    return getLastAppliedMode(_modeMap,mode);
517}
518
519const StateAttribute* State::getLastAppliedAttribute(StateAttribute::Type type, unsigned int member) const
520{
521    return getLastAppliedAttribute(_attributeMap,type,member);
522}
523
524
525void State::haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
526{
527    haveAppliedMode(getOrCreateTextureModeMap(unit),mode,value);
528}
529
530void State::haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode)
531{
532    haveAppliedMode(getOrCreateTextureModeMap(unit),mode);
533}
534
535void State::haveAppliedTextureAttribute(unsigned int unit,const StateAttribute* attribute)
536{
537    haveAppliedAttribute(getOrCreateTextureAttributeMap(unit),attribute);
538}
539
540void State::haveAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type, unsigned int member)
541{
542    haveAppliedAttribute(getOrCreateTextureAttributeMap(unit),type,member);
543}
544
545bool State::getLastAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode) const
546{
547    if (unit>=_textureModeMapList.size()) return false;
548    return getLastAppliedMode(_textureModeMapList[unit],mode);
549}
550
551const StateAttribute* State::getLastAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type, unsigned int member) const
552{
553    if (unit>=_textureAttributeMapList.size()) return false;
554    return getLastAppliedAttribute(_textureAttributeMapList[unit],type,member);
555}
556
557
558void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
559{
560    ModeStack& ms = modeMap[mode];
561
562    ms.last_applied_value = value & StateAttribute::ON;
563
564    // will need to disable this mode on next apply so set it to changed.
565    ms.changed = true;   
566}
567
568/** mode has been set externally, update state to reflect this setting.*/
569void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode)
570{
571    ModeStack& ms = modeMap[mode];
572
573    // don't know what last applied value is can't apply it.
574    // assume that it has changed by toggle the value of last_applied_value.
575    ms.last_applied_value = !ms.last_applied_value;
576
577    // will need to disable this mode on next apply so set it to changed.
578    ms.changed = true;   
579}
580
581/** attribute has been applied externally, update state to reflect this setting.*/
582void State::haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute)
583{
584    if (attribute)
585    {
586        AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
587
588        as.last_applied_attribute = attribute;
589
590        // will need to update this attribute on next apply so set it to changed.
591        as.changed = true;
592    }
593}
594
595void State::haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member)
596{
597   
598    AttributeMap::iterator itr = attributeMap.find(StateAttribute::TypeMemberPair(type,member));
599    if (itr!=attributeMap.end())
600    {
601        AttributeStack& as = itr->second;
602        as.last_applied_attribute = 0L;
603
604        // will need to update this attribute on next apply so set it to changed.
605        as.changed = true;
606    }
607}
608
609bool State::getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const
610{
611    ModeMap::const_iterator itr = modeMap.find(mode);
612    if (itr!=modeMap.end())
613    {
614        const ModeStack& ms = itr->second;
615        return ms.last_applied_value;
616    }
617    else
618    {
619        return false;
620    }
621}
622
623const StateAttribute* State::getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const
624{
625    AttributeMap::const_iterator itr = attributeMap.find(StateAttribute::TypeMemberPair(type,member));
626    if (itr!=attributeMap.end())
627    {
628        const AttributeStack& as = itr->second;
629        return as.last_applied_attribute;
630    }
631    else
632    {
633        return NULL;
634    }
635}
636
637void State::dirtyAllModes()
638{
639    for(ModeMap::iterator mitr=_modeMap.begin();
640        mitr!=_modeMap.end();
641        ++mitr)
642    {
643        ModeStack& ms = mitr->second;
644        ms.last_applied_value = !ms.last_applied_value;
645        ms.changed = true;   
646
647    }       
648
649    for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin();
650        tmmItr!=_textureModeMapList.end();
651        ++tmmItr)
652    {
653        for(ModeMap::iterator mitr=tmmItr->begin();
654            mitr!=tmmItr->end();
655            ++mitr)
656        {
657            ModeStack& ms = mitr->second;
658            ms.last_applied_value = !ms.last_applied_value;
659            ms.changed = true;   
660
661        }       
662    }
663}
664
665void State::dirtyAllAttributes()
666{
667    for(AttributeMap::iterator aitr=_attributeMap.begin();
668        aitr!=_attributeMap.end();
669        ++aitr)
670    {
671        AttributeStack& as = aitr->second;
672        as.last_applied_attribute = 0;
673        as.changed = true;
674    }
675   
676
677    for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin();
678        tamItr!=_textureAttributeMapList.end();
679        ++tamItr)
680    {
681        AttributeMap& attributeMap = *tamItr;
682        for(AttributeMap::iterator aitr=attributeMap.begin();
683            aitr!=attributeMap.end();
684            ++aitr)
685        {
686            AttributeStack& as = aitr->second;
687            as.last_applied_attribute = 0;
688            as.changed = true;
689        }
690    }
691
692}
693
694
695Polytope State::getViewFrustum() const
696{
697    Polytope cv;
698    cv.setToUnitFrustum();
699    cv.transformProvidingInverse((*_modelView)*(*_projection));
700    return cv;
701}
702
703
704
705void State::disableAllVertexArrays()
706{
707    disableVertexPointer();
708    disableTexCoordPointersAboveAndIncluding(0);
709    disableVertexAttribPointersAboveAndIncluding(0);
710    disableColorPointer();
711    disableFogCoordPointer();
712    disableIndexPointer();
713    disableNormalPointer();
714    disableSecondaryColorPointer();
715}
716
717void State::dirtyAllVertexArrays()
718{
719    dirtyVertexPointer();
720    dirtyTexCoordPointersAboveAndIncluding(0);
721    dirtyVertexAttribPointersAboveAndIncluding(0);
722    dirtyColorPointer();
723    dirtyFogCoordPointer();
724    dirtyIndexPointer();
725    dirtyNormalPointer();
726    dirtySecondaryColorPointer();
727}
728
729void State::setInterleavedArrays( GLenum format, GLsizei stride, const GLvoid* pointer)
730{
731    disableAllVertexArrays();
732
733    glInterleavedArrays( format, stride, pointer);
734
735    // the crude way, assume that all arrays have been effected so dirty them and
736    // disable them...
737    dirtyAllVertexArrays();
738}
739
740void State::initializeExtensionProcs()
741{
742    if (_extensionProcsInitialized) return;
743
744    setGLExtensionFuncPtr(_glClientActiveTexture,"glClientActiveTexture","glClientActiveTextureARB");
745    setGLExtensionFuncPtr(_glActiveTexture, "glActiveTexture","glActiveTextureARB");
746    setGLExtensionFuncPtr(_glFogCoordPointer, "glFogCoordPointer","glFogCoordPointerEXT");
747    setGLExtensionFuncPtr(_glSecondaryColorPointer, "glSecondaryColorPointer","glSecondaryColorPointerEXT");
748    setGLExtensionFuncPtr(_glVertexAttribPointer, "glVertexAttribPointer","glVertexAttribPointerARB");
749    setGLExtensionFuncPtr(_glEnableVertexAttribArray, "glEnableVertexAttribArray","glEnableVertexAttribArrayARB");
750    setGLExtensionFuncPtr(_glDisableVertexAttribArray, "glDisableVertexAttribArray","glDisableVertexAttribArrayARB");
751    setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
752
753    setGLExtensionFuncPtr(_glDrawArraysInstanced, "glDrawArraysInstanced","glDrawArraysInstancedARB","glDrawArraysInstancedEXT");
754    setGLExtensionFuncPtr(_glDrawElementsInstanced, "glDrawElementsInstanced","glDrawElementsInstancedARB","glDrawElementsInstancedEXT");
755
756    if ( osg::getGLVersionNumber() >= 2.0 || osg::isGLExtensionSupported(_contextID,"GL_ARB_vertex_shader") )
757    {
758        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&_glMaxTextureUnits);
759        glGetIntegerv(GL_MAX_TEXTURE_COORDS,&_glMaxTextureCoords);
760    }
761    else if ( osg::getGLVersionNumber() >= 1.3 ||
762                                 osg::isGLExtensionSupported(_contextID,"GL_ARB_multitexture") ||
763                                 osg::isGLExtensionSupported(_contextID,"GL_EXT_multitexture") )
764    {
765        GLint maxTextureUnits;
766        glGetIntegerv(GL_MAX_TEXTURE_UNITS,&maxTextureUnits);
767        _glMaxTextureUnits = maxTextureUnits;
768        _glMaxTextureCoords = maxTextureUnits;
769    }
770    else
771    {
772        _glMaxTextureUnits = 1;
773        _glMaxTextureCoords = 1;
774    }
775
776    _extensionProcsInitialized = true;
777}
778
779bool State::setClientActiveTextureUnit( unsigned int unit )
780{
781    if (unit!=_currentClientActiveTextureUnit)
782    {
783        if (_glClientActiveTexture && unit < (unsigned int)_glMaxTextureCoords)
784        {
785            _glClientActiveTexture(GL_TEXTURE0+unit);
786            _currentClientActiveTextureUnit = unit;
787        }
788        else
789        {
790            return unit==0;
791        }
792    }
793    return true;
794}
795
796
797/** set the current texture unit, return true if selected, false if selection failed such as when multitexturing is not supported.
798  * note, only updates values that change.*/
799bool State::setActiveTextureUnit( unsigned int unit )
800{
801    if (unit!=_currentActiveTextureUnit)
802    {
803        if (_glActiveTexture && unit < (unsigned int)(maximum(_glMaxTextureCoords,_glMaxTextureUnits)) )
804        {
805            _glActiveTexture(GL_TEXTURE0+unit);
806            _currentActiveTextureUnit = unit;
807        }
808        else
809        {
810            return unit==0;
811        }
812    }
813    return true;
814}
815
816void State::setFogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
817{
818    if (_glFogCoordPointer)
819    {
820
821        if (!_fogArray._enabled || _fogArray._dirty)
822        {
823            _fogArray._enabled = true;
824            glEnableClientState(GL_FOG_COORDINATE_ARRAY);
825        }
826        //if (_fogArray._pointer!=ptr || _fogArray._dirty)
827        {
828            _fogArray._pointer=ptr;
829            _glFogCoordPointer( type, stride, ptr );
830        }
831        _fogArray._dirty = false;
832    }
833   
834}
835
836void State::setSecondaryColorPointer( GLint size, GLenum type,
837                                      GLsizei stride, const GLvoid *ptr )
838{
839    if (_glSecondaryColorPointer)
840    {
841        if (!_secondaryColorArray._enabled || _secondaryColorArray._dirty)
842        {
843            _secondaryColorArray._enabled = true;
844            glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
845        }
846        //if (_secondaryColorArray._pointer!=ptr || _secondaryColorArray._dirty)
847        {
848            _secondaryColorArray._pointer=ptr;
849            _glSecondaryColorPointer( size, type, stride, ptr );
850        }
851        _secondaryColorArray._dirty = false;
852    }
853}
854
855/** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..);
856* note, only updates values that change.*/
857void State::setVertexAttribPointer( unsigned int index,
858                                      GLint size, GLenum type, GLboolean normalized,
859                                    GLsizei stride, const GLvoid *ptr )
860{
861    if (_glVertexAttribPointer)
862    {
863        if ( index >= _vertexAttribArrayList.size()) _vertexAttribArrayList.resize(index+1);
864        EnabledArrayPair& eap = _vertexAttribArrayList[index];
865
866        if (!eap._enabled || eap._dirty)
867        {
868            eap._enabled = true;
869            _glEnableVertexAttribArray( index );
870        }
871        //if (eap._pointer != ptr || eap._normalized!=normalized || eap._dirty)
872        {
873            _glVertexAttribPointer( index, size, type, normalized, stride, ptr );
874            eap._pointer = ptr;
875            eap._normalized = normalized;
876        }
877        eap._dirty = false;
878    }
879}     
880
881/** wrapper around DisableVertexAttribArrayARB(index);
882* note, only updates values that change.*/
883void State::disableVertexAttribPointer( unsigned int index )
884{
885    if (_glDisableVertexAttribArray)
886    {
887        if ( index >= _vertexAttribArrayList.size()) _vertexAttribArrayList.resize(index+1);
888        EnabledArrayPair& eap = _vertexAttribArrayList[index];
889
890        if (eap._enabled || eap._dirty)
891        {
892            eap._enabled = false;
893            eap._dirty = false;
894            _glDisableVertexAttribArray( index );
895        }
896    }
897}       
898
899void State::disableVertexAttribPointersAboveAndIncluding( unsigned int index )
900{
901    if (_glDisableVertexAttribArray)
902    {
903        while (index<_vertexAttribArrayList.size())
904        {
905            EnabledArrayPair& eap = _vertexAttribArrayList[index];
906            if (eap._enabled || eap._dirty)
907            {
908                eap._enabled = false;
909                eap._dirty = false;
910                _glDisableVertexAttribArray( index );
911            }
912            ++index;
913        }
914    }
915}
916
917bool State::computeSecondaryColorSupported() const
918{
919    _isSecondaryColorSupportResolved = true;
920    _isSecondaryColorSupported = osg::isGLExtensionSupported(_contextID,"GL_EXT_secondary_color");
921    return _isSecondaryColorSupported;
922}
923
924bool State::computeFogCoordSupported() const
925{
926    _isFogCoordSupportResolved = true;
927    _isFogCoordSupported = osg::isGLExtensionSupported(_contextID,"GL_EXT_fog_coord");
928    return _isFogCoordSupported;
929}
930
931bool State::computeVertexBufferObjectSupported() const
932{
933    _isVertexBufferObjectSupportResolved = true;
934    _isVertexBufferObjectSupported = osg::isGLExtensionSupported(_contextID,"GL_ARB_vertex_buffer_object");
935    return _isVertexBufferObjectSupported;
936}
937
938bool State::checkGLErrors(const char* str) const
939{
940    GLenum errorNo = glGetError();
941    if (errorNo!=GL_NO_ERROR)
942    {
943#ifdef OSG_GLU_AVAILABLE
944        const char* error = (char*)gluErrorString(errorNo);
945        if (error) osg::notify(WARN)<<"Warning: detected OpenGL error '" << error<<"'";
946        else       osg::notify(WARN)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
947#else
948        osg::notify(WARN)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
949#endif
950        if (str) osg::notify(WARN)<<" at "<<str<< std::endl;
951        else     osg::notify(WARN)<<" in osg::State."<< std::endl;
952
953        return true;
954    }
955    return false;
956}
957
958bool State::checkGLErrors(StateAttribute::GLMode mode) const
959{
960    GLenum errorNo = glGetError();
961    if (errorNo!=GL_NO_ERROR)
962    {
963#ifdef OSG_GLU_AVAILABLE
964        const char* error = (char*)gluErrorString(errorNo);
965        if (error) osg::notify(WARN)<<"Warning: detected OpenGL error '"<< error <<"' after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
966        else       osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
967#else
968        osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
969#endif
970        return true;
971    }
972    return false;
973}
974
975bool State::checkGLErrors(const StateAttribute* attribute) const
976{
977    GLenum errorNo = glGetError();
978    if (errorNo!=GL_NO_ERROR)
979    {
980#ifdef OSG_GLU_AVAILABLE
981        const char* error = (char*)gluErrorString(errorNo);
982        if (error) osg::notify(WARN)<<"Warning: detected OpenGL error '"<< error <<"' after applying attribute "<<attribute->className()<<" "<<attribute<< std::endl;
983        else       osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
984#else
985        osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
986#endif
987
988        return true;
989    }
990    return false;
991}
992
993
994void State::applyModelViewAndProjectionUniformsIfRequired()
995{
996    if (!_lastAppliedProgramObject) return;
997
998    if (_modelViewMatrixUniform.valid()) _lastAppliedProgramObject->apply(*_modelViewMatrixUniform);
999    if (_projectionMatrixUniform) _lastAppliedProgramObject->apply(*_projectionMatrixUniform);
1000    if (_modelViewProjectionMatrixUniform) _lastAppliedProgramObject->apply(*_modelViewProjectionMatrixUniform);
1001}
Note: See TracBrowser for help on using the browser.