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

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

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

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