Refactored the GL object deletion management to use new osg::GraphicsObjectManager/GLObjectManager base classes, and osg::ContextData container.

This approach unifies much of the code handling the clean up of OpenGL graphics data, avoids lots of local mutexes and static variables that were previously required,
and enables the clean up scheme to be easily extended by users providing their own GraphicsObjectManager subclasses.


git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@15130 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield 2015-09-23 09:47:34 +00:00
parent cb3396b0e5
commit 161246d864
37 changed files with 1339 additions and 1374 deletions

View File

@ -20,6 +20,8 @@
#include <osgViewer/Viewer> #include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers> #include <osgViewer/ViewerEventHandlers>
#include <osg/ContextData>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/WriteFile> #include <osgDB/WriteFile>
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
@ -618,8 +620,7 @@ public:
{ {
if (ea.getKey()=='r') if (ea.getKey()=='r')
{ {
osg::Texture::getTextureObjectManager(0)->reportStats(osg::notify(osg::NOTICE)); osg::getOrCreateContextData(0)->reportStats(osg::notify(osg::NOTICE));
osg::GLBufferObjectManager::getGLBufferObjectManager(0)->reportStats(osg::notify(osg::NOTICE));
} }
} }
return false; return false;
@ -631,8 +632,7 @@ struct ReportStatsAnimationCompletedCallback : public osgGA::AnimationPathManipu
virtual void completed(const osgGA::AnimationPathManipulator*) virtual void completed(const osgGA::AnimationPathManipulator*)
{ {
OSG_NOTICE<<"Animation completed"<<std::endl; OSG_NOTICE<<"Animation completed"<<std::endl;
osg::Texture::getTextureObjectManager(0)->reportStats(osg::notify(osg::NOTICE)); osg::getOrCreateContextData(0)->reportStats(osg::notify(osg::NOTICE));
osg::GLBufferObjectManager::getGLBufferObjectManager(0)->reportStats(osg::notify(osg::NOTICE));
} }
}; };

View File

@ -28,6 +28,7 @@
#include <osg/Projection> #include <osg/Projection>
#include <osg/Switch> #include <osg/Switch>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osg/ContextData>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgGA/GUIEventHandler> #include <osgGA/GUIEventHandler>
@ -313,12 +314,9 @@ void destroyFBO(GraphicsContext* gc, FboData &data)
data.fb = 0; data.fb = 0;
data.resolveFB = 0; data.resolveFB = 0;
State& state = *gc->getState(); State& state = *gc->getState();
double availableTime = 100.0;
RenderBuffer::flushDeletedRenderBuffers(state.getContextID(), 0.0, osg::get<GLRenderBufferManager>(state.getContextID())->flushAllDeletedGLObjects();
availableTime); osg::get<GLFrameBufferObjectManager>(state.getContextID())->flushAllDeletedGLObjects();
availableTime = 100.0;
FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),
0.0, availableTime);
} }
void setAttachmentsFromConfig(Camera* camera, const FboConfig& config); void setAttachmentsFromConfig(Camera* camera, const FboConfig& config);

View File

@ -20,6 +20,7 @@
#include <osg/Object> #include <osg/Object>
#include <osg/buffered_value> #include <osg/buffered_value>
#include <osg/FrameStamp> #include <osg/FrameStamp>
#include <osg/GLObjects>
#include <iosfwd> #include <iosfwd>
#include <list> #include <list>
@ -151,7 +152,7 @@ class BufferObjectProfile
class GLBufferObjectSet; class GLBufferObjectSet;
class GLBufferObjectManager; class GLBufferObjectManager;
class OSG_EXPORT GLBufferObject : public Referenced class OSG_EXPORT GLBufferObject : public GraphicsObject
{ {
public: public:
@ -207,6 +208,9 @@ class OSG_EXPORT GLBufferObject : public Referenced
_extensions->glBindBuffer(_profile._target,0); _extensions->glBindBuffer(_profile._target,0);
} }
/** release GLBufferObject to the orphan list to be reused or deleted.*/
void release();
inline bool isDirty() const { return _dirty; } inline bool isDirty() const { return _dirty; }
void dirty() { _dirty = true; } void dirty() { _dirty = true; }
@ -221,15 +225,6 @@ class OSG_EXPORT GLBufferObject : public Referenced
bool isPBOSupported() const { return _extensions->isPBOSupported; } bool isPBOSupported() const { return _extensions->isPBOSupported; }
static osg::ref_ptr<GLBufferObject> createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject);
static void deleteAllBufferObjects(unsigned int contextID);
static void discardAllBufferObjects(unsigned int contextID);
static void flushAllDeletedBufferObjects(unsigned int contextID);
static void discardAllDeletedBufferObjects(unsigned int contextID);
static void flushDeletedBufferObjects(unsigned int contextID,double currentTime, double& availbleTime);
static void releaseGLBufferObject(unsigned int contextID, GLBufferObject* to);
bool hasAllBufferDataBeenRead() const; bool hasAllBufferDataBeenRead() const;
void setBufferDataHasBeenRead(const osg::BufferData* bd); void setBufferDataHasBeenRead(const osg::BufferData* bd);
@ -327,14 +322,11 @@ class OSG_EXPORT GLBufferObjectSet : public Referenced
GLBufferObject* _tail; GLBufferObject* _tail;
}; };
class OSG_EXPORT GLBufferObjectManager : public osg::Referenced class OSG_EXPORT GLBufferObjectManager : public GraphicsObjectManager
{ {
public: public:
GLBufferObjectManager(unsigned int contextID); GLBufferObjectManager(unsigned int contextID);
unsigned int getContextID() const { return _contextID; }
void setNumberActiveGLBufferObjects(unsigned int size) { _numActiveGLBufferObjects = size; } void setNumberActiveGLBufferObjects(unsigned int size) { _numActiveGLBufferObjects = size; }
unsigned int& getNumberActiveGLBufferObjects() { return _numActiveGLBufferObjects; } unsigned int& getNumberActiveGLBufferObjects() { return _numActiveGLBufferObjects; }
unsigned int getNumberActiveGLBufferObjects() const { return _numActiveGLBufferObjects; } unsigned int getNumberActiveGLBufferObjects() const { return _numActiveGLBufferObjects; }
@ -357,12 +349,11 @@ class OSG_EXPORT GLBufferObjectManager : public osg::Referenced
void handlePendingOrphandedGLBufferObjects(); void handlePendingOrphandedGLBufferObjects();
void deleteAllGLBufferObjects(); void deleteAllGLObjects();
void discardAllGLBufferObjects(); void discardAllGLObjects();
void flushAllDeletedGLBufferObjects(); void flushAllDeletedGLObjects();
void discardAllDeletedGLBufferObjects(); void discardAllDeletedGLObjects();
void flushDeletedGLBufferObjects(double currentTime, double& availableTime); void flushDeletedGLObjects(double currentTime, double& availableTime);
void releaseGLBufferObject(GLBufferObject* to);
GLBufferObjectSet* getGLBufferObjectSet(const BufferObjectProfile& profile); GLBufferObjectSet* getGLBufferObjectSet(const BufferObjectProfile& profile);
@ -383,12 +374,12 @@ class OSG_EXPORT GLBufferObjectManager : public osg::Referenced
unsigned int& getNumberApplied() { return _numApplied; } unsigned int& getNumberApplied() { return _numApplied; }
double& getApplyTime() { return _applyTime; } double& getApplyTime() { return _applyTime; }
static osg::ref_ptr<GLBufferObjectManager>& getGLBufferObjectManager(unsigned int contextID);
protected: protected:
virtual ~GLBufferObjectManager();
typedef std::map< BufferObjectProfile, osg::ref_ptr<GLBufferObjectSet> > GLBufferObjectSetMap; typedef std::map< BufferObjectProfile, osg::ref_ptr<GLBufferObjectSet> > GLBufferObjectSetMap;
unsigned int _contextID;
unsigned int _numActiveGLBufferObjects; unsigned int _numActiveGLBufferObjects;
unsigned int _numOrphanedGLBufferObjects; unsigned int _numOrphanedGLBufferObjects;
unsigned int _currGLBufferObjectPoolSize; unsigned int _currGLBufferObjectPoolSize;
@ -471,11 +462,7 @@ class OSG_EXPORT BufferObject : public Object
GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _glBufferObjects[contextID].get(); } GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _glBufferObjects[contextID].get(); }
GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const;
{
if (!_glBufferObjects[contextID]) _glBufferObjects[contextID] = GLBufferObject::createGLBufferObject(contextID, this);
return _glBufferObjects[contextID].get();
}
unsigned int computeRequiredBufferSize() const; unsigned int computeRequiredBufferSize() const;

163
include/osg/ContextData Normal file
View File

@ -0,0 +1,163 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSG_CONTEXTDATA
#define OSG_CONTEXTDATA 1
#include <osg/GraphicsContext>
namespace osg {
class OSG_EXPORT ContextData : public GraphicsObjectManager
{
public:
ContextData(unsigned int contextID);
void incrementUsageCount() { ++_numContexts; }
void decrementUsageCount() { --_numContexts; }
void setNumContexts(unsigned int numContexts) { _numContexts = numContexts; }
unsigned int getNumContexts() const { return _numContexts; }
void setCompileContext(osg::GraphicsContext* gc) { _compileContext = gc; }
osg::GraphicsContext* getCompileContext() { return _compileContext.get(); }
/** Get a specific GL extensions object or GraphicsObjectManager, initialize if not already present.
* Note, must only be called from a the graphics context thread associated with this osg::State. */
template<typename T>
T* get()
{
const std::type_info* id(&typeid(T));
osg::ref_ptr<osg::Referenced>& ptr = _managerMap[id];
if (!ptr)
{
ptr = new T(_contextID);
}
return static_cast<T*>(ptr.get());
}
/** Get a specific GL extensions object or GraphicsObjectManager if it already exists in the extension map.
* Note, safe to call outwith a the graphics context thread associated with this osg::State.
* Returns NULL if the desired extension object has not been created yet.*/
template<typename T>
const T* get() const
{
const std::type_info* id(&typeid(T));
ManagerMap::const_iterator itr = _managerMap.find(id);
if (itr==_managerMap.end()) return 0;
else return itr->second.get();
}
/** Set a specific GL extensions object pr GraphicsObjectManager. */
template<typename T>
void set(T* ptr)
{
const std::type_info* id(&typeid(T));
_managerMap[id] = ptr;
}
/** Signal that a new frame has started.*/
virtual void newFrame(osg::FrameStamp*);
virtual void resetStats();
virtual void reportStats(std::ostream& out);
virtual void recomputeStats(std::ostream& out) const;
/** Flush all deleted OpenGL objects within the specified availableTime.
* Note, must be called from a thread which has current the graphics context associated with contextID. */
virtual void flushDeletedGLObjects(double currentTime, double& availableTime);
/** Flush all deleted OpenGL objects.
* Note, must be called from a thread which has current the graphics context associated with contextID. */
virtual void flushAllDeletedGLObjects();
/** Do a GL delete all OpenGL objects.
* Note, must be called from a thread which has current the graphics context associated with contextID. */
virtual void deleteAllGLObjects();
/** Discard all OpenGL objects.
* Note, unlike deleteAllGLjects discard does not
* do any OpenGL calls so can be called from any thread, but as a consequence it
* also doesn't remove the associated OpenGL resource so discard should only be
* called when the associated graphics context is being/has been closed. */
virtual void discardAllGLObjects();
public:
/** Create a contextID for a new graphics context, this contextID is used to set up the osg::State associate with context.
* Automatically increments the usage count of the contextID to 1.*/
static unsigned int createNewContextID();
/** Get the current max ContextID.*/
static unsigned int getMaxContextID();
/** Increment the usage count associate with a contextID. The usage count specifies how many graphics contexts a specific contextID is shared between.*/
static void incrementContextIDUsageCount(unsigned int contextID);
/** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/
static void decrementContextIDUsageCount(unsigned int contextID);
typedef GraphicsContext::GraphicsContexts GraphicsContexts;
/** Get all the registered graphics contexts.*/
static GraphicsContexts getAllRegisteredGraphicsContexts();
/** Get all the registered graphics contexts associated with a specific contextID.*/
static GraphicsContexts getRegisteredGraphicsContexts(unsigned int contextID);
/** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/
static void setCompileContext(unsigned int contextID, GraphicsContext* gc);
/** Get existing or create a new GraphicsContext to do background compilation for GraphicsContexts associated with specified contextID.*/
static GraphicsContext* getOrCreateCompileContext(unsigned int contextID);
/** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/
static GraphicsContext* getCompileContext(unsigned int contextID);
/** Register a GraphicsContext.*/
static void registerGraphicsContext(GraphicsContext* gc);
/** Unregister a GraphicsContext.*/
static void unregisterGraphicsContext(GraphicsContext* gc);
protected:
virtual ~ContextData();
unsigned int _numContexts;
osg::ref_ptr<osg::GraphicsContext> _compileContext;
// ManagerMap contains GL Extentsions objects used by StateAttribue to call OpenGL extensions/advanced features
typedef std::map<const std::type_info*, osg::ref_ptr<osg::Referenced> > ManagerMap;
ManagerMap _managerMap;
};
/** Get the ContextData for a specific contextID.*/
extern ContextData* getContextData(unsigned int contextID);
/** Get or create the ContextData for a specific contextID.*/
extern ContextData* getOrCreateContextData(unsigned int contextID);
template<typename T>
inline T* get(unsigned int contextID)
{
ContextData* gc = getOrCreateContextData(contextID);
return gc->get<T>();
}
// specialize for ContextData to avoid ContextData being nested within itself.
template<> inline ContextData* get<ContextData>(unsigned int contextID) { return getOrCreateContextData(contextID); }
}
#endif

View File

@ -95,10 +95,6 @@ class OSG_EXPORT Drawable : public Node
{ {
public: public:
static unsigned int s_numberDrawablesReusedLastInLastFrame;
static unsigned int s_numberNewDrawablesInLastFrame;
static unsigned int s_numberDeletedDrawablesInLastFrame;
Drawable(); Drawable();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
@ -355,31 +351,19 @@ class OSG_EXPORT Drawable : public Node
/** Return a OpenGL display list handle a newly generated or reused from display list cache. */ /** 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); 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 /** Use deleteDisplayList instead of glDeleteList to allow
* OpenGL display list to be cached until they can be deleted * OpenGL display list to be cached until they can be deleted
* by the OpenGL context in which they were created, specified * by the OpenGL context in which they were created, specified
* by contextID.*/ * by contextID.*/
static void deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint = 0); static void deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint = 0);
/** Flush all the cached display list which need to be deleted /** Set the minimum number of display lists to retain in the deleted display list cache. */
* in the OpenGL context related to contextID.*/ static void setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum);
static void flushAllDeletedDisplayLists(unsigned int contextID);
/** Get the minimum number of display lists to retain in the deleted display list cache. */
static unsigned int getMinimumNumberOfDisplayListsToRetainInCache();
/** Flush all the cached display list which need to be deleted
* in the OpenGL context related to contextID.
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
* this call is useful for when an OpenGL context has been destroyed. */
static void discardAllDeletedDisplayLists(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);
typedef unsigned int AttributeType; typedef unsigned int AttributeType;

View File

@ -202,26 +202,9 @@ class OSG_EXPORT FragmentProgram : public StateAttribute
/** Get list of Matrices */ /** Get list of Matrices */
inline const MatrixList& getMatrices() const { return _matrixList; } inline const MatrixList& getMatrices() const { return _matrixList; }
/** Force a recompile on next apply() of associated OpenGL vertex program objects.*/ /** Force a recompile on next apply() of associated OpenGL vertex program objects.*/
void dirtyFragmentProgramObject(); void dirtyFragmentProgramObject();
/** use deleteFragmentProgramObject instead of glDeletePrograms to allow
* OpenGL Fragment Program objects to be cached until they can be deleted
* by the OpenGL context in which they were created, specified
* by contextID.*/
static void deleteFragmentProgramObject(unsigned int contextID,GLuint handle);
/** flush all the cached fragment programs which need to be deleted
* in the OpenGL context related to contextID.*/
static void flushDeletedFragmentProgramObjects(unsigned int contextID,double currentTime, double& availableTime);
/** discard all the cached fragment programs which need to be deleted
* in the OpenGL context related to contextID.
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
* this call is useful for when an OpenGL context has been destroyed. */
static void discardDeletedFragmentProgramObjects(unsigned int contextID);
virtual void apply(State& state) const; virtual void apply(State& state) const;
virtual void compileGLObjects(State& state) const { apply(state); } virtual void compileGLObjects(State& state) const { apply(state); }

View File

@ -147,20 +147,6 @@ class OSG_EXPORT RenderBuffer: public Object
GLuint getObjectID(unsigned int contextID, const GLExtensions *ext) const; GLuint getObjectID(unsigned int contextID, const GLExtensions *ext) const;
inline int compare(const RenderBuffer &rb) const; inline int compare(const RenderBuffer &rb) const;
/** Mark internal RenderBuffer for deletion.
* Deletion requests are queued until they can be executed
* in the proper GL context. */
static void deleteRenderBuffer(unsigned int contextID, GLuint rb);
/** flush all the cached RenderBuffers which need to be deleted
* in the OpenGL context related to contextID.*/
static void flushDeletedRenderBuffers(unsigned int contextID,double currentTime, double& availableTime);
/** discard all the cached RenderBuffers which need to be deleted in the OpenGL context related to contextID.
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
* this call is useful for when an OpenGL context has been destroyed. */
static void discardDeletedRenderBuffers(unsigned int contextID);
static int getMaxSamples(unsigned int contextID, const GLExtensions* ext); static int getMaxSamples(unsigned int contextID, const GLExtensions* ext);
/** Resize any per context GLObject buffers to specified size. */ /** Resize any per context GLObject buffers to specified size. */
@ -372,19 +358,6 @@ class OSG_EXPORT FrameBufferObject: public StateAttribute
/** Bind the FBO as either the read or draw target, or both. */ /** Bind the FBO as either the read or draw target, or both. */
void apply(State &state, BindTarget target) const; void apply(State &state, BindTarget target) const;
/** Mark internal FBO for deletion.
* Deletion requests are queued until they can be executed
* in the proper GL context. */
static void deleteFrameBufferObject(unsigned int contextID, GLuint program);
/** flush all the cached FBOs which need to be deleted
* in the OpenGL context related to contextID.*/
static void flushDeletedFrameBufferObjects(unsigned int contextID,double currentTime, double& availableTime);
/** discard all the cached FBOs which need to be deleted
* in the OpenGL context related to contextID.*/
static void discardDeletedFrameBufferObjects(unsigned int contextID);
/** Resize any per context GLObject buffers to specified size. */ /** Resize any per context GLObject buffers to specified size. */
virtual void resizeGLObjectBuffers(unsigned int maxSize); virtual void resizeGLObjectBuffers(unsigned int maxSize);
@ -437,6 +410,19 @@ class OSG_EXPORT FrameBufferObject: public StateAttribute
_dirtyAttachmentList.setAllElementsTo(1); _dirtyAttachmentList.setAllElementsTo(1);
} }
class OSG_EXPORT GLRenderBufferManager : public GLObjectManager
{
public:
GLRenderBufferManager(unsigned int contextID);
virtual void deleteGLObject(GLuint globj);
};
class OSG_EXPORT GLFrameBufferObjectManager : public GLObjectManager
{
public:
GLFrameBufferObjectManager(unsigned int contextID);
virtual void deleteGLObject(GLuint globj);
};
} }

View File

@ -14,10 +14,16 @@
#ifndef OSG_GLOBJECTS #ifndef OSG_GLOBJECTS
#define OSG_GLOBJECTS 1 #define OSG_GLOBJECTS 1
#include <osg/Export> #include <osg/Referenced>
#include <osg/GL>
#include <list>
#include <string>
namespace osg { namespace osg {
// forward declare
class FrameStamp;
/** Flush all deleted OpenGL objects within the specified availableTime. /** Flush all deleted OpenGL objects within the specified availableTime.
* Note, must be called from a thread which has current the graphics context associated with contextID. */ * Note, must be called from a thread which has current the graphics context associated with contextID. */
extern OSG_EXPORT void flushDeletedGLObjects(unsigned int contextID, double currentTime, double& availableTime); extern OSG_EXPORT void flushDeletedGLObjects(unsigned int contextID, double currentTime, double& availableTime);
@ -37,6 +43,90 @@ extern OSG_EXPORT void deleteAllGLObjects(unsigned int contextID);
* called when the associated graphics context is being/has been closed. */ * called when the associated graphics context is being/has been closed. */
extern OSG_EXPORT void discardAllGLObjects(unsigned int contextID); extern OSG_EXPORT void discardAllGLObjects(unsigned int contextID);
class OSG_EXPORT GraphicsObject : public osg::Referenced
{
public:
GraphicsObject();
protected:
virtual ~GraphicsObject();
};
class OSG_EXPORT GraphicsObjectManager : public osg::Referenced
{
public:
GraphicsObjectManager(const std::string& name, unsigned int contextID);
unsigned int getContextID() const { return _contextID; }
/** Signal that a new frame has started.*/
virtual void newFrame(osg::FrameStamp* fs) {}
virtual void resetStats() {}
virtual void reportStats(std::ostream& out) {}
virtual void recomputeStats(std::ostream& out) const {}
/** Flush all deleted OpenGL objects within the specified availableTime.
* Note, must be called from a thread which has current the graphics context associated with contextID. */
virtual void flushDeletedGLObjects(double currentTime, double& availableTime) = 0;
/** Flush all deleted OpenGL objects.
* Note, must be called from a thread which has current the graphics context associated with contextID. */
virtual void flushAllDeletedGLObjects() = 0;
/** Do a GL delete all OpenGL objects.
* Note, must be called from a thread which has current the graphics context associated with contextID. */
virtual void deleteAllGLObjects() = 0;
/** Discard all OpenGL objects.
* Note, unlike deleteAllGLjects discard does not
* do any OpenGL calls so can be called from any thread, but as a consequence it
* also doesn't remove the associated OpenGL resource so discard should only be
* called when the associated graphics context is being/has been closed. */
virtual void discardAllGLObjects() = 0;
protected:
virtual ~GraphicsObjectManager();
std::string _name;
unsigned int _contextID;
};
class OSG_EXPORT GLObjectManager : public GraphicsObjectManager
{
public:
GLObjectManager(const std::string& name, unsigned int contextID);
virtual void flushDeletedGLObjects(double currentTime, double& availableTime);
virtual void flushAllDeletedGLObjects();
virtual void deleteAllGLObjects();
virtual void discardAllGLObjects();
/** schedule a GL object for deletion by the graphics thread.*/
virtual void sheduleGLObjectForDeletion(GLuint globj);
/** implementation of the actual creation of an GL object - subclasses from GLObjectManager must implement the appropriate GL calls.*/
virtual GLuint createGLObject();
/** implementation of the actual deletion of an GL object - subclasses from GLObjectManager must implement the appropriate GL calls.*/
virtual void deleteGLObject(GLuint globj) = 0;
protected:
virtual ~GLObjectManager();
typedef std::list<GLuint> GLObjectHandleList;
OpenThreads::Mutex _mutex;
GLObjectHandleList _deleteGLObjectHandles;
};
} }
#endif #endif

View File

@ -228,21 +228,6 @@ class OSG_EXPORT Program : public osg::StateAttribute
/** Query InfoLog from a glProgram */ /** Query InfoLog from a glProgram */
bool getGlProgramInfoLog(unsigned int contextID, std::string& log) const; bool getGlProgramInfoLog(unsigned int contextID, std::string& log) const;
/** Mark internal glProgram for deletion.
* Deletion requests are queued until they can be executed
* in the proper GL context. */
static void deleteGlProgram(unsigned int contextID, GLuint program);
/** flush all the cached glPrograms which need to be deleted
* in the OpenGL context related to contextID.*/
static void flushDeletedGlPrograms(unsigned int contextID,double currentTime, double& availableTime);
/** discard all the cached glPrograms which need to be deleted
* in the OpenGL context related to contextID.
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
* this call is useful for when an OpenGL context has been destroyed. */
static void discardDeletedGlPrograms(unsigned int contextID);
struct ActiveVarInfo { struct ActiveVarInfo {
ActiveVarInfo() : _location(-1), _type(Uniform::UNDEFINED), _size(-1) {} ActiveVarInfo() : _location(-1), _type(Uniform::UNDEFINED), _size(-1) {}
ActiveVarInfo( GLint loc, GLenum type, GLint size ) : _location(loc), _type(type), _size(size) {} ActiveVarInfo( GLint loc, GLenum type, GLint size ) : _location(loc), _type(type), _size(size) {}
@ -409,7 +394,7 @@ class OSG_EXPORT Program : public osg::StateAttribute
PerContextProgram& operator=(const PerContextProgram&); // disallowed PerContextProgram& operator=(const PerContextProgram&); // disallowed
}; };
struct OSG_EXPORT ProgramObjects : public osg::Referenced struct OSG_EXPORT ProgramObjects : public osg::GraphicsObject
{ {
typedef std::vector< osg::ref_ptr<PerContextProgram> > PerContextPrograms; typedef std::vector< osg::ref_ptr<PerContextProgram> > PerContextPrograms;

View File

@ -205,21 +205,6 @@ class OSG_EXPORT Shader : public osg::Object
/** If needed, compile the PCS's glShader */ /** If needed, compile the PCS's glShader */
void compileShader(osg::State& state) const; void compileShader(osg::State& state) const;
/** Mark internal glShader for deletion.
* Deletion requests are queued until they can be executed
* in the proper GL context. */
static void deleteGlShader(unsigned int contextID, GLuint shader);
/** flush all the cached glShaders which need to be deleted
* in the OpenGL context related to contextID.*/
static void flushDeletedGlShaders(unsigned int contextID,double currentTime, double& availableTime);
/** discard all the cached glShaders which need to be deleted in the OpenGL context related to contextID.
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
* this call is useful for when an OpenGL context has been destroyed. */
static void discardDeletedGlShaders(unsigned int contextID);
static Shader::Type getTypeId( const std::string& tname ); static Shader::Type getTypeId( const std::string& tname );
public: public:

View File

@ -155,7 +155,7 @@ class OSG_EXPORT State : public Referenced
typedef std::map<const std::type_info*, osg::ref_ptr<osg::Referenced> > ExtensionMap; typedef std::map<const std::type_info*, osg::ref_ptr<osg::Referenced> > ExtensionMap;
ExtensionMap _extensionMap; ExtensionMap _extensionMap;
/** Get a specific GL extensions object, initialize if not already present. /** Get a specific GL extensions object or GraphicsObjectManager, initialize if not already present.
* Note, must only be called from a the graphics context thread associated with this osg::State. */ * Note, must only be called from a the graphics context thread associated with this osg::State. */
template<typename T> template<typename T>
T* get() T* get()
@ -169,7 +169,7 @@ class OSG_EXPORT State : public Referenced
return static_cast<T*>(ptr.get()); return static_cast<T*>(ptr.get());
} }
/** Get a specific GL extensions object if it already exists in the extension map. /** Get a specific GL extensions object or GraphicsObjectManager if it already exists in the extension map.
* Note, safe to call outwith a the graphics context thread associated with this osg::State. * Note, safe to call outwith a the graphics context thread associated with this osg::State.
* Returns NULL if the desired extension object has not been created yet.*/ * Returns NULL if the desired extension object has not been created yet.*/
template<typename T> template<typename T>
@ -181,6 +181,13 @@ class OSG_EXPORT State : public Referenced
else return itr->second.get(); else return itr->second.get();
} }
/** Set a specific GL extensions object pr GraphicsObjectManager. */
template<typename T>
void set(T* ptr)
{
const std::type_info* id(&typeid(T));
_extensionMap[id] = ptr;
}
/* Set whether shader composition is enabled.*/ /* Set whether shader composition is enabled.*/
void setShaderCompositionEnabled(bool flag) { _shaderCompositionEnabled = flag; } void setShaderCompositionEnabled(bool flag) { _shaderCompositionEnabled = flag; }
@ -2945,6 +2952,7 @@ inline bool State::setActiveTextureUnit( unsigned int unit )
// forward declare speciailization of State::get() method // forward declare speciailization of State::get() method
template<> inline GLExtensions* State::get<GLExtensions>() { return _glExtensions.get(); } template<> inline GLExtensions* State::get<GLExtensions>() { return _glExtensions.get(); }
template<> inline const GLExtensions* State::get<GLExtensions>() const { return _glExtensions.get(); } template<> inline const GLExtensions* State::get<GLExtensions>() const { return _glExtensions.get(); }
template<> inline void State::set<GLExtensions>(GLExtensions* ptr) { _glExtensions = ptr; }
} }

View File

@ -405,9 +405,16 @@
#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF #define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
#endif #endif
//#define OSG_COLLECT_TEXTURE_APPLIED_STATS 1
namespace osg { namespace osg {
// forward declare
class TextureObjectSet;
class TextureObjectManager;
/** Texture pure virtual base class that encapsulates OpenGL texture /** Texture pure virtual base class that encapsulates OpenGL texture
* functionality common to the various types of OSG textures. * functionality common to the various types of OSG textures.
*/ */
@ -983,11 +990,7 @@ class OSG_EXPORT Texture : public osg::StateAttribute
unsigned int _size; unsigned int _size;
}; };
// forward declare class OSG_EXPORT TextureObject : public GraphicsObject
class TextureObjectSet;
class TextureObjectManager;
class OSG_EXPORT TextureObject : public osg::Referenced
{ {
public: public:
@ -1068,6 +1071,8 @@ class OSG_EXPORT Texture : public osg::StateAttribute
inline bool isReusable() const { return _allocated && _profile._width!=0; } inline bool isReusable() const { return _allocated && _profile._width!=0; }
/** release TextureObject to the orphan list to be reused or deleted.*/
void release();
GLuint _id; GLuint _id;
TextureProfile _profile; TextureProfile _profile;
@ -1086,150 +1091,6 @@ class OSG_EXPORT Texture : public osg::StateAttribute
typedef std::list< ref_ptr<TextureObject> > TextureObjectList; typedef std::list< ref_ptr<TextureObject> > TextureObjectList;
class OSG_EXPORT TextureObjectSet : public Referenced
{
public:
TextureObjectSet(TextureObjectManager* parent, const TextureProfile& profile);
const TextureProfile& getProfile() const { return _profile; }
void handlePendingOrphandedTextureObjects();
void deleteAllTextureObjects();
void discardAllTextureObjects();
void flushAllDeletedTextureObjects();
void discardAllDeletedTextureObjects();
void flushDeletedTextureObjects(double currentTime, double& availableTime);
osg::ref_ptr<TextureObject> takeFromOrphans(Texture* texture);
osg::ref_ptr<TextureObject> takeOrGenerate(Texture* texture);
void moveToBack(TextureObject* to);
void addToBack(TextureObject* to);
void orphan(TextureObject* to);
void remove(TextureObject* to);
void moveToSet(TextureObject* to, TextureObjectSet* set);
unsigned int size() const { return _profile._size * _numOfTextureObjects; }
bool makeSpace(unsigned int& size);
bool checkConsistency() const;
TextureObjectManager* getParent() { return _parent; }
unsigned int computeNumTextureObjectsInList() const;
unsigned int getNumOfTextureObjects() const { return _numOfTextureObjects; }
unsigned int getNumOrphans() const { return static_cast<unsigned int>(_orphanedTextureObjects.size()); }
unsigned int getNumPendingOrphans() const { return static_cast<unsigned int>(_pendingOrphanedTextureObjects.size()); }
protected:
virtual ~TextureObjectSet();
OpenThreads::Mutex _mutex;
TextureObjectManager* _parent;
unsigned int _contextID;
TextureProfile _profile;
unsigned int _numOfTextureObjects;
TextureObjectList _orphanedTextureObjects;
TextureObjectList _pendingOrphanedTextureObjects;
TextureObject* _head;
TextureObject* _tail;
};
class OSG_EXPORT TextureObjectManager : public osg::Referenced
{
public:
TextureObjectManager(unsigned int contextID);
unsigned int getContextID() const { return _contextID; }
void setNumberActiveTextureObjects(unsigned int size) { _numActiveTextureObjects = size; }
unsigned int& getNumberActiveTextureObjects() { return _numActiveTextureObjects; }
unsigned int getNumberActiveTextureObjects() const { return _numActiveTextureObjects; }
void setNumberOrphanedTextureObjects(unsigned int size) { _numOrphanedTextureObjects = size; }
unsigned int& getNumberOrphanedTextureObjects() { return _numOrphanedTextureObjects; }
unsigned int getNumberOrphanedTextureObjects() const { return _numOrphanedTextureObjects; }
void setCurrTexturePoolSize(unsigned int size) { _currTexturePoolSize = size; }
unsigned int& getCurrTexturePoolSize() { return _currTexturePoolSize; }
unsigned int getCurrTexturePoolSize() const { return _currTexturePoolSize; }
void setMaxTexturePoolSize(unsigned int size);
unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; }
bool hasSpace(unsigned int size) const { return (_currTexturePoolSize+size)<=_maxTexturePoolSize; }
bool makeSpace(unsigned int size);
osg::ref_ptr<TextureObject> generateTextureObject(const Texture* texture, GLenum target);
osg::ref_ptr<TextureObject> generateTextureObject(const Texture* texture,
GLenum target,
GLint numMipmapLevels,
GLenum internalFormat,
GLsizei width,
GLsizei height,
GLsizei depth,
GLint border);
void handlePendingOrphandedTextureObjects();
void deleteAllTextureObjects();
void discardAllTextureObjects();
void flushAllDeletedTextureObjects();
void discardAllDeletedTextureObjects();
void flushDeletedTextureObjects(double currentTime, double& availableTime);
void releaseTextureObject(TextureObject* to);
TextureObjectSet* getTextureObjectSet(const TextureProfile& profile);
void newFrame(osg::FrameStamp* fs);
void resetStats();
void reportStats(std::ostream& out);
void recomputeStats(std::ostream& out) const;
bool checkConsistency() const;
unsigned int& getFrameNumber() { return _frameNumber; }
unsigned int& getNumberFrames() { return _numFrames; }
unsigned int& getNumberDeleted() { return _numDeleted; }
double& getDeleteTime() { return _deleteTime; }
unsigned int& getNumberGenerated() { return _numGenerated; }
double& getGenerateTime() { return _generateTime; }
unsigned int& getNumberApplied() { return _numApplied; }
double& getApplyTime() { return _applyTime; }
protected:
typedef std::map< TextureProfile, osg::ref_ptr<TextureObjectSet> > TextureSetMap;
unsigned int _contextID;
unsigned int _numActiveTextureObjects;
unsigned int _numOrphanedTextureObjects;
unsigned int _currTexturePoolSize;
unsigned int _maxTexturePoolSize;
TextureSetMap _textureSetMap;
unsigned int _frameNumber;
unsigned int _numFrames;
unsigned int _numDeleted;
double _deleteTime;
unsigned int _numGenerated;
double _generateTime;
unsigned int _numApplied;
double _applyTime;
};
static osg::ref_ptr<Texture::TextureObjectManager>& getTextureObjectManager(unsigned int contextID);
static osg::ref_ptr<TextureObject> generateTextureObject(const Texture* texture, unsigned int contextID,GLenum target); static osg::ref_ptr<TextureObject> generateTextureObject(const Texture* texture, unsigned int contextID,GLenum target);
@ -1254,13 +1115,6 @@ class OSG_EXPORT Texture : public osg::StateAttribute
GLsizei depth, GLsizei depth,
GLint border) const; GLint border) const;
static void deleteAllTextureObjects(unsigned int contextID);
static void discardAllTextureObjects(unsigned int contextID);
static void flushAllDeletedTextureObjects(unsigned int contextID);
static void discardAllDeletedTextureObjects(unsigned int contextID);
static void flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availableTime);
static void releaseTextureObject(unsigned int contextID, TextureObject* to);
protected: protected:
typedef buffered_object< ref_ptr<TextureObject> > TextureObjectBuffer; typedef buffered_object< ref_ptr<TextureObject> > TextureObjectBuffer;
@ -1269,6 +1123,139 @@ class OSG_EXPORT Texture : public osg::StateAttribute
}; };
class OSG_EXPORT TextureObjectSet : public Referenced
{
public:
TextureObjectSet(TextureObjectManager* parent, const Texture::TextureProfile& profile);
const Texture::TextureProfile& getProfile() const { return _profile; }
void handlePendingOrphandedTextureObjects();
void deleteAllTextureObjects();
void discardAllTextureObjects();
void flushAllDeletedTextureObjects();
void discardAllDeletedTextureObjects();
void flushDeletedTextureObjects(double currentTime, double& availableTime);
osg::ref_ptr<Texture::TextureObject> takeFromOrphans(Texture* texture);
osg::ref_ptr<Texture::TextureObject> takeOrGenerate(Texture* texture);
void moveToBack(Texture::TextureObject* to);
void addToBack(Texture::TextureObject* to);
void orphan(Texture::TextureObject* to);
void remove(Texture::TextureObject* to);
void moveToSet(Texture::TextureObject* to, TextureObjectSet* set);
unsigned int size() const { return _profile._size * _numOfTextureObjects; }
bool makeSpace(unsigned int& size);
bool checkConsistency() const;
TextureObjectManager* getParent() { return _parent; }
unsigned int computeNumTextureObjectsInList() const;
unsigned int getNumOfTextureObjects() const { return _numOfTextureObjects; }
unsigned int getNumOrphans() const { return static_cast<unsigned int>(_orphanedTextureObjects.size()); }
unsigned int getNumPendingOrphans() const { return static_cast<unsigned int>(_pendingOrphanedTextureObjects.size()); }
protected:
virtual ~TextureObjectSet();
OpenThreads::Mutex _mutex;
TextureObjectManager* _parent;
unsigned int _contextID;
Texture::TextureProfile _profile;
unsigned int _numOfTextureObjects;
Texture::TextureObjectList _orphanedTextureObjects;
Texture::TextureObjectList _pendingOrphanedTextureObjects;
Texture::TextureObject* _head;
Texture::TextureObject* _tail;
};
class OSG_EXPORT TextureObjectManager : public GraphicsObjectManager
{
public:
TextureObjectManager(unsigned int contextID);
void setNumberActiveTextureObjects(unsigned int size) { _numActiveTextureObjects = size; }
unsigned int& getNumberActiveTextureObjects() { return _numActiveTextureObjects; }
unsigned int getNumberActiveTextureObjects() const { return _numActiveTextureObjects; }
void setNumberOrphanedTextureObjects(unsigned int size) { _numOrphanedTextureObjects = size; }
unsigned int& getNumberOrphanedTextureObjects() { return _numOrphanedTextureObjects; }
unsigned int getNumberOrphanedTextureObjects() const { return _numOrphanedTextureObjects; }
void setCurrTexturePoolSize(unsigned int size) { _currTexturePoolSize = size; }
unsigned int& getCurrTexturePoolSize() { return _currTexturePoolSize; }
unsigned int getCurrTexturePoolSize() const { return _currTexturePoolSize; }
void setMaxTexturePoolSize(unsigned int size);
unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; }
bool hasSpace(unsigned int size) const { return (_currTexturePoolSize+size)<=_maxTexturePoolSize; }
bool makeSpace(unsigned int size);
osg::ref_ptr<Texture::TextureObject> generateTextureObject(const Texture* texture, GLenum target);
osg::ref_ptr<Texture::TextureObject> generateTextureObject(const Texture* texture,
GLenum target,
GLint numMipmapLevels,
GLenum internalFormat,
GLsizei width,
GLsizei height,
GLsizei depth,
GLint border);
void handlePendingOrphandedTextureObjects();
void deleteAllGLObjects();
void discardAllGLObjects();
void flushAllDeletedGLObjects();
void discardAllDeletedGLObjects();
void flushDeletedGLObjects(double currentTime, double& availableTime);
TextureObjectSet* getTextureObjectSet(const Texture::TextureProfile& profile);
void newFrame(osg::FrameStamp* fs);
void resetStats();
void reportStats(std::ostream& out);
void recomputeStats(std::ostream& out) const;
bool checkConsistency() const;
unsigned int& getFrameNumber() { return _frameNumber; }
unsigned int& getNumberFrames() { return _numFrames; }
unsigned int& getNumberDeleted() { return _numDeleted; }
double& getDeleteTime() { return _deleteTime; }
unsigned int& getNumberGenerated() { return _numGenerated; }
double& getGenerateTime() { return _generateTime; }
protected:
~TextureObjectManager();
typedef std::map< Texture::TextureProfile, osg::ref_ptr<TextureObjectSet> > TextureSetMap;
unsigned int _numActiveTextureObjects;
unsigned int _numOrphanedTextureObjects;
unsigned int _currTexturePoolSize;
unsigned int _maxTexturePoolSize;
TextureSetMap _textureSetMap;
unsigned int _frameNumber;
unsigned int _numFrames;
unsigned int _numDeleted;
double _deleteTime;
unsigned int _numGenerated;
double _generateTime;
};
} }
#endif #endif

View File

@ -205,25 +205,6 @@ class OSG_EXPORT VertexProgram : public StateAttribute
/** Force a recompile on next apply() of associated OpenGL vertex program objects. */ /** Force a recompile on next apply() of associated OpenGL vertex program objects. */
void dirtyVertexProgramObject(); void dirtyVertexProgramObject();
/** Use deleteVertexProgramObject instead of glDeletePrograms to allow
* OpenGL Vertex Program objects to cached until they can be deleted
* by the OpenGL context in which they were created, specified
* by contextID.
*/
static void deleteVertexProgramObject(unsigned int contextID,GLuint handle);
/** Flush all the cached vertex programs which need to be deleted
* in the OpenGL context related to contextID.
*/
static void flushDeletedVertexProgramObjects(unsigned int contextID,double currentTime, double& availableTime);
/** discard all the cached vertex programs which need to be deleted
* in the OpenGL context related to contextID.
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
* this call is useful for when an OpenGL context has been destroyed.
*/
static void discardDeletedVertexProgramObjects(unsigned int contextID);
virtual void apply(State& state) const; virtual void apply(State& state) const;
virtual void compileGLObjects(State& state) const { apply(state); } virtual void compileGLObjects(State& state) const { apply(state); }

View File

@ -19,13 +19,13 @@ FOREACH( mylibfolder
osgFX osgFX
osgManipulator osgManipulator
osgParticle osgParticle
osgPresentation osgUI
osgVolume
osgShadow osgShadow
osgSim osgSim
osgTerrain osgTerrain
osgWidget osgWidget
osgUI osgPresentation
osgVolume
osgWrappers/serializers osgWrappers/serializers
osgWrappers/deprecated-dotosg osgWrappers/deprecated-dotosg
osgPlugins osgPlugins

View File

@ -24,6 +24,7 @@
#include <osg/State> #include <osg/State>
#include <osg/PrimitiveSet> #include <osg/PrimitiveSet>
#include <osg/Array> #include <osg/Array>
#include <osg/ContextData>
#include <OpenThreads/ScopedLock> #include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex> #include <OpenThreads/Mutex>
@ -79,6 +80,11 @@ GLBufferObject::~GLBufferObject()
//OSG_NOTICE<<"Destructing BufferObject "<<this<<std::endl; //OSG_NOTICE<<"Destructing BufferObject "<<this<<std::endl;
} }
void GLBufferObject::release()
{
if (_set) _set->orphan(this);
}
void GLBufferObject::setBufferObject(BufferObject* bufferObject) void GLBufferObject::setBufferObject(BufferObject* bufferObject)
{ {
assign(bufferObject); assign(bufferObject);
@ -844,7 +850,7 @@ unsigned int GLBufferObjectSet::computeNumGLBufferObjectsInList() const
GLBufferObjectManager::GLBufferObjectManager(unsigned int contextID): GLBufferObjectManager::GLBufferObjectManager(unsigned int contextID):
_contextID(contextID), GraphicsObjectManager("GLBufferObjectManager", contextID),
_numActiveGLBufferObjects(0), _numActiveGLBufferObjects(0),
_numOrphanedGLBufferObjects(0), _numOrphanedGLBufferObjects(0),
_currGLBufferObjectPoolSize(0), _currGLBufferObjectPoolSize(0),
@ -860,6 +866,10 @@ GLBufferObjectManager::GLBufferObjectManager(unsigned int contextID):
{ {
} }
GLBufferObjectManager::~GLBufferObjectManager()
{
}
void GLBufferObjectManager::setMaxGLBufferObjectPoolSize(unsigned int size) void GLBufferObjectManager::setMaxGLBufferObjectPoolSize(unsigned int size)
{ {
if (_maxGLBufferObjectPoolSize == size) return; if (_maxGLBufferObjectPoolSize == size) return;
@ -915,7 +925,7 @@ void GLBufferObjectManager::handlePendingOrphandedGLBufferObjects()
} }
} }
void GLBufferObjectManager::deleteAllGLBufferObjects() void GLBufferObjectManager::deleteAllGLObjects()
{ {
ElapsedTime elapsedTime(&(getDeleteTime())); ElapsedTime elapsedTime(&(getDeleteTime()));
@ -927,7 +937,7 @@ void GLBufferObjectManager::deleteAllGLBufferObjects()
} }
} }
void GLBufferObjectManager::discardAllGLBufferObjects() void GLBufferObjectManager::discardAllGLObjects()
{ {
for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin(); for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
itr != _glBufferObjectSetMap.end(); itr != _glBufferObjectSetMap.end();
@ -937,7 +947,7 @@ void GLBufferObjectManager::discardAllGLBufferObjects()
} }
} }
void GLBufferObjectManager::flushAllDeletedGLBufferObjects() void GLBufferObjectManager::flushAllDeletedGLObjects()
{ {
ElapsedTime elapsedTime(&(getDeleteTime())); ElapsedTime elapsedTime(&(getDeleteTime()));
@ -949,7 +959,7 @@ void GLBufferObjectManager::flushAllDeletedGLBufferObjects()
} }
} }
void GLBufferObjectManager::discardAllDeletedGLBufferObjects() void GLBufferObjectManager::discardAllDeletedGLObjects()
{ {
for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin(); for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin();
itr != _glBufferObjectSetMap.end(); itr != _glBufferObjectSetMap.end();
@ -959,7 +969,7 @@ void GLBufferObjectManager::discardAllDeletedGLBufferObjects()
} }
} }
void GLBufferObjectManager::flushDeletedGLBufferObjects(double currentTime, double& availableTime) void GLBufferObjectManager::flushDeletedGLObjects(double currentTime, double& availableTime)
{ {
ElapsedTime elapsedTime(&(getDeleteTime())); ElapsedTime elapsedTime(&(getDeleteTime()));
@ -971,13 +981,6 @@ void GLBufferObjectManager::flushDeletedGLBufferObjects(double currentTime, doub
} }
} }
void GLBufferObjectManager::releaseGLBufferObject(GLBufferObject* to)
{
if (to->_set) to->_set->orphan(to);
else OSG_NOTICE<<"GLBufferObjectManager::releaseGLBufferObject(GLBufferObject* to) Not implemented yet"<<std::endl;
}
void GLBufferObjectManager::newFrame(osg::FrameStamp* fs) void GLBufferObjectManager::newFrame(osg::FrameStamp* fs)
{ {
if (fs) _frameNumber = fs->getFrameNumber(); if (fs) _frameNumber = fs->getFrameNumber();
@ -1042,52 +1045,6 @@ void GLBufferObjectManager::recomputeStats(std::ostream& out)
out<<" getMaxGLBufferObjectPoolSize()="<<getMaxGLBufferObjectPoolSize()<<" current/max size = "<<double(currentSize)/double(getMaxGLBufferObjectPoolSize())<<std::endl; out<<" getMaxGLBufferObjectPoolSize()="<<getMaxGLBufferObjectPoolSize()<<" current/max size = "<<double(currentSize)/double(getMaxGLBufferObjectPoolSize())<<std::endl;
} }
osg::ref_ptr<GLBufferObjectManager>& GLBufferObjectManager::getGLBufferObjectManager(unsigned int contextID)
{
typedef osg::buffered_object< ref_ptr<GLBufferObjectManager> > GLBufferObjectManagerBuffer;
static GLBufferObjectManagerBuffer s_GLBufferObjectManager;
if (!s_GLBufferObjectManager[contextID]) s_GLBufferObjectManager[contextID] = new GLBufferObjectManager(contextID);
return s_GLBufferObjectManager[contextID];
}
osg::ref_ptr<GLBufferObject> GLBufferObject::createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject)
{
return GLBufferObjectManager::getGLBufferObjectManager(contextID)->generateGLBufferObject(bufferObject);
}
void GLBufferObject::deleteAllBufferObjects(unsigned int contextID)
{
GLBufferObjectManager::getGLBufferObjectManager(contextID)->deleteAllGLBufferObjects();
}
void GLBufferObject::discardAllBufferObjects(unsigned int contextID)
{
GLBufferObjectManager::getGLBufferObjectManager(contextID)->discardAllGLBufferObjects();
}
void GLBufferObject::flushAllDeletedBufferObjects(unsigned int contextID)
{
GLBufferObjectManager::getGLBufferObjectManager(contextID)->flushAllDeletedGLBufferObjects();
}
void GLBufferObject::discardAllDeletedBufferObjects(unsigned int contextID)
{
GLBufferObjectManager::getGLBufferObjectManager(contextID)->discardAllDeletedGLBufferObjects();
}
void GLBufferObject::flushDeletedBufferObjects(unsigned int contextID,double currentTime, double& availbleTime)
{
GLBufferObjectManager::getGLBufferObjectManager(contextID)->flushDeletedGLBufferObjects(currentTime, availbleTime);
}
void GLBufferObject::releaseGLBufferObject(unsigned int contextID, GLBufferObject* to)
{
GLBufferObjectManager::getGLBufferObjectManager(contextID)->releaseGLBufferObject(to);
}
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// BufferObject // BufferObject
@ -1108,6 +1065,11 @@ BufferObject::~BufferObject()
releaseGLObjects(0); releaseGLObjects(0);
} }
GLBufferObject* BufferObject::getOrCreateGLBufferObject(unsigned int contextID) const
{
if (!_glBufferObjects[contextID]) _glBufferObjects[contextID] = osg::get<GLBufferObjectManager>(contextID)->generateGLBufferObject(this);
return _glBufferObjects[contextID].get();
}
void BufferObject::setBufferData(unsigned int index, BufferData* bd) void BufferObject::setBufferData(unsigned int index, BufferData* bd)
{ {
@ -1136,7 +1098,7 @@ void BufferObject::releaseGLObjects(State* state) const
unsigned int contextID = state->getContextID(); unsigned int contextID = state->getContextID();
if (_glBufferObjects[contextID].valid()) if (_glBufferObjects[contextID].valid())
{ {
GLBufferObject::releaseGLBufferObject(contextID, _glBufferObjects[contextID].get()); _glBufferObjects[contextID]->release();
_glBufferObjects[contextID] = 0; _glBufferObjects[contextID] = 0;
} }
} }
@ -1147,7 +1109,7 @@ void BufferObject::releaseGLObjects(State* state) const
if (_glBufferObjects[i].valid()) if (_glBufferObjects[i].valid())
{ {
// OSG_NOTICE<<" GLBufferObject::releaseGLBufferObject("<<i<<", _glBufferObjects["<<i<<"]="<<_glBufferObjects[i].get()<<")"<<std::endl; // OSG_NOTICE<<" GLBufferObject::releaseGLBufferObject("<<i<<", _glBufferObjects["<<i<<"]="<<_glBufferObjects[i].get()<<")"<<std::endl;
GLBufferObject::releaseGLBufferObject(i, _glBufferObjects[i].get()); _glBufferObjects[i]->release();
_glBufferObjects[i] = 0; _glBufferObjects[i] = 0;
} }
} }
@ -1235,7 +1197,7 @@ void BufferObject::deleteBufferObject(unsigned int contextID,GLuint globj)
// implement deleteBufferObject for backwards compatibility by adding // implement deleteBufferObject for backwards compatibility by adding
// a GLBufferObject for the globj id to BufferObjectManager/Set for the specified context. // a GLBufferObject for the globj id to BufferObjectManager/Set for the specified context.
osg::ref_ptr<GLBufferObjectManager>& bufferObjectManager = GLBufferObjectManager::getGLBufferObjectManager(contextID); GLBufferObjectManager* bufferObjectManager = osg::get<GLBufferObjectManager>(contextID);
if (!bufferObjectManager) if (!bufferObjectManager)
{ {
OSG_NOTICE<<"Warning::BufferObject::deleteBufferObject("<<contextID<<", "<<globj<<") unable to get GLBufferObjectManager for context."<<std::endl; OSG_NOTICE<<"Warning::BufferObject::deleteBufferObject("<<contextID<<", "<<globj<<") unable to get GLBufferObjectManager for context."<<std::endl;

View File

@ -55,6 +55,7 @@ SET(TARGET_H
${HEADER_PATH}/ColorMaski ${HEADER_PATH}/ColorMaski
${HEADER_PATH}/ColorMatrix ${HEADER_PATH}/ColorMatrix
${HEADER_PATH}/ComputeBoundsVisitor ${HEADER_PATH}/ComputeBoundsVisitor
${HEADER_PATH}/ContextData
${HEADER_PATH}/ConvexPlanarOccluder ${HEADER_PATH}/ConvexPlanarOccluder
${HEADER_PATH}/ConvexPlanarPolygon ${HEADER_PATH}/ConvexPlanarPolygon
${HEADER_PATH}/CoordinateSystemNode ${HEADER_PATH}/CoordinateSystemNode
@ -257,6 +258,7 @@ SET(TARGET_SRC
ColorMaski.cpp ColorMaski.cpp
ColorMatrix.cpp ColorMatrix.cpp
ComputeBoundsVisitor.cpp ComputeBoundsVisitor.cpp
ContextData.cpp
ConvexPlanarOccluder.cpp ConvexPlanarOccluder.cpp
ConvexPlanarPolygon.cpp ConvexPlanarPolygon.cpp
CoordinateSystemNode.cpp CoordinateSystemNode.cpp

335
src/osg/ContextData.cpp Normal file
View File

@ -0,0 +1,335 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osg/ContextData>
#include <osg/FrameStamp>
#include <OpenThreads/ReentrantMutex>
#include <algorithm>
using namespace osg;
typedef std::map<unsigned int, osg::ref_ptr<ContextData> > ContextIDMap;
static ContextIDMap s_contextIDMap;
static OpenThreads::ReentrantMutex s_contextIDMapMutex;
static ContextData::GraphicsContexts s_registeredContexts;
ContextData::ContextData(unsigned int contextID):
GraphicsObjectManager("ContextData", contextID)
{
}
ContextData::~ContextData()
{
}
void ContextData::newFrame(osg::FrameStamp* frameStamp)
{
// OSG_NOTICE<<"ContextData::newFrame("<<frameStamp->getFrameNumber()<<")"<<std::endl;
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->newFrame(frameStamp);
}
}
void ContextData::resetStats()
{
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->resetStats();
}
}
void ContextData::reportStats(std::ostream& out)
{
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->reportStats(out);
}
}
void ContextData::recomputeStats(std::ostream& out) const
{
for(ManagerMap::const_iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->recomputeStats(out);
}
}
void ContextData::flushDeletedGLObjects(double currentTime, double& availableTime)
{
// OSG_NOTICE<<"ContextData::flushDeletedGLObjects("<<currentTime<<","<<availableTime<<")"<<std::endl;
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->flushDeletedGLObjects(currentTime, availableTime);
}
}
void ContextData::flushAllDeletedGLObjects()
{
// OSG_NOTICE<<"ContextData::flushAllDeletedGLObjects()"<<std::endl;
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->flushAllDeletedGLObjects();
}
}
void ContextData::deleteAllGLObjects()
{
// OSG_NOTICE<<"ContextData::deleteAllGLObjects()"<<std::endl;
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->deleteAllGLObjects();
}
}
void ContextData::discardAllGLObjects()
{
// OSG_NOTICE<<"ContextData::discardAllGLObjects()"<<std::endl;
for(ManagerMap::iterator itr = _managerMap.begin();
itr != _managerMap.end();
++itr)
{
osg::GraphicsObjectManager* gom = dynamic_cast<osg::GraphicsObjectManager*>(itr->second.get());
if (gom) gom->discardAllGLObjects();
}
}
ContextData* osg::getContextData(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
ContextIDMap::iterator itr = s_contextIDMap.find(contextID);
return (itr!=s_contextIDMap.end()) ? itr->second.get() : 0;
}
/** Get or create the ContextData for a specific contextID.*/
ContextData* osg::getOrCreateContextData(unsigned int contextID)
{
//OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
osg::ref_ptr<ContextData>& cd = s_contextIDMap[contextID];
if (!cd)
{
cd = new ContextData(contextID);
}
return cd.get();
}
unsigned int ContextData::createNewContextID()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
// first check to see if we can reuse contextID;
for(ContextIDMap::iterator itr = s_contextIDMap.begin();
itr != s_contextIDMap.end();
++itr)
{
if (!itr->second || itr->second->getNumContexts() == 0)
{
itr->second = new ContextData(itr->first);
itr->second->setNumContexts(1);
OSG_INFO<<"ContextData::createNewContextID() : reusing contextID="<<itr->first<<std::endl;
return itr->first;
}
}
unsigned int contextID = s_contextIDMap.size();
s_contextIDMap[contextID] = new ContextData(contextID);
s_contextIDMap[contextID]->setNumContexts(1);
OSG_INFO<<"ContextData::createNewContextID() creating contextID="<<contextID<<std::endl;
OSG_INFO<<"Updating the MaxNumberOfGraphicsContexts to "<<contextID+1<<std::endl;
// update the maximum number of graphics contexts,
// to ensure that texture objects and display buffers are configured to the correct size.
osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts( contextID + 1 );
return contextID;
}
unsigned int ContextData::getMaxContextID()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
unsigned int maxContextID = 0;
for(ContextIDMap::iterator itr = s_contextIDMap.begin();
itr != s_contextIDMap.end();
++itr)
{
if (itr->first > maxContextID) maxContextID = itr->first;
}
return maxContextID;
}
void ContextData::incrementContextIDUsageCount(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
if (!s_contextIDMap[contextID]) s_contextIDMap[contextID] = new ContextData(contextID);
s_contextIDMap[contextID]->incrementUsageCount();
OSG_NOTICE<<"ContextData::incrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]->getNumContexts()<<std::endl;
}
void ContextData::decrementContextIDUsageCount(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
if (s_contextIDMap[contextID].valid())
{
if (s_contextIDMap[contextID]->getNumContexts()!=0)
{
s_contextIDMap[contextID]->decrementUsageCount();
}
if (s_contextIDMap[contextID]->getNumContexts()==0)
{
s_contextIDMap[contextID] = 0;
}
}
}
void ContextData::registerGraphicsContext(GraphicsContext* gc)
{
OSG_INFO<<"ContextData::registerGraphicsContext "<<gc<<std::endl;
if (!gc) return;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc);
if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr);
s_registeredContexts.push_back(gc);
}
void ContextData::unregisterGraphicsContext(GraphicsContext* gc)
{
OSG_INFO<<"ContextData::unregisterGraphicsContext "<<gc<<std::endl;
if (!gc) return;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc);
if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr);
}
ContextData::GraphicsContexts ContextData::getAllRegisteredGraphicsContexts()
{
OSG_INFO<<"ContextData::getAllRegisteredGraphicsContexts s_registeredContexts.size()="<<s_registeredContexts.size()<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
return s_registeredContexts;
}
ContextData::GraphicsContexts ContextData::getRegisteredGraphicsContexts(unsigned int contextID)
{
GraphicsContexts contexts;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
for(GraphicsContexts::iterator itr = s_registeredContexts.begin();
itr != s_registeredContexts.end();
++itr)
{
GraphicsContext* gc = *itr;
if (gc->getState() && gc->getState()->getContextID()==contextID) contexts.push_back(gc);
}
OSG_INFO<<"ContextData::getRegisteredGraphicsContexts "<<contextID<<" contexts.size()="<<contexts.size()<<std::endl;
return contexts;
}
GraphicsContext* ContextData::getOrCreateCompileContext(unsigned int contextID)
{
OSG_NOTICE<<"ContextData::createCompileContext."<<std::endl;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
if (s_contextIDMap[contextID]->getCompileContext()) return s_contextIDMap[contextID]->getCompileContext();
}
GraphicsContexts contexts = ContextData::getRegisteredGraphicsContexts(contextID);
if (contexts.empty()) return 0;
GraphicsContext* src_gc = contexts.front();
const osg::GraphicsContext::Traits* src_traits = src_gc->getTraits();
osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
traits->screenNum = src_traits->screenNum;
traits->displayNum = src_traits->displayNum;
traits->hostName = src_traits->hostName;
traits->width = 100;
traits->height = 100;
traits->red = src_traits->red;
traits->green = src_traits->green;
traits->blue = src_traits->blue;
traits->alpha = src_traits->alpha;
traits->depth = src_traits->depth;
traits->sharedContext = src_gc;
traits->pbuffer = true;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits);
if (gc.valid() && gc->realize())
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
s_contextIDMap[contextID]->setCompileContext(gc.get());
OSG_NOTICE<<" succeeded ContextData::createCompileContext."<<std::endl;
return gc.release();
}
else
{
return 0;
}
}
void ContextData::setCompileContext(unsigned int contextID, GraphicsContext* gc)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
s_contextIDMap[contextID]->setCompileContext(gc);
}
GraphicsContext* ContextData::getCompileContext(unsigned int contextID)
{
// OSG_NOTICE<<"ContextData::getCompileContext "<<contextID<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
ContextIDMap::iterator itr = s_contextIDMap.find(contextID);
if (itr != s_contextIDMap.end()) return itr->second->getCompileContext();
else return 0;
}

View File

@ -21,6 +21,7 @@
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/Timer> #include <osg/Timer>
#include <osg/TriangleFunctor> #include <osg/TriangleFunctor>
#include <osg/ContextData>
#include <osg/io_utils> #include <osg/io_utils>
#include <algorithm> #include <algorithm>
@ -32,58 +33,7 @@
using namespace osg; using namespace osg;
unsigned int Drawable::s_numberDrawablesReusedLastInLastFrame = 0; static unsigned int s_minimumNumberOfDisplayListsToRetainInCache = 0;
unsigned int Drawable::s_numberNewDrawablesInLastFrame = 0;
unsigned int Drawable::s_numberDeletedDrawablesInLastFrame = 0;
// static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context
// is set. Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
typedef std::multimap<unsigned int,GLuint> DisplayListMap;
typedef osg::buffered_object<DisplayListMap> DeletedDisplayListCache;
static OpenThreads::Mutex s_mutex_deletedDisplayListCache;
static DeletedDisplayListCache s_deletedDisplayListCache;
GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint)
{
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
DisplayListMap& dll = s_deletedDisplayListCache[contextID];
if (dll.empty())
{
++s_numberNewDrawablesInLastFrame;
return glGenLists( 1 );
}
else
{
DisplayListMap::iterator itr = dll.lower_bound(sizeHint);
if (itr!=dll.end())
{
// OSG_NOTICE<<"Reusing a display list of size = "<<itr->first<<" for requested size = "<<sizeHint<<std::endl;
++s_numberDrawablesReusedLastInLastFrame;
GLuint globj = itr->second;
dll.erase(itr);
return globj;
}
else
{
// OSG_NOTICE<<"Creating a new display list of size = "<<sizeHint<<" although "<<dll.size()<<" are available"<<std::endl;
++s_numberNewDrawablesInLastFrame;
return glGenLists( 1 );
}
}
#else
OSG_NOTICE<<"Warning: Drawable::generateDisplayList(..) - not supported."<<std::endl;
return 0;
#endif
}
unsigned int s_minimumNumberOfDisplayListsToRetainInCache = 0;
void Drawable::setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum) void Drawable::setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum)
{ {
s_minimumNumberOfDisplayListsToRetainInCache = minimum; s_minimumNumberOfDisplayListsToRetainInCache = minimum;
@ -94,52 +44,22 @@ unsigned int Drawable::getMinimumNumberOfDisplayListsToRetainInCache()
return s_minimumNumberOfDisplayListsToRetainInCache; return s_minimumNumberOfDisplayListsToRetainInCache;
} }
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint) class DisplayListManager : public GraphicsObjectManager
{
public:
DisplayListManager(unsigned int contextID):
GraphicsObjectManager("DisplayListManager", contextID),
_numberDrawablesReusedLastInLastFrame(0),
_numberNewDrawablesInLastFrame(0),
_numberDeletedDrawablesInLastFrame(0)
{
}
virtual void flushDeletedGLObjects(double, double& availableTime)
{ {
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
if (globj!=0) // OSG_NOTICE<<"void DisplayListManager::flushDeletedGLObjects(, "<<availableTime<<")"<<std::endl;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
// insert the globj into the cache for the appropriate context.
s_deletedDisplayListCache[contextID].insert(DisplayListMap::value_type(sizeHint,globj));
}
#else
OSG_NOTICE<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
#endif
}
void Drawable::flushAllDeletedDisplayLists(unsigned int contextID)
{
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
DisplayListMap& dll = s_deletedDisplayListCache[contextID];
for(DisplayListMap::iterator ditr=dll.begin();
ditr!=dll.end();
++ditr)
{
glDeleteLists(ditr->second,1);
}
dll.clear();
#else
OSG_NOTICE<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
#endif
}
void Drawable::discardAllDeletedDisplayLists(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
DisplayListMap& dll = s_deletedDisplayListCache[contextID];
dll.clear();
}
void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availableTime)
{
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
// if no time available don't try to flush objects. // if no time available don't try to flush objects.
if (availableTime<=0.0) return; if (availableTime<=0.0) return;
@ -150,19 +70,17 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availabl
unsigned int noDeleted = 0; unsigned int noDeleted = 0;
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
DisplayListMap& dll = s_deletedDisplayListCache[contextID];
bool trimFromFront = true; bool trimFromFront = true;
if (trimFromFront) if (trimFromFront)
{ {
unsigned int prev_size = dll.size(); unsigned int prev_size = _displayListMap.size();
DisplayListMap::iterator ditr=dll.begin(); DisplayListMap::iterator ditr=_displayListMap.begin();
unsigned int maxNumToDelete = (dll.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0; unsigned int maxNumToDelete = (_displayListMap.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? _displayListMap.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
for(; for(;
ditr!=dll.end() && elapsedTime<availableTime && noDeleted<maxNumToDelete; ditr!=_displayListMap.end() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
++ditr) ++ditr)
{ {
glDeleteLists(ditr->second,1); glDeleteLists(ditr->second,1);
@ -170,24 +88,24 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availabl
elapsedTime = timer.delta_s(start_tick,timer.tick()); elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted; ++noDeleted;
++Drawable::s_numberDeletedDrawablesInLastFrame; ++_numberDeletedDrawablesInLastFrame;
} }
if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr); if (ditr!=_displayListMap.begin()) _displayListMap.erase(_displayListMap.begin(),ditr);
if (noDeleted+dll.size() != prev_size) if (noDeleted+_displayListMap.size() != prev_size)
{ {
OSG_WARN<<"Error in delete"<<std::endl; OSG_WARN<<"Error in delete"<<std::endl;
} }
} }
else else
{ {
unsigned int prev_size = dll.size(); unsigned int prev_size = _displayListMap.size();
DisplayListMap::reverse_iterator ditr=dll.rbegin(); DisplayListMap::reverse_iterator ditr=_displayListMap.rbegin();
unsigned int maxNumToDelete = (dll.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0; unsigned int maxNumToDelete = (_displayListMap.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? _displayListMap.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
for(; for(;
ditr!=dll.rend() && elapsedTime<availableTime && noDeleted<maxNumToDelete; ditr!=_displayListMap.rend() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
++ditr) ++ditr)
{ {
glDeleteLists(ditr->second,1); glDeleteLists(ditr->second,1);
@ -195,12 +113,12 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availabl
elapsedTime = timer.delta_s(start_tick,timer.tick()); elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted; ++noDeleted;
++Drawable::s_numberDeletedDrawablesInLastFrame; ++_numberDeletedDrawablesInLastFrame;
} }
if (ditr!=dll.rbegin()) dll.erase(ditr.base(),dll.end()); if (ditr!=_displayListMap.rbegin()) _displayListMap.erase(ditr.base(),_displayListMap.end());
if (noDeleted+dll.size() != prev_size) if (noDeleted+_displayListMap.size() != prev_size)
{ {
OSG_WARN<<"Error in delete"<<std::endl; OSG_WARN<<"Error in delete"<<std::endl;
} }
@ -216,6 +134,115 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availabl
#endif #endif
} }
virtual void flushAllDeletedGLObjects()
{
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
OSG_NOTICE<<"void DisplayListManager::flushAllDeletedGLObjects()"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
for(DisplayListMap::iterator ditr=_displayListMap.begin();
ditr!=_displayListMap.end();
++ditr)
{
glDeleteLists(ditr->second,1);
}
_displayListMap.clear();
#else
OSG_NOTICE<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
#endif
}
virtual void deleteAllGLObjects()
{
OSG_NOTICE<<"DisplayListManager::deleteAllGLObjects() Not currently implementated"<<std::endl;
}
virtual void discardAllGLObjects()
{
OSG_NOTICE<<"void DisplayListManager::discardAllGLObjects()"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
_displayListMap.clear();
}
void deleteDisplayList(GLuint globj, unsigned int sizeHint)
{
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
if (globj!=0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
// insert the globj into the cache for the appropriate context.
_displayListMap.insert(DisplayListMap::value_type(sizeHint,globj));
}
#else
OSG_NOTICE<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
#endif
}
GLuint generateDisplayList(unsigned int sizeHint)
{
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
if (_displayListMap.empty())
{
++_numberNewDrawablesInLastFrame;
return glGenLists( 1 );
}
else
{
DisplayListMap::iterator itr = _displayListMap.lower_bound(sizeHint);
if (itr!=_displayListMap.end())
{
// OSG_NOTICE<<"Reusing a display list of size = "<<itr->first<<" for requested size = "<<sizeHint<<std::endl;
++_numberDrawablesReusedLastInLastFrame;
GLuint globj = itr->second;
_displayListMap.erase(itr);
return globj;
}
else
{
// OSG_NOTICE<<"Creating a new display list of size = "<<sizeHint<<" although "<<_displayListMap.size()<<" are available"<<std::endl;
++_numberNewDrawablesInLastFrame;
return glGenLists( 1 );
}
}
#else
OSG_NOTICE<<"Warning: Drawable::generateDisplayList(..) - not supported."<<std::endl;
return 0;
#endif
}
protected:
int _numberDrawablesReusedLastInLastFrame;
int _numberNewDrawablesInLastFrame;
int _numberDeletedDrawablesInLastFrame;
typedef std::multimap<unsigned int,GLuint> DisplayListMap;
OpenThreads::Mutex _mutex_deletedDisplayListCache;
DisplayListMap _displayListMap;
};
GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint)
{
return osg::get<DisplayListManager>(contextID)->generateDisplayList(sizeHint);
}
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint)
{
osg::get<DisplayListManager>(contextID)->deleteDisplayList(globj, sizeHint);
}
bool Drawable::UpdateCallback::run(osg::Object* object, osg::Object* data) bool Drawable::UpdateCallback::run(osg::Object* object, osg::Object* data)
{ {
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(object); osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(object);

View File

@ -15,71 +15,21 @@
#include <osg/FragmentProgram> #include <osg/FragmentProgram>
#include <osg/State> #include <osg/State>
#include <osg/Timer> #include <osg/Timer>
#include <osg/ContextData>
#include <list>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
using namespace osg; using namespace osg;
// static cache of deleted fragment programs which can only class GLFragmentProgramManager : public GLObjectManager
// by completely deleted once the appropriate OpenGL context
// is set.
typedef std::list<GLuint> FragmentProgramObjectList;
typedef osg::buffered_object<FragmentProgramObjectList> DeletedFragmentProgramObjectCache;
static OpenThreads::Mutex s_mutex_deletedFragmentProgramObjectCache;
static DeletedFragmentProgramObjectCache s_deletedFragmentProgramObjectCache;
void FragmentProgram::deleteFragmentProgramObject(unsigned int contextID,GLuint handle)
{ {
if (handle!=0) public:
GLFragmentProgramManager(unsigned int contextID) : GLObjectManager("GLFragmentProgramManager",contextID) {}
virtual void deleteGLObject(GLuint globj)
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache); const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeletePrograms(1, &globj );
// insert the handle into the cache for the appropriate context.
s_deletedFragmentProgramObjectCache[contextID].push_back(handle);
} }
} };
void FragmentProgram::flushDeletedFragmentProgramObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
const GLExtensions* extensions = GLExtensions::Get(contextID,true);
FragmentProgramObjectList& vpol = s_deletedFragmentProgramObjectCache[contextID];
for(FragmentProgramObjectList::iterator titr=vpol.begin();
titr!=vpol.end() && elapsedTime<availableTime;
)
{
extensions->glDeletePrograms( 1L, &(*titr ) );
titr = vpol.erase(titr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
}
void FragmentProgram::discardDeletedFragmentProgramObjects(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
FragmentProgramObjectList& vpol = s_deletedFragmentProgramObjectCache[contextID];
vpol.clear();
}
FragmentProgram::FragmentProgram() FragmentProgram::FragmentProgram()
{ {
@ -117,7 +67,7 @@ void FragmentProgram::dirtyFragmentProgramObject()
{ {
if (_fragmentProgramIDList[i] != 0) if (_fragmentProgramIDList[i] != 0)
{ {
FragmentProgram::deleteFragmentProgramObject(i,_fragmentProgramIDList[i]); osg::get<GLFragmentProgramManager>(i)->deleteGLObject(_fragmentProgramIDList[i]);
_fragmentProgramIDList[i] = 0; _fragmentProgramIDList[i] = 0;
} }
} }
@ -207,7 +157,7 @@ void FragmentProgram::releaseGLObjects(State* state) const
unsigned int contextID = state->getContextID(); unsigned int contextID = state->getContextID();
if (_fragmentProgramIDList[contextID] != 0) if (_fragmentProgramIDList[contextID] != 0)
{ {
FragmentProgram::deleteFragmentProgramObject(contextID,_fragmentProgramIDList[contextID]); osg::get<GLFragmentProgramManager>(contextID)->deleteGLObject(_fragmentProgramIDList[contextID]);
_fragmentProgramIDList[contextID] = 0; _fragmentProgramIDList[contextID] = 0;
} }
} }

View File

@ -24,73 +24,37 @@
#include <osg/TextureCubeMap> #include <osg/TextureCubeMap>
#include <osg/TextureRectangle> #include <osg/TextureRectangle>
#include <osg/Notify> #include <osg/Notify>
#include <osg/ContextData>
#include <osg/Timer> #include <osg/Timer>
using namespace osg; using namespace osg;
GLRenderBufferManager::GLRenderBufferManager(unsigned int contextID):
GLObjectManager("GLRenderBufferManager",contextID)
{}
void GLRenderBufferManager::deleteGLObject(GLuint globj)
{
const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeleteRenderbuffers(1, &globj );
}
GLFrameBufferObjectManager::GLFrameBufferObjectManager(unsigned int contextID):
GLObjectManager("GLFrameBufferObjectManager",contextID)
{}
void GLFrameBufferObjectManager::deleteGLObject(GLuint globj)
{
const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeleteFramebuffers(1, &globj );
}
/************************************************************************** /**************************************************************************
* RenderBuffer * RenderBuffer
**************************************************************************/ **************************************************************************/
///////////////////////////////////////////////////////////////////////////
// static cache of glRenderbuffers flagged for deletion, which will actually
// be deleted in the correct GL context.
typedef std::list<GLuint> RenderBufferHandleList;
typedef osg::buffered_object<RenderBufferHandleList> DeletedRenderBufferCache;
static OpenThreads::Mutex s_mutex_deletedRenderBufferCache;
static DeletedRenderBufferCache s_deletedRenderBufferCache;
void RenderBuffer::deleteRenderBuffer(unsigned int contextID, GLuint rb)
{
if( rb )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedRenderBufferCache);
// add glProgram to the cache for the appropriate context.
s_deletedRenderBufferCache[contextID].push_back(rb);
}
}
void RenderBuffer::flushDeletedRenderBuffers(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const GLExtensions* extensions = GLExtensions::Get(contextID,true);
if(!extensions || !extensions->isFrameBufferObjectSupported ) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedRenderBufferCache);
RenderBufferHandleList& pList = s_deletedRenderBufferCache[contextID];
for(RenderBufferHandleList::iterator titr=pList.begin();
titr!=pList.end() && elapsedTime<availableTime;
)
{
extensions->glDeleteRenderbuffers(1, &(*titr) );
titr = pList.erase( titr );
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
}
void RenderBuffer::discardDeletedRenderBuffers(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedRenderBufferCache);
RenderBufferHandleList& pList = s_deletedRenderBufferCache[contextID];
pList.clear();
}
RenderBuffer::RenderBuffer() RenderBuffer::RenderBuffer()
: Object(), : Object(),
_internalFormat(GL_DEPTH_COMPONENT24), _internalFormat(GL_DEPTH_COMPONENT24),
@ -125,7 +89,7 @@ RenderBuffer::~RenderBuffer()
{ {
for(unsigned i=0; i<_objectID.size(); ++i) for(unsigned i=0; i<_objectID.size(); ++i)
{ {
if (_objectID[i]) deleteRenderBuffer(i, _objectID[i]); if (_objectID[i]) osg::get<GLRenderBufferManager>(i)->deleteGLObject(_objectID[i]);
} }
} }
@ -209,7 +173,7 @@ void RenderBuffer::releaseGLObjects(osg::State* state) const
unsigned int contextID = state->getContextID(); unsigned int contextID = state->getContextID();
if (_objectID[contextID]) if (_objectID[contextID])
{ {
deleteRenderBuffer(contextID, _objectID[contextID]); osg::get<GLRenderBufferManager>(contextID)->deleteGLObject(_objectID[contextID]);
_objectID[contextID] = 0; _objectID[contextID] = 0;
} }
} }
@ -219,7 +183,7 @@ void RenderBuffer::releaseGLObjects(osg::State* state) const
{ {
if (_objectID[i]) if (_objectID[i])
{ {
deleteRenderBuffer(i, _objectID[i]); osg::get<GLRenderBufferManager>(i)->deleteGLObject(_objectID[i]);
_objectID[i] = 0; _objectID[i] = 0;
} }
} }
@ -615,66 +579,6 @@ unsigned int FrameBufferAttachment::getTextureArrayLayer() const
* FrameBufferObject * FrameBufferObject
**************************************************************************/ **************************************************************************/
///////////////////////////////////////////////////////////////////////////
// static cache of glRenderbuffers flagged for deletion, which will actually
// be deleted in the correct GL context.
typedef std::list<GLuint> FrameBufferObjectHandleList;
typedef osg::buffered_object<FrameBufferObjectHandleList> DeletedFrameBufferObjectCache;
static OpenThreads::Mutex s_mutex_deletedFrameBufferObjectCache;
static DeletedFrameBufferObjectCache s_deletedFrameBufferObjectCache;
void FrameBufferObject::deleteFrameBufferObject(unsigned int contextID, GLuint rb)
{
if( rb )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFrameBufferObjectCache);
// add glProgram to the cache for the appropriate context.
s_deletedFrameBufferObjectCache[contextID].push_back(rb);
}
}
void FrameBufferObject::flushDeletedFrameBufferObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const GLExtensions* extensions = GLExtensions::Get(contextID,true);
if(!extensions || !extensions->isFrameBufferObjectSupported ) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFrameBufferObjectCache);
FrameBufferObjectHandleList& pList = s_deletedFrameBufferObjectCache[contextID];
for(FrameBufferObjectHandleList::iterator titr=pList.begin();
titr!=pList.end() && elapsedTime<availableTime;
)
{
extensions->glDeleteFramebuffers(1, &(*titr) );
titr = pList.erase( titr );
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
}
void FrameBufferObject::discardDeletedFrameBufferObjects(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFrameBufferObjectCache);
FrameBufferObjectHandleList& pList = s_deletedFrameBufferObjectCache[contextID];
pList.clear();
}
FrameBufferObject::FrameBufferObject() FrameBufferObject::FrameBufferObject()
: StateAttribute() : StateAttribute()
{ {
@ -691,7 +595,7 @@ FrameBufferObject::~FrameBufferObject()
{ {
for(unsigned i=0; i<_fboID.size(); ++i) for(unsigned i=0; i<_fboID.size(); ++i)
{ {
if (_fboID[i]) deleteFrameBufferObject(i, _fboID[i]); if (_fboID[i]) osg::get<GLFrameBufferObjectManager>(i)->deleteGLObject(_fboID[i]);
} }
} }
@ -709,7 +613,7 @@ void FrameBufferObject::releaseGLObjects(osg::State* state) const
unsigned int contextID = state->getContextID(); unsigned int contextID = state->getContextID();
if (_fboID[contextID]) if (_fboID[contextID])
{ {
deleteFrameBufferObject(contextID, _fboID[contextID]); osg::get<GLFrameBufferObjectManager>(contextID)->deleteGLObject(_fboID[contextID]);
_fboID[contextID] = 0; _fboID[contextID] = 0;
} }
} }
@ -719,7 +623,7 @@ void FrameBufferObject::releaseGLObjects(osg::State* state) const
{ {
if (_fboID[i]) if (_fboID[i])
{ {
deleteFrameBufferObject(i, _fboID[i]); osg::get<GLFrameBufferObjectManager>(i)->deleteGLObject(_fboID[i]);
_fboID[i] = 0; _fboID[i] = 0;
} }
} }

View File

@ -12,102 +12,139 @@
*/ */
#include <osg/GLObjects> #include <osg/GLObjects>
#include <osg/Texture>
#include <osg/VertexProgram> #include <osg/VertexProgram>
#include <osg/FragmentProgram> #include <osg/FragmentProgram>
#include <osg/Shader>
#include <osg/BufferObject>
#include <osg/FrameBufferObject> #include <osg/FrameBufferObject>
#include <osg/Drawable> #include <osg/ContextData>
#include <osg/OcclusionQueryNode>
using namespace osg;
void osg::flushDeletedGLObjects(unsigned int contextID, double currentTime, double& availableTime) void osg::flushDeletedGLObjects(unsigned int contextID, double currentTime, double& availableTime)
{ {
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE osg::getContextData(contextID)->flushDeletedGLObjects(currentTime, availableTime);
osg::Drawable::flushDeletedDisplayLists(contextID,availableTime);
#endif
#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
osg::FragmentProgram::flushDeletedFragmentProgramObjects(contextID,currentTime,availableTime);
osg::VertexProgram::flushDeletedVertexProgramObjects(contextID,currentTime,availableTime);
#endif
osg::GLBufferObject::flushDeletedBufferObjects(contextID,currentTime,availableTime);
osg::FrameBufferObject::flushDeletedFrameBufferObjects(contextID,currentTime,availableTime);
osg::RenderBuffer::flushDeletedRenderBuffers(contextID,currentTime,availableTime);
osg::Program::flushDeletedGlPrograms(contextID,currentTime,availableTime);
osg::Shader::flushDeletedGlShaders(contextID,currentTime,availableTime);
osg::Texture::flushDeletedTextureObjects(contextID,currentTime,availableTime);
osg::OcclusionQueryNode::flushDeletedQueryObjects(contextID,currentTime,availableTime);
} }
void osg::flushAllDeletedGLObjects(unsigned int contextID) void osg::flushAllDeletedGLObjects(unsigned int contextID)
{ {
double currentTime = DBL_MAX; osg::getContextData(contextID)->flushAllDeletedGLObjects();
double availableTime = DBL_MAX;
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
osg::Drawable::flushAllDeletedDisplayLists(contextID);
#endif
#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
osg::FragmentProgram::flushDeletedFragmentProgramObjects(contextID,currentTime,availableTime);
osg::VertexProgram::flushDeletedVertexProgramObjects(contextID,currentTime,availableTime);
#endif
osg::GLBufferObject::flushAllDeletedBufferObjects(contextID);
osg::Texture::flushAllDeletedTextureObjects(contextID);
osg::FrameBufferObject::flushDeletedFrameBufferObjects(contextID,currentTime,availableTime);
osg::Program::flushDeletedGlPrograms(contextID,currentTime,availableTime);
osg::RenderBuffer::flushDeletedRenderBuffers(contextID,currentTime,availableTime);
osg::Shader::flushDeletedGlShaders(contextID,currentTime,availableTime);
osg::OcclusionQueryNode::flushDeletedQueryObjects(contextID,currentTime,availableTime);
} }
void osg::deleteAllGLObjects(unsigned int contextID) void osg::deleteAllGLObjects(unsigned int contextID)
{ {
double currentTime = DBL_MAX; osg::getContextData(contextID)->deleteAllGLObjects();
double availableTime = DBL_MAX;
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
osg::Drawable::flushAllDeletedDisplayLists(contextID);
#endif
#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
osg::FragmentProgram::flushDeletedFragmentProgramObjects(contextID,currentTime,availableTime);
osg::VertexProgram::flushDeletedVertexProgramObjects(contextID,currentTime,availableTime);
#endif
osg::GLBufferObject::deleteAllBufferObjects(contextID);
osg::Texture::deleteAllTextureObjects(contextID);
osg::FrameBufferObject::flushDeletedFrameBufferObjects(contextID,currentTime,availableTime);
osg::Program::flushDeletedGlPrograms(contextID,currentTime,availableTime);
osg::RenderBuffer::flushDeletedRenderBuffers(contextID,currentTime,availableTime);
osg::Shader::flushDeletedGlShaders(contextID,currentTime,availableTime);
osg::OcclusionQueryNode::flushDeletedQueryObjects(contextID,currentTime,availableTime);
} }
void osg::discardAllGLObjects(unsigned int contextID) void osg::discardAllGLObjects(unsigned int contextID)
{ {
#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE osg::getContextData(contextID)->discardAllGLObjects();
osg::Drawable::discardAllDeletedDisplayLists(contextID); }
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE //
osg::FragmentProgram::discardDeletedFragmentProgramObjects(contextID); // GraphicsObject
osg::VertexProgram::discardDeletedVertexProgramObjects(contextID); //
#endif GraphicsObject::GraphicsObject()
{
osg::GLBufferObject::discardAllBufferObjects(contextID); // OSG_NOTICE<<"GraphicsObject::GraphicsObject() "<<this<<std::endl;
osg::Texture::discardAllTextureObjects(contextID); }
osg::FrameBufferObject::discardDeletedFrameBufferObjects(contextID); GraphicsObject::~GraphicsObject()
osg::Program::discardDeletedGlPrograms(contextID); {
osg::RenderBuffer::discardDeletedRenderBuffers(contextID); // OSG_NOTICE<<"GraphicsObject::~GraphicsObject() "<<this<<std::endl;
osg::Shader::discardDeletedGlShaders(contextID); }
osg::OcclusionQueryNode::discardDeletedQueryObjects(contextID);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// GraphicsObjectManager
//
GraphicsObjectManager::GraphicsObjectManager(const std::string& name, unsigned int contextID):
_name(name),
_contextID(contextID)
{
OSG_INFO<<_name<<"::"<<_name<<"()"<<this<<std::endl;
}
GraphicsObjectManager::~GraphicsObjectManager()
{
OSG_INFO<<_name<<"::~"<<_name<<"()"<<this<<std::endl;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// GLObjectManager
//
GLObjectManager::GLObjectManager(const std::string& name, unsigned int contextID):
GraphicsObjectManager(name, contextID)
{
}
GLObjectManager::~GLObjectManager()
{
}
void GLObjectManager::flushDeletedGLObjects(double, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
for(GLObjectHandleList::iterator itr = _deleteGLObjectHandles.begin();
itr != _deleteGLObjectHandles.end() && elapsedTime<availableTime;
)
{
deleteGLObject( *itr );
itr = _deleteGLObjectHandles.erase( itr );
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
availableTime -= elapsedTime;
}
void GLObjectManager::flushAllDeletedGLObjects()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
for(GLObjectHandleList::iterator itr = _deleteGLObjectHandles.begin();
itr != _deleteGLObjectHandles.end();
++itr)
{
deleteGLObject( *itr );
}
_deleteGLObjectHandles.clear();
}
void GLObjectManager::deleteAllGLObjects()
{
OSG_INFO<<"void "<<_name<<"::deleteAllGLObjects() : Not Implementated"<<std::endl;
}
void GLObjectManager::discardAllGLObjects()
{
// OSG_NOTICE<<"void "<<_name<<"::discardAllGLObjects()"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
_deleteGLObjectHandles.clear();
}
void GLObjectManager::sheduleGLObjectForDeletion(GLuint globj)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
// add glProgram to the cache for the appropriate context.
_deleteGLObjectHandles.push_back(globj);
}
GLuint GLObjectManager::createGLObject()
{
OSG_INFO<<"void "<<_name<<"::createGLObject() : Not Implementated"<<std::endl;
return 0;
} }

View File

@ -17,6 +17,7 @@
#include <osg/Camera> #include <osg/Camera>
#include <osg/View> #include <osg/View>
#include <osg/GLObjects> #include <osg/GLObjects>
#include <osg/ContextData>
#include <osg/FrameBufferObject> #include <osg/FrameBufferObject>
#include <osg/Program> #include <osg/Program>
@ -232,7 +233,7 @@ bool GraphicsContext::Traits::getContextVersion(unsigned int& major, unsigned in
return true; return true;
} }
#if 0
class ContextData class ContextData
{ {
public: public:
@ -261,197 +262,63 @@ public:
osg::ref_ptr<osg::GraphicsContext> _compileContext; osg::ref_ptr<osg::GraphicsContext> _compileContext;
}; };
#endif
typedef std::map<unsigned int, ContextData> ContextIDMap;
static ContextIDMap s_contextIDMap;
static OpenThreads::ReentrantMutex s_contextIDMapMutex;
static GraphicsContext::GraphicsContexts s_registeredContexts;
unsigned int GraphicsContext::createNewContextID() unsigned int GraphicsContext::createNewContextID()
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex); return ContextData::createNewContextID();
// first check to see if we can reuse contextID;
for(ContextIDMap::iterator itr = s_contextIDMap.begin();
itr != s_contextIDMap.end();
++itr)
{
if (itr->second._numContexts == 0)
{
// reuse contextID;
itr->second._numContexts = 1;
OSG_INFO<<"GraphicsContext::createNewContextID() reusing contextID="<<itr->first<<std::endl;
return itr->first;
}
}
unsigned int contextID = s_contextIDMap.size();
s_contextIDMap[contextID]._numContexts = 1;
OSG_INFO<<"GraphicsContext::createNewContextID() creating contextID="<<contextID<<std::endl;
OSG_INFO<<"Updating the MaxNumberOfGraphicsContexts to "<<contextID+1<<std::endl;
// update the maximum number of graphics contexts,
// to ensure that texture objects and display buffers are configured to the correct size.
osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts( contextID + 1 );
return contextID;
} }
unsigned int GraphicsContext::getMaxContextID() unsigned int GraphicsContext::getMaxContextID()
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex); return ContextData::getMaxContextID();
unsigned int maxContextID = 0;
for(ContextIDMap::iterator itr = s_contextIDMap.begin();
itr != s_contextIDMap.end();
++itr)
{
if (itr->first > maxContextID) maxContextID = itr->first;
}
return maxContextID;
} }
void GraphicsContext::incrementContextIDUsageCount(unsigned int contextID) void GraphicsContext::incrementContextIDUsageCount(unsigned int contextID)
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex); return ContextData::incrementContextIDUsageCount(contextID);
s_contextIDMap[contextID].incrementUsageCount();
OSG_INFO<<"GraphicsContext::incrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]._numContexts<<std::endl;
} }
void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID) void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID)
{ {
return ContextData::decrementContextIDUsageCount(contextID);
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
if (s_contextIDMap[contextID]._numContexts!=0)
{
s_contextIDMap[contextID].decrementUsageCount();
}
else
{
OSG_NOTICE<<"Warning: decrementContextIDUsageCount("<<contextID<<") called on expired contextID."<<std::endl;
}
OSG_INFO<<"GraphicsContext::decrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]._numContexts<<std::endl;
} }
void GraphicsContext::registerGraphicsContext(GraphicsContext* gc) void GraphicsContext::registerGraphicsContext(GraphicsContext* gc)
{ {
OSG_INFO<<"GraphicsContext::registerGraphicsContext "<<gc<<std::endl; ContextData::registerGraphicsContext(gc);
if (!gc) return;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc);
if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr);
s_registeredContexts.push_back(gc);
} }
void GraphicsContext::unregisterGraphicsContext(GraphicsContext* gc) void GraphicsContext::unregisterGraphicsContext(GraphicsContext* gc)
{ {
OSG_INFO<<"GraphicsContext::unregisterGraphicsContext "<<gc<<std::endl; ContextData::unregisterGraphicsContext(gc);
if (!gc) return;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc);
if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr);
} }
GraphicsContext::GraphicsContexts GraphicsContext::getAllRegisteredGraphicsContexts() GraphicsContext::GraphicsContexts GraphicsContext::getAllRegisteredGraphicsContexts()
{ {
OSG_INFO<<"GraphicsContext::getAllRegisteredGraphicsContexts s_registeredContexts.size()="<<s_registeredContexts.size()<<std::endl; return ContextData::getAllRegisteredGraphicsContexts();
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
return s_registeredContexts;
} }
GraphicsContext::GraphicsContexts GraphicsContext::getRegisteredGraphicsContexts(unsigned int contextID) GraphicsContext::GraphicsContexts GraphicsContext::getRegisteredGraphicsContexts(unsigned int contextID)
{ {
GraphicsContexts contexts; return ContextData::getRegisteredGraphicsContexts(contextID);
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
for(GraphicsContexts::iterator itr = s_registeredContexts.begin();
itr != s_registeredContexts.end();
++itr)
{
GraphicsContext* gc = *itr;
if (gc->getState() && gc->getState()->getContextID()==contextID) contexts.push_back(gc);
}
OSG_INFO<<"GraphicsContext::getRegisteredGraphicsContexts "<<contextID<<" contexts.size()="<<contexts.size()<<std::endl;
return contexts;
} }
GraphicsContext* GraphicsContext::getOrCreateCompileContext(unsigned int contextID) GraphicsContext* GraphicsContext::getOrCreateCompileContext(unsigned int contextID)
{ {
OSG_NOTICE<<"GraphicsContext::createCompileContext."<<std::endl; return ContextData::getOrCreateCompileContext(contextID);
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
if (s_contextIDMap[contextID]._compileContext.valid()) return s_contextIDMap[contextID]._compileContext.get();
}
GraphicsContext::GraphicsContexts contexts = GraphicsContext::getRegisteredGraphicsContexts(contextID);
if (contexts.empty()) return 0;
GraphicsContext* src_gc = contexts.front();
const osg::GraphicsContext::Traits* src_traits = src_gc->getTraits();
osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
traits->screenNum = src_traits->screenNum;
traits->displayNum = src_traits->displayNum;
traits->hostName = src_traits->hostName;
traits->width = 100;
traits->height = 100;
traits->red = src_traits->red;
traits->green = src_traits->green;
traits->blue = src_traits->blue;
traits->alpha = src_traits->alpha;
traits->depth = src_traits->depth;
traits->sharedContext = src_gc;
traits->pbuffer = true;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits);
if (gc.valid() && gc->realize())
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
s_contextIDMap[contextID]._compileContext = gc;
OSG_NOTICE<<" succeeded GraphicsContext::createCompileContext."<<std::endl;
return gc.release();
}
else
{
return 0;
}
} }
void GraphicsContext::setCompileContext(unsigned int contextID, GraphicsContext* gc) void GraphicsContext::setCompileContext(unsigned int contextID, GraphicsContext* gc)
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex); return ContextData::setCompileContext(contextID, gc);
s_contextIDMap[contextID]._compileContext = gc;
} }
GraphicsContext* GraphicsContext::getCompileContext(unsigned int contextID) GraphicsContext* GraphicsContext::getCompileContext(unsigned int contextID)
{ {
// OSG_NOTICE<<"GraphicsContext::getCompileContext "<<contextID<<std::endl; return ContextData::getCompileContext(contextID);
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
ContextIDMap::iterator itr = s_contextIDMap.find(contextID);
if (itr != s_contextIDMap.end()) return itr->second._compileContext.get();
else return 0;
} }
@ -530,8 +397,8 @@ void GraphicsContext::close(bool callCloseImplementation)
if (_state.valid()) if (_state.valid())
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex); osg::ContextData* cd = osg::getContextData(_state->getContextID());
if (s_contextIDMap[_state->getContextID()]._numContexts>1) sharedContextExists = true; if (cd && cd->getNumContexts()>1) sharedContextExists = true;
} }
// release all the OpenGL objects in the scene graphs associated with this // release all the OpenGL objects in the scene graphs associated with this
@ -1011,3 +878,4 @@ void SyncSwapBuffersCallback::swapBuffersImplementation(osg::GraphicsContext* gc
//OSG_NOTICE<<"After swap"<<std::endl; //OSG_NOTICE<<"After swap"<<std::endl;
} }

View File

@ -32,6 +32,7 @@
#include <osg/ColorMask> #include <osg/ColorMask>
#include <osg/PolygonOffset> #include <osg/PolygonOffset>
#include <osg/Depth> #include <osg/Depth>
#include <osg/ContextData>
#include <map> #include <map>
#include <vector> #include <vector>
@ -230,18 +231,22 @@ struct ClearQueriesCallback : public osg::Camera::DrawCallback
}; };
// static cache of deleted query objects which can only
// be completely deleted once the appropriate OpenGL context
// is set.
typedef std::list< GLuint > QueryObjectList;
typedef osg::buffered_object< QueryObjectList > DeletedQueryObjectCache;
static OpenThreads::Mutex s_mutex_deletedQueryObjectCache;
static DeletedQueryObjectCache s_deletedQueryObjectCache;
namespace osg namespace osg
{ {
class QueryObjectManager : public GLObjectManager
{
public:
QueryObjectManager(unsigned int contextID) : GLObjectManager("QueryObjectManager", contextID) {}
virtual void deleteGLObject(GLuint globj)
{
const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeleteQueries( 1L, &globj );
}
};
QueryGeometry::QueryGeometry( const std::string& oqnName ) QueryGeometry::QueryGeometry( const std::string& oqnName )
: _oqnName( oqnName ) : _oqnName( oqnName )
@ -378,7 +383,11 @@ QueryGeometry::releaseGLObjects( osg::State* state ) const
TestResult& tr = it->second; TestResult& tr = it->second;
if (tr._contextID == contextID) if (tr._contextID == contextID)
{ {
#if 1
osg::get<QueryObjectManager>(contextID)->sheduleGLObjectForDeletion(tr._id );
#else
QueryGeometry::deleteQueryObject( contextID, tr._id ); QueryGeometry::deleteQueryObject( contextID, tr._id );
#endif
tr._init = false; tr._init = false;
} }
it++; it++;
@ -389,52 +398,20 @@ QueryGeometry::releaseGLObjects( osg::State* state ) const
void void
QueryGeometry::deleteQueryObject( unsigned int contextID, GLuint handle ) QueryGeometry::deleteQueryObject( unsigned int contextID, GLuint handle )
{ {
if (handle!=0) osg::get<QueryObjectManager>(contextID)->sheduleGLObjectForDeletion(handle);
{
OpenThreads::ScopedLock< OpenThreads::Mutex > lock( s_mutex_deletedQueryObjectCache );
// insert the handle into the cache for the appropriate context.
s_deletedQueryObjectCache[contextID].push_back( handle );
}
} }
void void
QueryGeometry::flushDeletedQueryObjects( unsigned int contextID, double /*currentTime*/, double& availableTime ) QueryGeometry::flushDeletedQueryObjects( unsigned int contextID, double currentTime, double& availableTime )
{ {
// if no time available don't try to flush objects. osg::get<QueryObjectManager>(contextID)->flushDeletedGLObjects(currentTime, availableTime);
if (availableTime<=0.0) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedQueryObjectCache);
const osg::GLExtensions* extensions = osg::GLExtensions::Get( contextID, true );
QueryObjectList& qol = s_deletedQueryObjectCache[contextID];
for(QueryObjectList::iterator titr=qol.begin();
titr!=qol.end() && elapsedTime<availableTime;
)
{
extensions->glDeleteQueries( 1L, &(*titr ) );
titr = qol.erase(titr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
} }
void void
QueryGeometry::discardDeletedQueryObjects( unsigned int contextID ) QueryGeometry::discardDeletedQueryObjects( unsigned int contextID )
{ {
OpenThreads::ScopedLock< OpenThreads::Mutex > lock( s_mutex_deletedQueryObjectCache ); osg::get<QueryObjectManager>(contextID)->discardAllGLObjects();
QueryObjectList& qol = s_deletedQueryObjectCache[ contextID ];
qol.clear();
} }
// End support classes // End support classes

View File

@ -31,6 +31,7 @@
#include <osg/Program> #include <osg/Program>
#include <osg/Shader> #include <osg/Shader>
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/ContextData>
#include <OpenThreads/ScopedLock> #include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex> #include <OpenThreads/Mutex>
@ -39,62 +40,17 @@
using namespace osg; using namespace osg;
/////////////////////////////////////////////////////////////////////////// class GLProgramManager : public GLObjectManager
// static cache of glPrograms flagged for deletion, which will actually
// be deleted in the correct GL context.
typedef std::list<GLuint> GlProgramHandleList;
typedef osg::buffered_object<GlProgramHandleList> DeletedGlProgramCache;
static OpenThreads::Mutex s_mutex_deletedGlProgramCache;
static DeletedGlProgramCache s_deletedGlProgramCache;
void Program::deleteGlProgram(unsigned int contextID, GLuint program)
{ {
if( program ) public:
GLProgramManager(unsigned int contextID) : GLObjectManager("GLProgramManager", contextID) {}
virtual void deleteGLObject(GLuint globj)
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlProgramCache); const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeleteProgram( globj );
// add glProgram to the cache for the appropriate context.
s_deletedGlProgramCache[contextID].push_back(program);
}
}
void Program::flushDeletedGlPrograms(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlProgramCache);
const GLExtensions* extensions = GLExtensions::Get(contextID,true);
if( ! extensions->isGlslSupported ) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
GlProgramHandleList& pList = s_deletedGlProgramCache[contextID];
for(GlProgramHandleList::iterator titr=pList.begin();
titr!=pList.end() && elapsedTime<availableTime;
)
{
extensions->glDeleteProgram( *titr );
titr = pList.erase( titr );
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
}
void Program::discardDeletedGlPrograms(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlProgramCache);
GlProgramHandleList& pList = s_deletedGlProgramCache[contextID];
pList.clear();
} }
};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -733,7 +689,7 @@ Program::PerContextProgram::~PerContextProgram()
{ {
if (_ownsProgramHandle) if (_ownsProgramHandle)
{ {
Program::deleteGlProgram( _contextID, _glProgramHandle ); osg::get<GLProgramManager>(_contextID)->deleteGLObject(_glProgramHandle);
} }
} }

View File

@ -32,12 +32,21 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <osg/Shader> #include <osg/Shader>
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/ContextData>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
using namespace osg; using namespace osg;
class GLShaderManager : public GLObjectManager
{
public:
GLShaderManager(unsigned int contextID) : GLObjectManager("GLShaderManager",contextID) {}
virtual void deleteGLObject(GLuint globj)
{
const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeleteShader( globj );
}
};
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// //
@ -151,64 +160,6 @@ ShaderBinary* ShaderBinary::readShaderBinaryFile(const std::string& fileName)
return shaderBinary.release(); return shaderBinary.release();
} }
///////////////////////////////////////////////////////////////////////////
// static cache of glShaders flagged for deletion, which will actually
// be deleted in the correct GL context.
typedef std::list<GLuint> GlShaderHandleList;
typedef osg::buffered_object<GlShaderHandleList> DeletedGlShaderCache;
static OpenThreads::Mutex s_mutex_deletedGlShaderCache;
static DeletedGlShaderCache s_deletedGlShaderCache;
void Shader::deleteGlShader(unsigned int contextID, GLuint shader)
{
if( shader )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlShaderCache);
// add glShader to the cache for the appropriate context.
s_deletedGlShaderCache[contextID].push_back(shader);
}
}
void Shader::flushDeletedGlShaders(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const GLExtensions* extensions = GLExtensions::Get(contextID,true);
if( ! extensions->isGlslSupported ) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlShaderCache);
GlShaderHandleList& pList = s_deletedGlShaderCache[contextID];
for(GlShaderHandleList::iterator titr=pList.begin();
titr!=pList.end() && elapsedTime<availableTime;
)
{
extensions->glDeleteShader( *titr );
titr = pList.erase( titr );
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
}
void Shader::discardDeletedGlShaders(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlShaderCache);
GlShaderHandleList& pList = s_deletedGlShaderCache[contextID];
pList.clear();
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// osg::Shader // osg::Shader
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -513,7 +464,7 @@ Shader::PerContextShader::PerContextShader(const Shader* shader, unsigned int co
Shader::PerContextShader::~PerContextShader() Shader::PerContextShader::~PerContextShader()
{ {
Shader::deleteGlShader( _contextID, _glShaderHandle ); osg::get<GLShaderManager>(_contextID)->deleteGLObject(_glShaderHandle);
} }

View File

@ -17,6 +17,7 @@
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/Drawable> #include <osg/Drawable>
#include <osg/ApplicationUsage> #include <osg/ApplicationUsage>
#include <osg/ContextData>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
@ -301,14 +302,14 @@ void State::setInitialViewMatrix(const osg::RefMatrix* matrix)
void State::setMaxTexturePoolSize(unsigned int size) void State::setMaxTexturePoolSize(unsigned int size)
{ {
_maxTexturePoolSize = size; _maxTexturePoolSize = size;
osg::Texture::getTextureObjectManager(getContextID())->setMaxTexturePoolSize(size); osg::get<TextureObjectManager>(_contextID)->setMaxTexturePoolSize(size);
OSG_INFO<<"osg::State::_maxTexturePoolSize="<<_maxTexturePoolSize<<std::endl; OSG_INFO<<"osg::State::_maxTexturePoolSize="<<_maxTexturePoolSize<<std::endl;
} }
void State::setMaxBufferObjectPoolSize(unsigned int size) void State::setMaxBufferObjectPoolSize(unsigned int size)
{ {
_maxBufferObjectPoolSize = size; _maxBufferObjectPoolSize = size;
osg::GLBufferObjectManager::getGLBufferObjectManager(getContextID())->setMaxGLBufferObjectPoolSize(_maxBufferObjectPoolSize); osg::get<GLBufferObjectManager>(_contextID)->setMaxGLBufferObjectPoolSize(_maxBufferObjectPoolSize);
OSG_INFO<<"osg::State::_maxBufferObjectPoolSize="<<_maxBufferObjectPoolSize<<std::endl; OSG_INFO<<"osg::State::_maxBufferObjectPoolSize="<<_maxBufferObjectPoolSize<<std::endl;
} }

View File

@ -21,6 +21,7 @@
#include <osg/FrameBufferObject> #include <osg/FrameBufferObject>
#include <osg/TextureRectangle> #include <osg/TextureRectangle>
#include <osg/Texture1D> #include <osg/Texture1D>
#include <osg/ContextData>
#include <OpenThreads/ScopedLock> #include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex> #include <OpenThreads/Mutex>
@ -247,6 +248,11 @@ void Texture::TextureObject::bind()
if (_set) _set->moveToBack(this); if (_set) _set->moveToBack(this);
} }
void Texture::TextureObject::release()
{
if (_set) _set->orphan(this);
}
void Texture::TextureObject::setAllocated(GLint numMipmapLevels, void Texture::TextureObject::setAllocated(GLint numMipmapLevels,
GLenum internalFormat, GLenum internalFormat,
GLsizei width, GLsizei width,
@ -347,7 +353,7 @@ void Texture::TextureProfile::computeSize()
// //
// New texture object manager // New texture object manager
// //
Texture::TextureObjectSet::TextureObjectSet(TextureObjectManager* parent, const TextureProfile& profile): TextureObjectSet::TextureObjectSet(TextureObjectManager* parent, const Texture::TextureProfile& profile):
_parent(parent), _parent(parent),
_contextID(parent->getContextID()), _contextID(parent->getContextID()),
_profile(profile), _profile(profile),
@ -357,7 +363,7 @@ Texture::TextureObjectSet::TextureObjectSet(TextureObjectManager* parent, const
{ {
} }
Texture::TextureObjectSet::~TextureObjectSet() TextureObjectSet::~TextureObjectSet()
{ {
#if 0 #if 0
OSG_NOTICE<<"TextureObjectSet::~TextureObjectSet(), _numOfTextureObjects="<<_numOfTextureObjects<<std::endl; OSG_NOTICE<<"TextureObjectSet::~TextureObjectSet(), _numOfTextureObjects="<<_numOfTextureObjects<<std::endl;
@ -367,7 +373,7 @@ Texture::TextureObjectSet::~TextureObjectSet()
#endif #endif
} }
bool Texture::TextureObjectSet::checkConsistency() const bool TextureObjectSet::checkConsistency() const
{ {
OSG_NOTICE<<"TextureObjectSet::checkConsistency()"<<std::endl; OSG_NOTICE<<"TextureObjectSet::checkConsistency()"<<std::endl;
// check consistency of linked list. // check consistency of linked list.
@ -381,7 +387,7 @@ bool Texture::TextureObjectSet::checkConsistency() const
{ {
if ((to->_next)->_previous != to) if ((to->_next)->_previous != to)
{ {
OSG_NOTICE<<"Texture::TextureObjectSet::checkConsistency() : Error (to->_next)->_previous != to "<<std::endl; OSG_NOTICE<<"TextureObjectSet::checkConsistency() : Error (to->_next)->_previous != to "<<std::endl;
return false; return false;
} }
} }
@ -389,7 +395,7 @@ bool Texture::TextureObjectSet::checkConsistency() const
{ {
if (_tail != to) if (_tail != to)
{ {
OSG_NOTICE<<"Texture::TextureObjectSet::checkConsistency() : Error _tail != to"<<std::endl; OSG_NOTICE<<"TextureObjectSet::checkConsistency() : Error _tail != to"<<std::endl;
return false; return false;
} }
} }
@ -413,7 +419,7 @@ bool Texture::TextureObjectSet::checkConsistency() const
return true; return true;
} }
void Texture::TextureObjectSet::handlePendingOrphandedTextureObjects() void TextureObjectSet::handlePendingOrphandedTextureObjects()
{ {
// OSG_NOTICE<<"handlePendingOrphandedTextureObjects()"<<_pendingOrphanedTextureObjects.size()<<std::endl; // OSG_NOTICE<<"handlePendingOrphandedTextureObjects()"<<_pendingOrphanedTextureObjects.size()<<std::endl;
@ -421,11 +427,11 @@ void Texture::TextureObjectSet::handlePendingOrphandedTextureObjects()
unsigned int numOrphaned = _pendingOrphanedTextureObjects.size(); unsigned int numOrphaned = _pendingOrphanedTextureObjects.size();
for(TextureObjectList::iterator itr = _pendingOrphanedTextureObjects.begin(); for(Texture::TextureObjectList::iterator itr = _pendingOrphanedTextureObjects.begin();
itr != _pendingOrphanedTextureObjects.end(); itr != _pendingOrphanedTextureObjects.end();
++itr) ++itr)
{ {
TextureObject* to = itr->get(); Texture::TextureObject* to = itr->get();
_orphanedTextureObjects.push_back(to); _orphanedTextureObjects.push_back(to);
@ -443,15 +449,15 @@ void Texture::TextureObjectSet::handlePendingOrphandedTextureObjects()
} }
void Texture::TextureObjectSet::deleteAllTextureObjects() void TextureObjectSet::deleteAllTextureObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::deleteAllTextureObjects()"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::deleteAllTextureObjects()"<<std::endl;
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if (!_pendingOrphanedTextureObjects.empty()) if (!_pendingOrphanedTextureObjects.empty())
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl;
handlePendingOrphandedTextureObjects(); handlePendingOrphandedTextureObjects();
} }
} }
@ -460,10 +466,10 @@ void Texture::TextureObjectSet::deleteAllTextureObjects()
// detect all the active texture objects from their Textures // detect all the active texture objects from their Textures
unsigned int numOrphaned = 0; unsigned int numOrphaned = 0;
TextureObject* to = _head; Texture::TextureObject* to = _head;
while(to!=0) while(to!=0)
{ {
ref_ptr<TextureObject> glto = to; ref_ptr<Texture::TextureObject> glto = to;
to = to->_next; to = to->_next;
@ -489,14 +495,14 @@ void Texture::TextureObjectSet::deleteAllTextureObjects()
// OSG_NOTICE<<"done GLBufferObjectSet::deleteAllGLBufferObjects()"<<std::endl; // OSG_NOTICE<<"done GLBufferObjectSet::deleteAllGLBufferObjects()"<<std::endl;
} }
void Texture::TextureObjectSet::discardAllTextureObjects() void TextureObjectSet::discardAllTextureObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::discardAllTextureObjects()."<<std::endl; // OSG_NOTICE<<"TextureObjectSet::discardAllTextureObjects()."<<std::endl;
TextureObject* to = _head; Texture::TextureObject* to = _head;
while(to!=0) while(to!=0)
{ {
ref_ptr<TextureObject> glto = to; ref_ptr<Texture::TextureObject> glto = to;
to = to->_next; to = to->_next;
@ -524,19 +530,19 @@ void Texture::TextureObjectSet::discardAllTextureObjects()
_parent->getNumberDeleted() += numDeleted; _parent->getNumberDeleted() += numDeleted;
} }
void Texture::TextureObjectSet::flushAllDeletedTextureObjects() void TextureObjectSet::flushAllDeletedTextureObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::flushAllDeletedTextureObjects()"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::flushAllDeletedTextureObjects()"<<std::endl;
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if (!_pendingOrphanedTextureObjects.empty()) if (!_pendingOrphanedTextureObjects.empty())
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl;
handlePendingOrphandedTextureObjects(); handlePendingOrphandedTextureObjects();
} }
} }
for(TextureObjectList::iterator itr = _orphanedTextureObjects.begin(); for(Texture::TextureObjectList::iterator itr = _orphanedTextureObjects.begin();
itr != _orphanedTextureObjects.end(); itr != _orphanedTextureObjects.end();
++itr) ++itr)
{ {
@ -558,16 +564,16 @@ void Texture::TextureObjectSet::flushAllDeletedTextureObjects()
_orphanedTextureObjects.clear(); _orphanedTextureObjects.clear();
} }
void Texture::TextureObjectSet::discardAllDeletedTextureObjects() void TextureObjectSet::discardAllDeletedTextureObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::discardAllDeletedTextureObjects()"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::discardAllDeletedTextureObjects()"<<std::endl;
// clean up the pending orphans. // clean up the pending orphans.
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if (!_pendingOrphanedTextureObjects.empty()) if (!_pendingOrphanedTextureObjects.empty())
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl;
handlePendingOrphandedTextureObjects(); handlePendingOrphandedTextureObjects();
} }
} }
@ -587,15 +593,15 @@ void Texture::TextureObjectSet::discardAllDeletedTextureObjects()
_orphanedTextureObjects.clear(); _orphanedTextureObjects.clear();
} }
void Texture::TextureObjectSet::flushDeletedTextureObjects(double /*currentTime*/, double& availableTime) void TextureObjectSet::flushDeletedTextureObjects(double /*currentTime*/, double& availableTime)
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::flushDeletedTextureObjects(..)"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..)"<<std::endl;
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if (!_pendingOrphanedTextureObjects.empty()) if (!_pendingOrphanedTextureObjects.empty())
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<<std::endl;
handlePendingOrphandedTextureObjects(); handlePendingOrphandedTextureObjects();
} }
} }
@ -627,7 +633,7 @@ void Texture::TextureObjectSet::flushDeletedTextureObjects(double /*currentTime*
ElapsedTime timer; ElapsedTime timer;
TextureObjectList::iterator itr = _orphanedTextureObjects.begin(); Texture::TextureObjectList::iterator itr = _orphanedTextureObjects.begin();
for(; for(;
itr != _orphanedTextureObjects.end() && timer.elapsedTime()<availableTime && numDeleted<maxNumObjectsToDelete; itr != _orphanedTextureObjects.end() && timer.elapsedTime()<availableTime && numDeleted<maxNumObjectsToDelete;
++itr) ++itr)
@ -657,13 +663,13 @@ void Texture::TextureObjectSet::flushDeletedTextureObjects(double /*currentTime*
availableTime -= timer.elapsedTime(); availableTime -= timer.elapsedTime();
} }
bool Texture::TextureObjectSet::makeSpace(unsigned int& size) bool TextureObjectSet::makeSpace(unsigned int& size)
{ {
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if (!_pendingOrphanedTextureObjects.empty()) if (!_pendingOrphanedTextureObjects.empty())
{ {
// OSG_NOTICE<<"Texture::TextureObjectSet::Texture::TextureObjectSet::makeSpace(..) handling orphans"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::TextureObjectSet::makeSpace(..) handling orphans"<<std::endl;
handlePendingOrphandedTextureObjects(); handlePendingOrphandedTextureObjects();
} }
} }
@ -680,10 +686,10 @@ bool Texture::TextureObjectSet::makeSpace(unsigned int& size)
return size==0; return size==0;
} }
osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectSet::takeFromOrphans(Texture* texture) osg::ref_ptr<Texture::TextureObject> TextureObjectSet::takeFromOrphans(Texture* texture)
{ {
// take front of orphaned list. // take front of orphaned list.
ref_ptr<TextureObject> to = _orphanedTextureObjects.front(); ref_ptr<Texture::TextureObject> to = _orphanedTextureObjects.front();
// remove from orphan list. // remove from orphan list.
_orphanedTextureObjects.pop_front(); _orphanedTextureObjects.pop_front();
@ -704,7 +710,7 @@ osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectSet::takeFromOrphans(
} }
osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectSet::takeOrGenerate(Texture* texture) osg::ref_ptr<Texture::TextureObject> TextureObjectSet::takeOrGenerate(Texture* texture)
{ {
// see if we can recyle TextureObject from the orphan list // see if we can recyle TextureObject from the orphan list
{ {
@ -733,7 +739,7 @@ osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectSet::takeOrGenerate(T
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
ref_ptr<TextureObject> to = _head; ref_ptr<Texture::TextureObject> to = _head;
ref_ptr<Texture> original_texture = to->getTexture(); ref_ptr<Texture> original_texture = to->getTexture();
@ -761,7 +767,7 @@ osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectSet::takeOrGenerate(T
GLuint id; GLuint id;
glGenTextures( 1L, &id ); glGenTextures( 1L, &id );
osg::ref_ptr<TextureObject> to = new Texture::TextureObject(const_cast<Texture*>(texture),id,_profile); osg::ref_ptr<Texture::TextureObject> to = new Texture::TextureObject(const_cast<Texture*>(texture),id,_profile);
to->_set = this; to->_set = this;
++_numOfTextureObjects; ++_numOfTextureObjects;
@ -776,7 +782,7 @@ osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectSet::takeOrGenerate(T
return to; return to;
} }
void Texture::TextureObjectSet::moveToBack(Texture::TextureObject* to) void TextureObjectSet::moveToBack(Texture::TextureObject* to)
{ {
#if 0 #if 0
OSG_NOTICE<<"TextureObjectSet::moveToBack("<<to<<")"<<std::endl; OSG_NOTICE<<"TextureObjectSet::moveToBack("<<to<<")"<<std::endl;
@ -838,7 +844,7 @@ void Texture::TextureObjectSet::moveToBack(Texture::TextureObject* to)
CHECK_CONSISTENCY CHECK_CONSISTENCY
} }
void Texture::TextureObjectSet::addToBack(Texture::TextureObject* to) void TextureObjectSet::addToBack(Texture::TextureObject* to)
{ {
#if 0 #if 0
OSG_NOTICE<<"TextureObjectSet::addToBack("<<to<<")"<<std::endl; OSG_NOTICE<<"TextureObjectSet::addToBack("<<to<<")"<<std::endl;
@ -871,7 +877,7 @@ void Texture::TextureObjectSet::addToBack(Texture::TextureObject* to)
CHECK_CONSISTENCY CHECK_CONSISTENCY
} }
void Texture::TextureObjectSet::orphan(Texture::TextureObject* to) void TextureObjectSet::orphan(Texture::TextureObject* to)
{ {
// OSG_NOTICE<<"TextureObjectSet::orphan("<<to<<")"<<std::endl; // OSG_NOTICE<<"TextureObjectSet::orphan("<<to<<")"<<std::endl;
@ -893,7 +899,7 @@ void Texture::TextureObjectSet::orphan(Texture::TextureObject* to)
#endif #endif
} }
void Texture::TextureObjectSet::remove(Texture::TextureObject* to) void TextureObjectSet::remove(Texture::TextureObject* to)
{ {
if (to->_previous!=0) if (to->_previous!=0)
{ {
@ -920,7 +926,7 @@ void Texture::TextureObjectSet::remove(Texture::TextureObject* to)
to->_previous = 0; to->_previous = 0;
} }
void Texture::TextureObjectSet::moveToSet(TextureObject* to, TextureObjectSet* set) void TextureObjectSet::moveToSet(Texture::TextureObject* to, TextureObjectSet* set)
{ {
if (set==this) return; if (set==this) return;
if (!set) return; if (!set) return;
@ -935,10 +941,10 @@ void Texture::TextureObjectSet::moveToSet(TextureObject* to, TextureObjectSet* s
set->addToBack(to); set->addToBack(to);
} }
unsigned int Texture::TextureObjectSet::computeNumTextureObjectsInList() const unsigned int TextureObjectSet::computeNumTextureObjectsInList() const
{ {
unsigned int num=0; unsigned int num=0;
TextureObject* obj = _head; Texture::TextureObject* obj = _head;
while(obj!=NULL) while(obj!=NULL)
{ {
++num; ++num;
@ -948,8 +954,8 @@ unsigned int Texture::TextureObjectSet::computeNumTextureObjectsInList() const
} }
Texture::TextureObjectManager::TextureObjectManager(unsigned int contextID): TextureObjectManager::TextureObjectManager(unsigned int contextID):
_contextID(contextID), GraphicsObjectManager("TextureObjectManager", contextID),
_numActiveTextureObjects(0), _numActiveTextureObjects(0),
_numOrphanedTextureObjects(0), _numOrphanedTextureObjects(0),
_currTexturePoolSize(0), _currTexturePoolSize(0),
@ -959,13 +965,16 @@ Texture::TextureObjectManager::TextureObjectManager(unsigned int contextID):
_numDeleted(0), _numDeleted(0),
_deleteTime(0.0), _deleteTime(0.0),
_numGenerated(0), _numGenerated(0),
_generateTime(0.0), _generateTime(0.0)
_numApplied(0),
_applyTime(0.0)
{ {
} }
void Texture::TextureObjectManager::setMaxTexturePoolSize(unsigned int size) TextureObjectManager::~TextureObjectManager()
{
}
void TextureObjectManager::setMaxTexturePoolSize(unsigned int size)
{ {
if (_maxTexturePoolSize == size) return; if (_maxTexturePoolSize == size) return;
@ -977,7 +986,7 @@ void Texture::TextureObjectManager::setMaxTexturePoolSize(unsigned int size)
_maxTexturePoolSize = size; _maxTexturePoolSize = size;
} }
bool Texture::TextureObjectManager::makeSpace(unsigned int size) bool TextureObjectManager::makeSpace(unsigned int size)
{ {
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
itr != _textureSetMap.end() && size>0; itr != _textureSetMap.end() && size>0;
@ -990,12 +999,12 @@ bool Texture::TextureObjectManager::makeSpace(unsigned int size)
} }
osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectManager::generateTextureObject(const Texture* texture, GLenum target) osg::ref_ptr<Texture::TextureObject> TextureObjectManager::generateTextureObject(const Texture* texture, GLenum target)
{ {
return generateTextureObject(texture, target, 0, 0, 0, 0, 0, 0); return generateTextureObject(texture, target, 0, 0, 0, 0, 0, 0);
} }
osg::ref_ptr<Texture::TextureObject> Texture::TextureObjectManager::generateTextureObject(const Texture* texture, osg::ref_ptr<Texture::TextureObject> TextureObjectManager::generateTextureObject(const Texture* texture,
GLenum target, GLenum target,
GLint numMipmapLevels, GLint numMipmapLevels,
GLenum internalFormat, GLenum internalFormat,
@ -1032,14 +1041,14 @@ Texture::TextureObject* Texture::generateAndAssignTextureObject(
return _textureObjectBuffer[contextID].get(); return _textureObjectBuffer[contextID].get();
} }
Texture::TextureObjectSet* Texture::TextureObjectManager::getTextureObjectSet(const TextureProfile& profile) TextureObjectSet* TextureObjectManager::getTextureObjectSet(const Texture::TextureProfile& profile)
{ {
osg::ref_ptr<Texture::TextureObjectSet>& tos = _textureSetMap[profile]; osg::ref_ptr<TextureObjectSet>& tos = _textureSetMap[profile];
if (!tos) tos = new Texture::TextureObjectSet(this, profile); if (!tos) tos = new TextureObjectSet(this, profile);
return tos.get(); return tos.get();
} }
void Texture::TextureObjectManager::handlePendingOrphandedTextureObjects() void TextureObjectManager::handlePendingOrphandedTextureObjects()
{ {
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
itr != _textureSetMap.end(); itr != _textureSetMap.end();
@ -1049,12 +1058,8 @@ void Texture::TextureObjectManager::handlePendingOrphandedTextureObjects()
} }
} }
void Texture::TextureObjectManager::deleteAllTextureObjects() void TextureObjectManager::deleteAllGLObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectManager::deleteAllTextureObjects() _contextID="<<_contextID<<std::endl;
ElapsedTime elapsedTime(&(getDeleteTime()));
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
itr != _textureSetMap.end(); itr != _textureSetMap.end();
++itr) ++itr)
@ -1063,10 +1068,8 @@ void Texture::TextureObjectManager::deleteAllTextureObjects()
} }
} }
void Texture::TextureObjectManager::discardAllTextureObjects() void TextureObjectManager::discardAllGLObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectManager::discardAllTextureObjects() _contextID="<<_contextID<<" _numActiveTextureObjects="<<_numActiveTextureObjects<<std::endl;
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
itr != _textureSetMap.end(); itr != _textureSetMap.end();
++itr) ++itr)
@ -1075,12 +1078,8 @@ void Texture::TextureObjectManager::discardAllTextureObjects()
} }
} }
void Texture::TextureObjectManager::flushAllDeletedTextureObjects() void TextureObjectManager::flushAllDeletedGLObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectManager::flushAllDeletedTextureObjects() _contextID="<<_contextID<<std::endl;
ElapsedTime elapsedTime(&(getDeleteTime()));
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
itr != _textureSetMap.end(); itr != _textureSetMap.end();
++itr) ++itr)
@ -1089,10 +1088,8 @@ void Texture::TextureObjectManager::flushAllDeletedTextureObjects()
} }
} }
void Texture::TextureObjectManager::discardAllDeletedTextureObjects() void TextureObjectManager::discardAllDeletedGLObjects()
{ {
// OSG_NOTICE<<"Texture::TextureObjectManager::discardAllDeletedTextureObjects() _contextID="<<_contextID<<" _numActiveTextureObjects="<<_numActiveTextureObjects<<std::endl;
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
itr != _textureSetMap.end(); itr != _textureSetMap.end();
++itr) ++itr)
@ -1101,10 +1098,8 @@ void Texture::TextureObjectManager::discardAllDeletedTextureObjects()
} }
} }
void Texture::TextureObjectManager::flushDeletedTextureObjects(double currentTime, double& availableTime) void TextureObjectManager::flushDeletedGLObjects(double currentTime, double& availableTime)
{ {
ElapsedTime elapsedTime(&(getDeleteTime()));
for(TextureSetMap::iterator itr = _textureSetMap.begin(); for(TextureSetMap::iterator itr = _textureSetMap.begin();
(itr != _textureSetMap.end()) && (availableTime > 0.0); (itr != _textureSetMap.end()) && (availableTime > 0.0);
++itr) ++itr)
@ -1113,14 +1108,7 @@ void Texture::TextureObjectManager::flushDeletedTextureObjects(double currentTim
} }
} }
void Texture::TextureObjectManager::releaseTextureObject(Texture::TextureObject* to) void TextureObjectManager::newFrame(osg::FrameStamp* fs)
{
if (to->_set) to->_set->orphan(to);
else OSG_NOTICE<<"TextureObjectManager::releaseTextureObject(Texture::TextureObject* to) Not implemented yet"<<std::endl;
}
void Texture::TextureObjectManager::newFrame(osg::FrameStamp* fs)
{ {
if (fs) _frameNumber = fs->getFrameNumber(); if (fs) _frameNumber = fs->getFrameNumber();
else ++_frameNumber; else ++_frameNumber;
@ -1128,19 +1116,18 @@ void Texture::TextureObjectManager::newFrame(osg::FrameStamp* fs)
++_numFrames; ++_numFrames;
} }
void Texture::TextureObjectManager::reportStats(std::ostream& out) void TextureObjectManager::reportStats(std::ostream& out)
{ {
double numFrames(_numFrames==0 ? 1.0 : _numFrames); double numFrames(_numFrames==0 ? 1.0 : _numFrames);
out<<"TextureObjectMananger::reportStats()"<<std::endl; out<<"TextureObjectMananger::reportStats()"<<std::endl;
out<<" total _numOfTextureObjects="<<_numActiveTextureObjects<<", _numOrphanedTextureObjects="<<_numOrphanedTextureObjects<<" _currTexturePoolSize="<<_currTexturePoolSize<<std::endl; out<<" total _numOfTextureObjects="<<_numActiveTextureObjects<<", _numOrphanedTextureObjects="<<_numOrphanedTextureObjects<<" _currTexturePoolSize="<<_currTexturePoolSize<<std::endl;
out<<" total _numGenerated="<<_numGenerated<<", _generateTime="<<_generateTime<<", averagePerFrame="<<_generateTime/numFrames*1000.0<<"ms"<<std::endl; out<<" total _numGenerated="<<_numGenerated<<", _generateTime="<<_generateTime<<", averagePerFrame="<<_generateTime/numFrames*1000.0<<"ms"<<std::endl;
out<<" total _numDeleted="<<_numDeleted<<", _deleteTime="<<_deleteTime<<", averagePerFrame="<<_deleteTime/numFrames*1000.0<<"ms"<<std::endl; out<<" total _numDeleted="<<_numDeleted<<", _deleteTime="<<_deleteTime<<", averagePerFrame="<<_deleteTime/numFrames*1000.0<<"ms"<<std::endl;
out<<" total _numApplied="<<_numApplied<<", _applyTime="<<_applyTime<<", averagePerFrame="<<_applyTime/numFrames*1000.0<<"ms"<<std::endl;
out<<" getMaxTexturePoolSize()="<<getMaxTexturePoolSize()<<" current/max size = "<<double(_currTexturePoolSize)/double(getMaxTexturePoolSize())<<std::endl; out<<" getMaxTexturePoolSize()="<<getMaxTexturePoolSize()<<" current/max size = "<<double(_currTexturePoolSize)/double(getMaxTexturePoolSize())<<std::endl;
recomputeStats(out); recomputeStats(out);
} }
void Texture::TextureObjectManager::resetStats() void TextureObjectManager::resetStats()
{ {
_numFrames = 0; _numFrames = 0;
_numDeleted = 0; _numDeleted = 0;
@ -1148,15 +1135,12 @@ void Texture::TextureObjectManager::resetStats()
_numGenerated = 0; _numGenerated = 0;
_generateTime = 0; _generateTime = 0;
_numApplied = 0;
_applyTime = 0;
} }
void Texture::TextureObjectManager::recomputeStats(std::ostream& out) const void TextureObjectManager::recomputeStats(std::ostream& out) const
{ {
out<<"Texture::TextureObjectManager::recomputeStats()"<<std::endl; out<<"TextureObjectManager::recomputeStats()"<<std::endl;
unsigned int numObjectsInLists = 0; unsigned int numObjectsInLists = 0;
unsigned int numActive = 0; unsigned int numActive = 0;
unsigned int numOrphans = 0; unsigned int numOrphans = 0;
@ -1184,7 +1168,7 @@ void Texture::TextureObjectManager::recomputeStats(std::ostream& out) const
if (currentSize != _currTexturePoolSize) out<<" WARNING: _currTexturePoolSize("<<_currTexturePoolSize<<") != currentSize, delta = "<<int(_currTexturePoolSize)-int(currentSize)<<std::endl; if (currentSize != _currTexturePoolSize) out<<" WARNING: _currTexturePoolSize("<<_currTexturePoolSize<<") != currentSize, delta = "<<int(_currTexturePoolSize)-int(currentSize)<<std::endl;
} }
bool Texture::TextureObjectManager::checkConsistency() const bool TextureObjectManager::checkConsistency() const
{ {
unsigned int numObjectsInLists = 0; unsigned int numObjectsInLists = 0;
unsigned int numActive = 0; unsigned int numActive = 0;
@ -1207,25 +1191,15 @@ bool Texture::TextureObjectManager::checkConsistency() const
{ {
recomputeStats(osg::notify(osg::NOTICE)); recomputeStats(osg::notify(osg::NOTICE));
throw "Texture::TextureObjectManager::checkConsistency() sizes inconsistent"; throw "TextureObjectManager::checkConsistency() sizes inconsistent";
return false; return false;
} }
return true; return true;
} }
osg::ref_ptr<Texture::TextureObjectManager>& Texture::getTextureObjectManager(unsigned int contextID)
{
typedef osg::buffered_object< ref_ptr<Texture::TextureObjectManager> > TextureObjectManagerBuffer;
static TextureObjectManagerBuffer s_TextureObjectManager;
if (!s_TextureObjectManager[contextID]) s_TextureObjectManager[contextID] = new Texture::TextureObjectManager(contextID);
return s_TextureObjectManager[contextID];
}
osg::ref_ptr<Texture::TextureObject> Texture::generateTextureObject(const Texture* texture, unsigned int contextID, GLenum target) osg::ref_ptr<Texture::TextureObject> Texture::generateTextureObject(const Texture* texture, unsigned int contextID, GLenum target)
{ {
return getTextureObjectManager(contextID)->generateTextureObject(texture, target); return osg::get<TextureObjectManager>(contextID)->generateTextureObject(texture, target);
} }
osg::ref_ptr<Texture::TextureObject> Texture::generateTextureObject(const Texture* texture, unsigned int contextID, osg::ref_ptr<Texture::TextureObject> Texture::generateTextureObject(const Texture* texture, unsigned int contextID,
@ -1237,37 +1211,7 @@ osg::ref_ptr<Texture::TextureObject> Texture::generateTextureObject(const Textur
GLsizei depth, GLsizei depth,
GLint border) GLint border)
{ {
return getTextureObjectManager(contextID)->generateTextureObject(texture,target,numMipmapLevels,internalFormat,width,height,depth,border); return osg::get<TextureObjectManager>(contextID)->generateTextureObject(texture,target,numMipmapLevels,internalFormat,width,height,depth,border);
}
void Texture::deleteAllTextureObjects(unsigned int contextID)
{
getTextureObjectManager(contextID)->deleteAllTextureObjects();
}
void Texture::discardAllTextureObjects(unsigned int contextID)
{
getTextureObjectManager(contextID)->discardAllTextureObjects();
}
void Texture::flushAllDeletedTextureObjects(unsigned int contextID)
{
getTextureObjectManager(contextID)->flushAllDeletedTextureObjects();
}
void Texture::discardAllDeletedTextureObjects(unsigned int contextID)
{
getTextureObjectManager(contextID)->discardAllDeletedTextureObjects();
}
void Texture::flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availbleTime)
{
getTextureObjectManager(contextID)->flushDeletedTextureObjects(currentTime, availbleTime);
}
void Texture::releaseTextureObject(unsigned int contextID, Texture::TextureObject* to)
{
getTextureObjectManager(contextID)->releaseTextureObject(to);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1453,7 +1397,7 @@ void Texture::dirtyTextureObject()
{ {
if (_textureObjectBuffer[i].valid()) if (_textureObjectBuffer[i].valid())
{ {
Texture::releaseTextureObject(i, _textureObjectBuffer[i].get()); _textureObjectBuffer[i]->release();
_textureObjectBuffer[i] = 0; _textureObjectBuffer[i] = 0;
} }
} }
@ -2829,7 +2773,7 @@ void Texture::releaseGLObjects(State* state) const
unsigned int contextID = state->getContextID(); unsigned int contextID = state->getContextID();
if (_textureObjectBuffer[contextID].valid()) if (_textureObjectBuffer[contextID].valid())
{ {
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
} }

View File

@ -134,10 +134,6 @@ void Texture1D::apply(State& state) const
// current OpenGL context. // current OpenGL context.
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
// get the texture object for the current contextID. // get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID); TextureObject* textureObject = getTextureObject(contextID);
@ -153,7 +149,7 @@ void Texture1D::apply(State& state) const
if (!textureObject->match(GL_TEXTURE_1D, new_numMipmapLevels, _internalFormat, new_width, 1, 1, _borderWidth)) if (!textureObject->match(GL_TEXTURE_1D, new_numMipmapLevels, _internalFormat, new_width, 1, 1, _borderWidth))
{ {
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
textureObject = 0; textureObject = 0;
} }

View File

@ -14,6 +14,7 @@
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osg/State> #include <osg/State>
#include <osg/ContextData>
#include <osg/Notify> #include <osg/Notify>
using namespace osg; using namespace osg;
@ -165,10 +166,6 @@ void Texture2D::apply(State& state) const
// current OpenGL context. // current OpenGL context.
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
// get the texture object for the current contextID. // get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID); TextureObject* textureObject = getTextureObject(contextID);
if (textureObject) if (textureObject)
@ -186,7 +183,7 @@ void Texture2D::apply(State& state) const
if (textureObjectInvalidated) if (textureObjectInvalidated)
{ {
// OSG_NOTICE<<"Discarding TextureObject"<<std::endl; // OSG_NOTICE<<"Discarding TextureObject"<<std::endl;
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
textureObject = 0; textureObject = 0;
} }

View File

@ -235,10 +235,6 @@ void Texture2DArray::apply(State& state) const
// current OpenGL context. // current OpenGL context.
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
const GLExtensions* extensions = state.get<GLExtensions>(); const GLExtensions* extensions = state.get<GLExtensions>();
// if not supported, then return // if not supported, then return
@ -268,7 +264,7 @@ void Texture2DArray::apply(State& state) const
if (!textureObject->match(GL_TEXTURE_2D_ARRAY_EXT, new_numMipmapLevels, _internalFormat, new_width, new_height, textureDepth, _borderWidth)) if (!textureObject->match(GL_TEXTURE_2D_ARRAY_EXT, new_numMipmapLevels, _internalFormat, new_width, new_height, textureDepth, _borderWidth))
{ {
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
textureObject = 0; textureObject = 0;
} }

View File

@ -93,10 +93,6 @@ void Texture2DMultisample::apply(State& state) const
return; return;
} }
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
// get the texture object for the current contextID. // get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID); TextureObject* textureObject = getTextureObject(contextID);

View File

@ -204,10 +204,6 @@ void Texture3D::apply(State& state) const
// current OpenGL context. // current OpenGL context.
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
const GLExtensions* extensions = state.get<GLExtensions>(); const GLExtensions* extensions = state.get<GLExtensions>();
if (!extensions->isTexture3DSupported) if (!extensions->isTexture3DSupported)
@ -233,7 +229,7 @@ void Texture3D::apply(State& state) const
if (!textureObject->match(GL_TEXTURE_3D, new_numMipmapLevels, _internalFormat, new_width, new_height, new_depth, _borderWidth)) if (!textureObject->match(GL_TEXTURE_3D, new_numMipmapLevels, _internalFormat, new_width, new_height, new_depth, _borderWidth))
{ {
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
textureObject = 0; textureObject = 0;
} }

View File

@ -199,10 +199,6 @@ void TextureCubeMap::apply(State& state) const
// current OpenGL context. // current OpenGL context.
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
const GLExtensions* extensions = state.get<GLExtensions>(); const GLExtensions* extensions = state.get<GLExtensions>();
if (!extensions->isCubeMapSupported) if (!extensions->isCubeMapSupported)
@ -226,7 +222,7 @@ void TextureCubeMap::apply(State& state) const
if (!textureObject->match(GL_TEXTURE_CUBE_MAP, new_numMipmapLevels, _internalFormat, new_width, new_height, 1, _borderWidth)) if (!textureObject->match(GL_TEXTURE_CUBE_MAP, new_numMipmapLevels, _internalFormat, new_width, new_height, 1, _borderWidth))
{ {
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
textureObject = 0; textureObject = 0;
} }

View File

@ -167,11 +167,6 @@ void TextureRectangle::apply(State& state) const
// current OpenGL context. // current OpenGL context.
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
Texture::TextureObjectManager* tom = Texture::getTextureObjectManager(contextID).get();
ElapsedTime elapsedTime(&(tom->getApplyTime()));
tom->getNumberApplied()++;
// get the texture object for the current contextID. // get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID); TextureObject* textureObject = getTextureObject(contextID);
@ -189,7 +184,7 @@ void TextureRectangle::apply(State& state) const
if (!textureObject->match(GL_TEXTURE_RECTANGLE, new_numMipmapLevels, _internalFormat, new_width, new_height, 1, _borderWidth)) if (!textureObject->match(GL_TEXTURE_RECTANGLE, new_numMipmapLevels, _internalFormat, new_width, new_height, 1, _borderWidth))
{ {
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); _textureObjectBuffer[contextID]->release();
_textureObjectBuffer[contextID] = 0; _textureObjectBuffer[contextID] = 0;
textureObject = 0; textureObject = 0;
} }

View File

@ -15,71 +15,21 @@
#include <osg/VertexProgram> #include <osg/VertexProgram>
#include <osg/State> #include <osg/State>
#include <osg/Timer> #include <osg/Timer>
#include <osg/ContextData>
#include <list>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
using namespace osg; using namespace osg;
// static cache of deleted vertex programs which can only class GLVertexProgramManager : public GLObjectManager
// by completely deleted once the appropriate OpenGL context
// is set.
typedef std::list<GLuint> VertexProgramObjectList;
typedef osg::buffered_object<VertexProgramObjectList> DeletedVertexProgramObjectCache;
static OpenThreads::Mutex s_mutex_deletedVertexProgramObjectCache;
static DeletedVertexProgramObjectCache s_deletedVertexProgramObjectCache;
void VertexProgram::deleteVertexProgramObject(unsigned int contextID,GLuint handle)
{ {
if (handle!=0) public:
GLVertexProgramManager(unsigned int contextID) : GLObjectManager("GLVertexProgramManager",contextID) {}
virtual void deleteGLObject(GLuint globj)
{ {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexProgramObjectCache); const GLExtensions* extensions = GLExtensions::Get(_contextID,true);
if (extensions->isGlslSupported) extensions->glDeletePrograms(1, &globj );
// insert the handle into the cache for the appropriate context.
s_deletedVertexProgramObjectCache[contextID].push_back(handle);
} }
} };
void VertexProgram::flushDeletedVertexProgramObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexProgramObjectCache);
const GLExtensions* extensions = GLExtensions::Get(contextID,true);
VertexProgramObjectList& vpol = s_deletedVertexProgramObjectCache[contextID];
for(VertexProgramObjectList::iterator titr=vpol.begin();
titr!=vpol.end() && elapsedTime<availableTime;
)
{
extensions->glDeletePrograms( 1L, &(*titr ) );
titr = vpol.erase(titr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
}
availableTime -= elapsedTime;
}
void VertexProgram::discardDeletedVertexProgramObjects(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexProgramObjectCache);
VertexProgramObjectList& vpol = s_deletedVertexProgramObjectCache[contextID];
vpol.clear();
}
VertexProgram::VertexProgram() VertexProgram::VertexProgram()
{ {
@ -117,7 +67,7 @@ void VertexProgram::dirtyVertexProgramObject()
{ {
if (_vertexProgramIDList[i] != 0) if (_vertexProgramIDList[i] != 0)
{ {
VertexProgram::deleteVertexProgramObject(i,_vertexProgramIDList[i]); osg::get<GLVertexProgramManager>(i)->deleteGLObject(_vertexProgramIDList[i]);
_vertexProgramIDList[i] = 0; _vertexProgramIDList[i] = 0;
} }
} }
@ -207,7 +157,7 @@ void VertexProgram::releaseGLObjects(State* state) const
unsigned int contextID = state->getContextID(); unsigned int contextID = state->getContextID();
if (_vertexProgramIDList[contextID] != 0) if (_vertexProgramIDList[contextID] != 0)
{ {
VertexProgram::deleteVertexProgramObject(contextID,_vertexProgramIDList[contextID]); osg::get<GLVertexProgramManager>(contextID)->deleteGLObject(_vertexProgramIDList[contextID]);
_vertexProgramIDList[contextID] = 0; _vertexProgramIDList[contextID] = 0;
} }
} }

View File

@ -19,6 +19,7 @@
#include <osg/Texture3D> #include <osg/Texture3D>
#include <osg/TextureRectangle> #include <osg/TextureRectangle>
#include <osg/TextureCubeMap> #include <osg/TextureCubeMap>
#include <osg/ContextData>
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/GLU> #include <osg/GLU>
@ -537,12 +538,8 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo)
fbo = 0; fbo = 0;
// clean up. // clean up.
double availableTime = 100.0f; osg::get<osg::GLRenderBufferManager>(state.getContextID())->flushAllDeletedGLObjects();
double currentTime = state.getFrameStamp()?state.getFrameStamp()->getReferenceTime():0.0; osg::get<osg::GLFrameBufferObjectManager>(state.getContextID())->flushAllDeletedGLObjects();
osg::RenderBuffer::flushDeletedRenderBuffers(state.getContextID(),currentTime,availableTime);
osg::FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),currentTime,availableTime);
} }
else else
{ {
@ -568,10 +565,8 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo)
_resolveFbo = 0; _resolveFbo = 0;
// clean up. // clean up.
double availableTime = 100.0f; osg::get<osg::GLRenderBufferManager>(state.getContextID())->flushAllDeletedGLObjects();
double currentTime = state.getFrameStamp()?state.getFrameStamp()->getReferenceTime():0.0; osg::get<osg::GLFrameBufferObjectManager>(state.getContextID())->flushAllDeletedGLObjects();
osg::RenderBuffer::flushDeletedRenderBuffers(state.getContextID(),currentTime,availableTime);
osg::FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),currentTime,availableTime);
} }
else else
{ {

View File

@ -24,6 +24,7 @@
#include <osg/ColorMatrix> #include <osg/ColorMatrix>
#include <osg/LightModel> #include <osg/LightModel>
#include <osg/CollectOccludersVisitor> #include <osg/CollectOccludersVisitor>
#include <osg/ContextData>
#include <osg/GLU> #include <osg/GLU>
@ -963,11 +964,7 @@ void SceneView::draw()
state->initializeExtensionProcs(); state->initializeExtensionProcs();
osg::Texture::TextureObjectManager* tom = osg::Texture::getTextureObjectManager(state->getContextID()).get(); osg::get<ContextData>(state->getContextID())->newFrame(state->getFrameStamp());
tom->newFrame(state->getFrameStamp());
osg::GLBufferObjectManager* bom = osg::GLBufferObjectManager::getGLBufferObjectManager(state->getContextID()).get();
bom->newFrame(state->getFrameStamp());
if (!_initCalled) init(); if (!_initCalled) init();