diff --git a/examples/osgsimplepager/osgsimplepager.cpp b/examples/osgsimplepager/osgsimplepager.cpp index 83775174b..0f72c5c0f 100644 --- a/examples/osgsimplepager/osgsimplepager.cpp +++ b/examples/osgsimplepager/osgsimplepager.cpp @@ -144,6 +144,9 @@ int main( int argc, char **argv ) // setting frame block to true can help achieve constant frame rates on single CPU systems. databasePager->setUseFrameBlock(false); + // set whether to pre compile GL objects before merging new subgraphs with main scene graph + databasePager->setCompileGLObjectsForContextID(sceneView->getState()->getContextID(),true); + // register any PagedLOD that need to be tracked in the scene graph databasePager->registerPagedLODs(sceneView->getSceneData()); diff --git a/examples/osgsimulation/osgsimulation.cpp b/examples/osgsimulation/osgsimulation.cpp index 76a4d9ce0..a4732d464 100644 --- a/examples/osgsimulation/osgsimulation.cpp +++ b/examples/osgsimulation/osgsimulation.cpp @@ -81,6 +81,74 @@ osg::Node* createEarth() } +class ModelPositionCallback : public osg::NodeCallback +{ +public: + + ModelPositionCallback(): + _latitude(0.0), + _longitude(0.0), + _height(1000.0) + {} + + void updateParameters() + { + _longitude += (2.0*osg::PI)/360.0; + } + + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + updateParameters(); + + osg::NodePath nodePath = nv->getNodePath(); + + osg::MatrixTransform* mt = nodePath.empty() ? 0 : dynamic_cast(nodePath.back()); + if (mt) + { + osg::CoordinateSystemNode* csn = 0; + + // find coordinate system node from our parental chain + unsigned int i; + for(i=0; i(nodePath[i]); + } + + if (csn) + { + + + osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel(); + if (ellipsoid) + { + osg::Matrixd matrix; + for(i+=1; iasTransform(); + if (transform) transform->computeLocalToWorldMatrix(matrix, nv); + } + + //osg::Matrixd matrix; + ellipsoid->computeLocalToWorldTransformFromLatLongHeight(_latitude,_longitude,_height,matrix); + matrix.preMult(osg::Matrixd::rotate(_rotation)); + + mt->setMatrix(matrix); + } + + } + } + + traverse(node,nv); + } + + double _latitude; + double _longitude; + double _height; + osg::Quat _rotation; +}; + + class FindNamedNodeVisitor : public osg::NodeVisitor { public: @@ -104,6 +172,11 @@ public: }; +void addModel(osgProducer::Viewer* viewer,osg::Node* model) +{ + +} + int main(int argc, char **argv) { diff --git a/include/osg/Drawable b/include/osg/Drawable index 3019efe44..f9ddd5309 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -116,6 +116,7 @@ class SG_EXPORT Drawable : public Object { public: + static unsigned int s_numberDrawablesReusedLastInLastFrame; static unsigned int s_numberNewDrawablesInLastFrame; static unsigned int s_numberDeletedDrawablesInLastFrame; @@ -352,8 +353,15 @@ class SG_EXPORT Drawable : public Object virtual void drawImplementation(State& state) const = 0; + /** Return a OpenGL display list handle a newly generated or reused from display list cache. */ static GLuint generateDisplayList(unsigned int contextID, unsigned int sizeHint = 0); + /** Set the minimum number of display lists to retain in the deleted display list cache. */ + static void setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum); + + /** Get the minimum number of display lists to retain in the deleted display list cache. */ + static unsigned int getMinimumNumberOfDisplayListsToRetainInCache(); + /** use deleteDisplayList instead of glDeleteList to allow * OpenGL display list to be cached until they can be deleted * by the OpenGL context in which they were created, specified @@ -362,7 +370,11 @@ class SG_EXPORT Drawable : public Object /** flush all the cached display list which need to be deleted * in the OpenGL context related to contextID.*/ - static void flushDeletedDisplayLists(unsigned int contextID,double currentTime, double& availableTime); + static void flushAllDeletedDisplayLists(unsigned int contextID); + + /** flush the cached display list which need to be deleted + * in the OpenGL context related to contextID.*/ + static void flushDeletedDisplayLists(unsigned int contextID,double& availableTime); /** use deleteVertexBufferObject instead of glDeleteList to allow * OpenGL buffer objects to be cached until they can be deleted @@ -764,7 +776,7 @@ inline void Drawable::draw(State& state) const else if (_useDisplayList) { #ifdef USE_SEPARATE_COMPILE_AND_EXECUTE - globj = generateDisplayList(contextID, getGLObjectSizeHint()); // glGenLists( 1 ); + globj = generateDisplayList(contextID, getGLObjectSizeHint()); glNewList( globj, GL_COMPILE ); if (_drawCallback.valid()) _drawCallback->drawImplementation(state,this); @@ -774,7 +786,7 @@ inline void Drawable::draw(State& state) const glCallList( globj); #else - globj = generateDisplayList(contextID, getGLObjectSizeHint()); // glGenLists( 1 ); + globj = generateDisplayList(contextID, getGLObjectSizeHint()); glNewList( globj, GL_COMPILE_AND_EXECUTE ); if (_drawCallback.valid()) _drawCallback->drawImplementation(state,this); diff --git a/include/osg/StateAttribute b/include/osg/StateAttribute index 0644a12de..2c35b088e 100644 --- a/include/osg/StateAttribute +++ b/include/osg/StateAttribute @@ -20,8 +20,6 @@ #include -#define THREAD_SAFE_GLOBJECT_DELETE_LISTS 1 - namespace osg { diff --git a/include/osg/Texture b/include/osg/Texture index d9686447f..6ca1e91bb 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -24,11 +24,6 @@ #include #include -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - #include - #include -#endif - // If not defined by gl.h use the definition found in: // http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_filter_anisotropic.txt #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT @@ -651,80 +646,36 @@ class SG_EXPORT Texture : public osg::StateAttribute * in the specified TextureObjectListMap. */ void takeTextureObjects(TextureObjectListMap& toblm); + + static TextureObject* generateTextureObject(unsigned int contextID,GLenum target); + + static TextureObject* generateTextureObject(unsigned int contextID, + GLenum target, + GLint numMipmapLevels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border); + + + /** Set the minimum number of texture objects to retain in the deleted display list cache. */ + static void setMinimumNumberOfTextureObjectsToRetainInCache(unsigned int minimum); + + /** Get the minimum number of display lists to retain in the deleted display list cache. */ + static unsigned int getMinimumNumberOfTextureObjectsToRetainInCache(); + + static void flushAllDeletedTextureObjects(unsigned int contextID); + + static void flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availableTime); + + + protected: + typedef buffered_object< ref_ptr > TextureObjectBuffer; mutable TextureObjectBuffer _textureObjectBuffer; - class SG_EXPORT TextureObjectManager : public osg::Referenced - { - public: - - TextureObjectManager(): - _expiryDelay(0.0) {} - - virtual TextureObject* generateTextureObject(unsigned int contextID,GLenum target); - - virtual TextureObject* generateTextureObject(unsigned int contextID, - GLenum target, - GLint numMipmapLevels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border); - - virtual TextureObject* reuseTextureObject(unsigned int contextID, - GLenum target, - GLint numMipmapLevels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border); - - inline TextureObject* reuseOrGenerateTextureObject(unsigned int contextID, - GLenum target, - GLint numMipmapLevels, - GLenum internalFormat, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border) - { - TextureObject* to = reuseTextureObject(contextID,target,numMipmapLevels,internalFormat,width,height,depth,border); - if (to) return to; - else return generateTextureObject(contextID,target,numMipmapLevels,internalFormat,width,height,depth,border); - } - - virtual void addTextureObjects(TextureObjectListMap& toblm); - - virtual void addTextureObjectsFrom(Texture& texture); - - virtual void flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime); - - - void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; } - - double getExpiryDelay() const { return _expiryDelay; } - - /** How long to keep unused texture objects before deletion. */ - double _expiryDelay; - - TextureObjectListMap _textureObjectListMap; - -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - // mutex to keep access serialized. - OpenThreads::Mutex _mutex; -#endif - }; - - - static void setTextureObjectManager(TextureObjectManager* tom); - static TextureObjectManager* getTextureObjectManager(); - static void flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime); - - - }; } diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 27b890a58..bcc36e986 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -198,11 +198,11 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl } - /** Turn the compilation of rendering objects for specfied graphics context on (true) or off(false).*/ - void setCompileGLObjectsForContexID(unsigned int contextID, bool on); + /** Turn the compilation of rendering objects for specfied graphics context on (true) or off(false). */ + void setCompileGLObjectsForContextID(unsigned int contextID, bool on); - /** Get whether the compilation of rendering objects for specfied graphics context on (true) or off(false).*/ - bool getCompileGLObjectsForContexID(unsigned int contextID); + /** Get whether the compilation of rendering objects for specfied graphics context on (true) or off(false). */ + bool getCompileGLObjectsForContextID(unsigned int contextID); /** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph. * note, should only be called from the draw thread.*/ @@ -249,6 +249,10 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl virtual ~DatabasePager(); + OpenThreads::Mutex _run_mutex; + bool _startThreadCalled; + + osg::ref_ptr _databasePagerThreadBlock; inline void updateDatabasePagerThreadBlock() diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index 19a24856b..e5d043249 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -414,7 +414,10 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSetting /** Do draw traversal of draw bins generated by cull traversal.*/ virtual void draw(); - /** Flush all the OpenGL objects, such as texture objects, display lists etc.*/ + /** Flush all deleted OpenGL objects, such as texture objects, display lists etc.*/ + virtual void flushAllDeletedGLObjects(); + + /** Flush deleted OpenGL objects, such as texture objects, display lists etc within specified available time.*/ virtual void flushDeletedGLObjects(double& availableTime); protected: diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index be0832644..b759eee2f 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -26,13 +26,12 @@ #include #include -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - #include - #include -#endif +#include +#include using namespace osg; +unsigned int Drawable::s_numberDrawablesReusedLastInLastFrame = 0; unsigned int Drawable::s_numberNewDrawablesInLastFrame = 0; unsigned int Drawable::s_numberDeletedDrawablesInLastFrame = 0; @@ -42,43 +41,72 @@ unsigned int Drawable::s_numberDeletedDrawablesInLastFrame = 0; typedef std::list DisplayListList; typedef std::map DeletedDisplayListCache; -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - static OpenThreads::Mutex s_mutex_deletedDisplayListCache; -#endif - +static OpenThreads::Mutex s_mutex_deletedDisplayListCache; static DeletedDisplayListCache s_deletedDisplayListCache; -GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint) +GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int /*sizeHint*/) { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - OpenThreads::ScopedLock lock(s_mutex_deletedDisplayListCache); -#endif + OpenThreads::ScopedLock lock(s_mutex_deletedDisplayListCache); + DisplayListList& dll = s_deletedDisplayListCache[contextID]; - if (dll.empty()) return glGenLists( 1 ); + if (dll.empty()) + { + ++s_numberNewDrawablesInLastFrame; + return glGenLists( 1 ); + } else { - notify(NOTICE)<<"reusing display list "< lock(s_mutex_deletedDisplayListCache); -#endif + // insert the globj into the cache for the appropriate context. s_deletedDisplayListCache[contextID].push_back(globj); } } -/** flush all the cached display list which need to be deleted - * in the OpenGL context related to contextID.*/ -void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentTime*/, double& availableTime) +void Drawable::flushAllDeletedDisplayLists(unsigned int contextID) +{ + OpenThreads::ScopedLock lock(s_mutex_deletedDisplayListCache); + + DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID); + if (citr!=s_deletedDisplayListCache.end()) + { + DisplayListList& dll = citr->second; + + for(DisplayListList::iterator ditr=dll.begin(); + ditr!=dll.end(); + ++ditr) + { + glDeleteLists(*ditr,1); + } + + dll.clear(); + } +} + +void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availableTime) { // if no time available don't try to flush objects. if (availableTime<=0.0) return; @@ -90,17 +118,15 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentT unsigned int noDeleted = 0; { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedDisplayListCache); -#endif DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID); if (citr!=s_deletedDisplayListCache.end()) { DisplayListList& dll = citr->second; - + for(DisplayListList::iterator ditr=dll.begin(); - ditr!=dll.end() && elapsedTimes_minimumNumberOfDisplayListsToRetainInCache; ) { glDeleteLists(*ditr,1); @@ -114,24 +140,20 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentT } elapsedTime = timer.delta_s(start_tick,timer.tick()); - if (noDeleted) notify(NOTICE)<<"Number display lists deleted = "< lock(s_mutex_deletedVertexBufferObjectCache); -#endif // insert the globj into the cache for the appropriate context. s_deletedVertexBufferObjectCache[contextID].push_back(globj); @@ -151,9 +173,7 @@ void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*c { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedVertexBufferObjectCache); -#endif DeletedDisplayListCache::iterator citr = s_deletedVertexBufferObjectCache.find(contextID); if (citr!=s_deletedVertexBufferObjectCache.end()) @@ -267,11 +287,11 @@ void Drawable::compileGLObjects(State& state) const // call the globj if already set otherwise comple and execute. if( globj != 0 ) - { + { glDeleteLists( globj, 1 ); } - globj = glGenLists( 1 ); + globj = generateDisplayList(contextID, getGLObjectSizeHint()); glNewList( globj, GL_COMPILE ); if (_drawCallback.valid()) diff --git a/src/osg/FragmentProgram.cpp b/src/osg/FragmentProgram.cpp index 606840458..2df8b87ff 100644 --- a/src/osg/FragmentProgram.cpp +++ b/src/osg/FragmentProgram.cpp @@ -18,10 +18,8 @@ #include -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - #include - #include -#endif +#include +#include using namespace osg; @@ -31,18 +29,14 @@ using namespace osg; typedef std::list FragmentProgramObjectList; typedef std::map DeletedFragmentProgramObjectCache; -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - static OpenThreads::Mutex s_mutex_deletedFragmentProgramObjectCache; -#endif +static OpenThreads::Mutex s_mutex_deletedFragmentProgramObjectCache; static DeletedFragmentProgramObjectCache s_deletedFragmentProgramObjectCache; void FragmentProgram::deleteFragmentProgramObject(unsigned int contextID,GLuint handle) { if (handle!=0) { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedFragmentProgramObjectCache); -#endif // insert the handle into the cache for the appropriate context. s_deletedFragmentProgramObjectCache[contextID].push_back(handle); @@ -60,9 +54,7 @@ void FragmentProgram::flushDeletedFragmentProgramObjects(unsigned int contextID, double elapsedTime = 0.0; { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedFragmentProgramObjectCache); -#endif DeletedFragmentProgramObjectCache::iterator citr = s_deletedFragmentProgramObjectCache.find(contextID); if (citr!=s_deletedFragmentProgramObjectCache.end()) diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index 6e984c62c..e44dc741b 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include + using namespace osg; #ifndef GL_TEXTURE_WRAP_R @@ -41,7 +44,80 @@ unsigned int Texture::s_numberTextureReusedLastInLastFrame = 0; unsigned int Texture::s_numberNewTextureInLastFrame = 0; unsigned int Texture::s_numberDeletedTextureInLastFrame = 0; -Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(unsigned int /*contextID*/,GLenum target) +unsigned int s_minimumNumberOfTextureObjectsToRetainInCache = 0; +void Texture::setMinimumNumberOfTextureObjectsToRetainInCache(unsigned int minimum) +{ + s_minimumNumberOfTextureObjectsToRetainInCache = minimum; +} + +unsigned int Texture::getMinimumNumberOfTextureObjectsToRetainInCache() +{ + return s_minimumNumberOfTextureObjectsToRetainInCache; +} + +class SG_EXPORT TextureObjectManager : public osg::Referenced +{ +public: + + TextureObjectManager(): + _expiryDelay(0.0) {} + + virtual Texture::TextureObject* generateTextureObject(unsigned int contextID,GLenum target); + + virtual Texture::TextureObject* generateTextureObject(unsigned int contextID, + GLenum target, + GLint numMipmapLevels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border); + + virtual Texture::TextureObject* reuseTextureObject(unsigned int contextID, + GLenum target, + GLint numMipmapLevels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border); + + inline Texture::TextureObject* reuseOrGenerateTextureObject(unsigned int contextID, + GLenum target, + GLint numMipmapLevels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border) + { + Texture::TextureObject* to = reuseTextureObject(contextID,target,numMipmapLevels,internalFormat,width,height,depth,border); + if (to) return to; + else return generateTextureObject(contextID,target,numMipmapLevels,internalFormat,width,height,depth,border); + } + + void addTextureObjects(Texture::TextureObjectListMap& toblm); + + void addTextureObjectsFrom(Texture& texture); + + void flushAllTextureObjects(unsigned int contextID); + + void flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime); + + void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; } + + double getExpiryDelay() const { return _expiryDelay; } + + /** How long to keep unused texture objects before deletion. */ + double _expiryDelay; + + Texture::TextureObjectListMap _textureObjectListMap; + + // mutex to keep access serialized. + OpenThreads::Mutex _mutex; +}; + +Texture::TextureObject* TextureObjectManager::generateTextureObject(unsigned int /*contextID*/,GLenum target) { GLuint id; glGenTextures( 1L, &id ); @@ -51,7 +127,7 @@ Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(uns static int s_number = 0; -Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(unsigned int /*contextID*/, +Texture::TextureObject* TextureObjectManager::generateTextureObject(unsigned int /*contextID*/, GLenum target, GLint numMipmapLevels, GLenum internalFormat, @@ -61,7 +137,7 @@ Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(uns GLint border) { ++s_number; - ++s_numberNewTextureInLastFrame; + ++Texture::s_numberNewTextureInLastFrame; // notify(NOTICE)<<"creating new texture object "< lock(_mutex); -#endif - TextureObjectList& tol = _textureObjectListMap[contextID]; - for(TextureObjectList::iterator itr = tol.begin(); + Texture::TextureObjectList& tol = _textureObjectListMap[contextID]; + for(Texture::TextureObjectList::iterator itr = tol.begin(); itr != tol.end(); ++itr) { @@ -97,7 +171,7 @@ Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsign // notify(NOTICE)<<"reusing texture object "< lock(_mutex); -#endif - for(TextureObjectListMap::iterator itr = toblm.begin(); + for(Texture::TextureObjectListMap::iterator itr = toblm.begin(); itr != toblm.end(); ++itr) { - TextureObjectList& tol = _textureObjectListMap[itr->first]; + Texture::TextureObjectList& tol = _textureObjectListMap[itr->first]; tol.insert(tol.end(),itr->second.begin(),itr->second.end()); } } -void Texture::TextureObjectManager::addTextureObjectsFrom(Texture& texture) +void TextureObjectManager::addTextureObjectsFrom(Texture& texture) { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(_mutex); -#endif texture.takeTextureObjects(_textureObjectListMap); } -void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime) +void TextureObjectManager::flushAllTextureObjects(unsigned int contextID) +{ + OpenThreads::ScopedLock lock(_mutex); + + Texture::TextureObjectListMap::iterator tmitr = _textureObjectListMap.find(contextID); + if (tmitr!=_textureObjectListMap.end()) + { + Texture::TextureObjectList& tol = tmitr->second; + + for(Texture::TextureObjectList::iterator itr=tol.begin(); + itr!=tol.end(); + ++itr) + { + glDeleteTextures( 1L, &((*itr)->_id)); + } + tol.clear(); + } +} + +void TextureObjectManager::flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime) { // if no time available don't try to flush objects. if (availableTime<=0.0) return; @@ -146,17 +235,15 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d unsigned int numTexturesDeleted = 0; { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(_mutex); -#endif - TextureObjectListMap::iterator tmitr = _textureObjectListMap.find(contextID); + Texture::TextureObjectListMap::iterator tmitr = _textureObjectListMap.find(contextID); if (tmitr!=_textureObjectListMap.end()) { - TextureObjectList& tol = tmitr->second; + Texture::TextureObjectList& tol = tmitr->second; // reset the time of any uninitialized objects. - TextureObjectList::iterator itr; + Texture::TextureObjectList::iterator itr; for(itr=tol.begin(); itr!=tol.end(); ++itr) @@ -167,13 +254,13 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d double expiryTime = currentTime-_expiryDelay; for(itr=tol.begin(); - itr!=tol.end() && elapsedTimes_minimumNumberOfTextureObjectsToRetainInCache && numObjectsDeleted_timeStamp_id)); itr = tol.erase(itr); @@ -195,20 +282,45 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d availableTime -= elapsedTime; } -static ref_ptr s_textureObjectManager; -void Texture::setTextureObjectManager(Texture::TextureObjectManager* tom) +static TextureObjectManager* getTextureObjectManager() { - s_textureObjectManager = tom; -} - -Texture::TextureObjectManager* Texture::getTextureObjectManager() -{ - if (!s_textureObjectManager) s_textureObjectManager = new Texture::TextureObjectManager; + static ref_ptr s_textureObjectManager; + if (!s_textureObjectManager) s_textureObjectManager = new TextureObjectManager; return s_textureObjectManager.get(); } -void Texture::flushTextureObjects(unsigned int contextID,double currentTime, double& availbleTime) + +Texture::TextureObject* Texture::generateTextureObject(unsigned int contextID,GLenum target) +{ + return getTextureObjectManager()->generateTextureObject(contextID,target); +} + +Texture::TextureObject* Texture::generateTextureObject(unsigned int contextID, + GLenum target, + GLint numMipmapLevels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border) +{ + return getTextureObjectManager()->reuseOrGenerateTextureObject(contextID, + target, + numMipmapLevels, + internalFormat, + width, + height, + depth, + border); +} + +void Texture::flushAllDeletedTextureObjects(unsigned int contextID) +{ + getTextureObjectManager()->flushAllTextureObjects(contextID); +} + +void Texture::flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availbleTime) { getTextureObjectManager()->flushTextureObjects(contextID, currentTime, availbleTime); } @@ -1097,9 +1209,7 @@ void Texture::releaseGLObjects(State* state) const unsigned int contextID = state->getContextID(); if (_textureObjectBuffer[contextID].valid()) { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(getTextureObjectManager()->_mutex); -#endif getTextureObjectManager()->_textureObjectListMap[contextID].push_back(_textureObjectBuffer[contextID]); _textureObjectBuffer[contextID] = 0; diff --git a/src/osg/Texture1D.cpp b/src/osg/Texture1D.cpp index 22cc94116..12469abcf 100644 --- a/src/osg/Texture1D.cpp +++ b/src/osg/Texture1D.cpp @@ -118,7 +118,7 @@ void Texture1D::apply(State& state) const { // we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object. - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_1D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_1D); textureObject->bind(); @@ -139,7 +139,7 @@ void Texture1D::apply(State& state) const { // we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object. - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_1D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_1D); textureObject->bind(); @@ -310,7 +310,7 @@ void Texture1D::copyTexImage1D(State& state, int x, int y, int width) _min_filter = LINEAR; _mag_filter = LINEAR; - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_1D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_1D); textureObject->bind(); diff --git a/src/osg/Texture2D.cpp b/src/osg/Texture2D.cpp index e6918af88..2a81f6d7b 100644 --- a/src/osg/Texture2D.cpp +++ b/src/osg/Texture2D.cpp @@ -134,7 +134,7 @@ void Texture2D::apply(State& state) const else if (_subloadCallback.valid()) { - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_2D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_2D); textureObject->bind(); @@ -161,7 +161,7 @@ void Texture2D::apply(State& state) const computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _numMipmapLevels); - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->reuseOrGenerateTextureObject( + _textureObjectBuffer[contextID] = textureObject = generateTextureObject( contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0); textureObject->bind(); @@ -251,7 +251,7 @@ void Texture2D::copyTexImage2D(State& state, int x, int y, int width, int height _min_filter = LINEAR; _mag_filter = LINEAR; - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_2D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_2D); textureObject->bind(); diff --git a/src/osg/Texture3D.cpp b/src/osg/Texture3D.cpp index d12e23416..c18bb55bc 100644 --- a/src/osg/Texture3D.cpp +++ b/src/osg/Texture3D.cpp @@ -135,7 +135,7 @@ void Texture3D::apply(State& state) const else if (_subloadCallback.valid()) { - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_3D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_3D); textureObject->bind(); @@ -155,7 +155,7 @@ void Texture3D::apply(State& state) const else if (_image.valid() && _image->data()) { - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_3D); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_3D); textureObject->bind(); diff --git a/src/osg/TextureCubeMap.cpp b/src/osg/TextureCubeMap.cpp index 738cbec8c..a0ac6cf2b 100644 --- a/src/osg/TextureCubeMap.cpp +++ b/src/osg/TextureCubeMap.cpp @@ -234,7 +234,7 @@ void TextureCubeMap::apply(State& state) const } else if (_subloadCallback.valid()) { - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_CUBE_MAP); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_CUBE_MAP); textureObject->bind(); @@ -258,7 +258,7 @@ void TextureCubeMap::apply(State& state) const // compute the dimensions of the texture. computeRequiredTextureDimensions(state,*_images[0],_textureWidth, _textureHeight, _numMipmapLevels); - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->reuseOrGenerateTextureObject( + _textureObjectBuffer[contextID] = textureObject = generateTextureObject( contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0); textureObject->bind(); diff --git a/src/osg/TextureRectangle.cpp b/src/osg/TextureRectangle.cpp index 48ca586c8..078c21c98 100644 --- a/src/osg/TextureRectangle.cpp +++ b/src/osg/TextureRectangle.cpp @@ -154,7 +154,7 @@ void TextureRectangle::apply(State& state) const else if (_subloadCallback.valid()) { // we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object. - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_RECTANGLE); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_RECTANGLE); textureObject->bind(); @@ -173,7 +173,7 @@ void TextureRectangle::apply(State& state) const else if (_image.valid() && _image->data()) { // we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object. - _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_RECTANGLE); + _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_RECTANGLE); textureObject->bind(); diff --git a/src/osg/VertexProgram.cpp b/src/osg/VertexProgram.cpp index fa0994e73..363d11cd6 100644 --- a/src/osg/VertexProgram.cpp +++ b/src/osg/VertexProgram.cpp @@ -18,10 +18,8 @@ #include -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - #include - #include -#endif +#include +#include using namespace osg; @@ -31,18 +29,14 @@ using namespace osg; typedef std::list VertexProgramObjectList; typedef std::map DeletedVertexProgramObjectCache; -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS - static OpenThreads::Mutex s_mutex_deletedVertexProgramObjectCache; -#endif +static OpenThreads::Mutex s_mutex_deletedVertexProgramObjectCache; static DeletedVertexProgramObjectCache s_deletedVertexProgramObjectCache; void VertexProgram::deleteVertexProgramObject(unsigned int contextID,GLuint handle) { if (handle!=0) { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedVertexProgramObjectCache); -#endif // insert the handle into the cache for the appropriate context. s_deletedVertexProgramObjectCache[contextID].push_back(handle); @@ -60,9 +54,7 @@ void VertexProgram::flushDeletedVertexProgramObjects(unsigned int contextID,doub double elapsedTime = 0.0; { -#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedVertexProgramObjectCache); -#endif DeletedVertexProgramObjectCache::iterator citr = s_deletedVertexProgramObjectCache.find(contextID); if (citr!=s_deletedVertexProgramObjectCache.end()) diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index f9c354fa8..43fcf4d9f 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -21,6 +21,8 @@ DatabasePager::DatabasePager() { //osg::notify(osg::INFO)<<"Constructing DatabasePager()"< lock(s_mutex); + OpenThreads::ScopedLock lock(_run_mutex); - static bool s_startThreadCalled = false; - - if (!s_startThreadCalled) + if (!_startThreadCalled) { - s_startThreadCalled = true; + _startThreadCalled = true; _done = false; osg::notify(osg::DEBUG_INFO)<<"DatabasePager::startThread()"<setExpiryDelay(30.0f); + osg::Texture::setMinimumNumberOfTextureObjectsToRetainInCache(100); + // need to set the texture object manager to be able to reuse textures + // by keeping deleted texture objects around for 10 seconds after being deleted. + osg::Drawable::setMinimumNumberOfDisplayListsToRetainInCache(2000); + bool firstTime = true; do @@ -416,7 +419,22 @@ void DatabasePager::run() // it is created this thread is the only one to write to the _loadedModel pointer. // osg::notify(osg::NOTICE)<<"In DatabasePager thread readNodeFile("<_fileName<<")"<tick(); - databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); + + + bool serialize_readNodeFile = true; + if (serialize_readNodeFile) + { + // do *not* assume that we only have one DatabasePager, or that reaNodeFile is thread safe... + static OpenThreads::Mutex s_serialize_readNodeFile_mutex; + OpenThreads::ScopedLock lock(s_serialize_readNodeFile_mutex); + databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); + } + else + { + // assume that we only have one DatabasePager, or that reaNodeFile is thread safe... + databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); + } + //osg::notify(osg::NOTICE)<<" node read in "<delta_m(before,osg::Timer::instance()->tick())<<" ms"<0.02) { std::string str; if (osg::Texture::s_numberTextureReusedLastInLastFrame > 0) str += " RT "; if (osg::Texture::s_numberNewTextureInLastFrame > 0) str += " NT "; if (osg::Texture::s_numberDeletedTextureInLastFrame > 0) str += " DT "; + if (osg::Drawable::s_numberDrawablesReusedLastInLastFrame > 0) str += " RD "; if (osg::Drawable::s_numberNewDrawablesInLastFrame > 0) str += " ND "; if (osg::Drawable::s_numberDeletedDrawablesInLastFrame > 0) str += " DD "; @@ -528,13 +547,14 @@ void DatabasePager::addLoadedDataToSceneGraph(double timeStamp) osg::notify(osg::NOTICE)<<"\tosg::Texture::s_numberTextureReusedLastInLastFrame = "<