Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGWindow.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //---------------------------------------------------------------------------
00040 //  Includes
00041 //---------------------------------------------------------------------------
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 
00046 #include "OSGConfig.h"
00047 
00048 #include <OSGBase.h>
00049 #include <OSGGL.h>
00050 
00051 #if !defined(WIN32) && !defined(darwin)
00052 #include <GL/glx.h>
00053 #endif
00054 
00055 #if defined(__sgi) || defined(__hpux) || defined(__linux)
00056 #include <dlfcn.h>
00057 #endif
00058 
00059 #if defined(darwin)
00060 #include <mach-o/dyld.h>
00061 #endif
00062 
00063 #if defined(__sun)
00064 #include <dlfcn.h>
00065 #include <link.h>
00066 #endif
00067 
00068 #include <OSGBaseFunctions.h>
00069 #include <OSGDrawAction.h>
00070 #include <OSGRenderActionBase.h>
00071 #include "OSGViewport.h"
00072 
00073 #include "OSGBackground.h"
00074 #include "OSGCamera.h"
00075 #include "OSGWindow.h"
00076 
00077 OSG_USING_NAMESPACE
00078 
00079 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
00080 #pragma warning (disable)
00081 #endif
00082 
00083 /***************************************************************************\
00084  *                            Description                                  *
00085 \***************************************************************************/
00086 
00102 // Window-sytem specific virtual functions
00103 
00132 // only needed in dev docs
00133 
00134 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
00135 
00193 #endif
00194 
00195 /***************************************************************************\
00196  *                           Class variables                               *
00197 \***************************************************************************/
00198 
00202 std::vector<WindowPtr              >  OSG::Window::_allWindows;
00203 UInt32                                OSG::Window::_currentWindowId = 0;
00204 // GLobject handling
00205 
00210 Lock                                 *OSG::Window::_GLObjectLock;
00211 
00215 Lock                                 *OSG::Window::_staticWindowLock;
00216 
00220 std::vector<OSG::Window::GLObject *>  OSG::Window::_glObjects; 
00221 
00224 //std::list<std::pair<UInt32,UInt32> >  OSG::Window::_glObjectDestroyList;
00225 
00226 // GL extension handling
00227 
00228 // The name of the dynamic library for OpenGL extension functions
00229 // By default it's NULL, which tries to find them in the current 
00230 // executable
00231 const Char8 *OSG::Window::_glLibraryName = NULL;    
00232 
00233 std::vector<std::string            >  OSG::Window::_registeredExtensions;
00234 std::vector<std::string            >  OSG::Window::_ignoredExtensions;
00235 std::vector<bool                   >  OSG::Window::_commonExtensions;
00236 std::vector<std::string            >  OSG::Window::_registeredFunctions;
00237 std::vector<Int32                  >  OSG::Window::_registeredFunctionExts;
00238 
00239 // GL constant handling
00240 
00241 std::vector<GLenum                 >  OSG::Window::_registeredConstants;
00242 
00243 
00244 // Just a constant to indicate that the GL constant is unknown
00245 const Real32 OSG::Window::unknownConstant = -1e100;    
00246 
00247 /***************************************************************************\
00248  *                           Class methods                                 *
00249 \***************************************************************************/
00250 
00251 /*-------------------------------------------------------------------------*\
00252  -  private                                                                -
00253 \*-------------------------------------------------------------------------*/
00254 
00258 void OSG::Window::initMethod (void)
00259 {
00260 }
00261 
00262 /***************************************************************************\
00263  *                           Instance methods                              *
00264 \***************************************************************************/
00265 
00266 /*-------------------------------------------------------------------------*\
00267  -  protected                                                              -
00268 \*-------------------------------------------------------------------------*/
00269 
00270 
00271 /*------------- constructors & destructors --------------------------------*/
00272 
00276 OSG::Window::Window(void) :
00277      Inherited( ),
00278     _windowId (0)
00279 {
00280     // only called for prototypes, no need to init them
00281 }
00282 
00286 OSG::Window::Window(const Window &source) :
00287     Inherited(source),
00288     _glObjectDestroyList(source._glObjectDestroyList),
00289     _lastValidate(source._lastValidate.size(),0),
00290     _ids(source._ids.size(),0),
00291     _extensions(),
00292     _availExtensions(),
00293     _extFunctions(),
00294     _availConstants(),
00295     _numAvailConstants(0),
00296     _windowId(0)
00297 {       
00298     // mark all GL objects as not yet initialized
00299     doInitRegisterGLObject(1, _glObjects.size() - 1);
00300 }
00301 
00305 OSG::Window::~Window(void)
00306 {
00307     // delete the ports and the context
00308 }
00309 
00310 
00311 /*-------------------------------------------------------------------------*\
00312  -  private                                                                -
00313 \*-------------------------------------------------------------------------*/
00314 
00318 void OSG::Window::onCreate(const Window *)
00319 {
00320     // Don't add the prototype instances to the list
00321     if(GlobalSystemState != Running)
00322         return;
00323         
00324     _allWindows.push_back(WindowPtr(this)); 
00325 
00326     _windowId = ++_currentWindowId;
00327 }
00328 
00329 void OSG::Window::onCreateAspect(const Window *, const Window *)
00330 {
00331     // Don't add the prototype instances to the list
00332     if(GlobalSystemState != Running)
00333         return;
00334 
00335     _windowId = _currentWindowId;
00336 }
00337 
00341 void OSG::Window::onDestroy(void)
00342 {
00343     // decrement GLObjects reference counter.
00344     for(UInt32 i = 1; i < _glObjects.size(); ++i)
00345     {
00346         GLObject *obj = _glObjects[i];
00347         if(obj == NULL)
00348         {
00349             FDEBUG(("Window::onDestroy: object %u already destroyed!\n", i));
00350             continue;
00351         }
00352         // has the object been used in this context at all?
00353         if(i < getGlObjectLastReinitialize().size() && getGlObjectLastReinitialize()[i] != 0)
00354         {
00355             obj->decRefCounter();
00356             // we can't call here the destroy callbacks because the
00357             // gl context is not guaranteed to be current, but destroying
00358             // the context should delete all gl objects.
00359         }
00360     }
00361 
00362     std::vector<WindowPtr>::iterator it;
00363     it = std::find(_allWindows.begin(), _allWindows.end(), WindowPtr(this));
00364     
00365     // prototype window are not added to the list, so they might not be found.
00366     if(it != _allWindows.end()) 
00367         _allWindows.erase( it );
00368 }
00369 
00370 void OSG::Window::staticAcquire(void)
00371 {
00372     // Is the ThreadManager initialized yet?
00373     if(GlobalSystemState != Running)
00374         return;
00375         
00376     if(_staticWindowLock == NULL)
00377     {
00378         _staticWindowLock = ThreadManager::the()->getLock(NULL);
00379     }
00380     _staticWindowLock->aquire();
00381 }
00382 
00383 void OSG::Window::staticRelease(void)
00384 {
00385     // Is the ThreadManager initialized yet?
00386     if(GlobalSystemState != Running)
00387         return;
00388         
00389     _staticWindowLock->release();
00390 }
00391 
00392 /*-------------------------------------------------------------------------*\
00393  -  public                                                                 -
00394 \*-------------------------------------------------------------------------*/
00395 
00399 void OSG::Window::changed(BitVector whichField, UInt32 origin)
00400 {
00401     Inherited::changed(whichField, origin);
00402 }
00403 
00404 /*------------------------------ access -----------------------------------*/
00405 
00406 void OSG::Window::addPort(const ViewportPtr &portP)
00407 {
00408     if(portP != NullFC)
00409     {
00410         _mfPort.push_back(portP);
00411 // CHECK CHECK
00412 //        _mfPort.back()->setParent(FieldContainer::getPtr<WindowPtr>(*this));
00413 
00414         beginEditCP(portP, Viewport::ParentFieldMask);
00415         {
00416             _mfPort.back()->setParent(WindowPtr(*this));
00417         }
00418         endEditCP  (portP, Viewport::ParentFieldMask);
00419     }
00420 }
00421 
00422 void OSG::Window::insertPort(UInt32 portIndex, const ViewportPtr &portP)
00423 {    
00424     MFViewportPtr::iterator portIt = _mfPort.begin();
00425 
00426     if(portP != NullFC)
00427     {
00428         portIt += portIndex;
00429   
00430 // CHECK CHECK      
00431 //        (*(_mfPort.insert(portIt, portP)))->setParent(
00432 //            FieldContainer::getPtr<WindowPtr>(*this));
00433 
00434         beginEditCP(portP, Viewport::ParentFieldMask);
00435         {
00436             (*(_mfPort.insert(portIt, portP)))->setParent(
00437                 WindowPtr(*this));
00438         }
00439         endEditCP  (portP, Viewport::ParentFieldMask);
00440 
00441     }
00442 }
00443 
00444 
00445 void OSG::Window::replacePort(UInt32 portIndex, const ViewportPtr &portP)
00446 {
00447     if(portP != NullFC)
00448     {
00449         _mfPort[portIndex]->setParent(NullFC);
00450         _mfPort[portIndex] = portP;
00451 // CHECK CHECK
00452 //        _mfPort.getValue(portIndex)->setParent(
00453 //            FieldContainer::getPtr<WindowPtr>(*this));
00454         _mfPort[portIndex]->setParent(
00455             WindowPtr(*this));
00456     }
00457 }
00458 
00459 void OSG::Window::replacePortBy(const ViewportPtr &portP, 
00460                              const ViewportPtr &newportP)
00461 {
00462     MFViewportPtr::iterator portIt = _mfPort.find(portP);
00463 
00464     if(newportP != NullFC)
00465     {
00466         if(portIt != _mfPort.end())
00467         {
00468             (*portIt)->setParent(NullFC);
00469             (*portIt) = newportP;
00470 // CHECK CHECK
00471 //            (*portIt)->setParent(
00472 //                FieldContainer::getPtr<WindowPtr>(*this));
00473             (*portIt)->setParent(
00474                 WindowPtr(*this));
00475         }
00476     }
00477 }
00478 
00479 void OSG::Window::subPort(const ViewportPtr &portP)
00480 {
00481     MFViewportPtr::iterator portIt = _mfPort.find(portP);
00482 
00483     if(portIt != _mfPort.end())
00484     {
00485         (*portIt)->setParent(NullFC);
00486 
00487         _mfPort.erase(portIt);
00488     }
00489 
00490 }
00491 
00492 void OSG::Window::subPort(UInt32  portIndex)
00493 {
00494     MFViewportPtr::iterator portIt = _mfPort.begin();
00495 
00496     portIt += portIndex;
00497 
00498     if(portIt != _mfPort.end())
00499     {
00500         (*portIt)->setParent(NullFC);
00501 
00502         _mfPort.erase(portIt);
00503     }
00504 }
00505 
00506 
00507 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_EXT)
00508 
00509 /*------------------------ GL object handling -----------------------------*/
00510 
00519 UInt32 OSG::Window::registerGLObject(GLObjectFunctor functor, UInt32 num)
00520 {
00521     UInt32    id, i; 
00522     GLObject *pGLObject;
00523 
00524     staticAcquire();
00525     
00526     // reserve index 0, illegal for most OpenGL functions
00527     if(_glObjects.empty())
00528         _glObjects.push_back( NULL );   
00529 
00530     id        = _glObjects.size();
00531     pGLObject = new GLObject(functor);
00532     
00533     // does the requested block fit into the capacity?
00534     
00535     if(_glObjects.capacity() >= id + num)
00536     {
00537         _glObjects.insert(_glObjects.end(), num, pGLObject );
00538         
00539         initRegisterGLObject(id, num);
00540 
00541         staticRelease();
00542        
00543         return id;
00544     }
00545     
00546     // doesn't fit, try to find a block in the middle
00547     
00548     UInt32 cnt = 0;        
00549 
00550     // start searching at 1, id 0 is reserved for GL
00551     for(i = 1; i < _glObjects.size(); ++i)
00552     {       
00553         if(!_glObjects[i]) 
00554         {
00555             if(cnt == 0)
00556             {
00557                 id = i;
00558             }
00559 
00560             ++cnt;
00561 
00562             if(cnt == num) 
00563             {
00564                 // block of unused entries found ...
00565                         
00566                 while(i >= id) 
00567                 {
00568                     _glObjects[i] = pGLObject;
00569                     i = i - 1;
00570                 } 
00571                 
00572                 initRegisterGLObject(id, num);
00573 
00574                 staticRelease();
00575                    
00576                 return id;
00577             }
00578         }
00579         else
00580         {
00581             cnt = 0;
00582         }
00583     }
00584     
00585     // no block found, add at the end
00586     
00587     // fill the empty slots at the end 
00588     i = id + cnt - 1;
00589     while ( i >= id )
00590     {
00591         _glObjects[i] = pGLObject;
00592         i = i - 1;
00593     }
00594     
00595     // expand the vector for the rest 
00596     for ( i = 1; i <= num - cnt; i++ ) 
00597     {       
00598         _glObjects.push_back( pGLObject );
00599     }
00600                 
00601     initRegisterGLObject(id, num);
00602     
00603     staticRelease();
00604     
00605     return id;
00606 }
00607 
00614 void OSG::Window::validateGLObject(UInt32 id)
00615 {
00616     if ( id == 0 )
00617     {
00618         SWARNING << "Window::validateGLObject: id is 0!" << std::endl;
00619             return;
00620     }
00621     
00622     GLObject *obj = _glObjects[id];
00623     
00624     if(obj == NULL)
00625     {
00626         SWARNING << "Window::validateGLObject: obj is NULL!" << std::endl;
00627         return;
00628     }
00629 
00630     if(id >= _lastValidate.size()) // can happen if multi-threading
00631     {
00632         _lastValidate.insert(_lastValidate.end(), 
00633                              id + 1 - _lastValidate.size(),
00634                              0);
00635     }
00636     
00637     FDEBUG(("Window 0x%p (event %d,ri:%d,rf:%d): "
00638             "Validating object %d: last reinit:%d, last validate:"
00639             "%d last refresh: %d => %s\n", 
00640             this, getGlObjectEventCounter(), 
00641             _mfGlObjectLastReinitialize.size(),
00642             _mfGlObjectLastRefresh.size(),
00643             id, 
00644             (_mfGlObjectLastReinitialize.size() > id)?
00645                 _mfGlObjectLastReinitialize[id]:0xffffffff,
00646             _lastValidate[id],
00647             (_mfGlObjectLastRefresh.size() > id)?
00648                 _mfGlObjectLastRefresh[id]:0xffffffff,
00649             (_mfGlObjectLastReinitialize[id] == 0)?"init":
00650             ((_mfGlObjectLastReinitialize[id] > _lastValidate[id])?"reinit":
00651             ((_mfGlObjectLastRefresh[id] > _lastValidate[id])?"refresh":
00652             "up-to-date"))
00653           ));
00654     
00655     if(_mfGlObjectLastReinitialize[id] == 0)
00656     {
00657         obj->incRefCounter();
00658         obj->getFunctor().call(this, packIdStatus(id, initialize));
00659         _mfGlObjectLastReinitialize[id] = 1;
00660         _lastValidate[id] = getGlObjectEventCounter();
00661     }
00662     else if(_mfGlObjectLastReinitialize[id] > _lastValidate[id])
00663     {
00664         obj->getFunctor().call(this, packIdStatus(id, reinitialize));
00665         _lastValidate[id] = getGlObjectEventCounter();
00666     }
00667     else if(_mfGlObjectLastRefresh[id] > _lastValidate[id])
00668     {
00669         obj->getFunctor().call(this, packIdStatus(id, needrefresh));
00670         _lastValidate[id] = getGlObjectEventCounter();
00671     }
00672 }
00673 
00674 
00681 void OSG::Window::validateAllGLObjects(void)
00682 {
00683     activate();
00684     frameInit();
00685 
00686     for (UInt32 i = 1; i < _glObjects.size(); ++i)
00687         validateGLObject(i);
00688     
00689     frameExit();
00690 }   
00691 
00698 void OSG::Window::refreshGLObject( UInt32 id )
00699 {
00700     if ( id == 0 )
00701     {
00702         SWARNING << "Window::refreshGLObject: id is 0!" << std::endl;
00703         return;
00704     }
00705 
00706     std::vector<WindowPtr>::iterator it;
00707 
00708     for ( it = _allWindows.begin(); it != _allWindows.end(); ++it)
00709     {
00710         beginEditCP(*it, GlObjectEventCounterFieldMask|
00711                          GlObjectLastRefreshFieldMask);
00712 
00713         UInt32 lastinv = (*it)->getGlObjectEventCounter() + 1;
00714         MFUInt32 &field = (*it)->_mfGlObjectLastRefresh;
00715         if(field.size() <= id)
00716             field.getValues().insert(field.end(), id - field.size() + 1, 0 );
00717         field[id] = lastinv;
00718         (*it)->setGlObjectEventCounter(lastinv);
00719 
00720         endEditCP  (*it, GlObjectEventCounterFieldMask|
00721                          GlObjectLastRefreshFieldMask);
00722     }
00723 }
00724 
00731 void OSG::Window::reinitializeGLObject(UInt32 id)
00732 {
00733     if ( id == 0 )
00734     {
00735         SWARNING << "Window::reinitializeGLObject: id is 0!" << std::endl;
00736         return;
00737     }
00738 
00739     std::vector<WindowPtr>::iterator it;
00740 
00741     for(it = _allWindows.begin(); it != _allWindows.end(); ++it)
00742     {
00743         beginEditCP(*it, GlObjectEventCounterFieldMask|
00744                          GlObjectLastReinitializeFieldMask);
00745 
00746         UInt32 lastinv = (*it)->getGlObjectEventCounter() + 1;
00747 
00748         MFUInt32 &field = (*it)->_mfGlObjectLastReinitialize;
00749         if(field.size() < id)
00750             field.getValues().insert(field.end(), id - field.size() + 1, 0 );
00751         // is it already validated?
00752         if(field[id] == 0)
00753             continue;
00754         field[id] = lastinv;
00755         (*it)->setGlObjectEventCounter(lastinv);
00756 
00757         endEditCP  (*it, GlObjectEventCounterFieldMask|
00758                          GlObjectLastReinitializeFieldMask);
00759     }
00760 }
00761 
00768 void OSG::Window::initRegisterGLObject(UInt32 id, UInt32 num)
00769 {
00770     if ( id == 0 )
00771     {
00772         SWARNING << "Window::initRegisterGLObject: id is 0!" << std::endl;
00773         return;
00774     }
00775 
00776     std::vector<WindowPtr>::iterator it;
00777 
00778     for(it = _allWindows.begin(); it != _allWindows.end(); ++it)
00779     {
00780         (*it)->doInitRegisterGLObject(id, num);
00781     }
00782 }
00783 
00790 void OSG::Window::doInitRegisterGLObject(UInt32 id, UInt32 num)
00791 {
00792     WindowPtr win(this);
00793     
00794     beginEditCP(win, GlObjectLastReinitializeFieldMask|
00795                      GlObjectLastRefreshFieldMask);
00796 
00797     if(_mfGlObjectLastReinitialize.size() < id + num)
00798     {
00799         _mfGlObjectLastReinitialize.resize(id + num);
00800         _mfGlObjectLastRefresh.resize(id + num);
00801         _lastValidate.resize(id + num);
00802     }
00803 
00804     for(UInt32 i = id; i < id + num; ++i)
00805     {
00806         _mfGlObjectLastReinitialize[i] = 0;
00807         _mfGlObjectLastRefresh     [i] = 0;
00808         _lastValidate[i] = 0;
00809    }
00810 
00811     endEditCP  (win, GlObjectLastReinitializeFieldMask|
00812                      GlObjectLastRefreshFieldMask);
00813 }
00814 
00821 void OSG::Window::destroyGLObject(UInt32 id, UInt32 num)
00822 {
00823     std::vector<WindowPtr>::iterator it;
00824 
00825     for(it = _allWindows.begin(); it != _allWindows.end(); ++it)
00826     {
00827 #ifdef OSG_DEBUG
00828         if(id + num > (*it)->_mfGlObjectLastReinitialize.size())
00829         {
00830             FWARNING(("Window::destroyGLObject:: id %d + num %d exceed"
00831                 "registered objects size %d!\n", id, num, 
00832                 (*it)->_mfGlObjectLastReinitialize.size()));
00833             return;
00834         }
00835 #endif
00836         // has the object been used in this context at all?
00837         if((*it)->getGlObjectLastReinitialize()[id] != 0) 
00838             (*it)->_glObjectDestroyList.push_back(DestroyEntry(id,num));
00839     }
00840 }
00841 
00842 
00843 /*----------------------- GL extension handling ---------------------------*/
00844 
00845 
00849 UInt32 OSG::Window::registerExtension(const Char8 *s)
00850 {
00851     FDEBUG(("Window::registerExtension: register '%s': ", s));
00852     staticAcquire();
00853    
00854     if(s == NULL)
00855     {
00856         staticRelease();
00857         return TypeTraits<UInt32>::getMax();
00858     }
00859     
00860     std::vector<std::string>::iterator i;
00861     
00862     i = std::find(_registeredExtensions.begin(), _registeredExtensions.end(), 
00863                   s);
00864     
00865     if(i < _registeredExtensions.end())
00866     {
00867         staticRelease();
00868         FPDEBUG(("reusing id %d\n", i - _registeredExtensions.begin()));
00869         return i - _registeredExtensions.begin();
00870     }
00871         
00872     UInt32 r = _registeredExtensions.size();
00873     _registeredExtensions.push_back(s);
00874     
00875     FPDEBUG(("new id %d\n", r));
00876     
00877     staticRelease();
00878     return r;
00879 }
00880 
00885 bool OSG::Window::hasExtension(const Char8 *s)
00886 {
00887     if(std::find(_ignoredExtensions.begin(),
00888                  _ignoredExtensions.end(),
00889                  s)                         != _ignoredExtensions.end())
00890     {
00891         return false;
00892     }
00893     
00894     if(std::find(_extensions.begin(),
00895                  _extensions.end(),
00896                  s)                         != _extensions.end())
00897     {
00898         return true;
00899     }
00900     
00901     return false;
00902 }
00903 
00906 void OSG::Window::ignoreExtensions(const Char8 *s)
00907 {    
00908     FDEBUG(("Window:: Ignoring extensions '%s'\n", s));
00909 
00910     staticAcquire();
00911     
00912     std::back_insert_iterator< std::vector<std::string> > 
00913             extension_back_inserter(_ignoredExtensions);
00914 
00915     std::string toex(s);
00916     
00917     for(string_token_iterator ignit = string_token_iterator(toex, ",. ");
00918         ignit != string_token_iterator(); ++ignit)
00919     {          
00920         std::string ignore = *ignit;
00921 
00922         FDEBUG(("Ignoring '%s':", ignore.c_str()));
00923         
00924         if(std::find(_ignoredExtensions.begin(),
00925                      _ignoredExtensions.end(),
00926                      ignore.c_str())            != _ignoredExtensions.end())
00927         {
00928             FPDEBUG((" already ignored.\n"));
00929             continue;
00930         }
00931         
00932         _ignoredExtensions.push_back(ignore);
00933         
00934         std::vector<std::string>::iterator regit;
00935         
00936         // if extension is registered, disable it on all existing Windows
00937         
00938         regit = std::find(_registeredExtensions.begin(),
00939                           _registeredExtensions.end(),
00940                           ignore.c_str());                                 
00941         
00942         Int32 ind = -1;
00943         
00944         if(regit != _registeredExtensions.end())
00945         {
00946             ind = regit - _registeredExtensions.begin();
00947             FPDEBUG(("(reg as %d)", ind));
00948         }
00949 
00950         // Walk all existing windows and remove the ignored extension 
00951         // from the _extensions vector. Disable it if it was a registered one.
00952         
00953         std::vector<WindowPtr>::iterator winit;
00954 
00955         for(winit = _allWindows.begin(); winit != _allWindows.end(); ++winit)
00956         {
00957             FPDEBUG((" %p:", (*winit).getCPtr()));
00958             
00959             std::vector<std::string>::iterator extit;
00960             
00961             extit = std::find((*winit)->_extensions.begin(),
00962                               (*winit)->_extensions.end(),
00963                               ignore.c_str()); 
00964                                                                      
00965             if(extit != (*winit)->_extensions.end())
00966             {
00967                 FPDEBUG((" removed"));
00968                 (*winit)->_extensions.erase(extit);
00969             }
00970             else
00971             {
00972                 FPDEBUG((" nonsupp"));            
00973             }
00974                         
00975             if(ind >= 0)
00976             {
00977                 if((*winit)->_availExtensions.size() > UInt32(ind))
00978                 {
00979                     (*winit)->_availExtensions[ind] = false;
00980                     FPDEBUG((" disabled"));            
00981                 }
00982                 if((*winit)->_commonExtensions.size() > UInt32(ind))
00983                 {
00984                     (*winit)->_commonExtensions[ind] = false;
00985                     FPDEBUG((" uncommoned"));            
00986                 }
00987             }
00988         }
00989         FPDEBUG(("\n"));    
00990     }
00991 
00992     std::sort(_ignoredExtensions.begin(), _ignoredExtensions.end());
00993     
00994     staticRelease();
00995 }
00996 
01000 UInt32 OSG::Window::registerFunction(const Char8 *s, Int32 ext)
01001 {
01002     if(s == NULL)
01003         return TypeTraits<UInt32>::getMax();
01004 
01005     FDEBUG(("Window::registerFunction: register '%s': ", s));
01006 
01007     staticAcquire();
01008     
01009     std::vector<std::string>::iterator i;
01010     
01011     i = std::find(_registeredFunctions.begin(), _registeredFunctions.end(), 
01012                   s);
01013     
01014     if(i < _registeredFunctions.end())
01015     {
01016         staticRelease();
01017         FPDEBUG(("reusing id %d\n", i - _registeredFunctions.begin()));
01018         return i - _registeredFunctions.begin();
01019     }
01020             
01021     UInt32 r=_registeredFunctions.size();
01022     _registeredFunctions.push_back(s);
01023     _registeredFunctionExts.push_back(ext);
01024 
01025     FPDEBUG(("new id %d\n", r));
01026     
01027     staticRelease();
01028     return r;
01029 }
01030 
01034 void OSG::Window::registerConstant(GLenum val)
01035 {
01036     staticAcquire();
01037    
01038     _registeredConstants.push_back(val);
01039     
01040     staticRelease();
01041 }
01042 
01043 #endif // remove the OpenGL object handling from user docs
01044 
01050 void OSG::Window::dumpExtensions(void)
01051 {   
01052     std::vector<std::string>::iterator it;
01053     std::cout << "GL Extensions: ";
01054     for ( it = _extensions.begin(); it != _extensions.end(); it++ )
01055     {
01056         std::cout << it->c_str() << ", ";
01057     }
01058     std::cout << std::endl;       
01059 }
01060 
01061 
01072 void OSG::Window::frameInit(void)
01073 {
01074     static bool ignoreEnvDone = false;
01075     
01076     if(!ignoreEnvDone)
01077     {
01078         ignoreEnvDone = true;
01079         char *p = getenv("OSG_IGNORE_EXTENSIONS");
01080         if(p)
01081             ignoreExtensions(p);
01082     }
01083     
01084     // get extensions and split them
01085     if(_extensions.empty())
01086     {
01087         FDEBUG(("Window %p: GL Extensions: %s\n", this, 
01088                 glGetString(GL_EXTENSIONS) ));
01089 
01090         std::string foo(reinterpret_cast<const char*>
01091                         (glGetString(GL_EXTENSIONS)));
01092 
01093         for(string_token_iterator it = string_token_iterator(foo, ",. ");
01094             it != string_token_iterator(); ++it)
01095         {          
01096             if(! std::binary_search(_ignoredExtensions.begin(),
01097                                     _ignoredExtensions.end(),
01098                                     *it))
01099             {
01100                 _extensions.push_back(*it);
01101             }
01102         }
01103         std::sort(_extensions.begin(), _extensions.end());
01104                  
01105         // if we don't have any extensions, add something anyway
01106         if(_extensions.empty())
01107             _availExtensions.resize(_registeredExtensions.size(), false);
01108     }
01109     
01110     // any new extension registered ? 
01111     if(_registeredExtensions.size() > _availExtensions.size())
01112     {
01113         staticAcquire();
01114         FDEBUG(("Window %p: exts: ", this));
01115 
01116         while(_registeredExtensions.size() > _availExtensions.size())
01117         {                          
01118             UInt32 s = _availExtensions.size();
01119 
01120             /* perform a binary search over the retrieved extension strings.
01121                Push back the result as an availability flag for the extension
01122                requested by the application */         
01123             bool supported = std::binary_search( 
01124                                 _extensions.begin(),
01125                                 _extensions.end(),
01126                                 _registeredExtensions[s]);
01127 
01128             _availExtensions.push_back(supported);
01129             FPDEBUG(("%s:", _registeredExtensions[s].c_str()));
01130             if(_commonExtensions.size() <= s)
01131             {
01132                 _commonExtensions.push_back(supported);
01133                 FPDEBUG(("ok "));
01134             }
01135             else if (!supported)
01136             {
01137                 _commonExtensions[s] = false;
01138                 FPDEBUG(("NF "));
01139             }
01140         }
01141         FPDEBUG(("\n"));
01142         staticRelease();
01143     }
01144     
01145     // any new functions registered ? 
01146     while(_registeredFunctions.size() > _extFunctions.size())
01147     {   
01148         const Char8 *s    = _registeredFunctions[_extFunctions.size()].c_str();
01149         Int32        ext  = _registeredFunctionExts[_extFunctions.size()];
01150         void        *func = NULL;
01151         
01152         if(ext == -1 || _availExtensions[ext] == true)
01153             func = (void*)getFunctionByName(s);
01154 
01155         _extFunctions.push_back(func);
01156     }
01157 
01158     // any new constants registered ? 
01159     while(_registeredConstants.size() > _numAvailConstants)
01160     {   
01161         for(std::vector<GLenum>::iterator it = _registeredConstants.begin() + 
01162                                                _numAvailConstants;
01163             it != _registeredConstants.end();
01164             ++it)
01165         {
01166             Vec2f val(unknownConstant, unknownConstant); 
01167             glGetFloatv(*it, static_cast<GLfloat*>(val.getValues()));
01168             _availConstants[*it] = val;
01169             FDEBUG(("Window(%p): Constant 0x%x value is %.3f %.3f\n", this,
01170                     *it, val[0], val[1]));
01171         }
01172         _numAvailConstants = _registeredConstants.size();
01173         glGetError(); // clear the error flag 
01174     }
01175 }
01176 
01185 void OSG::Window::frameExit(void)
01186 {   
01187     std::list<DestroyEntry>::iterator st,en;
01188 
01189     st = _glObjectDestroyList.begin();
01190     en = _glObjectDestroyList.end  ();
01191 
01192     while(st != en)
01193     {
01194         UInt32 i = st->first, n = st->second;
01195 
01196         GLObject *obj = _glObjects[ i ];
01197         
01198         if(obj == NULL)
01199         {
01200             FDEBUG(("Window::frameExit: objects %d (%d) already destroyed?!?\n",
01201                     i, n));
01202             ++st;
01203             continue;
01204         }
01205            
01206         UInt32 rc = obj->getRefCounter();
01207 
01208         // has the object been used in this context at all?
01209         if(getGlObjectLastReinitialize()[i] != 0) 
01210         {                  
01211             _glObjects[i]->getFunctor().call( this, packIdStatus(i, destroy));
01212 
01213             if((rc = _glObjects[ i ]->decRefCounter()) <= 0)
01214             {           
01215                 // call functor with the final-flag
01216                 _glObjects[i]->getFunctor().call( this, 
01217                                                 packIdStatus(i, finaldestroy));
01218             }
01219         }
01220 
01221         // if the GLObject is removed from each GL-Context, free GLObject-IDs.
01222         if(rc <= 0)
01223         {
01224             delete _glObjects[ i ];
01225             for ( UInt32 j = 0; j < n ; j++)
01226             {
01227                 _glObjects[i+j] = NULL;
01228             }   
01229         }
01230         ++st;
01231     }
01232 
01233     _glObjectDestroyList.clear();
01234     
01235     // Test for OpenGL errors. Just a little precaution to catch
01236     // stray errors. This is the only OpenGL error test in opt mode
01237  
01238     GLenum glerr;
01239 
01240     while((glerr = glGetError()) != GL_NO_ERROR)
01241     {
01242         FWARNING(("Window::frameExit: Caught stray OpenGL error %s (%#x).\n",
01243                 gluErrorString(glerr),
01244                 glerr));
01245 #ifndef OSG_DEBUG
01246         FWARNING(("Rerun with debug-libraries to get more accurate "
01247                   "information.\n"));
01248 #endif
01249     }
01250     
01251 }
01252 
01253 
01254 // Query for a GL extension function
01255 // Yes, this is system dependent, but the system dependent parts are 
01256 // #ifdefed anyway, and very similar code would show up in a number of places,
01257 // making maintaining it unnecessarily hard
01258 // Note: the order of the cases is important, do not change it!
01259 
01265 OSG::Window::GLExtensionFunction OSG::Window::getFunctionByName(
01266     const Char8 *s)
01267 {
01268     GLExtensionFunction retval = NULL;
01269 
01270 #if defined(darwin)
01271 
01272     if (NSIsSymbolNameDefined(s))
01273     {
01274         NSSymbol symbol = NSLookupAndBindSymbol(s);
01275         if (symbol != 0)
01276             retval = GLExtensionFunction(NSAddressOfSymbol(symbol));
01277     }
01278 
01279 #elif defined(WIN32)
01280 
01281     retval = (void(__cdecl*)(void)) wglGetProcAddress(s);
01282     
01283 #elif defined(__sgi)   || defined(darwin) || defined(__hpux) || \
01284       defined(__linux) || defined(__sun)
01285 
01286     /* Workaround for multiple nVidia/Linux installation bugs, based on code by */
01287     /* Manfred Weiler (Patch 783637) */
01288     
01289     static void (*(*__GetProcAddress)(const GLubyte *))(void) = NULL; 
01290 
01291     static void *libHandle = NULL; 
01292 
01293     if(libHandle == NULL) 
01294     { 
01295         libHandle = dlopen(_glLibraryName, RTLD_NOW | RTLD_LOCAL); 
01296 
01297         if(!libHandle) 
01298         { 
01299             FWARNING(("Error in dlopen: %s\n",dlerror())); 
01300             abort(); 
01301         } 
01302         else
01303         {
01304             FDEBUG(("Opened lib %s for GL extension handling.\n", 
01305                     (_glLibraryName==NULL)?"(executable)":_glLibraryName));
01306         }
01307     } 
01308 
01309     if(__GetProcAddress == NULL) 
01310     { 
01311         __GetProcAddress = (void (*(*)(const GLubyte*))()) dlsym(libHandle, "glXGetProcAddressARB"); 
01312 
01313         if(__GetProcAddress == NULL) 
01314         { 
01315             __GetProcAddress = (void (*(*)(const GLubyte*))()) dlsym(libHandle, "glXGetProcAddress"); 
01316             
01317             if(__GetProcAddress == NULL) 
01318             {
01319                 FWARNING(("Neither glXGetProcAddress nor "
01320                         "glXGetProcAddressARB found! Disabling all "
01321                         " extensions for Window %p!")); 
01322                 _availExtensions.clear();
01323                 _availExtensions.resize(_registeredExtensions.size(), false);
01324             } 
01325             else
01326             {
01327                 FDEBUG(("Using glXGetProcAddress for GL extension handling.\n"));
01328             }
01329         } 
01330         else
01331         {
01332             FDEBUG(("Using glXGetProcAddressARB for GL extension handling.\n"));
01333         }
01334     } 
01335 
01336     if(__GetProcAddress != NULL) 
01337     { 
01338         retval = reinterpret_cast<GLExtensionFunction>(__GetProcAddress((const GLubyte*)s)); 
01339     } 
01340     else 
01341     { 
01342         retval = (GLExtensionFunction)(dlsym(libHandle, s)); 
01343     } 
01344 
01345 #else
01346 
01347     FWARNING(("Window::getFunctionByName: couldn't find implementation!\n"
01348               "Please contact the developers at info@opensg.org.\n"));
01349     retval = NULL;
01350 
01351 #endif
01352 
01353     if(retval == NULL)
01354     {
01355         FWARNING(("Window::getFunctionByName: Couldn't get function '%s' for "
01356                  "Window %p.\n", s, this));
01357     }
01358     else
01359     {
01360         FDEBUG(("Window::getFunctionByName: got function '%s' for "
01361                  "Window %p at %p.\n", s, this, retval));
01362     }
01363 
01364     return retval;
01365 }
01366 
01367 
01371 const Vec2f& OSG::Window::getConstantValuev(GLenum id)
01372 {
01373     static Vec2f inf(Inf, Inf);
01374 
01375     ConstHash::iterator it = _availConstants.find(id);
01376 
01377     if(it != _availConstants.end())
01378         return _availConstants[id];
01379 
01380     return inf;
01381 }
01382 
01383 
01390 void OSG::Window::setupGL( void )
01391 {   
01392     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
01393     glPixelStorei( GL_PACK_ALIGNMENT, 1 );
01394     
01395     glDepthFunc( GL_LEQUAL );
01396     glEnable( GL_DEPTH_TEST );
01397     
01398     glEnable( GL_NORMALIZE );
01399     
01400     // switch off default light
01401     GLfloat nul[4]={0,0,0,0};
01402     glLightfv(GL_LIGHT0, GL_DIFFUSE, nul);
01403     glLightfv(GL_LIGHT0, GL_SPECULAR, nul);
01404     
01405     frameInit();    // call it to setup extensions
01406 }
01407 
01408 /*-------------------------- your_category---------------------------------*/
01409 
01416 void OSG::Window::draw(DrawAction * action)
01417 {
01418     activate();
01419     frameInit();    // query recently registered GL extensions
01420     
01421     resizeGL();
01422 
01423     drawAllViewports(action);
01424 
01425     swap();
01426     frameExit();    // after frame cleanup: delete GL objects, if needed
01427 }
01428 
01434 void OSG::Window::drawAllViewports(DrawAction * action)
01435 {
01436     MFViewportPtr::iterator       portIt  = _mfPort.begin();
01437     MFViewportPtr::const_iterator portEnd = _mfPort.end();
01438 
01439     if(action != NULL)
01440     {
01441         action->setWindow(this);
01442         
01443         while(portIt != portEnd)
01444         {
01445             (*portIt)->draw(action);
01446 
01447             ++portIt;
01448         }
01449     }
01450     else
01451     {
01452         SWARNING << "Window::drawAllViewports: no action!" << std::endl;
01453     }
01454 }
01455     
01462 void OSG::Window::render(RenderActionBase *action)
01463 {
01464     activate();
01465     frameInit();    // query recently registered GL extensions
01466     
01467 //  resizeGL();
01468 
01469     renderAllViewports(action);
01470 
01471     swap();
01472     frameExit();    // after frame cleanup: delete GL objects, if needed
01473 }
01474     
01475 
01481 void OSG::Window::renderAllViewports(RenderActionBase *action)
01482 {
01483     MFViewportPtr::iterator       portIt  = _mfPort.begin();
01484     MFViewportPtr::const_iterator portEnd = _mfPort.end();
01485 
01486     if(action != NULL)
01487     {
01488         action->setWindow(this);
01489         
01490         while(portIt != portEnd)
01491         {
01492             (*portIt)->render(action);
01493             ++portIt;
01494         }
01495     }
01496     else
01497     {
01498         SWARNING << "Window::renderAllViewports: no action!" << std::endl;
01499     }
01500 }
01501     
01502 
01508 void OSG::Window::resize( int width, int height )
01509 {
01510     WindowPtr win(*this);
01511     beginEditCP(win, WidthFieldMask|HeightFieldMask|ResizePendingFieldMask);
01512     setWidth( width );
01513     setHeight( height );
01514     setResizePending( true );
01515     endEditCP  (win, WidthFieldMask|HeightFieldMask|ResizePendingFieldMask);
01516 }
01517     
01518 
01524 void OSG::Window::resizeGL( void )
01525 {
01526     if ( isResizePending () )
01527     {
01528         glViewport( 0, 0, getWidth(), getHeight() );
01529         WindowPtr</