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 <cstdlib>
00044 #include <cstdio>
00045
00046 #include "OSGConfig.h"
00047
00048 #include "OSGGLU.h"
00049
00050 #if !defined(WIN32) && !defined(__APPLE__) && !defined(OSG_EMBEDDED)
00051 #include <GL/glx.h>
00052 #endif
00053 
00054 #if defined(OSG_EMBEDDED) && defined(WIN32)
00055 #include <gles/egl.h>
00056 #endif
00057 
00058 #if defined(__sgi) || defined(__APPLE__) || defined(__linux)
00059 #include <dlfcn.h>
00060 #endif
00061 
00062 #if defined(__APPLE__)
00063 #include <mach-o/dyld.h>
00064 #endif
00065 
00066 #if defined(__sun)
00067 #include <dlfcn.h>
00068 #include <link.h>
00069 #endif
00070 
00071 #include "OSGBaseFunctions.h"
00072
00073 #include "OSGViewport.h"
00074
00075 #include "OSGBackground.h"
00076 #include "OSGCamera.h"
00077 #include "OSGWindow.h"
00078
00079 #include "OSGRenderActionBase.h"
00080
00081 #include "OSGStageValidator.h"
00082
00083 #ifdef OSG_NEW_SHADER
00084 #include "OSGShaderCache.h"
00085 #endif
00086 
00087 //#define OSG_WIN_QUEUE_ALL 1
00088
00089 OSG_BEGIN_NAMESPACE
00090
00091 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
00092 #pragma warning (disable)
00093 #endif
00094 
00095 // If true, then try just using glXGetProcAddress() directly.
00096 #define TRY_USING_GLXGETPROC_DIRECTLY 1
00097 
00098 // Documentation for this class is emited in the
00099 // OSGWindowBase.cpp file.
00100 // To modify it, please change the .fcd file (OSGWindow.fcd) and
00101 // regenerate the base file.
00187 // Window-sytem specific virtual functions
00188
00217 /***************************************************************************\
00218  *                           Class variables                               *
00219 \***************************************************************************/
00220
00225 Window::WindowStore OSG::Window::_allWindows;
00226 Int32               OSG::Window::_currentWindowId = 0;
00227
00228 // GLobject handling
00229
00230 #ifndef OSG_EMBEDDED
00231 
00236 LockRefPtr                            OSG::Window::_GLObjectLock = NULL;
00237
00242 LockRefPtr                            OSG::Window::_staticWindowLock = NULL;
00243 #endif
00244 
00249 std::vector<OSG::Window::GLObject *>  OSG::Window::_glObjects;
00250
00251 // GL extension handling
00252
00253 // The name of the dynamic library for OpenGL extension functions
00254 // By default it's NULL, which tries to find them in the current 
00255 // executable
00256 const Char8 *OSG::Window::_glLibraryName = NULL;
00257
00258 std::vector<std::string            >  OSG::Window::_registeredExtensions;
00259 std::vector<std::string            >  OSG::Window::_ignoredExtensions;
00260 std::vector<bool                   >  OSG::Window::_commonExtensions;
00261 std::vector<std::string            >  OSG::Window::_registeredFunctions;
00262 std::vector<Int32                  >  OSG::Window::_registeredFunctionExts;
00263 std::vector<UInt32                 >  OSG::Window::_registeredFunctionVersions;
00264
00265 // GL constant handling
00266
00267 std::vector<GLenum                 >  OSG::Window::_registeredConstants;
00268
00269
00270 // Just a constant to indicate that the GL constant is unknown
00271
00272 const Real32 OSG::Window::unknownConstant =  TypeTraits<Real32>::getMax();
00273
00274 /***************************************************************************\
00275  *                           Class methods                                 *
00276 \***************************************************************************/
00277
00278 /*-------------------------------------------------------------------------*\
00279  -  private                                                                -
00280 \*-------------------------------------------------------------------------*/
00281
00285 void OSG::Window::initMethod(InitPhase ePhase)
00286 {
00287     Inherited::initMethod(ePhase);
00288 }
00289
00290 bool OSG::Window::cleanup(void)
00291 {
00292 #ifndef OSG_EMBEDDED
00293     _staticWindowLock = NULL;
00294     _GLObjectLock     = NULL;
00295 #endif
00296 
00297     for(UInt32 i = 0; i < _glObjects.size(); ++i)
00298     {
00299         delete _glObjects[i];
00300     }
00301
00302     return true;
00303 }
00304
00305 /***************************************************************************\
00306  *                           Instance methods                              *
00307 \***************************************************************************/
00308
00309 /*-------------------------------------------------------------------------*\
00310  -  protected                                                              -
00311 \*-------------------------------------------------------------------------*/
00312
00313
00314 /*------------- constructors & destructors --------------------------------*/
00315
00319 OSG::Window::Window(void) :
00320      Inherited          (    ),
00321     _glObjectDestroyList(    ),
00322     _lastValidate       (    ),
00323     _ids                (    ),
00324     _glVersion          (    ),
00325     _extensions         (    ),
00326     _availExtensions    (    ),
00327     _extFunctions       (    ),
00328     _availConstants     (    ),
00329     _numAvailConstants  (    ),
00330     _windowId           (  -1),
00331     _pStageValidator    (NULL),
00332     _pShaderCache       (NULL),
00333
00334     _pWaitTask          (NULL),
00335     _pSwapTask          (NULL),
00336     _pFrameInitTask     (NULL),
00337     _pFrameExitTask     (NULL),
00338     _pActivateTask      (NULL),
00339     _oEnv               (    )
00340 {
00341     // only called for prototypes, no need to init them
00342     _oEnv.setWindow(this);
00343 }
00344
00348 OSG::Window::Window(const Window &source) :
00349     Inherited           (source                        ),
00350     _glObjectDestroyList(source._glObjectDestroyList   ),
00351     _lastValidate       (source._lastValidate.size(), 0),
00352     _ids                (source._ids.size(),          0),
00353     _extensions         (                              ),
00354     _availExtensions    (                              ),
00355     _extFunctions       (                              ),
00356     _availConstants     (                              ),
00357     _numAvailConstants  (                             0),
00358     _windowId           (                            -1),
00359     _pStageValidator    (NULL                          ),
00360     _pShaderCache       (NULL                          ),
00361     _pWaitTask          (NULL                          ),
00362     _pSwapTask          (NULL                          ),
00363     _pFrameInitTask     (NULL                          ),
00364     _pFrameExitTask     (NULL                          ),
00365     _pActivateTask      (NULL                          ),
00366     _oEnv               (                              )
00367 {
00368     _oEnv.setWindow(this);
00369 }
00370
00374 OSG::Window::~Window(void)
00375 {
00376     // delete the ports and the context
00377 }
00378
00379
00380 /*-------------------------------------------------------------------------*\
00381  -  private                                                                -
00382 \*-------------------------------------------------------------------------*/
00383
00387 void OSG::Window::onCreate(const Window *source)
00388 {
00389     Inherited::onCreate(source);
00390
00391     // Don't add the prototype instances to the list
00392     if(GlobalSystemState != Running)
00393         return;
00394
00395     if(source != NULL)
00396     {
00397         // mark all GL objects as not yet initialized
00398         doResetGLObjectStatus(1, _glObjects.size() - 1);
00399     }
00400
00401     _allWindows.push_back(this);
00402
00403     _windowId = _currentWindowId++;
00404
00405     _pContextThread = WindowDrawThread::get(NULL, false);
00406 }
00407
00408 void OSG::Window::onCreateAspect(const Window *createAspect,
00409                                  const Window *source)
00410 {
00411     Inherited::onCreateAspect(createAspect, source);
00412
00413     // Don't add the prototype instances to the list
00414     if(GlobalSystemState != Running)
00415         return;
00416
00417     if(createAspect != NULL)
00418     {
00419         _windowId = createAspect->_windowId;
00420     }
00421
00422     _pStageValidator = new StageValidator;
00423 #ifdef OSG_NEW_SHADER
00424     _pShaderCache    = new ShaderCache;
00425 #endif
00426 }
00427
00431 void OSG::Window::onDestroy(UInt32 uiContainerId)
00432 {
00433     // decrement GLObjects reference counter.
00434     for(UInt32 i = 1; i < _glObjects.size(); ++i)
00435     {
00436         GLObject *obj = _glObjects[i];
00437
00438         if(obj == NULL)
00439         {
00440             FDEBUG(("Window::onDestroy: object %u already destroyed!\n", i));
00441             continue;
00442         }
00443
00444         // has the object been used in this context at all?
00445         if(i < getMFGlObjectLastReinitialize()->size() &&
00446            getGlObjectLastReinitialize(i) != 0)
00447         {
00448             obj->decRefCounter();
00449             // we can't call here the destroy callbacks because the
00450             // gl context is not guaranteed to be current, but destroying
00451             // the context should delete all gl objects.
00452         }
00453     }
00454
00455     WindowStore::iterator winIt;
00456
00457     winIt = std::find(_allWindows.begin(),
00458                       _allWindows.end  (),
00459                       this);
00460
00461     // prototype window are not added to the list, so they might not be found.
00462
00463     if(winIt != _allWindows.end())
00464         _allWindows.erase(winIt);
00465
00466     Inherited::onDestroy(uiContainerId);
00467 }
00468
00469 void OSG::Window::onDestroyAspect(UInt32  uiContainerId,
00470                                   UInt32  uiAspect     )
00471 {
00472     delete _pStageValidator;
00473 #ifdef OSG_NEW_SHADER
00474     delete _pShaderCache;
00475 #endif
00476 
00477     _pStageValidator = NULL;
00478     _pShaderCache    = NULL;
00479
00480     _pWaitTask       = NULL;
00481     _pSwapTask       = NULL;
00482     _pFrameInitTask  = NULL;
00483     _pFrameExitTask  = NULL;
00484     _pActivateTask   = NULL;
00485
00486     if(_pAspectStore->getRefCount() == 1 && _pContextThread != NULL)
00487     {
00488         fprintf(stderr, "Terminate context thread %p\n", this);
00489
00490         _pContextThread->queueTask(
00491             new WindowDrawTask(WindowDrawTask::EndThread));
00492
00493         Thread::join(_pContextThread);
00494     }
00495
00496     _pContextThread = NULL;
00497
00498     Inherited::onDestroyAspect(uiContainerId, uiAspect);
00499 }
00500
00501 void OSG::Window::staticAcquire(void)
00502 {
00503     // Is the ThreadManager initialized yet?
00504     if(GlobalSystemState != Running)
00505         return;
00506
00507 #ifndef OSG_EMBEDDED
00508     if(_staticWindowLock == NULL)
00509     {
00510         _staticWindowLock =
00511             ThreadManager::the()->getLock("OSG::Window::_staticWindowLock",
00512                                           false);
00513
00514         addPostFactoryExitFunction(&Window::cleanup);
00515     }
00516     _staticWindowLock->acquire();
00517 #endif
00518 }
00519
00520 void OSG::Window::staticRelease(void)
00521 {
00522     // Is the ThreadManager initialized yet?
00523     if(GlobalSystemState != Running)
00524         return;
00525
00526 #ifndef OSG_EMBEDDED
00527     _staticWindowLock->release();
00528 #endif
00529 }
00530
00531 /*-------------------------------------------------------------------------*\
00532  -  public                                                                 -
00533 \*-------------------------------------------------------------------------*/
00534
00538 void OSG::Window::changed(ConstFieldMaskArg whichField,
00539                           UInt32            origin,
00540                           BitVector         details)
00541 {
00542     Inherited::changed(whichField, origin, details);
00543 }
00544
00545 /*------------------------------ access -----------------------------------*/
00546
00547 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_EXT)
00548 
00549 /*------------------------ GL object handling -----------------------------*/
00550
00559 UInt32 OSG::Window::registerGLObject(GLObjectFunctor        functor,
00560                                      GLObjectDestroyFunctor destroy,
00561                                      UInt32                 num)
00562 {
00563     UInt32    osgId, i;
00564     GLObject *pGLObject;
00565
00566     staticAcquire();
00567
00568     // reserve index 0, illegal for most OpenGL functions
00569     if(_glObjects.empty())
00570         _glObjects.push_back(NULL);
00571
00572     osgId     = _glObjects.size();
00573     pGLObject = new GLObject(functor, destroy);
00574
00575     // does the requested block fit into the capacity?
00576
00577     if(_glObjects.capacity() >= osgId + num)
00578     {
00579         _glObjects.insert(_glObjects.end(), num, pGLObject );
00580
00581         resetGLObjectStatus(osgId, num);
00582
00583         staticRelease();
00584
00585         return osgId;
00586     }
00587
00588     // doesn't fit, try to find a block in the middle
00589
00590     UInt32 cnt = 0;
00591
00592     // start searching at 1, id 0 is reserved for GL
00593     for(i = 1; i < _glObjects.size(); ++i)
00594     {
00595         if(_glObjects[i] == NULL)
00596         {
00597             if(cnt == 0)
00598             {
00599                 osgId = i;
00600             }
00601
00602             ++cnt;
00603
00604             if(cnt == num)
00605             {
00606                 // block of unused entries found ...
00607
00608                 while(i >= osgId)
00609                 {
00610                     _glObjects[i] = pGLObject;
00611                     i = i - 1;
00612                 }
00613
00614                 resetGLObjectStatus(osgId, num);
00615
00616                 staticRelease();
00617
00618                 return osgId;
00619             }
00620         }
00621         else
00622         {
00623             cnt   = 0;
00624             osgId = 0;
00625         }
00626     }
00627
00628     // no block found, add at the end
00629
00630     if(osgId > 0) // ok the last entries in the vector were empty
00631     {
00632         // fill the empty slots at the end 
00633         i = osgId + cnt - 1;
00634
00635         while(i >= osgId)
00636         {
00637             _glObjects[i] = pGLObject;
00638
00639             i = i - 1;
00640         }
00641     }
00642     else
00643     {
00644         // we found no empty entries so the new id is the size of the vector.
00645         osgId = _glObjects.size();
00646     }
00647
00648     // expand the vector for the rest 
00649     for(i = 1; i <= num - cnt; i++)
00650     {
00651         _glObjects.push_back(pGLObject);
00652     }
00653
00654     resetGLObjectStatus(osgId, num);
00655
00656     staticRelease();
00657
00658     return osgId;
00659 }
00660
00667 UInt32 OSG::Window::validateGLObject(UInt32   osgId,
00668                                      DrawEnv *pEnv,
00669                                      UInt32   uiOptions)
00670 {
00671     UInt32 returnValue = 0;
00672
00673     if ( osgId == 0 )
00674     {
00675         SWARNING << "Window::validateGLObject: id is 0!" << std::endl;
00676         return returnValue;
00677     }
00678
00679     GLObject *obj = _glObjects[osgId];
00680
00681     if(obj == NULL)
00682     {
00683         SWARNING << "Window::validateGLObject: obj with id " << osgId
00684                  <<" is NULL!" << std::endl;
00685         return returnValue;
00686     }
00687
00688     if(osgId >= _lastValidate.size()) // can happen if multi-threading
00689     {
00690 /*
00691         _lastValidate.insert(_lastValidate.end(), 
00692                              osgId + 1 - _lastValidate.size(),
00693                              0);
00694  */
00695         _lastValidate.resize(osgId + 1, 0);
00696     }
00697
00698     if(osgId >= _mfGlObjectLastReinitialize.size())
00699     {
00700         editMField( GlObjectLastReinitializeFieldId,
00701                    _mfGlObjectLastReinitialize     );
00702
00703         _mfGlObjectLastReinitialize.resize(osgId + 1, 0);
00704     }
00705
00706     FDEBUG(("Window 0x%p (event %d,ri:%d,rf:%d): "
00707             "Validating object %d: last reinit:%d, last validate:"
00708             "%d last refresh: %d => %s\n",
00709             this, getGlObjectEventCounter(),
00710             _mfGlObjectLastReinitialize.size(),
00711             _mfGlObjectLastRefresh.size(),
00712             osgId,
00713             (_mfGlObjectLastReinitialize.size() > osgId)?
00714                 _mfGlObjectLastReinitialize[osgId]:0xffffffff,
00715             _lastValidate[osgId],
00716             (_mfGlObjectLastRefresh.size() > osgId)?
00717                 _mfGlObjectLastRefresh[osgId]:0xffffffff,
00718             (_mfGlObjectLastReinitialize[osgId] == 0)?"init":
00719             ((_mfGlObjectLastReinitialize[osgId] > _lastValidate[osgId])?"reinit":
00720             ((_mfGlObjectLastRefresh[osgId] > _lastValidate[osgId])?"refresh":
00721             "up-to-date"))
00722           ));
00723
00724     if(_mfGlObjectLastReinitialize[osgId] == 0)
00725     {
00726         editMField( GlObjectLastReinitializeFieldId,
00727                    _mfGlObjectLastReinitialize     );
00728
00729         obj->incRefCounter();
00730         returnValue = obj->getFunctor()(pEnv, osgId, initialize, uiOptions);
00731         _mfGlObjectLastReinitialize[osgId] = 1;
00732         _lastValidate[osgId] = getGlObjectEventCounter();
00733     }
00734     else if(_mfGlObjectLastReinitialize[osgId] > _lastValidate[osgId])
00735     {
00736         returnValue = obj->getFunctor()(pEnv, osgId, reinitialize, uiOptions);
00737         _lastValidate[osgId] = getGlObjectEventCounter();
00738     }
00739     else if(_mfGlObjectLastRefresh[osgId] > _lastValidate[osgId])
00740     {
00741         returnValue = obj->getFunctor()(pEnv, osgId, needrefresh, uiOptions);
00742         _lastValidate[osgId] = getGlObjectEventCounter();
00743     }
00744
00745     return returnValue;
00746 }
00747
00754 void OSG::Window::validateAllGLObjects(void)
00755 {
00756     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
00757     {
00758         activate();
00759         doFrameInit();
00760
00761         for (UInt32 i = 1; i < _glObjects.size(); ++i)
00762         {
00763             if(_glObjects[i] != NULL)
00764                 validateGLObject(i, &_oEnv);
00765         }
00766
00767         doFrameExit();
00768         deactivate();
00769     }
00770     else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
00771                                                          ParallelPartitionDraw)
00772     {
00773         fprintf(stderr, "Window::validateAllGLObjects::pardraw NI\n");
00774     }
00775     else
00776     {
00777         fprintf(stderr, "Unknow partition draw mode\n");
00778     }
00779 }
00780
00788 void OSG::Window::refreshGLObject(UInt32 osgId)
00789 {
00790     if(osgId == 0)
00791     {
00792         SWARNING << "Window::refreshGLObject: id is 0!" << std::endl;
00793         return;
00794     }
00795
00796     staticAcquire();
00797
00798     doRefreshGLObject(osgId);
00799
00800     staticRelease();
00801 }
00802
00808 void OSG::Window::refreshAllGLObjects(void)
00809 {
00810     staticAcquire();
00811
00812     for(UInt32 i = 1; i < _glObjects.size(); ++i)
00813         doRefreshGLObject(i);
00814
00815     staticRelease();
00816 }
00817
00822 void Window::doRefreshGLObject(UInt32 osgId)
00823 {
00824     WindowStore::const_iterator winIt  = _allWindows.begin();
00825     WindowStore::const_iterator winEnd = _allWindows.end  ();
00826
00827     for(; winIt != winEnd; ++winIt)
00828     {
00829         Window *pWin = *winIt;
00830
00831         if(pWin == NULL)
00832             continue;
00833
00834         pWin->editMField(GlObjectLastRefreshFieldMask,
00835                          pWin->_mfGlObjectLastRefresh);
00836
00837         UInt32    lastinv = pWin->getGlObjectEventCounter() + 1;
00838
00839         MFUInt32 &field   = pWin->_mfGlObjectLastRefresh;
00840
00841         if(field.size() <= osgId)
00842             field.resize(osgId + 1, 0);
00843
00844         field[osgId] = lastinv;
00845
00846         pWin->setGlObjectEventCounter(lastinv);
00847     }
00848 }
00849
00850
00859 void OSG::Window::reinitializeGLObject(UInt32 osgId)
00860 {
00861     if ( osgId == 0 )
00862     {
00863         SWARNING << "Window::reinitializeGLObject: id is 0!" << std::endl;
00864         return;
00865     }
00866
00867     staticAcquire();
00868
00869     doReinitializeGLObject(osgId);
00870
00871     staticRelease();
00872 }
00873
00879 void OSG::Window::reinitializeAllGLObjects(void)
00880 {
00881     staticAcquire();
00882
00883     for(UInt32 i = 1; i < _glObjects.size(); ++i)
00884         doReinitializeGLObject(i);
00885
00886     staticRelease();
00887 }
00888
00894 void Window::doReinitializeGLObject(UInt32 osgId)
00895 {
00896     WindowStore::const_iterator winIt  = _allWindows.begin();
00897     WindowStore::const_iterator winEnd = _allWindows.end  ();
00898
00899     for(; winIt != winEnd; ++winIt)
00900     {
00901         Window *pWin = *winIt;
00902
00903         if(pWin == NULL)
00904             continue;
00905
00906         pWin->editMField(GlObjectLastReinitializeFieldMask,
00907                          pWin->_mfGlObjectLastReinitialize);
00908
00909         UInt32    lastinv = pWin->getGlObjectEventCounter() + 1;
00910
00911         MFUInt32 &field   = pWin->_mfGlObjectLastReinitialize;
00912
00913         if(field.size() <= osgId)
00914             field.resize(osgId + 1, 0);
00915
00916         // is it already validated?
00917         if(field[osgId] == 0)
00918             continue;
00919
00920         field[osgId] = lastinv;
00921
00922         pWin->setGlObjectEventCounter(lastinv);
00923     }
00924 }
00925
00926
00934 void Window::resetGLObjectStatus(UInt32 osgId, UInt32 num)
00935 {
00936     if(osgId == 0)
00937     {
00938         SWARNING << "Window::resetGLObject: osgId is 0." << std::endl;
00939         return;
00940     }
00941
00942     WindowStore::const_iterator winIt  = _allWindows.begin();
00943     WindowStore::const_iterator winEnd = _allWindows.end  ();
00944
00945     for(; winIt != winEnd; ++winIt)
00946     {
00947         Window *pWin = *winIt;
00948
00949         if(pWin == NULL)
00950             continue;
00951
00952         pWin->doResetGLObjectStatus(osgId, num);
00953     }
00954 }
00955
00962 void Window::doResetGLObjectStatus(UInt32 osgId, UInt32 num)
00963 {
00964     editMField(GlObjectLastReinitializeFieldMask, _mfGlObjectLastReinitialize);
00965     editMField(GlObjectLastRefreshFieldMask,      _mfGlObjectLastRefresh     );
00966
00967     if(_mfGlObjectLastReinitialize.size() < osgId + num)
00968         _mfGlObjectLastReinitialize.resize(osgId + num, 0);
00969
00970     if(_mfGlObjectLastRefresh.size() < osgId + num)
00971         _mfGlObjectLastRefresh.resize(osgId + num, 0);
00972
00973     if(_lastValidate.size() < osgId + num)
00974         _lastValidate.resize(osgId + num, 0);
00975
00976     for(UInt32 i = osgId; i < osgId + num; ++i)
00977     {
00978         _mfGlObjectLastReinitialize[i] = 0;
00979         _mfGlObjectLastRefresh     [i] = 0;
00980         _lastValidate              [i] = 0;
00981     }
00982 }
00983
00991 void OSG::Window::destroyGLObject(UInt32 osgId, UInt32 num)
00992 {
00993 #ifdef OSG_DEBUG
00994     if(osgId >= _glObjects.size() || _glObjects[osgId] == NULL)
00995     {
00996         FWARNING(("Window::destroyGLObject: object %d is NULL!\n", osgId));
00997         return;
00998     }
00999 #endif
01000 
01001     // Has this object ever been used?
01002     if(_glObjects[osgId] && _glObjects[osgId]->getRefCounter() == 0)
01003     {
01004         if(_glObjects[osgId])
01005             delete _glObjects[osgId];
01006
01007         for(UInt32 j = 0; j < num ; j++)
01008         {
01009             _glObjects[osgId + j] = NULL;
01010         }
01011
01012         return;
01013     }
01014
01015     WindowStore::const_iterator winIt  = _allWindows.begin();
01016     WindowStore::const_iterator winEnd = _allWindows.end  ();
01017
01018     for(; winIt != winEnd; ++winIt)
01019     {
01020         Window *pWin = *winIt;
01021
01022         if(pWin == NULL)
01023             continue;
01024
01025         if(osgId + num > pWin->_mfGlObjectLastReinitialize.size())
01026         {
01027             // this can happen if a GLObject is temporarily created in one
01028             // aspect, used there and then discarded without ever being
01029             // synced to other aspects.
01030
01031 #ifdef OSG_DEBUG
01032             FWARNING(("Window::destroyGLObject: id %d + num %d exceed "
01033                       "registered objects size %d!\n", osgId, num,
01034                       pWin->_mfGlObjectLastReinitialize.size()));
01035 #endif
01036             continue;
01037         }
01038
01039         // has the object been used in this context at all?
01040         if(pWin->getGlObjectLastReinitialize(osgId) != 0)
01041             pWin->_glObjectDestroyList.push_back(DestroyEntry(osgId, num));
01042     }
01043 }
01044
01045
01046 /*----------------------- GL extension handling ---------------------------*/
01047
01048
01054 UInt32 OSG::Window::registerExtension(const Char8 *s)
01055 {
01056     FDEBUG(("Window::registerExtension: register '%s': \n", s));
01057
01058     staticAcquire();
01059
01060     if(s == NULL)
01061     {
01062         staticRelease();
01063         return TypeTraits<UInt32>::getMax();
01064     }
01065
01066     // Check if it has already been registered and if it has then return the
01067     // index we already used.
01068     Int32 r = getExtensionId(s);
01069
01070     if(-1 != r)
01071     {
01072         FPDEBUG(("reusing id %d\n", r));
01073     }
01074     else
01075     {
01076         r = _registeredExtensions.size();
01077
01078         _registeredExtensions.push_back(s);
01079
01080         FPDEBUG(("new id %d\n", r));
01081     }
01082
01083     staticRelease();
01084     return r;
01085 }
01086
01093 bool OSG::Window::hasExtension(const Char8 *s)
01094 {
01095     if(std::find(_ignoredExtensions.begin(),
01096                  _ignoredExtensions.end(),
01097                  s)                         != _ignoredExtensions.end())
01098     {
01099         return false;
01100     }
01101
01102     if(std::find(_extensions.begin(),
01103                  _extensions.end(),
01104                  s)                         != _extensions.end())
01105     {
01106         return true;
01107     }
01108
01109     return false;
01110 }
01111
01118 void OSG::Window::ignoreExtensions(const Char8 *s)
01119 {
01120     FDEBUG(("Window:: Ignoring extensions '%s'\n", s));
01121
01122     staticAcquire();
01123
01124     std::back_insert_iterator< std::vector<std::string> >
01125             extension_back_inserter(_ignoredExtensions);
01126
01127     std::string toex(s);
01128
01129     for(string_token_iterator ignit = string_token_iterator(toex, ",. ");
01130         ignit != string_token_iterator(); ++ignit)
01131     {
01132         std::string ignore = *ignit;
01133
01134         FDEBUG(("Ignoring '%s':", ignore.c_str()));
01135
01136         if(std::find(_ignoredExtensions.begin(),
01137                      _ignoredExtensions.end(),
01138                      ignore.c_str())            != _ignoredExtensions.end())
01139         {
01140             FPDEBUG((" already ignored.\n"));
01141             continue;
01142         }
01143
01144         _ignoredExtensions.push_back(ignore);
01145
01146         std::vector<std::string>::iterator regit;
01147
01148         // if extension is registered, disable it on all existing Windows
01149
01150         regit = std::find(_registeredExtensions.begin(),
01151                           _registeredExtensions.end(),
01152                           ignore.c_str());
01153
01154         Int32 ind = -1;
01155
01156         if(regit != _registeredExtensions.end())
01157         {
01158             ind = regit - _registeredExtensions.begin();
01159             FPDEBUG(("(reg as %d)", ind));
01160         }
01161
01162         // Walk all existing windows and remove the ignored extension 
01163         // from the _extensions vector. Disable it if it was a registered one.
01164
01165         WindowStore::const_iterator winIt  = _allWindows.begin();
01166         WindowStore::const_iterator winEnd = _allWindows.end  ();
01167
01168         for(; winIt != winEnd; ++winIt)
01169         {
01170             FPDEBUG((" %p:", winIt->get()));
01171
01172             std::vector<std::string>::iterator extit;
01173
01174             extit = std::find((*winIt)->_extensions.begin(),
01175                               (*winIt)->_extensions.end(),
01176                               ignore.c_str());
01177
01178             if(extit != (*winIt)->_extensions.end())
01179             {
01180                 FPDEBUG((" removed"));
01181                 (*winIt)->_extensions.erase(extit);
01182             }
01183             else
01184             {
01185                 FPDEBUG((" nonsupp"));
01186             }
01187
01188             if(ind >= 0)
01189             {
01190                 if((*winIt)->_availExtensions.size() > UInt32(ind))
01191                 {
01192                     (*winIt)->_availExtensions[ind] = false;
01193                     FPDEBUG((" disabled"));
01194                 }
01195                 if((*winIt)->_commonExtensions.size() > UInt32(ind))
01196                 {
01197                     (*winIt)->_commonExtensions[ind] = false;
01198                     FPDEBUG((" uncommoned"));
01199                 }
01200             }
01201         }
01202         FPDEBUG(("\n"));
01203     }
01204
01205     std::sort(_ignoredExtensions.begin(), _ignoredExtensions.end());
01206
01207     staticRelease();
01208 }
01209
01214 UInt32 OSG::Window::registerFunction(const Char8 *s,
01215                                            Int32  ext,
01216                                            UInt32 version)
01217 {
01218     if(s == NULL)
01219         return TypeTraits<UInt32>::getMax();
01220
01221     FDEBUG(("Window::registerFunction: register '%s': \n", s));
01222
01223     staticAcquire();
01224
01225     std::vector<std::string>::iterator i;
01226
01227     i = std::find(_registeredFunctions.begin(), _registeredFunctions.end(),
01228                   s);
01229
01230     if(i < _registeredFunctions.end())
01231     {
01232         staticRelease();
01233         FDEBUG(("reusing id %td\n", i - _registeredFunctions.begin()));
01234         return i - _registeredFunctions.begin();
01235     }
01236
01237     UInt32 r=_registeredFunctions.size();
01238
01239     _registeredFunctions       .push_back(s);
01240     _registeredFunctionExts    .push_back(ext);
01241     _registeredFunctionVersions.push_back(version);
01242
01243     FPDEBUG(("new id %d\n", r));
01244
01245     staticRelease();
01246     return r;
01247 }
01248
01253 void OSG::Window::registerConstant(GLenum val)
01254 {
01255     staticAcquire();
01256
01257     if(std::find(_registeredConstants.begin(),
01258                  _registeredConstants.end  (),
01259                  val                        ) ==  _registeredConstants.end())
01260     {
01261         _registeredConstants.push_back(val);
01262     }
01263
01264     staticRelease();
01265 }
01266
01267 #endif // remove the OpenGL object handling from user docs
01268 
01275 void OSG::Window::dumpExtensions(void)
01276 {
01277     std::vector<std::string>::iterator it;
01278     std::cout << "GL Extensions: ";
01279
01280     for(it = _extensions.begin(); it != _extensions.end(); ++it)
01281     {
01282         std::cout << it->c_str() << ", ";
01283     }
01284
01285     std::cout << std::endl;
01286 }
01287
01288 void OSG::Window::doTerminate(void)
01289 {
01290     if(_pContextThread != NULL)
01291     {
01292         fprintf(stderr, "Terminate draw thread %p\n", this);
01293
01294         _pContextThread->queueTask(
01295             new WindowDrawTask(WindowDrawTask::EndThread));
01296
01297         Thread::join(_pContextThread);
01298     }
01299
01300     _pContextThread = NULL;
01301 }
01302
01312 void OSG::Window::doFrameInit(bool reinitExtFuctions)
01313 {
01314     static bool ignoreEnvDone = false;
01315
01316     if(!ignoreEnvDone)
01317     {
01318         ignoreEnvDone = true;
01319
01320 #ifndef OSG_EMBEDDED
01321         Char8 *p = getenv("OSG_IGNORE_EXTENSIONS");
01322
01323         if(p)
01324             ignoreExtensions(p);
01325 #endif
01326     }
01327
01328     // get version/extensions and split them
01329     if(_extensions.empty())
01330     {
01331         const char *version =
01332                 reinterpret_cast<const char *>(glGetString(GL_VERSION));
01333
01334         if(version != NULL)
01335         {
01336             int major = atoi(version);
01337             int minor = atoi(strchr(version, '.') + 1);
01338
01339             _glVersion = (major << 8) + minor;
01340         }
01341         else
01342         {
01343             FFATAL(("Window::frameInit: Couldn't detect OpenGL version "
01344                     "assuming version 1.1!\n"));
01345             _glVersion = (1 << 8) + 1;
01346         }
01347
01348 #ifdef __APPLE__
01349 
01350         const char* glVendor   =
01351             reinterpret_cast<const char *>(glGetString(GL_VENDOR));
01352         const char* glRenderer =
01353             reinterpret_cast<const char *>(glGetString(GL_RENDERER));
01354
01355         if(glVendor != NULL && glRenderer != NULL)
01356         {
01357             // TODO; is there a better way to switch some
01358             // extentions for a specific os/vendor/renderer combo
01359             FLOG (( "GL Vendor/Renderer: %s/%s\n", glVendor, glRenderer ));
01360
01361             if ( strstr(glVendor, "ATI") && strstr(glRenderer,"X1600") )
01362             {
01363                   FWARNING (("Switch of non_power_of_two for ATI\n"));
01364                   ignoreExtensions("GL_ARB_texture_non_power_of_two");
01365             }
01366         }
01367
01368 #endif // __APPLE
01369 
01370         const char *gl_extensions =
01371             reinterpret_cast<const char*> (glGetString(GL_EXTENSIONS));
01372
01373         FDEBUG(("Window %p: GL Version: %4x ('%s')\n", this,
01374                 _glVersion, glGetString(GL_VERSION) ));
01375
01376         FDEBUG(("Window %p: GL Extensions: %s\n", this, gl_extensions));
01377
01378         std::string foo(gl_extensions != NULL ? gl_extensions : "");
01379
01380         FDEBUG(("Window %p: Ignored extensions: ", this));
01381
01382         for(string_token_iterator it = string_token_iterator(foo, ",. ");
01383             it != string_token_iterator(); ++it)
01384         {
01385             if(! std::binary_search(_ignoredExtensions.begin(),
01386                                     _ignoredExtensions.end(),
01387                                     *it))
01388             {
01389                 _extensions.push_back(*it);
01390             }
01391             else
01392             {
01393                 FPDEBUG(("%s ", (*it).c_str()));
01394             }
01395         }
01396         FPDEBUG(("\n"));
01397         std::sort(_extensions.begin(), _extensions.end());
01398
01399         // if we don't have any extensions, add something anyway
01400         if(_extensions.empty())
01401             _availExtensions.resize(_registeredExtensions.size(), false);
01402     }
01403
01404     // any new extension registered ? 
01405     if(_registeredExtensions.size() > _availExtensions.size())
01406     {
01407         staticAcquire();
01408         FDEBUG(("Window %p: exts: ", this));
01409
01410         while(_registeredExtensions.size() > _availExtensions.size())
01411         {
01412             UInt32 s = _availExtensions.size();
01413
01414             /* perform a binary search over the retrieved extension strings.
01415                Push back the result as an availability flag for the extension
01416                requested by the application */
01417             bool supported = std::binary_search(
01418                                 _extensions.begin(),
01419                                 _extensions.end(),
01420                                 _registeredExtensions[s]);
01421
01422             /* Is this extension ignored? */
01423             bool ignored   = std::binary_search(
01424                                 _ignoredExtensions.begin(),
01425                                 _ignoredExtensions.end(),
01426                                 _registeredExtensions[s]);
01427
01428             _availExtensions.push_back(supported && !ignored);
01429
01430             FPDEBUG(("%s:", _registeredExtensions[s].c_str()));
01431
01432             if(_commonExtensions.size() <= s)
01433             {
01434                 _commonExtensions.push_back(supported && !ignored);
01435
01436                 if(supported && !ignored)
01437                 {
01438                     FPDEBUG(("ok "));
01439                 }
01440                 else if(!supported)
01441                 {
01442                     FPDEBUG(("NF "));
01443                 }
01444                 else
01445                 {
01446                     FPDEBUG(("IGN "));
01447                 }
01448             }
01449             else if (!supported)
01450             {
01451                 _commonExtensions[s] = false;
01452                 FPDEBUG(("NF "));
01453             }
01454             else
01455             {
01456                 _commonExtensions[s] = false;
01457                 FPDEBUG(("IGN "));
01458             }
01459         }
01460         FPDEBUG(("\n"));
01461         staticRelease();
01462     }
01463
01464     if(reinitExtFuctions  == true)
01465     {
01466         _extFunctions.clear();
01467     }
01468
01469     // any new functions registered ? 
01470     while(_registeredFunctions.size() > _extFunctions.size())
01471     {
01472         const Char8 *s    = _registeredFunctions[_extFunctions.size()].c_str();
01473         FPDEBUG(("Window %p: Looking up ext function: %s ... ", this, s));
01474
01475         Int32        ext  = _registeredFunctionExts    [_extFunctions.size()];
01476         UInt32       ver  = _registeredFunctionVersions[_extFunctions.size()];
01477
01478         GLExtensionFunction func = NULL;
01479
01480         // XXX: I think this should be "and".  And what is "ext"?
01481         if(ext == -1 || _availExtensions[ext] == true || _glVersion >= ver)
01482         {
01483             func = getFunctionByName(s);
01484             if (NULL != func)
01485             {
01486                 FDEBUG((" FOUND\n"));
01487             }
01488             else
01489             {
01490                 FDEBUG((" NULL\n"));
01491             }
01492         }
01493         else
01494         {
01495             FDEBUG((" N/A\n"));
01496         }
01497
01498         _extFunctions.push_back(func);
01499     }
01500
01501 #ifndef OSG_EMBEDDED
01502     // any new constants registered ? 
01503     while(_registeredConstants.size() > _numAvailConstants)
01504     {
01505         for(std::vector<GLenum>::iterator it = _registeredConstants.begin() +
01506                                                _numAvailConstants;
01507             it != _registeredConstants.end();
01508             ++it)
01509         {
01510             Vec2f val(unknownConstant, unknownConstant);
01511             glGetFloatv(*it, static_cast<GLfloat*>(val.getValues()));
01512             _availConstants[*it] = val;
01513             FDEBUG(("Window(%p): Constant 0x%x value is %.3f %.3f\n", this,
01514                     *it, val[0], val[1]));
01515         }
01516         _numAvailConstants = _registeredConstants.size();
01517
01518         glGetError(); // clear the error flag 
01519     }
01520 #endif
01521 
01522     _pStageValidator->incEventCounter();
01523 }
01524
01534 void OSG::Window::doFrameExit(void)
01535 {
01536     std::list<DestroyEntry>::iterator st,en;
01537
01538     st = _glObjectDestroyList.begin();
01539     en = _glObjectDestroyList.end  ();
01540
01541     while(st != en)
01542     {
01543         UInt32 i = st->first, n = st->second;
01544
01545         GLObject *obj = _glObjects[i];
01546
01547         if(obj == NULL)
01548         {
01549             FDEBUG(("Window::doFrameExit: objects %d (%d) already destroyed ?\n",
01550                     i, n));
01551             ++st;
01552             continue;
01553         }
01554
01555         FDEBUG(("Window::doFrameExit: Destroying GLObject %d (%d) - GL id %d\n",
01556                 i, n, getGLObjectId(i)));
01557
01558         UInt32 rc = obj->getRefCounter();
01559
01560         // has the object been used in this context at all?
01561         if(getGlObjectLastReinitialize(i) != 0)
01562         {
01563             _glObjects[i]->getDestroyFunctor()(&_oEnv, i, destroy);
01564             doResetGLObjectStatus(i, n);
01565
01566             if((rc = _glObjects[ i ]->decRefCounter()) <= 0)
01567             {
01568                 // call functor with the final-flag
01569                 _glObjects[i]->getDestroyFunctor()(&_oEnv, i, finaldestroy);
01570             }
01571         }
01572
01573         // if the GLObject is removed from each GL-Context, free GLObject-IDs.
01574         if(rc <= 0)
01575         {
01576             delete _glObjects[i];
01577
01578             for(UInt32 j = 0; j < n ; j++)
01579             {
01580                 _glObjects[i+j] = NULL;
01581                 this->setGLObjectId(i+j, 0);
01582             }
01583         }
01584
01585         ++st;
01586     }
01587
01588     _glObjectDestroyList.clear();
01589
01590     // Test for OpenGL errors. Just a little precaution to catch
01591     // stray errors. This is the only OpenGL error test in opt mode
01592     // and it needs to be enabled using the OSG_TEST_GL_ERRORS envvar.
01593     // In debug mode it is always on.
01594
01595     static bool inited = false;
01596 #ifndef OSG_DEBUG
01597     static bool testGLErrors = false;
01598 #else
01599     static bool testGLErrors = true;
01600 #endif
01601 
01602     if(!inited)
01603     {
01604         inited = true;
01605         char *p = getenv("OSG_DEBUG");
01606         if(p)
01607             testGLErrors = true;
01608     }
01609
01610     if(testGLErrors)
01611     {
01612         GLenum glerr;
01613
01614         while((glerr = glGetError()) != GL_NO_ERROR)
01615         {
01616 #ifndef OSG_EMBEDDED
01617             FWARNING(("Window::frameExit: Caught stray OpenGL "
01618                       "error %s (%#x).\n",
01619                       gluErrorString(glerr),
01620                       glerr));
01621 #else
01622             FWARNING(("Window::frameExit: Caught stray OpenGL error %#x.\n",
01623                       glerr));
01624 #endif
01625 
01626 #ifndef OSG_DEBUG
01627             FWARNING(("Rerun with debug-libraries to get more accurate "
01628                       "information.\n"));
01629 #endif
01630         }
01631     }
01632
01633 }
01634
01635
01636 // Query for a GL extension function
01637 // Yes, this is system dependent, but the system dependent parts are 
01638 // #ifdefed anyway, and very similar code would show up in a number of places,
01639 // making maintaining it unnecessarily hard
01640 // Note: the order of the cases is important, do not change it!
01641
01647 OSG::Window::GLExtensionFunction OSG::Window::getFunctionByName(
01648     const Char8 *s)
01649 {
01650     GLExtensionFunction retval = NULL;
01651
01652     FINFO(("Window::getFunctionByName: %s\n", s));
01653
01654     FDEBUG(("Window %p: GL Vendor: %s\n", this, glGetString(GL_VENDOR)));
01655
01656 #if defined(__APPLE__)
01657 
01658     if (NSIsSymbolNameDefined(s))
01659     {
01660         NSSymbol symbol = NSLookupAndBindSymbol(s);
01661
01662         if(symbol != 0)
01663             retval = GLExtensionFunction(NSAddressOfSymbol(symbol));
01664     }
01665 #elif defined(OSG_EMBEDDED) && defined(WIN32)
01666 
01667     retval = (void(__cdecl*)(void)) eglGetProcAddress(s);
01668
01669 #elif defined(WIN32)
01670 
01671     retval = (void(__cdecl*)(void)) wglGetProcAddress(s);
01672
01673 #elif defined(__sgi)   || defined(__hpux) || \
01674       defined(__linux) || defined(__sun)
01675 
01676     /* Workaround for multiple nVidia/Linux installation bugs, based on 
01677        code by
01678        Manfred Weiler (Patch 783637) 
01679      */
01680
01681     static void (*(*__GetProcAddress)(const GLubyte *))(void) = NULL;
01682
01683     static void *libHandle = NULL;
01684     std::string  libHandleName;
01685
01686     // If we haven't found the library previously, then look for it.
01687     if(libHandle == NULL)
01688     {
01689         libHandle = dlopen(_glLibraryName, RTLD_NOW | RTLD_LOCAL);
01690
01691         if(!libHandle)
01692         {
01693             FWARNING(("Error in dlopen when opening GL lib: %s\n",dlerror()));
01694             abort();
01695         }
01696         else
01697         {
01698             libHandleName = (_glLibraryName == NULL ? "(executable)"
01699                                                     : _glLibraryName);
01700             FDEBUG(("Opened lib %s for GL extension handling.\n",
01701                     libHandleName.c_str()));
01702         }
01703     }
01704
01705     if(__GetProcAddress == NULL)
01706     {
01707         FINFO(("Finding glxGetProcAddress method: "));
01708
01709 #ifdef TRY_USING_GLXGETPROC_DIRECTLY
01710 
01711         // Try pulling in ARB function directly.
01712 /*
01713 #ifdef GLX_ARB_get_proc_address
01714         if(__GetProcAddress == NULL)
01715         {
01716             __GetProcAddress = glXGetProcAddressARB;
01717             FINFO((" Using glxGetProcAddressARB directly.\n"));
01718         }
01719 #endif
01720 */
01721         // If GLX version is 1.4 or greater then the method should exist.
01722 #ifdef GLX_VERSION_1_4
01723         if(__GetProcAddress == NULL)
01724         {
01725             __GetProcAddress = glXGetProcAddress;
01726             FPINFO((" Using glxGetProcAddress directly.\n"));
01727         }
01728 #endif
01729 #endif
01730         if(__GetProcAddress == NULL)
01731         {
01732             __GetProcAddress =
01733 #if __GNUC__ < 4
01734                 (void (*(*)(const GLubyte*))())
01735 #else
01736                 reinterpret_cast<void (*(*)(const GLubyte*))()>
01737 #endif
01738                     (dlsym(libHandle,
01739                           "glXGetProcAddressARB"));
01740
01741             if(__GetProcAddress == NULL)
01742             {
01743                 __GetProcAddress =
01744 #if __GNUC__ < 4
01745                     (void (*(*)(const GLubyte*))())
01746 #else
01747                     reinterpret_cast<void (*(*)(const GLubyte*))()>
01748 #endif
01749                         (dlsym(libHandle,
01750                               "glXGetProcAddress"));
01751
01752                 if(__GetProcAddress == NULL)
01753                 {
01754                     // Couldn't find it linked to the executable. Try to open
01755                     // libGL.so directly.
01756
01757                     dlclose(libHandle);
01758
01759                     libHandle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL);
01760
01761                     if(!libHandle)
01762                     {
01763                         FWARNING(("Error in dlopen: %s\n",dlerror()));
01764                         abort();
01765                     }
01766                     else
01767                     {
01768                         FPINFO((" Using libGL.so directly.\n"));
01769                     }
01770
01771                     __GetProcAddress =
01772 #if __GNUC__ < 4
01773                         (void (*(*)(const GLubyte*))())
01774 #else
01775                         reinterpret_cast<void (*(*)(const GLubyte*))()>
01776 #endif
01777                             (dlsym(libHandle, "glXGetProcAddressARB"));
01778
01779                     if(__GetProcAddress == NULL)
01780                     {
01781                         __GetProcAddress =
01782 #if __GNUC__ < 4
01783                             (void (*(*)(const GLubyte*))())
01784 #else
01785                             reinterpret_cast<void (*(*)(const GLubyte*))()>
01786 #endif
01787                                 (dlsym(libHandle, "glXGetProcAddress"));
01788                     }
01789
01790
01791                     if(__GetProcAddress == NULL)
01792                     {
01793                         FWARNING(("Neither glXGetProcAddress nor "
01794                                   "glXGetProcAddressARB found! Disabling all "
01795                                   " extensions for Window %p!\n", this));
01796
01797                         _availExtensions.clear();
01798                         _availExtensions.resize(_registeredExtensions.size(),
01799                                                 false);
01800                     }
01801                 }
01802                 else
01803                 {
01804                     FPINFO((" Using glXGetProcAddress (from %s).\n",
01805                             libHandleName.c_str()));
01806                 }
01807             }
01808             else
01809             {
01810                 FPINFO(("Using glXGetProcAddressARB (from %s).\n",
01811                         libHandleName.c_str()));
01812             }
01813         }
01814     }
01815
01816     if(__GetProcAddress != NULL)
01817     {
01818         retval =
01819             reinterpret_cast<GLExtensionFunction>(
01820                 __GetProcAddress(reinterpret_cast<const GLubyte*>(s)));
01821     }
01822     else
01823     {
01824         retval =
01825 #if __GNUC__ < 4
01826             (GLExtensionFunction)
01827 #else
01828             reinterpret_cast<GLExtensionFunction>
01829 #endif
01830                 (dlsym(libHandle, s));
01831     }
01832
01833 #else
01834 
01835     FWARNING(("Window::getFunctionByName: couldn't find implementation!\n"
01836               "Please contact the developers at info@opensg.org.\n"));
01837
01838     retval = NULL;
01839 #endif
01840 
01841     if(retval == NULL)
01842     {
01843         FWARNING(("Window::getFunctionByName: Couldn't get function '%s' for "
01844                  "Window %p.\n", s, this));
01845     }
01846     else
01847     {
01848         FDEBUG(("Window::getFunctionByName: got function '%s' for "
01849                  "Window %p at %p.\n", s, this, retval));
01850     }
01851
01852     return retval;
01853 }
01854
01855
01859 const Vec2f& OSG::Window::getConstantValuev(GLenum val)
01860 {
01861     static Vec2f inf(Inf, Inf);
01862
01863     ConstHash::iterator it = _availConstants.find(val);
01864
01865     if(it != _availConstants.end())
01866         return _availConstants[val];
01867
01868     return inf;
01869 }
01870
01871
01879 void OSG::Window::setupGL( void )
01880 {
01881     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01882     glPixelStorei(GL_PACK_ALIGNMENT,   1);
01883
01884     glDepthFunc(GL_LEQUAL    );
01885     glEnable   (GL_DEPTH_TEST);
01886
01887     glEnable   (GL_NORMALIZE );
01888
01889     // switch off default light
01890     Real nul[4]={0.f,0.f,0.f,0.f};
01891
01892     GLP::glLightfv(GL_LIGHT0, GL_DIFFUSE,  nul);
01893     GLP::glLightfv(GL_LIGHT0, GL_SPECULAR, nul);
01894
01895     _sfRendererInfo.getValue().assign(
01896         reinterpret_cast<const char *>(glGetString(GL_VERSION)));
01897
01898     _sfRendererInfo.getValue() += " - ";
01899
01900     _sfRendererInfo.getValue() +=
01901         reinterpret_cast<const char *>(glGetString(GL_RENDERER));
01902
01903
01904     doFrameInit();    // call it to setup extensions
01905 }
01906
01907 void Window::setupTasks(void)
01908 {
01909     _pWaitTask       = new WindowDrawTask(WindowDrawTask::WaitAtBarrier);
01910     _pSwapTask       = new WindowDrawTask(WindowDrawTask::Swap         );
01911     _pFrameInitTask  = new WindowDrawTask(WindowDrawTask::FrameInit    );
01912     _pFrameExitTask  = new WindowDrawTask(WindowDrawTask::FrameExit    );
01913     _pActivateTask   = new WindowDrawTask(WindowDrawTask::Activate     );
01914 }
01915
01916 /*-------------------------- your_category---------------------------------*/
01917
01925 void OSG::Window::render(RenderActionBase *action)
01926 {
01927     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
01928     {
01929         activate   ();
01930         doFrameInit();    // query recently registered GL extensions
01931
01932         if(_mfDrawTasks.empty() == false)
01933         {
01934             MFDrawTask::const_iterator tIt  = _mfDrawTasks.begin();
01935             MFDrawTask::const_iterator tEnd = _mfDrawTasks.end  ();
01936
01937             for(; tIt != tEnd; ++tIt)
01938             {
01939                 (*tIt)->execute(this, &_oEnv);
01940             }
01941
01942             editMField(DrawTasksFieldMask, _mfDrawTasks);
01943
01944             _mfDrawTasks.clear();
01945         }
01946
01947         doRenderAllViewports(action);
01948
01949         swap       ();
01950         doFrameExit(); // after frame cleanup: delete dead GL objects
01951         deactivate ();
01952     }
01953     else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
01954                                                          ParallelPartitionDraw)
01955     {
01956         OSG_ASSERT(_pContextThread != NULL);
01957
01958         if(_pContextThread->isRunning() == false)
01959         {
01960             WindowDrawThread *pDrawThread =
01961                 dynamic_cast<WindowDrawThread *>(_pContextThread.get());
01962
01963             OSG_ASSERT(pDrawThread != NULL);
01964
01965             fprintf(stderr, "running partition drawthread r\n");
01966
01967             if(_pInitTask == NULL)
01968             {
01969                 _pInitTask = new WindowDrawTask(WindowDrawTask::Init);
01970             }
01971
01972             pDrawThread->queueTaskFront(_pInitTask);
01973
01974             pDrawThread->setWindow(this);
01975             pDrawThread->run(Thread::getCurrentAspect());
01976
01977             _pInitTask = NULL;
01978         }
01979
01980         if(_pWaitTask == NULL)
01981         {
01982             setupTasks();
01983         }
01984 //        fprintf(stderr, "Window::render::ParallelPartitionDraw NI\n");
01985
01986 #ifdef OSG_WIN_QUEUE_ALL
01987         _pContextThread->queueTask(_pWaitTask);
01988 #endif
01989 
01990         if(this->getKeepContextActive() == false)
01991             this->doDeactivate();
01992
01993         _pContextThread->queueTask(_pFrameInitTask);
01994
01995         if(_mfDrawTasks.empty() == false)
01996         {
01997             MFDrawTask::const_iterator tIt  = _mfDrawTasks.begin();
01998             MFDrawTask::const_iterator tEnd = _mfDrawTasks.end  ();
01999
02000             for(; tIt != tEnd; ++tIt)
02001             {
02002                 _pContextThread->queueTask(*tIt);
02003             }
02004
02005             editMField(DrawTasksFieldMask, _mfDrawTasks);
02006
02007             _mfDrawTasks.clear();
02008         }
02009
02010         doRenderAllViewports(action);
02011
02012 #ifdef OSG_WIN_QUEUE_ALL
02013 //        _pDrawThread->dumpTasks();
02014
02015         _pWaitTask->waitForBarrier();
02016 #endif
02017 
02018         _pContextThread->queueTask(_pSwapTask     );
02019
02020         _pContextThread->queueTask(_pFrameExitTask);
02021
02022         _pContextThread->queueTask(_pWaitTask     );
02023
02024         _pWaitTask->waitForBarrier();
02025     }
02026     else
02027     {
02028         fprintf(stderr, "Unknow partition draw mode\n");
02029     }
02030 }
02031
02032 void OSG::Window::renderNoFinish(RenderActionBase *action)
02033 {
02034     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02035     {
02036         activate   ();
02037         doFrameInit();    // query recently registered GL extensions
02038
02039         if(_mfDrawTasks.empty() == false)
02040         {
02041             MFDrawTask::const_iterator tIt  = _mfDrawTasks.begin();
02042             MFDrawTask::const_iterator tEnd = _mfDrawTasks.end  ();
02043
02044             for(; tIt != tEnd; ++tIt)
02045             {
02046                 (*tIt)->execute(this, &_oEnv);
02047             }
02048
02049             editMField(DrawTasksFieldMask, _mfDrawTasks);
02050
02051             _mfDrawTasks.clear();
02052         }
02053
02054         doRenderAllViewports(action);
02055     }
02056     else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02057                                                          ParallelPartitionDraw)
02058     {
02059         OSG_ASSERT(_pContextThread != NULL);
02060
02061         if(_pContextThread->isRunning() == false)
02062         {
02063             WindowDrawThread *pDrawThread =
02064                 dynamic_cast<WindowDrawThread *>(_pContextThread.get());
02065
02066             OSG_ASSERT(pDrawThread != NULL);
02067
02068             fprintf(stderr, "running partition drawthread rnf\n");
02069
02070             if(_pInitTask == NULL)
02071             {
02072                 _pInitTask = new WindowDrawTask(WindowDrawTask::Init);
02073             }
02074
02075             pDrawThread->queueTaskFront(_pInitTask);
02076
02077             pDrawThread->setWindow(this);
02078             pDrawThread->run(Thread::getCurrentAspect());
02079
02080             _pInitTask = NULL;
02081         }
02082
02083         if(_pWaitTask == NULL)
02084         {
02085             setupTasks();
02086         }
02087
02088         _pContextThread->queueTask(_pFrameInitTask);
02089
02090         if(_mfDrawTasks.empty() == false)
02091         {
02092             MFDrawTask::const_iterator tIt  = _mfDrawTasks.begin();
02093             MFDrawTask::const_iterator tEnd = _mfDrawTasks.end  ();
02094
02095             for(; tIt != tEnd; ++tIt)
02096             {
02097                 _pContextThread->queueTask(*tIt);
02098             }
02099
02100             editMField(DrawTasksFieldMask, _mfDrawTasks);
02101
02102             _mfDrawTasks.clear();
02103         }
02104
02105         this->doRenderAllViewports(action);
02106     }
02107     else
02108     {
02109         fprintf(stderr, "Unknow partition draw mode\n");
02110     }
02111 }
02112
02113 void OSG::Window::frameFinish(bool bActivate)
02114 {
02115     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02116     {
02117         if(bActivate == true)
02118             activate();
02119
02120         swap       ();
02121         doFrameExit(); // after frame cleanup: delete dead GL objects
02122
02123     }
02124     else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02125                                                          ParallelPartitionDraw)
02126     {
02127         OSG_ASSERT(_pContextThread != NULL);
02128
02129         if(_pWaitTask == NULL || _pContextThread->isRunning() == false)
02130         {
02131             fprintf(stderr, "Window::frameFinish::frame not started\n");
02132         }
02133
02134         if(bActivate == true)
02135             _pContextThread->queueTask(_pActivateTask);
02136
02137         _pContextThread->queueTask(_pSwapTask     );
02138
02139         _pContextThread->queueTask(_pFrameExitTask);
02140
02141         _pContextThread->queueTask(_pWaitTask     );
02142
02143         _pWaitTask->waitForBarrier();
02144     }
02145     else
02146     {
02147         fprintf(stderr, "Unknow partition draw mode\n");
02148     }
02149 }
02150
02151 void OSG::Window::runFrameExit(void)
02152 {
02153     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02154     {
02155         doActivate  ();
02156         doFrameExit (); // after frame cleanup: delete dead GL objects
02157         doDeactivate();
02158     }
02159     else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02160                                                          ParallelPartitionDraw)
02161     {
02162         if(_pWaitTask == NULL || _pContextThread->isRunning() == false)
02163         {
02164             fprintf(stderr, "Window::runFrameExit::frame not started\n");
02165         }
02166
02167         _pContextThread->queueTask(_pActivateTask);
02168         _pContextThread->queueTask(_pFrameExitTask);
02169
02170         _pContextThread->queueTask(_pWaitTask     );
02171
02172         _pWaitTask->waitForBarrier();
02173     }
02174     else
02175     {
02176         fprintf(stderr, "Unknow partition draw mode\n");
02177     }
02178 }
02179
02180 void OSG::Window::frameInit(void)
02181 {
02182     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02183     {
02184         this->doFrameInit();
02185     }
02186 }
02187
02188 void OSG::Window::frameExit(void)
02189 {
02190     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02191     {
02192         this->doFrameExit();
02193     }
02194 }
02195
02196 void OSG::Window::renderAllViewports(RenderActionBase *action)
02197 {
02198     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02199     {
02200         this->doRenderAllViewports(action);
02201     }
02202 }
02203
02210 void OSG::Window::doRenderAllViewports(RenderActionBase *action)
02211 {
02212     MFUnrecChildViewportPtr::const_iterator portIt  = getMFPort()->begin();
02213     MFUnrecChildViewportPtr::const_iterator portEnd = getMFPort()->end();
02214     Int32                                   iVPId   = 0;
02215
02216     if(action != NULL)
02217     {
02218         commitChanges();
02219
02220         action->setWindow(this);
02221
02222         if(this->getDrawerId() < 0)
02223         {
02224             action->setDrawerId(this->_windowId);
02225         }
02226         else
02227         {
02228             action->setDrawerId(this->getDrawerId());
02229         }
02230
02231         if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02232                                                        SequentialPartitionDraw)
02233         {
02234             action->setDrawPartPar(false);
02235         }
02236         else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02237                                                          ParallelPartitionDraw)
02238         {
02239             action->setDrawPartPar(true);
02240         }
02241
02242         action->frameInit();
02243
02244         for(; portIt != portEnd; ++portIt, ++iVPId)
02245         {
02246             if((*portIt)->getDrawableId() < 0)
02247             {
02248                 action->setDrawableId(iVPId);
02249             }
02250             else
02251             {
02252                 action->setDrawableId((*portIt)->getDrawableId());
02253             }
02254
02255             if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02256                                                        SequentialPartitionDraw)
02257             {
02258                 (*portIt)->render(action);
02259             }
02260             else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02261                                                          ParallelPartitionDraw)
02262             {
02263                 (*portIt)->render(action);
02264
02265 #if 0
02266                 OSG_ASSERT(_pWaitTask != NULL);
02267
02268                 _pContextThread->queueTask(_pWaitTask     );
02269
02270                 _pWaitTask->waitForBarrier();
02271 #endif
02272             }
02273         }
02274     }
02275     else
02276     {
02277         SWARNING << "Window::renderAllViewports: no action!" << std::endl;
02278     }
02279 }
02280
02287 void OSG::Window::resize( int width, int height )
02288 {
02289     setWidth        (width );
02290     setHeight       (height);
02291     setResizePending(true  );
02292 }
02293
02294
02295 void OSG::Window::init(GLInitFunctor oFunc)
02296 {
02297     if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
02298     {
02299         this->activate();
02300
02301         setupGL();
02302
02303         if(oFunc)
02304             oFunc();
02305
02306         this->deactivate();
02307     }
02308     else if((_sfDrawMode.getValue() & DrawerMask) == StdDrawer)
02309     {
02310         if(_pInitTask == NULL)
02311         {
02312             _pInitTask = new WindowDrawTask(WindowDrawTask::Init);
02313         }
02314
02315         _pInitTask->setInitFunc(oFunc);
02316
02317         OSG_ASSERT(_pContextThread != NULL);
02318
02319         if(_pContextThread->isRunning() == false)
02320         {
02321             WindowDrawThread *pDrawThread =
02322                 dynamic_cast<WindowDrawThread *>(_pContextThread.get());
02323
02324             OSG_ASSERT(pDrawThread != NULL);
02325
02326             fprintf(stderr, "running partition drawthread init\n");
02327
02328             pDrawThread->queueTaskFront(_pInitTask);
02329
02330             pDrawThread->setWindow(this);
02331             pDrawThread->run(Thread::getCurrentAspect());
02332
02333             _pInitTask = NULL;
02334         }
02335
02336         if(_pWaitTask == NULL)
02337         {
02338             setupTasks();
02339         }
02340
02341         _pContextThread->queueTask(_pWaitTask);
02342
02343         _pWaitTask->waitForBarrier();
02344     }
02345     else
02346     {
02347         fprintf(stderr, "Unknown partition draw mode\n");
02348     }
02349 }
02350
02351
02358 void OSG::Window::doResizeGL( void )
02359 {
02360     if(isResizePending() == true)
02361     {
02362         glViewport(0, 0, getWidth(), getHeight());
02363
02364         setResizePending(false);
02365     }
02366 }
02367
02368 void OSG::Window::requestStageRun(Int32 iStageId)
02369 {
02370     if(iStageId < 0)
02371     {
02372         SWARNING << "Window::requestStageRun: id is < 0!" << std::endl;
02373         return;
02374     }
02375
02376     WindowStore::const_iterator winIt  = _allWindows.begin();
02377     WindowStore::const_iterator winEnd = _allWindows.end  ();
02378
02379     for(; winIt != winEnd; ++winIt)
02380     {
02381         Window *pWin = *winIt;
02382
02383         if(pWin == NULL)
02384             continue;
02385
02386         pWin->_pStageValidator->requestRun(iStageId);
02387     }
02388 }
02389
02390 /*------------------------------- dump ----------------------------------*/
02391
02394 void OSG::Window::dump(      UInt32    OSG_CHECK_ARG(uiIndent),
02395                        const BitVector OSG_CHECK_ARG(bvFlags )) const
02396 {
02397     SLOG << "Dump Window NI" << std::endl;
02398 }
02399
02400 void Window::resolveLinks(void)
02401 {
02402     Inherited::resolveLinks();
02403 }
02404
02405 void Window::queueTaskFromDrawer(DrawTask *pTask)
02406 {
02407     if(pTask == NULL)
02408         return;
02409
02410     OSG_ASSERT(_pContextThread != NULL);
02411
02412     if((_sfDrawMode.getValue() & PartitionDrawMask) == ParallelPartitionDraw)
02413     {
02414         _pContextThread->queueTask(pTask);
02415     }
02416     else
02417     {
02418         pTask->execute(this, &_oEnv);
02419     }
02420 }
02421
02422 void Window::queueTask(DrawTask *pTask)
02423 {
02424     if(pTask == NULL)
02425         return;
02426
02427     if((_sfDrawMode.getValue() & DrawerMask) == StdDrawer)
02428     {
02429         if((_sfDrawMode.getValue() & PartitionDrawMask) ==
02430                                                          ParallelPartitionDraw)
02431         {
02432             OSG_ASSERT(_pContextThread != NULL);
02433
02434             _pContextThread->queueTask(pTask);
02435         }
02436         else
02437         {
02438             editMField(DrawTasksFieldMask, _mfDrawTasks);
02439
02440             _mfDrawTasks.push_back(pTask);
02441         }
02442     }
02443     else if((_sfDrawMode.getValue() & DrawerMask) == ParallelDrawer)
02444     {
02445         editMField(DrawTasksFieldMask, _mfDrawTasks);
02446
02447         _mfDrawTasks.push_back(pTask);
02448     }
02449 }
02450
02451 void OSG::Window::queueGlobalTask(DrawTask *pTask)
02452 {
02453     WindowStore::const_iterator winIt  = _allWindows.begin();
02454     WindowStore::const_iterator winEnd = _allWindows.end  ();
02455
02456     for(; winIt != winEnd; ++winIt)
02457     {
02458         Window *pWin = *winIt;
02459
02460         if(pWin == NULL)
02461             continue;
02462
02463         pWin->queueTask(pTask);
02464     }
02465 }
02466
02467 void Window::pushToDrawTasks(DrawTask * const value)
02468 {
02469     if(value == NULL)
02470         return;
02471
02472     editMField(DrawTasksFieldMask, _mfDrawTasks);
02473
02474     _mfDrawTasks.push_back(value);
02475 }
02476
02477 void Window::clearDrawTasks(void)
02478 {
02479     editMField(DrawTasksFieldMask, _mfDrawTasks);
02480
02481     _mfDrawTasks.clear();
02482 }
02483
02484 OSG_END_NAMESPACE