changed: gcc8 base update
[opensg.git] / Source / System / Window / Base / OSGWindow.cpp
blob6d51d74c6af1fe8f65d41a1696559447ee470f7e
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include "OSGGLU.h"
50 #include "OSGGLFuncProtos.h"
52 #if !defined(WIN32) && !defined(__APPLE__) && !defined(OSG_EMBEDDED)
53 # if defined(OSG_USE_OGL3_PROTOS) || defined(OSG_USE_OGL4_PROTOS)
54 //# include <GL3/glx3.h>
55 # include <GLArb/glxarb.h>
56 # else
57 # include <GL/glx.h>
58 # endif
59 #endif
61 #if defined(OSG_EMBEDDED) && defined(WIN32)
62 #include <gles/egl.h>
63 #endif
65 #if defined(__sgi) || defined(__APPLE__) || defined(__linux)
66 #include <dlfcn.h>
67 #endif
69 #if defined(__APPLE__)
70 #include <mach-o/dyld.h>
71 #endif
73 #if defined(__sun)
74 #include <dlfcn.h>
75 #include <link.h>
76 #endif
78 #include <boost/algorithm/string.hpp>
80 #include "OSGBaseFunctions.h"
82 #include "OSGViewport.h"
84 #include "OSGBackground.h"
85 #include "OSGCamera.h"
86 #include "OSGWindow.h"
88 #include "OSGRenderActionBase.h"
89 #include "OSGRenderActionTask.h"
91 #include "OSGTraversalValidator.h"
92 #include "OSGShaderCache.h"
94 //#define OSG_WIN_QUEUE_ALL 1
96 OSG_BEGIN_NAMESPACE
98 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
99 #pragma warning (disable)
100 #endif
102 // If true, then try just using glXGetProcAddress() directly.
103 #define TRY_USING_GLXGETPROC_DIRECTLY 1
105 // Documentation for this class is emited in the
106 // OSGWindowBase.cpp file.
107 // To modify it, please change the .fcd file (OSGWindow.fcd) and
108 // regenerate the base file.
110 // Window-sytem specific virtual functions
112 /*! \fn void OSG::Window::init(void)
114 Initialize the Window and its OpenGL context. This method needs to be
115 called once after the Window has been created and its Window
116 System-specific parameters are set.
118 It leaves the OpenGL context current to simplify modifying the OpenGL
119 state.
122 /*! \fn void OSG::Window::activate(void)
124 Activate the Window's OpenGL context, so that OpenGL can be called.
127 /*! \fn void OSG::Window::deactivate(void)
129 Deativate the Window's OpenGL context. OpenGL calls are no longer possible
130 after this call.
133 /*! \fn void OSG::Window::swap(void)
135 Swap the back and front buffers.
137 \warning The correct OpenGL context needs to be active for this to work!
140 /***************************************************************************\
141 * Class variables *
142 \***************************************************************************/
144 /*! The global window list, needed by Window::refreshGLObject. All Windows are
145 added here at creation time and removed at deletion.
148 Window::WindowStore OSG::Window::_allWindows;
149 Int32 OSG::Window::_currentWindowId = 0;
151 // GLobject handling
153 /*! The lock used to mutex access of the GLObjects' reference count. One
154 should be enough for all of them, as they are pretty rarely changed, only
155 when they are used for the first time.
158 LockRefPtr OSG::Window::_GLObjectLock = NULL;
160 /*! The lock used to mutex access of the Window's static elements to manage
161 OpenGL extensions/functions/constants/objects.
164 LockRefPtr OSG::Window::_staticWindowLock = NULL;
166 /*! Global list of all GL Objects used in the system. See \ref
167 PageSystemOGLObjects for a description.
170 std::vector<OSG::Window::GLObject *> OSG::Window::_glObjects;
172 // GL extension handling
174 // The name of the dynamic library for OpenGL extension functions
175 // By default it's NULL, which tries to find them in the current
176 // executable
177 const Char8 *OSG::Window::_glLibraryName = NULL;
179 std::vector<std::string > OSG::Window::_registeredExtensions;
180 std::vector<std::string > OSG::Window::_ignoredExtensions;
181 std::vector<bool > OSG::Window::_commonExtensions;
182 std::vector<std::string > OSG::Window::_registeredFunctions;
183 std::vector<Int32 > OSG::Window::_registeredFunctionExts;
184 std::vector<UInt32 > OSG::Window::_registeredFunctionVersions;
186 // GL constant handling
188 std::vector<GLenum > OSG::Window::_registeredConstants;
191 // Just a constant to indicate that the GL constant is unknown
193 const Real32 OSG::Window::unknownConstant = TypeTraits<Real32>::getMax();
195 /***************************************************************************\
196 * Class methods *
197 \***************************************************************************/
199 /*-------------------------------------------------------------------------*\
200 - private -
201 \*-------------------------------------------------------------------------*/
203 /*! initialize the static features of the class, e.g. action callbacks
206 void OSG::Window::initMethod(InitPhase ePhase)
208 Inherited::initMethod(ePhase);
211 bool OSG::Window::cleanup(void)
213 _staticWindowLock = NULL;
214 _GLObjectLock = NULL;
216 GLObject *pCurr = NULL;
218 for(UInt32 i = 0; i < _glObjects.size(); ++i)
220 if(_glObjects[i] != pCurr)
222 pCurr = _glObjects[i];
224 delete _glObjects[i];
228 return true;
231 /***************************************************************************\
232 * Instance methods *
233 \***************************************************************************/
235 /*-------------------------------------------------------------------------*\
236 - protected -
237 \*-------------------------------------------------------------------------*/
240 /*------------- constructors & destructors --------------------------------*/
242 /*! Constructor
245 OSG::Window::Window(void) :
246 Inherited ( ),
247 _glObjectDestroyList( ),
248 _lastValidate ( ),
249 _ids ( ),
250 _idInfo ( ),
251 _glVersion ( 0),
252 _extensions ( ),
253 _availExtensions ( ),
254 _extFunctions ( ),
255 _availConstants ( ),
256 _windowId ( -1),
257 _pTravValidator (NULL),
258 _pShaderCache (NULL),
260 _pInitTask (NULL),
261 _pWaitTask (NULL),
262 _pSwapTask (NULL),
263 _pFrameInitTask (NULL),
264 _pFrameExitTask (NULL),
265 _pActivateTask (NULL),
266 _pDeactivateTask (NULL),
267 _pGLFinishTask (NULL),
268 _oEnv ( )
270 // only called for prototypes, no need to init them
271 _oEnv.setWindow(this);
274 /*! Copy Constructor
277 OSG::Window::Window(const Window &source) :
278 Inherited (source ),
279 _glObjectDestroyList(source._glObjectDestroyList ),
280 _lastValidate (source._lastValidate.size(), 0),
281 _ids (source._ids.size(), 0),
282 _idInfo (source._idInfo.size(), 0),
283 _glVersion ( 0),
284 _extensions ( ),
285 _availExtensions ( ),
286 _extFunctions ( ),
287 _availConstants ( ),
288 _windowId ( -1),
289 _pTravValidator (NULL ),
290 _pShaderCache (NULL ),
291 _pInitTask (NULL ),
292 _pWaitTask (NULL ),
293 _pSwapTask (NULL ),
294 _pFrameInitTask (NULL ),
295 _pFrameExitTask (NULL ),
296 _pActivateTask (NULL ),
297 _pDeactivateTask (NULL ),
298 _pGLFinishTask (NULL ),
299 _oEnv ( )
301 _oEnv.setWindow(this);
304 /*! Destructor
307 OSG::Window::~Window(void)
309 // delete the ports and the context
313 /*-------------------------------------------------------------------------*\
314 - private -
315 \*-------------------------------------------------------------------------*/
317 /*! Instance initialisation
320 void OSG::Window::onCreate(const Window *source)
322 Inherited::onCreate(source);
324 // Don't add the prototype instances to the list
325 if(GlobalSystemState != Running)
326 return;
328 if(source != NULL)
330 // mark all GL objects as not yet initialized
331 doResetGLObjectStatus(1, UInt32(_glObjects.size() - 1));
334 staticAcquire();
336 _allWindows.push_back(this);
338 _windowId = _currentWindowId++;
340 staticRelease();
342 char buffer[50];
343 sprintf(buffer, "Window(%d)::_pContextThread", _windowId);
345 _pContextThread = WindowDrawThread::get(buffer, false);
348 void OSG::Window::onCreateAspect(const Window *createAspect,
349 const Window *source)
351 Inherited::onCreateAspect(createAspect, source);
353 // Don't add the prototype instances to the list
354 if(GlobalSystemState != Running)
355 return;
357 if(createAspect != NULL)
359 _windowId = createAspect->_windowId;
362 _pTravValidator = new TraversalValidator;
363 _pShaderCache = new ShaderCache;
366 /*! instance deletion
369 void OSG::Window::onDestroy(UInt32 uiContainerId)
371 // decrement GLObjects reference counter.
372 for(UInt32 i = 1; i < _glObjects.size(); ++i)
374 GLObject *obj = _glObjects[i];
376 if(obj == NULL)
378 FDEBUG(("Window::onDestroy: object %u already destroyed!\n", i));
379 continue;
382 // has the object been used in this context at all?
383 if(i < getMFGlObjectLastReinitialize()->size() &&
384 getGlObjectLastReinitialize(i) != 0)
386 obj->decRefCounter();
387 // we can't call here the destroy callbacks because the
388 // gl context is not guaranteed to be current, but destroying
389 // the context should delete all gl objects.
393 staticAcquire();
395 WindowStore::iterator winIt;
397 winIt = std::find(_allWindows.begin(),
398 _allWindows.end (),
399 this);
401 // prototype window are not added to the list, so they might not be found.
403 if(winIt != _allWindows.end())
404 _allWindows.erase(winIt);
406 staticRelease();
408 Inherited::onDestroy(uiContainerId);
411 void OSG::Window::onDestroyAspect(UInt32 uiContainerId,
412 UInt32 uiAspect )
414 delete _pTravValidator;
415 delete _pShaderCache;
417 _pTravValidator = NULL;
418 _pShaderCache = NULL;
420 if(_pAspectStore->getRefCount() == 1 && _pContextThread != NULL)
422 if(_pContextThread->isRunning() == true)
424 fprintf(stderr, "Terminate context thread %p %p\n",
425 static_cast<void *>(this),
426 static_cast<void *>(_pContextThread.get()));
428 if(0x0000 != (_sfDrawMode.getValue() & ExternalContext))
430 this->doDeactivate();
432 _pContextThread->queueTask(_pActivateTask);
435 _pContextThread->queueTask(
436 new WindowDrawTask(WindowDrawTask::EndThread));
438 Thread::join(_pContextThread);
440 else
442 if((_sfDrawMode.getValue() & PartitionDrawMask) ==
443 SequentialPartitionDraw &&
444 this->hasContext() == true)
446 activate ();
447 doFrameExit(); // after frame cleanup: delete dead GL objects
448 deactivate ();
453 _pWaitTask = NULL;
454 _pSwapTask = NULL;
455 _pFrameInitTask = NULL;
456 _pFrameExitTask = NULL;
457 _pActivateTask = NULL;
458 _pDeactivateTask = NULL;
459 _pGLFinishTask = NULL;
461 _pContextThread = NULL;
463 Inherited::onDestroyAspect(uiContainerId, uiAspect);
466 void OSG::Window::staticAcquire(void)
468 // Is the ThreadManager initialized yet?
469 if(GlobalSystemState != Running)
470 return;
472 if(_staticWindowLock == NULL)
474 _staticWindowLock =
475 ThreadManager::the()->getLock("OSG::Window::_staticWindowLock",
476 false);
478 addPostFactoryExitFunction(&Window::cleanup);
480 _staticWindowLock->acquire();
483 void OSG::Window::staticRelease(void)
485 // Is the ThreadManager initialized yet?
486 if(GlobalSystemState != Running)
487 return;
489 _staticWindowLock->release();
492 /*-------------------------------------------------------------------------*\
493 - public -
494 \*-------------------------------------------------------------------------*/
496 /*! react to field changes
499 void OSG::Window::changed(ConstFieldMaskArg whichField,
500 UInt32 origin,
501 BitVector details)
503 Inherited::changed(whichField, origin, details);
506 /*------------------------------ access -----------------------------------*/
508 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_EXT)
510 /*------------------------ GL object handling -----------------------------*/
512 /*! Register a number of OpenGL objects. By default the number is 1, but more
513 can be necessary for things like text. It returns the first id of the
514 contiguous reserved ID block.
516 See \ref PageSystemOGLObjects for a description of the OpenGL object
517 concept.
520 UInt32 OSG::Window::registerGLObject(GLObjectFunctor functor,
521 GLObjectDestroyFunctor destroy,
522 UInt32 num)
524 UInt32 osgId, i;
525 GLObject *pGLObject;
527 staticAcquire();
529 // reserve index 0, illegal for most OpenGL functions
530 if(_glObjects.empty())
531 _glObjects.push_back(NULL);
533 osgId = UInt32(_glObjects.size());
534 pGLObject = new GLObject(functor, destroy);
536 // does the requested block fit into the capacity?
538 if(_glObjects.capacity() >= osgId + num)
540 _glObjects.insert(_glObjects.end(), num, pGLObject );
542 resetGLObjectStatus(osgId, num);
544 staticRelease();
546 return osgId;
549 // doesn't fit, try to find a block in the middle
551 UInt32 cnt = 0;
553 // start searching at 1, id 0 is reserved for GL
554 for(i = 1; i < _glObjects.size(); ++i)
556 if(_glObjects[i] == NULL)
558 if(cnt == 0)
560 osgId = i;
563 ++cnt;
565 if(cnt == num)
567 // block of unused entries found ...
569 while(i >= osgId)
571 _glObjects[i] = pGLObject;
572 i = i - 1;
575 resetGLObjectStatus(osgId, num);
577 staticRelease();
579 return osgId;
582 else
584 cnt = 0;
585 osgId = 0;
589 // no block found, add at the end
591 if(osgId > 0) // ok the last entries in the vector were empty
593 // fill the empty slots at the end
594 i = osgId + cnt - 1;
596 while(i >= osgId)
598 _glObjects[i] = pGLObject;
600 i = i - 1;
603 else
605 // we found no empty entries so the new id is the size of the vector.
606 osgId = UInt32(_glObjects.size());
609 // expand the vector for the rest
610 for(i = 1; i <= num - cnt; i++)
612 _glObjects.push_back(pGLObject);
615 resetGLObjectStatus(osgId, num);
617 staticRelease();
619 return osgId;
622 /*! Validate the given object, i.e. make sure it is up-to-date in the current
623 context.
625 See \ref PageSystemOGLObjects for a description of the OpenGL object
626 concept.
628 UInt32 OSG::Window::validateGLObject(UInt32 osgId,
629 DrawEnv *pEnv,
630 UInt64 uiOptions)
632 UInt32 returnValue = 0;
634 if ( osgId == 0 )
636 SWARNING << "Window::validateGLObject: id is 0!" << std::endl;
637 return returnValue;
640 GLObject *obj = _glObjects[osgId];
642 if(obj == NULL)
644 SWARNING << "Window::validateGLObject: obj with id " << osgId
645 <<" is NULL!" << std::endl;
646 return returnValue;
649 if(osgId >= _lastValidate.size()) // can happen if multi-threading
651 _lastValidate.resize(osgId + 1, 0);
654 if(osgId >= _mfGlObjectLastReinitialize.size())
656 editMField( GlObjectLastReinitializeFieldId,
657 _mfGlObjectLastReinitialize );
659 _mfGlObjectLastReinitialize.resize(osgId + 1, 0);
662 if(osgId >= _mfGlObjectLastRefresh.size())
664 editMField(GlObjectLastRefreshFieldId, _mfGlObjectLastRefresh);
666 _mfGlObjectLastRefresh.resize(osgId + 1, 0);
669 FDEBUG(("Window 0x%p (event %d,ri:%" PRISize ",rf:%" PRISize "): "
670 "Validating object %d: last reinit:%d, last validate:"
671 "%d last refresh: %d => %s\n",
672 static_cast<void *>(this), getGlObjectEventCounter(),
673 _mfGlObjectLastReinitialize.size(),
674 _mfGlObjectLastRefresh.size(),
675 osgId,
676 (_mfGlObjectLastReinitialize.size() > osgId)?
677 _mfGlObjectLastReinitialize[osgId]:0xffffffff,
678 _lastValidate[osgId],
679 (_mfGlObjectLastRefresh.size() > osgId)?
680 _mfGlObjectLastRefresh[osgId]:0xffffffff,
681 (_mfGlObjectLastReinitialize[osgId] == 0)?"init":
682 ((_mfGlObjectLastReinitialize[osgId] > _lastValidate[osgId])?"reinit":
683 ((_mfGlObjectLastRefresh[osgId] > _lastValidate[osgId])?"refresh":
684 "up-to-date"))
687 if(_mfGlObjectLastReinitialize[osgId] == 0)
689 editMField( GlObjectLastReinitializeFieldId,
690 _mfGlObjectLastReinitialize );
692 obj->incRefCounter();
693 returnValue = obj->getFunctor()(pEnv, osgId, initialize, uiOptions);
694 _mfGlObjectLastReinitialize[osgId] = 1;
695 _lastValidate[osgId] = getGlObjectEventCounter();
697 else if(_mfGlObjectLastReinitialize[osgId] > _lastValidate[osgId])
699 returnValue = obj->getFunctor()(pEnv, osgId, reinitialize, uiOptions);
700 _lastValidate[osgId] = getGlObjectEventCounter();
702 else if(_mfGlObjectLastRefresh[osgId] > _lastValidate[osgId])
704 returnValue = obj->getFunctor()(pEnv, osgId, needrefresh, uiOptions);
705 _lastValidate[osgId] = getGlObjectEventCounter();
708 return returnValue;
711 /*! Validate all existing GL objects. Use with care, and only if the correct
712 OpenGL context is active.
714 See \ref PageSystemOGLObjects for a description of the OpenGL object
715 concept.
717 void OSG::Window::validateAllGLObjects(void)
719 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
721 activate();
722 doFrameInit();
724 for (UInt32 i = 1; i < _glObjects.size(); ++i)
726 if(_glObjects[i] != NULL)
727 validateGLObject(i, &_oEnv);
730 doFrameExit();
731 deactivate();
733 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
734 ParallelPartitionDraw)
736 fprintf(stderr, "Window::validateAllGLObjects::pardraw NI\n");
738 else
740 fprintf(stderr, "Unknow partition draw mode\n");
744 /*! Mark the given object for refresh. The next time it is validated the
745 registered callback function will be called for a refresh action.
747 See \ref PageSystemOGLObjects for a description of the OpenGL object
748 concept.
751 void OSG::Window::refreshGLObject(UInt32 osgId)
753 if(osgId == 0)
755 SWARNING << "Window::refreshGLObject: id is 0!" << std::endl;
756 return;
759 staticAcquire();
761 doRefreshGLObject(osgId);
763 staticRelease();
766 /*! Refresh all existing GL objects.
768 See \ref PageSystemOGLObjects for a description of the OpenGL object
769 concept.
771 void OSG::Window::refreshAllGLObjects(void)
773 staticAcquire();
775 for(UInt32 i = 1; i < _glObjects.size(); ++i)
776 doRefreshGLObject(i);
778 staticRelease();
781 /*! Do the actual refresh work, without checks.
782 \note This function must be called while holding _staticWindowLock
783 and \a osgId must not be 0.
785 void Window::doRefreshGLObject(UInt32 osgId)
787 WindowStore::const_iterator winIt = _allWindows.begin();
788 WindowStore::const_iterator winEnd = _allWindows.end ();
790 for(; winIt != winEnd; ++winIt)
792 Window *pWin = *winIt;
794 if(pWin == NULL)
795 continue;
797 pWin->editMField(GlObjectLastRefreshFieldMask,
798 pWin->_mfGlObjectLastRefresh);
800 UInt32 lastinv = pWin->getGlObjectEventCounter() + 1;
802 MFUInt32 &field = pWin->_mfGlObjectLastRefresh;
804 if(field.size() <= osgId)
805 field.resize(osgId + 1, 0);
807 field[osgId] = lastinv;
809 pWin->setGlObjectEventCounter(lastinv);
814 /*! Mark the given object for reinitialisation. The next time it is validated
816 registered callback function will be called for a reinit action.
818 See \ref PageSystemOGLObjects for a description of the OpenGL object
819 concept.
822 void OSG::Window::reinitializeGLObject(UInt32 osgId)
824 if ( osgId == 0 )
826 SWARNING << "Window::reinitializeGLObject: id is 0!" << std::endl;
827 return;
830 staticAcquire();
832 doReinitializeGLObject(osgId);
834 staticRelease();
837 /*! Reinitialize all existing GL objects.
839 See \ref PageSystemOGLObjects for a description of the OpenGL object
840 concept.
842 void OSG::Window::reinitializeAllGLObjects(void)
844 staticAcquire();
846 for(UInt32 i = 1; i < _glObjects.size(); ++i)
847 doReinitializeGLObject(i);
849 staticRelease();
852 /*! Do the actual reinitialization work, without checks.
853 \note This function must be called while holding _staticWindowLock
854 and \a osgId must not be 0.
857 void Window::doReinitializeGLObject(UInt32 osgId)
859 WindowStore::const_iterator winIt = _allWindows.begin();
860 WindowStore::const_iterator winEnd = _allWindows.end ();
862 for(; winIt != winEnd; ++winIt)
864 Window *pWin = *winIt;
866 if(pWin == NULL)
867 continue;
869 pWin->editMField(GlObjectLastReinitializeFieldMask,
870 pWin->_mfGlObjectLastReinitialize);
872 UInt32 lastinv = pWin->getGlObjectEventCounter() + 1;
874 MFUInt32 &field = pWin->_mfGlObjectLastReinitialize;
876 if(field.size() <= osgId)
877 field.resize(osgId + 1, 0);
879 // is it already validated?
880 if(field[osgId] == 0)
881 continue;
883 field[osgId] = lastinv;
885 pWin->setGlObjectEventCounter(lastinv);
890 /*! Reset the GL object status counters for the given GL objects
891 in all Windows.
892 This function must be called while holding _staticWindowLock.
894 See \ref PageSystemOGLObjects for a description of the OpenGL object
895 concept.
897 void Window::resetGLObjectStatus(UInt32 osgId, UInt32 num)
899 if(osgId == 0)
901 SWARNING << "Window::resetGLObject: osgId is 0." << std::endl;
902 return;
905 WindowStore::const_iterator winIt = _allWindows.begin();
906 WindowStore::const_iterator winEnd = _allWindows.end ();
908 for(; winIt != winEnd; ++winIt)
910 Window *pWin = *winIt;
912 if(pWin == NULL)
913 continue;
915 pWin->doResetGLObjectStatus(osgId, num);
919 /*! Reset the GL object status counters for the given GL objects
920 in this window.
922 See \ref PageSystemOGLObjects for a description of the OpenGL object
923 concept.
925 void Window::doResetGLObjectStatus(UInt32 osgId, UInt32 num)
927 editMField(GlObjectLastReinitializeFieldMask, _mfGlObjectLastReinitialize);
928 editMField(GlObjectLastRefreshFieldMask, _mfGlObjectLastRefresh );
930 if(_mfGlObjectLastReinitialize.size() < osgId + num)
931 _mfGlObjectLastReinitialize.resize(osgId + num, 0);
933 if(_mfGlObjectLastRefresh.size() < osgId + num)
934 _mfGlObjectLastRefresh.resize(osgId + num, 0);
936 if(_lastValidate.size() < osgId + num)
937 _lastValidate.resize(osgId + num, 0);
939 for(UInt32 i = osgId; i < osgId + num; ++i)
941 _mfGlObjectLastReinitialize[i] = 0;
942 _mfGlObjectLastRefresh [i] = 0;
943 _lastValidate [i] = 0;
947 /*! Mark the given objects for destruction. The actual destruction will happen
948 later.
950 See \ref PageSystemOGLObjects for a description of the OpenGL object
951 concept.
954 void OSG::Window::destroyGLObject(UInt32 osgId, UInt32 num)
956 #ifdef OSG_DEBUG
957 if(osgId >= _glObjects.size() || _glObjects[osgId] == NULL)
959 FWARNING(("Window::destroyGLObject: object %d is NULL!\n", osgId));
960 return;
962 #endif
964 // Has this object ever been used?
965 if(_glObjects[osgId] && _glObjects[osgId]->getRefCounter() == 0)
967 if(_glObjects[osgId])
968 delete _glObjects[osgId];
970 for(UInt32 j = 0; j < num ; j++)
972 _glObjects[osgId + j] = NULL;
975 return;
978 staticAcquire();
980 WindowStore::const_iterator winIt = _allWindows.begin();
981 WindowStore::const_iterator winEnd = _allWindows.end ();
983 for(; winIt != winEnd; ++winIt)
985 Window *pWin = *winIt;
987 if(pWin == NULL)
988 continue;
990 if(osgId + num > pWin->_mfGlObjectLastReinitialize.size())
992 // this can happen if a GLObject is temporarily created in one
993 // aspect, used there and then discarded without ever being
994 // synced to other aspects.
995 // if it can happen and nothing is wrong we don't warn. (GV)
997 #ifdef OSG_DEBUGX
998 FWARNING(("Window(%p)::destroyGLObject: id %d + num %d exceed "
999 "registered objects size %d!\n", pWin, osgId, num,
1000 pWin->_mfGlObjectLastReinitialize.size()));
1001 #endif
1002 continue;
1005 // has the object been used in this context at all?
1006 if(pWin->getGlObjectLastReinitialize(osgId) != 0)
1007 pWin->_glObjectDestroyList.push_back(DestroyEntry(osgId, num));
1010 staticRelease();
1014 /*----------------------- GL extension handling ---------------------------*/
1017 /*! Register a new OpenGL extension.
1019 Ignores NULL strings.
1020 See \ref PageSystemOGLExt for details.
1022 UInt32 OSG::Window::registerExtension(const Char8 *s)
1024 FDEBUG(("Window::registerExtension: register '%s': \n", s));
1026 staticAcquire();
1028 if(s == NULL)
1030 staticRelease();
1031 return TypeTraits<UInt32>::getMax();
1034 // Check if it has already been registered and if it has then return the
1035 // index we already used.
1036 Int32 r = getExtensionIdX(s);
1038 if(-1 != r)
1040 FPDEBUG(("reusing id %d\n", r));
1042 else
1044 r = Int32(_registeredExtensions.size());
1046 _registeredExtensions.push_back(s);
1048 FPDEBUG(("new id %d\n", r));
1051 staticRelease();
1052 return r;
1055 /*! Check if the Window supports the given extension.
1056 Should be used for initialisation checks only, for checks done often it's
1057 recommended to register the extensions and use hasExtension(UInt32)
1058 instead.
1061 bool OSG::Window::hasExtension(const Char8 *s)
1063 if(_sfIgnoreAllExtensions.getValue() == true)
1064 return false;
1066 if(std::find(_ignoredExtensions.begin(),
1067 _ignoredExtensions.end(),
1068 s) != _ignoredExtensions.end())
1070 return false;
1073 if(std::find(_extensions.begin(),
1074 _extensions.end(),
1075 s) != _extensions.end())
1077 return true;
1080 return false;
1083 /*! Register new OpenGL extensions to ignore. See \ref PageSystemOGLExt
1084 for details.
1085 These extensions get added to _ignoredExtensions and are prevented from
1086 being looked up.
1089 void OSG::Window::ignoreExtensions(const Char8 *s)
1091 FDEBUG(("Window:: Ignoring extensions '%s'\n", s));
1093 staticAcquire();
1095 std::back_insert_iterator< std::vector<std::string> >
1096 extension_back_inserter(_ignoredExtensions);
1098 std::string toex(s);
1100 for(string_token_iterator ignit = string_token_iterator(toex, ",. ");
1101 ignit != string_token_iterator(); ++ignit)
1103 std::string ignore = *ignit;
1105 FDEBUG(("Ignoring '%s':", ignore.c_str()));
1107 if(std::find(_ignoredExtensions.begin(),
1108 _ignoredExtensions.end(),
1109 ignore.c_str()) != _ignoredExtensions.end())
1111 FPDEBUG((" already ignored.\n"));
1112 continue;
1115 _ignoredExtensions.push_back(ignore);
1117 std::vector<std::string>::iterator regit;
1119 // if extension is registered, disable it on all existing Windows
1121 regit = std::find(_registeredExtensions.begin(),
1122 _registeredExtensions.end(),
1123 ignore.c_str());
1125 Int32 ind = -1;
1127 if(regit != _registeredExtensions.end())
1129 ind = regit - _registeredExtensions.begin();
1130 FPDEBUG(("(reg as %d)", ind));
1133 // Walk all existing windows and remove the ignored extension
1134 // from the _extensions vector. Disable it if it was a registered one.
1136 WindowStore::const_iterator winIt = _allWindows.begin();
1137 WindowStore::const_iterator winEnd = _allWindows.end ();
1139 for(; winIt != winEnd; ++winIt)
1141 FPDEBUG((" %p:", static_cast<void *>(winIt->get())));
1143 std::vector<std::string>::iterator extit;
1145 extit = std::find((*winIt)->_extensions.begin(),
1146 (*winIt)->_extensions.end(),
1147 ignore.c_str());
1149 if(extit != (*winIt)->_extensions.end())
1151 FPDEBUG((" removed"));
1152 (*winIt)->_extensions.erase(extit);
1154 else
1156 FPDEBUG((" nonsupp"));
1159 if(ind >= 0)
1161 if((*winIt)->_availExtensions.size() > UInt32(ind))
1163 (*winIt)->_availExtensions[ind] = false;
1164 FPDEBUG((" disabled"));
1166 if((*winIt)->_commonExtensions.size() > UInt32(ind))
1168 (*winIt)->_commonExtensions[ind] = false;
1169 FPDEBUG((" uncommoned"));
1173 FPDEBUG(("\n"));
1176 std::sort(_ignoredExtensions.begin(), _ignoredExtensions.end());
1178 staticRelease();
1181 /*! Register a new OpenGL extension function. See \ref PageSystemOGLExt for
1182 details. Ignores NULL strings.
1185 UInt32 OSG::Window::registerFunction(const Char8 *s,
1186 Int32 ext,
1187 UInt32 version)
1189 if(s == NULL)
1190 return TypeTraits<UInt32>::getMax();
1192 FDEBUG(("Window::registerFunction: register '%s': \n", s));
1194 staticAcquire();
1196 std::vector<std::string>::iterator i;
1198 i = std::find(_registeredFunctions.begin(), _registeredFunctions.end(),
1201 if(i < _registeredFunctions.end())
1203 staticRelease();
1204 FDEBUG(("reusing id %td\n", i - _registeredFunctions.begin()));
1205 return i - _registeredFunctions.begin();
1208 UInt32 r = UInt32(_registeredFunctions.size());
1210 _registeredFunctions .push_back(s);
1211 _registeredFunctionExts .push_back(ext);
1212 _registeredFunctionVersions.push_back(version);
1214 FPDEBUG(("new id %d\n", r));
1216 staticRelease();
1217 return r;
1220 /*! Register a new OpenGL constant. See \ref PageSystemOGLExt for
1221 details.
1224 void OSG::Window::registerConstant(GLenum val)
1226 staticAcquire();
1228 if(std::find(_registeredConstants.begin(),
1229 _registeredConstants.end (),
1230 val ) == _registeredConstants.end())
1232 _registeredConstants.push_back(val);
1235 staticRelease();
1238 #endif // remove the OpenGL object handling from user docs
1240 /*! Dump all the registered extensions to std::cout.
1242 See \ref PageSystemOGLObjects for a description of the OpenGL object
1243 concept.
1246 void OSG::Window::dumpExtensions(void)
1248 std::vector<std::string>::iterator it;
1249 std::cout << "GL Extensions: ";
1251 for(it = _extensions.begin(); it != _extensions.end(); ++it)
1253 std::cout << it->c_str() << ", ";
1256 std::cout << std::endl;
1259 void OSG::Window::doTerminate(void)
1261 if(_pContextThread != NULL)
1263 if(_pContextThread->isRunning() == true)
1265 fprintf(stderr, "Terminate draw thread %p | %p\n",
1266 static_cast<void *>(this),
1267 static_cast<void *>(_pActivateTask.get()));
1269 if(0x0000 != (_sfDrawMode.getValue() & ExternalContext))
1271 this->doDeactivate();
1273 _pContextThread->queueTask(_pActivateTask);
1276 _pContextThread->queueTask(
1277 new WindowDrawTask(WindowDrawTask::EndThread));
1279 Thread::join(_pContextThread);
1281 else
1283 if((_sfDrawMode.getValue() & PartitionDrawMask) ==
1284 SequentialPartitionDraw)
1286 activate ();
1287 doFrameExit(); // after frame cleanup: delete dead GL objects
1288 deactivate ();
1293 _pContextThread = NULL;
1296 /*! Do everything that needs to be done before the Window is redrawn. This
1297 function has to be called for every frame the Window is drawn.
1299 The convenience functions render and draw take care of it, if they are
1300 used.
1302 The main task currently is checking and updating OpenGL extensions.
1305 void OSG::Window::doFrameInit(bool reinitExtFuctions)
1307 static bool ignoreEnvDone = false;
1309 if(!ignoreEnvDone)
1311 ignoreEnvDone = true;
1313 Char8 *p = getenv(OSG_NAMESPACE_PREFIX"_IGNORE_EXTENSIONS");
1315 if(p)
1316 ignoreExtensions(p);
1319 // get version/extensions and split them
1320 if(_extensions.empty())
1322 const char *version =
1323 reinterpret_cast<const char *>(glGetString(GL_VERSION));
1325 #if defined(OSG_OGL_ES2) && !defined(OSG_OGL_ES2_SIMGL3)
1326 UInt32 uiVersionOff = 10;
1327 #else
1328 UInt32 uiVersionOff = 0;
1329 #endif
1330 if(version != NULL)
1332 int major = atoi(version + uiVersionOff);
1333 int minor = atoi(strchr(version + uiVersionOff, '.') + 1);
1335 _glVersion = (major << 8) + minor;
1337 else
1339 FFATAL(("Window::frameInit: Couldn't detect OpenGL version "
1340 "assuming version 1.1!\n"));
1341 _glVersion = (1 << 8) + 1;
1344 #ifdef __APPLE__
1346 const char* glVendor =
1347 reinterpret_cast<const char *>(glGetString(GL_VENDOR));
1348 const char* glRenderer =
1349 reinterpret_cast<const char *>(glGetString(GL_RENDERER));
1351 if(glVendor != NULL && glRenderer != NULL)
1353 // TODO; is there a better way to switch some
1354 // extentions for a specific os/vendor/renderer combo
1355 FLOG (( "GL Vendor/Renderer: %s/%s\n", glVendor, glRenderer ));
1357 if ( strstr(glVendor, "ATI") && strstr(glRenderer,"X1600") )
1359 FWARNING (("Switch of non_power_of_two for ATI\n"));
1360 ignoreExtensions("GL_ARB_texture_non_power_of_two");
1364 #endif // __APPLE
1366 #if defined(OSG_USE_OGL3_PROTOS) || \
1367 defined(OSG_USE_OGL4_PROTOS) || \
1368 defined(OSG_OGL_ES2_SIMGL3) || \
1369 (defined(OSG_OGL_COREONLY) && !defined(OSG_OGL_ES2))
1371 Int32 iNumExtensions = 0;
1373 glGetIntegerv(GL_NUM_EXTENSIONS, &iNumExtensions);
1375 OSGGETGLFUNCBYNAME_GL3(glGetStringi,
1376 osgGlGetStringi,
1377 "glGetStringi",
1378 this);
1380 for(Int32 i = 0; i < iNumExtensions; ++i)
1382 std::string gl_extension =
1383 reinterpret_cast<const char *>(osgGlGetStringi(GL_EXTENSIONS,
1384 i ));
1386 if(! std::binary_search(_ignoredExtensions.begin(),
1387 _ignoredExtensions.end(),
1388 gl_extension))
1390 _extensions.push_back(gl_extension);
1394 #else
1396 const char *gl_extensions =
1397 reinterpret_cast<const char*> (glGetString(GL_EXTENSIONS));
1399 FDEBUG(("Window %p: GL Version: %4x ('%s')\n",
1400 static_cast<void *>(this),
1401 _glVersion, glGetString(GL_VERSION) ));
1403 FDEBUG(("Window %p: GL Extensions: %s\n",
1404 static_cast<void *>(this), gl_extensions));
1406 std::string foo(gl_extensions != NULL ? gl_extensions : "");
1408 FDEBUG(("Window %p: Ignored extensions: ", static_cast<void *>(this)));
1410 for(string_token_iterator it = string_token_iterator(foo, ",. ");
1411 it != string_token_iterator(); ++it)
1413 if(! std::binary_search(_ignoredExtensions.begin(),
1414 _ignoredExtensions.end(),
1415 *it))
1417 _extensions.push_back(*it);
1419 else
1421 FPDEBUG(("%s ", (*it).c_str()));
1424 FPDEBUG(("\n"));
1426 #endif
1428 std::sort(_extensions.begin(), _extensions.end());
1430 // if we don't have any extensions, add something anyway
1431 if(_extensions.empty())
1432 _availExtensions.resize(_registeredExtensions.size(), false);
1435 // any new extension registered ?
1436 if(_registeredExtensions.size() > _availExtensions.size())
1438 staticAcquire();
1439 FDEBUG(("Window %p: exts: ", static_cast<void *>(this)));
1441 while(_registeredExtensions.size() > _availExtensions.size())
1443 UInt32 s = UInt32(_availExtensions.size());
1445 /* perform a binary search over the retrieved extension strings.
1446 Push back the result as an availability flag for the extension
1447 requested by the application */
1448 bool supported = std::binary_search(
1449 _extensions.begin(),
1450 _extensions.end(),
1451 _registeredExtensions[s]);
1453 /* Is this extension ignored? */
1454 bool ignored = std::binary_search(
1455 _ignoredExtensions.begin(),
1456 _ignoredExtensions.end(),
1457 _registeredExtensions[s]);
1459 _availExtensions.push_back(supported && !ignored);
1461 FPDEBUG(("%s:", _registeredExtensions[s].c_str()));
1463 if(_commonExtensions.size() <= s)
1465 _commonExtensions.push_back(supported && !ignored);
1467 if(supported && !ignored)
1469 FPDEBUG(("ok "));
1471 else if(!supported)
1473 FPDEBUG(("NF "));
1475 else
1477 FPDEBUG(("IGN "));
1480 else if (!supported)
1482 _commonExtensions[s] = false;
1483 FPDEBUG(("NF "));
1485 else
1487 _commonExtensions[s] = false;
1488 FPDEBUG(("IGN "));
1491 FPDEBUG(("\n"));
1493 staticRelease();
1496 if(reinitExtFuctions == true)
1498 _extFunctions.clear();
1501 // any new functions registered ?
1502 while(_registeredFunctions.size() > _extFunctions.size())
1504 const Char8 *s = _registeredFunctions[_extFunctions.size()].c_str();
1505 FPDEBUG(("Window %p: Looking up ext function: %s ... ",
1506 static_cast<void *>(this), s));
1508 Int32 ext = _registeredFunctionExts [_extFunctions.size()];
1509 UInt32 ver = _registeredFunctionVersions[_extFunctions.size()];
1511 GLExtensionFunction func = NULL;
1513 // XXX: I think this should be "and". And what is "ext"?
1514 if(ext == -1 || _availExtensions[ext] == true || _glVersion >= ver)
1516 func = getFunctionByName(s);
1517 if (NULL != func)
1519 FDEBUG((" FOUND\n"));
1521 else
1523 FDEBUG((" NULL\n"));
1526 else
1528 FDEBUG((" N/A\n"));
1531 _extFunctions.push_back(func);
1534 // any new constants registered ?
1535 while(_registeredConstants.size() > _availConstants.size())
1537 std::vector<GLenum>::const_iterator cIt =
1538 _registeredConstants.begin() + _availConstants.size();
1539 std::vector<GLenum>::const_iterator cEnd =
1540 _registeredConstants.end ();
1542 for(; cIt != cEnd; ++cIt)
1544 Vec2f val(unknownConstant, unknownConstant);
1546 glGetFloatv(*cIt, static_cast<GLfloat *>(val.getValues()));
1547 _availConstants[*cIt] = val;
1549 FDEBUG(("Window(%p): Constant 0x%x value is %.3f %.3f\n",
1550 static_cast<void *>(this),
1551 *cIt, val[0], val[1]));
1554 glGetError();
1557 _pTravValidator->incEventCounter();
1560 /*! Do everything that needs to be done after the Window is redrawn. This
1561 function has to be called for every frame the Window is drawn.
1563 The convenience functions render and draw take care of it, if they are
1564 used.
1566 The main task currently is deleting OpenGL objects.
1569 void OSG::Window::doFrameExit(void)
1571 std::list<DestroyEntry>::iterator st,en;
1573 st = _glObjectDestroyList.begin();
1574 en = _glObjectDestroyList.end ();
1576 while(st != en)
1578 UInt32 i = st->first, n = st->second;
1580 GLObject *obj = _glObjects[i];
1582 if(obj == NULL)
1584 FDEBUG(("Window::doFrameExit: objects %d (%d) already destroyed ?\n",
1585 i, n));
1586 ++st;
1587 continue;
1590 FDEBUG(("Window::doFrameExit: Destroying GLObject %d (%d) - GL id %"
1591 PRIUSize "\n",
1592 i, n, getGLObjectId(i)));
1594 UInt32 rc = obj->getRefCounter();
1596 // has the object been used in this context at all?
1597 if(getGlObjectLastReinitialize(i) != 0)
1599 _glObjects[i]->getDestroyFunctor()(&_oEnv, i, destroy);
1600 doResetGLObjectStatus(i, n);
1602 for(UInt32 j = 0; j < n ; j++)
1604 this->setGLObjectId(i+j, 0);
1607 if((rc = _glObjects[ i ]->decRefCounter()) <= 0)
1609 // call functor with the final-flag
1610 _glObjects[i]->getDestroyFunctor()(&_oEnv, i, finaldestroy);
1614 // if the GLObject is removed from each GL-Context, free GLObject-IDs.
1615 if(rc <= 0)
1617 delete _glObjects[i];
1619 for(UInt32 j = 0; j < n ; j++)
1621 _glObjects[i+j] = NULL;
1625 ++st;
1628 _glObjectDestroyList.clear();
1630 // Test for OpenGL errors. Just a little precaution to catch
1631 // stray errors. This is the only OpenGL error test in opt mode
1632 // and it needs to be enabled using the OSG_TEST_GL_ERRORS envvar.
1633 // In debug mode it is always on.
1635 static bool inited = false;
1636 #ifndef OSG_DEBUG
1637 static bool testGLErrors = false;
1638 #else
1639 static bool testGLErrors = true;
1640 #endif
1642 if(!inited)
1644 inited = true;
1645 char *pD = getenv(OSG_NAMESPACE_PREFIX"_DEBUG");
1646 char *pN = getenv(OSG_NAMESPACE_PREFIX"_NO_GL_CHECK_ON_FRAMEEXIT");
1648 if(pD)
1649 testGLErrors = true;
1651 if(pN)
1652 testGLErrors = false;
1655 if(testGLErrors && this->hasContext() == true)
1657 GLenum glerr;
1659 while((glerr = glGetError()) != GL_NO_ERROR)
1661 FWARNING(("Window::frameExit: Caught stray OpenGL "
1662 "error %s (%#x).\n",
1663 gluErrorString(glerr),
1664 glerr));
1666 #ifndef OSG_DEBUG
1667 FWARNING(("Rerun with debug-libraries to get more accurate "
1668 "information.\n"));
1669 #endif
1676 // Query for a GL extension function
1677 // Yes, this is system dependent, but the system dependent parts are
1678 // #ifdefed anyway, and very similar code would show up in a number of places,
1679 // making maintaining it unnecessarily hard
1680 // Note: the order of the cases is important, do not change it!
1682 /*! Query OpenGL for the pointer to an extension function.
1684 This is called internally when extension functions are first cached.
1687 OSG::Window::GLExtensionFunction OSG::Window::getFunctionByName(
1688 const Char8 *s)
1690 GLExtensionFunction retval = NULL;
1692 if(_sfIgnoreAllExtensions.getValue() == true)
1694 return NULL;
1697 FINFO(("Window::getFunctionByName: %s\n", s));
1699 FDEBUG(("Window %p: GL Vendor: %s\n",
1700 static_cast<void *>(this), glGetString(GL_VENDOR)));
1702 #if defined(__APPLE__) && !defined(OSG_OGL_ES2)
1704 if (NSIsSymbolNameDefined(s))
1706 NSSymbol symbol = NSLookupAndBindSymbol(s);
1708 if(symbol != 0)
1709 retval = GLExtensionFunction(NSAddressOfSymbol(symbol));
1711 #elif defined(OSG_EMBEDDED) && defined(WIN32)
1713 retval = (void(__cdecl*)(void)) eglGetProcAddress(s);
1715 #elif defined(WIN32)
1717 retval = (void(__cdecl*)(void)) wglGetProcAddress(s);
1719 #elif defined(__sgi) || defined(__hpux) || \
1720 defined(__linux) || defined(__sun)
1722 /* Workaround for multiple nVidia/Linux installation bugs, based on
1723 code by
1724 Manfred Weiler (Patch 783637)
1727 static void (*(*__GetProcAddress)(const GLubyte *))(void) = NULL;
1729 static void *libHandle = NULL;
1730 std::string libHandleName;
1732 // If we haven't found the library previously, then look for it.
1733 if(libHandle == NULL)
1735 libHandle = dlopen(_glLibraryName, RTLD_NOW | RTLD_LOCAL);
1737 if(!libHandle)
1739 FWARNING(("Error in dlopen when opening GL lib: %s\n",dlerror()));
1740 abort();
1742 else
1744 libHandleName = (_glLibraryName == NULL ? "(executable)"
1745 : _glLibraryName);
1746 FDEBUG(("Opened lib %s for GL extension handling.\n",
1747 libHandleName.c_str()));
1751 if(__GetProcAddress == NULL)
1753 FINFO(("Finding glxGetProcAddress method: "));
1755 #ifdef TRY_USING_GLXGETPROC_DIRECTLY
1757 // Try pulling in ARB function directly.
1759 #ifdef GLX_ARB_get_proc_address
1760 if(__GetProcAddress == NULL)
1762 __GetProcAddress = glXGetProcAddressARB;
1763 FINFO((" Using glxGetProcAddressARB directly.\n"));
1765 #endif
1767 // If GLX version is 1.4 or greater then the method should exist.
1768 #ifdef GLX_VERSION_1_4
1769 if(__GetProcAddress == NULL)
1771 __GetProcAddress = glXGetProcAddress;
1772 FPINFO((" Using glxGetProcAddress directly.\n"));
1774 #endif
1775 #endif
1776 if(__GetProcAddress == NULL)
1778 __GetProcAddress =
1779 #if __GNUC__ < 4
1780 (void (*(*)(const GLubyte*))())
1781 #else
1782 reinterpret_cast<void (*(*)(const GLubyte*))()>
1783 #endif
1784 (dlsym(libHandle,
1785 "glXGetProcAddressARB"));
1787 if(__GetProcAddress == NULL)
1789 __GetProcAddress =
1790 #if __GNUC__ < 4
1791 (void (*(*)(const GLubyte*))())
1792 #else
1793 reinterpret_cast<void (*(*)(const GLubyte*))()>
1794 #endif
1795 (dlsym(libHandle,
1796 "glXGetProcAddress"));
1798 if(__GetProcAddress == NULL)
1800 // Couldn't find it linked to the executable. Try to open
1801 // libGL.so directly.
1803 dlclose(libHandle);
1805 libHandle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL);
1807 if(!libHandle)
1809 FWARNING(("Error in dlopen: %s\n",dlerror()));
1810 abort();
1812 else
1814 FPINFO((" Using libGL.so directly.\n"));
1817 __GetProcAddress =
1818 #if __GNUC__ < 4
1819 (void (*(*)(const GLubyte*))())
1820 #else
1821 reinterpret_cast<void (*(*)(const GLubyte*))()>
1822 #endif
1823 (dlsym(libHandle, "glXGetProcAddressARB"));
1825 if(__GetProcAddress == NULL)
1827 __GetProcAddress =
1828 #if __GNUC__ < 4
1829 (void (*(*)(const GLubyte*))())
1830 #else
1831 reinterpret_cast<void (*(*)(const GLubyte*))()>
1832 #endif
1833 (dlsym(libHandle, "glXGetProcAddress"));
1837 if(__GetProcAddress == NULL)
1839 FWARNING(("Neither glXGetProcAddress nor "
1840 "glXGetProcAddressARB found! Disabling all "
1841 " extensions for Window %p!\n",
1842 static_cast<void *>(this)));
1844 _availExtensions.clear();
1845 _availExtensions.resize(_registeredExtensions.size(),
1846 false);
1849 else
1851 FPINFO((" Using glXGetProcAddress (from %s).\n",
1852 libHandleName.c_str()));
1855 else
1857 FPINFO(("Using glXGetProcAddressARB (from %s).\n",
1858 libHandleName.c_str()));
1863 if(__GetProcAddress != NULL)
1865 retval =
1866 reinterpret_cast<GLExtensionFunction>(
1867 __GetProcAddress(reinterpret_cast<const GLubyte*>(s)));
1869 else
1871 retval =
1872 #if __GNUC__ < 4
1873 (GLExtensionFunction)
1874 #else
1875 reinterpret_cast<GLExtensionFunction>
1876 #endif
1877 (dlsym(libHandle, s));
1880 #else
1882 FWARNING(("Window::getFunctionByName: couldn't find implementation!\n"
1883 "Please contact the developers at info@opensg.org.\n"));
1885 retval = NULL;
1886 #endif
1888 if(retval == NULL)
1890 FWARNING(("Window::getFunctionByName: Couldn't get function '%s' for "
1891 "Window %p.\n", s, static_cast<void *>(this)));
1893 else
1895 FDEBUG(("Window::getFunctionByName: got function '%s' for "
1896 "Window %p at %p.\n",
1898 static_cast<void *>(this),
1899 reinterpret_cast<void *>(retval)));
1902 return retval;
1906 /*! Return the value of the registered constant, (Inf, Inf) if not
1907 registered or no value received yet.
1909 const Vec2f& OSG::Window::getConstantValuev(GLenum val)
1911 static Vec2f inf(Inf, Inf);
1913 ConstHash::iterator it = _availConstants.find(val);
1915 if(it != _availConstants.end())
1916 return _availConstants[val];
1918 return inf;
1922 /*! Initialize the OpenGL state OpenSG expects. This should be called once
1923 whenever a new Window is opened.
1925 Don't call it directly, call the Window System-specific init() method
1926 instead.
1929 void OSG::Window::setupGL( void )
1931 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1932 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1934 glDepthFunc(GL_LEQUAL );
1935 glEnable (GL_DEPTH_TEST);
1937 #if !defined(OSG_OGL_COREONLY) || defined(OSG_CHECK_COREONLY)
1938 glEnable (GL_NORMALIZE );
1940 // switch off default light
1941 Real32 nul[4]={0.f,0.f,0.f,0.f};
1943 glLightfv(GL_LIGHT0, GL_DIFFUSE, nul);
1944 glLightfv(GL_LIGHT0, GL_SPECULAR, nul);
1945 #endif
1947 _sfRendererInfo.getValue().assign(
1948 reinterpret_cast<const char *>(glGetString(GL_VERSION)));
1950 _sfRendererInfo.getValue() += " - ";
1952 _sfRendererInfo.getValue() +=
1953 reinterpret_cast<const char *>(glGetString(GL_RENDERER));
1955 #ifndef __APPLE__
1956 std::string szVendor =
1957 reinterpret_cast<const char *>(glGetString(GL_VENDOR));
1959 boost::to_lower(szVendor);
1961 std::string::size_type rc = szVendor.find("nvidia", 0);
1963 if(rc != std::string::npos)
1965 _uiOGLFeatures |= HasAttribAliasing;
1967 else
1969 rc = szVendor.find("ati", 0);
1971 if(rc != std::string::npos)
1973 _uiOGLFeatures |= HasVAODListProblems;
1976 #endif
1978 doFrameInit(); // call it to setup extensions
1981 void Window::setupTasks(void)
1983 _pWaitTask = new WindowDrawTask(WindowDrawTask::WaitAtBarrier);
1984 _pSwapTask = new WindowDrawTask(WindowDrawTask::Swap );
1985 _pFrameInitTask = new WindowDrawTask(WindowDrawTask::FrameInit );
1986 _pFrameExitTask = new WindowDrawTask(WindowDrawTask::FrameExit );
1987 _pActivateTask = new WindowDrawTask(WindowDrawTask::Activate );
1990 /*-------------------------- your_category---------------------------------*/
1992 /*! Render the Window using the given RenderAction.
1994 It takes care of all initialisation and cleanup functions and contains just
1995 5 lines of code. If you know that the correct context is active or you want
1996 to delay swaps (and you knwo what you are doing) you can just copy and
1997 manipulate it.
1999 void OSG::Window::render(RenderActionBase *action)
2001 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2003 activate ();
2004 doFrameInit(); // query recently registered GL extensions
2006 if(_mfDrawTasks.empty() == false)
2008 MFDrawTask::const_iterator tIt = _mfDrawTasks.begin();
2009 MFDrawTask::const_iterator tEnd = _mfDrawTasks.end ();
2011 for(; tIt != tEnd; ++tIt)
2013 (*tIt)->execute(this, &_oEnv);
2016 editMField(DrawTasksFieldMask, _mfDrawTasks);
2018 _mfDrawTasks.clear();
2021 doRenderAllViewports(action);
2023 swap ();
2024 doFrameExit(); // after frame cleanup: delete dead GL objects
2025 deactivate ();
2027 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2028 ParallelPartitionDraw)
2030 if(0x0000 != (_sfDrawMode.getValue() & ExternalContext))
2032 this->doDeactivate();
2035 OSG_ASSERT(_pContextThread != NULL);
2037 if(_pWaitTask == NULL)
2039 setupTasks();
2042 if(_pContextThread->isRunning() == false)
2044 WindowDrawThread *pDrawThread =
2045 dynamic_cast<WindowDrawThread *>(_pContextThread.get());
2047 OSG_ASSERT(pDrawThread != NULL);
2049 fprintf(stderr, "running partition drawthread r\n");
2051 if(_pInitTask == NULL)
2053 _pInitTask = new WindowDrawTask(WindowDrawTask::Init);
2056 pDrawThread->queueTaskFront(_pInitTask);
2058 pDrawThread->setWindow(this);
2059 pDrawThread->run(Thread::getCurrentAspect());
2061 _pInitTask = NULL;
2063 _pContextThread->queueTask(_pWaitTask);
2065 _pWaitTask->waitForBarrier();
2069 #ifdef OSG_WIN_QUEUE_ALL
2070 _pContextThread->queueTask(_pWaitTask);
2071 #endif
2073 if(0x0000 != (_sfDrawMode.getValue() & ExternalContext))
2075 _pContextThread->queueTask(_pActivateTask );
2078 _pContextThread->queueTask(_pFrameInitTask);
2080 if(_mfDrawTasks.empty() == false)
2082 MFDrawTask::const_iterator tIt = _mfDrawTasks.begin();
2083 MFDrawTask::const_iterator tEnd = _mfDrawTasks.end ();
2085 for(; tIt != tEnd; ++tIt)
2087 _pContextThread->queueTask(*tIt);
2090 editMField(DrawTasksFieldMask, _mfDrawTasks);
2092 _mfDrawTasks.clear();
2095 doRenderAllViewports(action);
2097 #ifdef OSG_WIN_QUEUE_ALL
2098 // _pDrawThread->dumpTasks();
2100 _pWaitTask->waitForBarrier();
2101 #endif
2103 if(0x0000 == (_sfDrawMode.getValue() & PassiveContext))
2105 _pContextThread->queueTask(_pSwapTask);
2108 _pContextThread->queueTask(_pFrameExitTask);
2110 if(0x0000 == (_sfDrawMode.getValue() & ExternalContext))
2112 _pContextThread->queueTask(_pWaitTask );
2114 _pWaitTask->waitForBarrier();
2116 else
2118 if(0x0000 != (_sfDrawMode.getValue() & PassiveContext))
2120 if(action->getUseGLFinish() == false)
2122 if(_pGLFinishTask == NULL)
2124 _pGLFinishTask =
2125 new RenderActionTask(
2126 RenderActionTask::HandleGLFinishNoWait);
2129 _pContextThread->queueTask(_pGLFinishTask);
2133 if(_pDeactivateTask == NULL)
2135 _pDeactivateTask =
2136 new WindowDrawTask(WindowDrawTask::DeactivateAndWait);
2139 _pContextThread->queueTask(_pDeactivateTask);
2141 _pDeactivateTask->waitForBarrier();
2143 this->doActivate();
2146 else
2148 fprintf(stderr, "Unknow partition draw mode\n");
2152 void OSG::Window::renderNoFinish(RenderActionBase *action)
2154 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2156 activate ();
2157 doFrameInit(); // query recently registered GL extensions
2159 if(_mfDrawTasks.empty() == false)
2161 MFDrawTask::const_iterator tIt = _mfDrawTasks.begin();
2162 MFDrawTask::const_iterator tEnd = _mfDrawTasks.end ();
2164 for(; tIt != tEnd; ++tIt)
2166 (*tIt)->execute(this, &_oEnv);
2169 editMField(DrawTasksFieldMask, _mfDrawTasks);
2171 _mfDrawTasks.clear();
2174 doRenderAllViewports(action);
2176 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2177 ParallelPartitionDraw)
2179 OSG_ASSERT(_pContextThread != NULL);
2181 if(_pWaitTask == NULL)
2183 setupTasks();
2186 if(_pContextThread->isRunning() == false)
2188 WindowDrawThread *pDrawThread =
2189 dynamic_cast<WindowDrawThread *>(_pContextThread.get());
2191 OSG_ASSERT(pDrawThread != NULL);
2193 fprintf(stderr, "running partition drawthread rnf\n");
2195 if(_pInitTask == NULL)
2197 _pInitTask = new WindowDrawTask(WindowDrawTask::Init);
2200 pDrawThread->queueTaskFront(_pInitTask);
2202 pDrawThread->setWindow(this);
2203 pDrawThread->run(Thread::getCurrentAspect());
2205 _pInitTask = NULL;
2207 _pContextThread->queueTask(_pWaitTask);
2209 _pWaitTask->waitForBarrier();
2212 if(_mfDrawTasks.empty() == false)
2214 MFDrawTask::const_iterator tIt = _mfDrawTasks.begin();
2215 MFDrawTask::const_iterator tEnd = _mfDrawTasks.end ();
2217 for(; tIt != tEnd; ++tIt)
2219 _pContextThread->queueTask(*tIt);
2222 editMField(DrawTasksFieldMask, _mfDrawTasks);
2224 _mfDrawTasks.clear();
2227 this->doRenderAllViewports(action);
2229 else
2231 fprintf(stderr, "Unknow partition draw mode\n");
2235 void OSG::Window::frameFinish(bool bActivate)
2237 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2239 if(bActivate == true)
2240 activate();
2242 swap ();
2243 doFrameExit(); // after frame cleanup: delete dead GL objects
2246 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2247 ParallelPartitionDraw)
2249 OSG_ASSERT(_pContextThread != NULL);
2251 if(_pWaitTask == NULL || _pContextThread->isRunning() == false)
2253 fprintf(stderr, "Window::frameFinish::frame not started\n");
2256 if(bActivate == true)
2257 _pContextThread->queueTask(_pActivateTask);
2259 _pContextThread->queueTask(_pSwapTask );
2261 _pContextThread->queueTask(_pFrameExitTask);
2263 _pContextThread->queueTask(_pWaitTask );
2265 _pWaitTask->waitForBarrier();
2267 else
2269 fprintf(stderr, "Unknow partition draw mode\n");
2273 void OSG::Window::runFrameExit(void)
2275 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2277 activate ();
2278 doFrameExit (); // after frame cleanup: delete dead GL objects
2279 deactivate();
2281 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2282 ParallelPartitionDraw)
2284 if(_pWaitTask == NULL || _pContextThread->isRunning() == false)
2286 fprintf(stderr, "Window::runFrameExit::frame not started\n");
2289 _pContextThread->queueTask(_pActivateTask);
2290 _pContextThread->queueTask(_pFrameExitTask);
2292 _pContextThread->queueTask(_pWaitTask );
2294 _pWaitTask->waitForBarrier();
2296 else
2298 fprintf(stderr, "Unknow partition draw mode\n");
2302 void Window::activate(void)
2304 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2306 if(0x0000 == (_sfDrawMode.getValue() & PassiveContext))
2308 this->doActivate();
2313 void Window::deactivate(void)
2315 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2317 if(0x0000 == (_sfDrawMode.getValue() & PassiveContext))
2319 this->doDeactivate();
2324 // swap front and back buffers
2325 bool Window::swap(void)
2327 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2329 if(0x0000 == (_sfDrawMode.getValue() & PassiveContext))
2331 return this->doSwap();
2335 return true;
2338 void OSG::Window::frameInit(void)
2340 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2342 this->doFrameInit();
2346 void OSG::Window::frameExit(void)
2348 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2350 this->doFrameExit();
2354 void OSG::Window::renderAllViewports(RenderActionBase *action)
2356 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2358 this->doRenderAllViewports(action);
2362 /*! Render all the Viewports of the Window using the given RenderAction.
2364 A simple convenience function that loops all Viewports and call their draw
2365 method.
2368 void OSG::Window::doRenderAllViewports(RenderActionBase *action)
2370 if(action != NULL)
2372 commitChanges();
2374 MFUnrecChildViewportPtr::const_iterator portIt = getMFPort()->begin();
2375 MFUnrecChildViewportPtr::const_iterator portEnd = getMFPort()->end ();
2376 Int32 iVPId = 0;
2378 action->setWindow(this);
2380 if(this->getDrawerId() < 0)
2382 action->setDrawerId(this->_windowId);
2384 else
2386 action->setDrawerId(this->getDrawerId());
2389 if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2390 SequentialPartitionDraw)
2392 action->setDrawPartPar(false);
2394 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2395 ParallelPartitionDraw)
2397 action->setDrawPartPar(true);
2400 action->frameInit();
2402 for(; portIt != portEnd; ++portIt, ++iVPId)
2404 if((*portIt)->getDrawableId() < 0)
2406 action->setDrawableId(iVPId);
2408 else
2410 action->setDrawableId((*portIt)->getDrawableId());
2413 if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2414 SequentialPartitionDraw)
2416 (*portIt)->render(action);
2418 else if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2419 ParallelPartitionDraw)
2421 (*portIt)->render(action);
2423 #if 0
2424 OSG_ASSERT(_pWaitTask != NULL);
2426 _pContextThread->queueTask(_pWaitTask );
2428 _pWaitTask->waitForBarrier();
2429 #endif
2433 else
2435 SWARNING << "Window::renderAllViewports: no action!" << std::endl;
2439 /*! Resize notifier function.
2441 As OpenSG does not do Window System event management it needs to be
2442 notified whenever the size of a Window changes.
2445 void OSG::Window::resize( int width, int height )
2447 setWidth (width );
2448 setHeight (height);
2452 void OSG::Window::init(GLInitFunctor oFunc)
2454 if((_sfDrawMode.getValue() & PartitionDrawMask) == SequentialPartitionDraw)
2456 this->activate();
2458 setupGL();
2460 if(oFunc)
2461 oFunc();
2463 this->deactivate();
2465 else if((_sfDrawMode.getValue() & DrawerMask) == StdDrawer)
2467 if(_pInitTask == NULL)
2469 _pInitTask = new WindowDrawTask(WindowDrawTask::Init);
2472 _pInitTask->setInitFunc(oFunc);
2474 OSG_ASSERT(_pContextThread != NULL);
2476 if(_pContextThread->isRunning() == false)
2478 WindowDrawThread *pDrawThread =
2479 dynamic_cast<WindowDrawThread *>(_pContextThread.get());
2481 OSG_ASSERT(pDrawThread != NULL);
2483 fprintf(stderr, "running partition drawthread init\n");
2485 pDrawThread->queueTaskFront(_pInitTask);
2487 pDrawThread->setWindow(this);
2488 pDrawThread->run(Thread::getCurrentAspect());
2490 _pInitTask = NULL;
2493 if(_pWaitTask == NULL)
2495 setupTasks();
2498 _pContextThread->queueTask(_pWaitTask);
2500 _pWaitTask->waitForBarrier();
2502 else
2504 fprintf(stderr, "Unknown partition draw mode 0x%04x\n",
2505 _sfDrawMode.getValue());
2509 void OSG::Window::requestStageRun(Int32 iStageId)
2511 if(iStageId < 0)
2513 SWARNING << "Window::requestStageRun: id is < 0!" << std::endl;
2514 return;
2517 WindowStore::const_iterator winIt = _allWindows.begin();
2518 WindowStore::const_iterator winEnd = _allWindows.end ();
2520 for(; winIt != winEnd; ++winIt)
2522 Window *pWin = *winIt;
2524 if(pWin == NULL)
2525 continue;
2527 pWin->_pTravValidator->requestRun(iStageId);
2531 /*------------------------------- dump ----------------------------------*/
2533 /*! output the instance for debug purposes
2535 void OSG::Window::dump( UInt32 OSG_CHECK_ARG(uiIndent),
2536 const BitVector OSG_CHECK_ARG(bvFlags )) const
2538 SLOG << "Dump Window NI" << std::endl;
2541 void Window::staticDump(void)
2543 fprintf(stderr, "Window::sdump %zd %zd\n",
2544 _glObjects.size(),
2545 _glObjects.capacity());
2547 for(UInt32 i = 0; i < _glObjects.size(); ++i)
2549 fprintf(stderr, "gl[%d] = %p\n", i, static_cast<void *>(_glObjects[i]));
2553 void Window::resolveLinks(void)
2555 if(_pShaderCache != NULL)
2557 _pShaderCache->clear();
2560 Inherited::resolveLinks();
2563 void Window::queueTaskFromDrawer(DrawTask *pTask)
2565 if(pTask == NULL)
2566 return;
2568 OSG_ASSERT(_pContextThread != NULL);
2570 if((_sfDrawMode.getValue() & PartitionDrawMask) == ParallelPartitionDraw)
2572 _pContextThread->queueTask(pTask);
2574 else
2576 pTask->execute(this, &_oEnv);
2580 void Window::queueTask(DrawTask *pTask)
2582 if(pTask == NULL)
2583 return;
2585 if((_sfDrawMode.getValue() & DrawerMask) == StdDrawer)
2587 if((_sfDrawMode.getValue() & PartitionDrawMask) ==
2588 ParallelPartitionDraw)
2590 if(0x0000 != (_sfDrawMode.getValue() & ExternalContext))
2592 editMField(DrawTasksFieldMask, _mfDrawTasks);
2594 _mfDrawTasks.push_back(pTask);
2596 else
2598 OSG_ASSERT(_pContextThread != NULL);
2600 _pContextThread->queueTask(pTask);
2603 else
2605 editMField(DrawTasksFieldMask, _mfDrawTasks);
2607 _mfDrawTasks.push_back(pTask);
2610 else if((_sfDrawMode.getValue() & DrawerMask) == ParallelDrawer)
2612 editMField(DrawTasksFieldMask, _mfDrawTasks);
2614 _mfDrawTasks.push_back(pTask);
2618 void OSG::Window::queueGlobalTask(DrawTask *pTask)
2620 if(pTask == NULL)
2621 return;
2623 WindowStore::const_iterator winIt = _allWindows.begin();
2624 WindowStore::const_iterator winEnd = _allWindows.end ();
2626 for(; winIt != winEnd; ++winIt)
2628 Window *pWin = *winIt;
2630 if(pWin == NULL)
2631 continue;
2633 pWin->queueTask(pTask);
2637 void Window::submitTask(HardwareContextTask *pTask)
2639 if(pTask == NULL)
2640 return;
2642 OSG_ASSERT(_pContextThread != NULL);
2644 if((_sfDrawMode.getValue() & PartitionDrawMask) == ParallelPartitionDraw)
2646 _pContextThread->queueTask(pTask);
2648 else
2650 pTask->execute(this, &_oEnv);
2654 void Window::submitTaskAndWait(BlockingTask *pTask)
2656 if(pTask == NULL)
2657 return;
2659 OSG_ASSERT(_pContextThread != NULL);
2661 if((_sfDrawMode.getValue() & PartitionDrawMask) == ParallelPartitionDraw)
2663 pTask->activateBarrier(true);
2664 pTask->setNumWaitFor(2);
2666 _pContextThread->queueTask(pTask);
2668 pTask->waitForBarrier();
2670 else
2672 pTask->execute(this, &_oEnv);
2676 void Window::pushToDrawTasks(DrawTask * const value)
2678 if(value == NULL)
2679 return;
2681 editMField(DrawTasksFieldMask, _mfDrawTasks);
2683 _mfDrawTasks.push_back(value);
2686 void Window::clearDrawTasks(void)
2688 editMField(DrawTasksFieldMask, _mfDrawTasks);
2690 _mfDrawTasks.clear();
2693 OSG_END_NAMESPACE