Updated to DatabasePager support
This commit is contained in:
@@ -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());
|
||||
|
||||
|
||||
@@ -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<osg::MatrixTransform*>(nodePath.back());
|
||||
if (mt)
|
||||
{
|
||||
osg::CoordinateSystemNode* csn = 0;
|
||||
|
||||
// find coordinate system node from our parental chain
|
||||
unsigned int i;
|
||||
for(i=0; i<nodePath.size() && csn==0; ++i)
|
||||
{
|
||||
csn = dynamic_cast<osg::CoordinateSystemNode*>(nodePath[i]);
|
||||
}
|
||||
|
||||
if (csn)
|
||||
{
|
||||
|
||||
|
||||
osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
|
||||
if (ellipsoid)
|
||||
{
|
||||
osg::Matrixd matrix;
|
||||
for(i+=1; i<nodePath.size()-1; ++i)
|
||||
{
|
||||
osg::Transform* transform = nodePath[i]->asTransform();
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#define THREAD_SAFE_GLOBJECT_DELETE_LISTS 1
|
||||
|
||||
namespace osg {
|
||||
|
||||
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
#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<TextureObject> > 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);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Block> _databasePagerThreadBlock;
|
||||
|
||||
inline void updateDatabasePagerThreadBlock()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -26,13 +26,12 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
#endif
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
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<GLuint> DisplayListList;
|
||||
typedef std::map<GLuint,DisplayListList> 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<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
|
||||
#endif
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> 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 "<<std::endl;
|
||||
++s_numberDrawablesReusedLastInLastFrame;
|
||||
// notify(NOTICE)<<"reusing display list "<<std::endl;
|
||||
GLuint globj = dll.back();
|
||||
dll.pop_back();
|
||||
return globj;
|
||||
}
|
||||
}
|
||||
|
||||
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint)
|
||||
unsigned int s_minimumNumberOfDisplayListsToRetainInCache = 0;
|
||||
void Drawable::setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum)
|
||||
{
|
||||
s_minimumNumberOfDisplayListsToRetainInCache = minimum;
|
||||
}
|
||||
|
||||
unsigned int Drawable::getMinimumNumberOfDisplayListsToRetainInCache()
|
||||
{
|
||||
return s_minimumNumberOfDisplayListsToRetainInCache;
|
||||
}
|
||||
|
||||
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int /*sizeHint*/)
|
||||
{
|
||||
if (globj!=0)
|
||||
{
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> 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<OpenThreads::Mutex> 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<OpenThreads::Mutex> 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() && elapsedTime<availableTime;
|
||||
ditr!=dll.end() && elapsedTime<availableTime && dll.size()>s_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 = "<<noDeleted<<" elapsed time"<<elapsedTime<<std::endl;
|
||||
// if (noDeleted) notify(NOTICE)<<"Number display lists deleted = "<<noDeleted<<" elapsed time"<<elapsedTime<<std::endl;
|
||||
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
static OpenThreads::Mutex s_mutex_deletedVertexBufferObjectCache;
|
||||
#endif
|
||||
static OpenThreads::Mutex s_mutex_deletedVertexBufferObjectCache;
|
||||
static DeletedDisplayListCache s_deletedVertexBufferObjectCache;
|
||||
|
||||
void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj)
|
||||
{
|
||||
if (globj!=0)
|
||||
{
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> 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<OpenThreads::Mutex> 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())
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
#endif
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
@@ -31,18 +29,14 @@ using namespace osg;
|
||||
typedef std::list<GLuint> FragmentProgramObjectList;
|
||||
typedef std::map<unsigned int,FragmentProgramObjectList> 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<OpenThreads::Mutex> 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<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
|
||||
#endif
|
||||
|
||||
DeletedFragmentProgramObjectCache::iterator citr = s_deletedFragmentProgramObjectCache.find(contextID);
|
||||
if (citr!=s_deletedFragmentProgramObjectCache.end())
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <osg/GLU>
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
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 "<<s_number<<std::endl;
|
||||
|
||||
// no useable texture object found so return 0
|
||||
@@ -71,7 +147,7 @@ Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(uns
|
||||
return new Texture::TextureObject(id,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
}
|
||||
|
||||
Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsigned int contextID,
|
||||
Texture::TextureObject* TextureObjectManager::reuseTextureObject(unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -80,12 +156,10 @@ Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsign
|
||||
GLsizei depth,
|
||||
GLint border)
|
||||
{
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> 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 "<<std::endl;
|
||||
|
||||
++s_numberTextureReusedLastInLastFrame;
|
||||
++Texture::s_numberTextureReusedLastInLastFrame;
|
||||
|
||||
return textureObject;
|
||||
}
|
||||
@@ -108,31 +182,46 @@ Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsign
|
||||
|
||||
|
||||
|
||||
void Texture::TextureObjectManager::addTextureObjects(Texture::TextureObjectListMap& toblm)
|
||||
void TextureObjectManager::addTextureObjects(Texture::TextureObjectListMap& toblm)
|
||||
{
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> 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<OpenThreads::Mutex> 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<OpenThreads::Mutex> 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<OpenThreads::Mutex> 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() && elapsedTime<availableTime && numObjectsDeleted<maxNumObjectsToDelete;
|
||||
itr!=tol.end() && elapsedTime<availableTime && tol.size()>s_minimumNumberOfTextureObjectsToRetainInCache && numObjectsDeleted<maxNumObjectsToDelete;
|
||||
)
|
||||
{
|
||||
if ((*itr)->_timeStamp<expiryTime)
|
||||
{
|
||||
--s_number;
|
||||
++s_numberDeletedTextureInLastFrame;
|
||||
++Texture::s_numberDeletedTextureInLastFrame;
|
||||
|
||||
glDeleteTextures( 1L, &((*itr)->_id));
|
||||
itr = tol.erase(itr);
|
||||
@@ -195,20 +282,45 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
static ref_ptr<Texture::TextureObjectManager> 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<TextureObjectManager> 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<OpenThreads::Mutex> lock(getTextureObjectManager()->_mutex);
|
||||
#endif
|
||||
|
||||
getTextureObjectManager()->_textureObjectListMap[contextID].push_back(_textureObjectBuffer[contextID]);
|
||||
_textureObjectBuffer[contextID] = 0;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
#endif
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
@@ -31,18 +29,14 @@ using namespace osg;
|
||||
typedef std::list<GLuint> VertexProgramObjectList;
|
||||
typedef std::map<unsigned int,VertexProgramObjectList> 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<OpenThreads::Mutex> 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<OpenThreads::Mutex> lock(s_mutex_deletedVertexProgramObjectCache);
|
||||
#endif
|
||||
|
||||
DeletedVertexProgramObjectCache::iterator citr = s_deletedVertexProgramObjectCache.find(contextID);
|
||||
if (citr!=s_deletedVertexProgramObjectCache.end())
|
||||
|
||||
@@ -21,6 +21,8 @@ DatabasePager::DatabasePager()
|
||||
{
|
||||
//osg::notify(osg::INFO)<<"Constructing DatabasePager()"<<std::endl;
|
||||
|
||||
_startThreadCalled = false;
|
||||
|
||||
_done = false;
|
||||
_acceptNewRequests = true;
|
||||
_databasePagerThreadPaused = false;
|
||||
@@ -82,6 +84,7 @@ int DatabasePager::cancel()
|
||||
OpenThreads::Thread::YieldCurrentThread();
|
||||
}
|
||||
|
||||
_startThreadCalled = false;
|
||||
}
|
||||
//std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
|
||||
return result;
|
||||
@@ -209,15 +212,11 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou
|
||||
|
||||
if (!isRunning())
|
||||
{
|
||||
static OpenThreads::Mutex s_mutex;
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> 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()"<<std::endl;
|
||||
setSchedulePriority(_threadPriorityDuringFrame);
|
||||
@@ -355,8 +354,12 @@ void DatabasePager::run()
|
||||
|
||||
// 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::Texture::getTextureObjectManager()->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("<<databaseRequest->_fileName<<")"<<std::endl;
|
||||
//osg::Timer_t before = osg::Timer::instance()->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<OpenThreads::Mutex> 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 "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<std::endl;
|
||||
|
||||
bool loadedObjectsNeedToBeCompiled = false;
|
||||
@@ -508,16 +526,17 @@ void DatabasePager::run()
|
||||
|
||||
void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
|
||||
{
|
||||
|
||||
/*
|
||||
static double s_previous = timeStamp;
|
||||
double timeDelta = timeStamp-s_previous;
|
||||
|
||||
|
||||
if (timeDelta>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 = "<<osg::Texture::s_numberTextureReusedLastInLastFrame<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"\tosg::Texture::s_numberNewTextureInLastFrame = "<<osg::Texture::s_numberNewTextureInLastFrame <<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"\tosg::Texture::s_numberDeletedTextureInLastFrame = "<<osg::Texture::s_numberDeletedTextureInLastFrame <<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"\tosg::Drawable::s_numberDrawablesReusedLastInLastFrame = "<<osg::Drawable::s_numberDrawablesReusedLastInLastFrame <<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"\tosg::Drawable::s_numberNewDrawablesInLastFrame = "<<osg::Drawable::s_numberNewDrawablesInLastFrame <<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"\tosg::Drawable::s_numberDeletedDrawablesInLastFrame = "<<osg::Drawable::s_numberDeletedDrawablesInLastFrame <<std::endl;
|
||||
|
||||
}
|
||||
|
||||
s_previous = timeStamp;
|
||||
|
||||
*/
|
||||
// osg::Timer_t before = osg::Timer::instance()->tick();
|
||||
|
||||
DatabaseRequestList localFileLoadedList;
|
||||
@@ -625,7 +645,7 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int numberOfPagedLODToTest = _inactivePagedLODList.size();
|
||||
// unsigned int numberOfPagedLODToTest = _inactivePagedLODList.size();
|
||||
unsigned int targetNumOfInActivePagedLODs = 1000;
|
||||
unsigned int targetNumOfRemovedChildPagedLODs = 0;
|
||||
if (_inactivePagedLODList.size()>targetNumOfInActivePagedLODs) targetNumOfRemovedChildPagedLODs = _inactivePagedLODList.size()-targetNumOfInActivePagedLODs;
|
||||
@@ -751,7 +771,7 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph)
|
||||
if (subgraph) subgraph->accept(fplv);
|
||||
}
|
||||
|
||||
void DatabasePager::setCompileGLObjectsForContexID(unsigned int contextID, bool on)
|
||||
void DatabasePager::setCompileGLObjectsForContextID(unsigned int contextID, bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
@@ -763,7 +783,7 @@ void DatabasePager::setCompileGLObjectsForContexID(unsigned int contextID, bool
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabasePager::getCompileGLObjectsForContexID(unsigned int contextID)
|
||||
bool DatabasePager::getCompileGLObjectsForContextID(unsigned int contextID)
|
||||
{
|
||||
return _activeGraphicsContexts.count(contextID)!=0;
|
||||
}
|
||||
|
||||
@@ -31,10 +31,8 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
#endif
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
using namespace osgGL2;
|
||||
|
||||
@@ -81,18 +79,15 @@ private:
|
||||
typedef std::list<GLhandleARB> GL2ObjectList;
|
||||
typedef std::map<unsigned int, GL2ObjectList> DeletedGL2ObjectCache;
|
||||
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
static OpenThreads::Mutex s_mutex_deletedGL2ObjectCache;
|
||||
#endif
|
||||
static OpenThreads::Mutex s_mutex_deletedGL2ObjectCache;
|
||||
static DeletedGL2ObjectCache s_deletedGL2ObjectCache;
|
||||
|
||||
void ProgramObject::deleteObject(unsigned int contextID, GLhandleARB handle)
|
||||
{
|
||||
if (handle!=0)
|
||||
{
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGL2ObjectCache);
|
||||
#endif
|
||||
|
||||
// add handle to the cache for the appropriate context.
|
||||
s_deletedGL2ObjectCache[contextID].push_back(handle);
|
||||
}
|
||||
@@ -108,9 +103,7 @@ void ProgramObject::flushDeletedGL2Objects(unsigned int contextID,double /*curre
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
{
|
||||
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGL2ObjectCache);
|
||||
#endif
|
||||
|
||||
DeletedGL2ObjectCache::iterator citr = s_deletedGL2ObjectCache.find(contextID);
|
||||
if( citr != s_deletedGL2ObjectCache.end() )
|
||||
|
||||
@@ -576,7 +576,7 @@ bool Viewer::realize()
|
||||
|
||||
|
||||
// tell the database pager which graphic context the compile of rendering objexts is needed.
|
||||
databasePager->setCompileGLObjectsForContexID((*p)->getSceneView()->getState()->getContextID(),true);
|
||||
databasePager->setCompileGLObjectsForContextID((*p)->getSceneView()->getState()->getContextID(),true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ void Font::GlyphTexture::apply(osg::State& state) const
|
||||
|
||||
// being bound for the first time, need to allocate the texture
|
||||
|
||||
_textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->reuseOrGenerateTextureObject(
|
||||
_textureObjectBuffer[contextID] = textureObject = osg::Texture::generateTextureObject(
|
||||
contextID,GL_TEXTURE_2D,1,GL_ALPHA,getTextureWidth(), getTextureHeight(),1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -615,13 +615,27 @@ void SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& mod
|
||||
}
|
||||
|
||||
|
||||
void SceneView::flushAllDeletedGLObjects()
|
||||
{
|
||||
_requiresFlush = false;
|
||||
|
||||
double availableTime = 100.0f;
|
||||
double currentTime = _state->getFrameStamp()?_state->getFrameStamp()->getReferenceTime():0.0;
|
||||
|
||||
osg::Texture::flushAllDeletedTextureObjects(_state->getContextID());
|
||||
osg::Drawable::flushAllDeletedDisplayLists(_state->getContextID());
|
||||
osg::Drawable::flushDeletedVertexBufferObjects(_state->getContextID(),currentTime,availableTime);
|
||||
osg::VertexProgram::flushDeletedVertexProgramObjects(_state->getContextID(),currentTime,availableTime);
|
||||
osg::FragmentProgram::flushDeletedFragmentProgramObjects(_state->getContextID(),currentTime,availableTime);
|
||||
}
|
||||
|
||||
void SceneView::flushDeletedGLObjects(double& availableTime)
|
||||
{
|
||||
_requiresFlush = false;
|
||||
|
||||
double currentTime = _state->getFrameStamp()?_state->getFrameStamp()->getReferenceTime():0.0;
|
||||
osg::Texture::flushTextureObjects(_state->getContextID(),currentTime,availableTime);
|
||||
osg::Drawable::flushDeletedDisplayLists(_state->getContextID(),currentTime,availableTime);
|
||||
osg::Texture::flushDeletedTextureObjects(_state->getContextID(),currentTime,availableTime);
|
||||
osg::Drawable::flushDeletedDisplayLists(_state->getContextID(),availableTime);
|
||||
osg::Drawable::flushDeletedVertexBufferObjects(_state->getContextID(),currentTime,availableTime);
|
||||
osg::VertexProgram::flushDeletedVertexProgramObjects(_state->getContextID(),currentTime,availableTime);
|
||||
osg::FragmentProgram::flushDeletedFragmentProgramObjects(_state->getContextID(),currentTime,availableTime);
|
||||
|
||||
Reference in New Issue
Block a user