Added automatically removal from the OjbectCache when a object or it's subgraph contain Texture that no longer have an osg::Image.
This commit is contained in:
parent
994b066329
commit
9ae47b921b
@ -11,6 +11,7 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <osg/Texture>
|
||||
#include <osgDB/ObjectCache>
|
||||
#include <osgDB/Options>
|
||||
|
||||
@ -188,15 +189,95 @@ void ObjectCache::clear()
|
||||
_objectCache.clear();
|
||||
}
|
||||
|
||||
namespace ObjectCacheUtils
|
||||
{
|
||||
|
||||
struct ContainsUnreffedTextures : public osg::NodeVisitor
|
||||
{
|
||||
ContainsUnreffedTextures() :
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
foundUnreffedTexture(false)
|
||||
{}
|
||||
|
||||
bool foundUnreffedTexture;
|
||||
|
||||
bool check(const osg::Texture* texture)
|
||||
{
|
||||
if (!texture) return false;
|
||||
|
||||
unsigned int numImages = 0;
|
||||
for(unsigned int i=0; i<texture->getNumImages(); ++i)
|
||||
{
|
||||
if (texture->getImage(i)) ++numImages;
|
||||
}
|
||||
|
||||
return numImages==0;
|
||||
}
|
||||
|
||||
bool check(const osg::StateSet* stateset)
|
||||
{
|
||||
for(unsigned int i=0; i<stateset->getNumTextureAttributeLists(); ++i)
|
||||
{
|
||||
const osg::StateAttribute* sa = stateset->getTextureAttribute(i, osg::StateAttribute::TEXTURE);
|
||||
if (sa && check(sa->asTexture())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check(osg::Object* object)
|
||||
{
|
||||
if (object->asStateAttribute()) return check(dynamic_cast<const osg::Texture*>(object));
|
||||
if (object->asStateSet()) return check(object->asStateSet());
|
||||
if (!object->asNode()) return false;
|
||||
|
||||
foundUnreffedTexture = false;
|
||||
|
||||
object->asNode()->accept(*this);
|
||||
|
||||
return foundUnreffedTexture;
|
||||
}
|
||||
|
||||
void apply(osg::Node& node)
|
||||
{
|
||||
if (node.getStateSet())
|
||||
{
|
||||
if (check(node.getStateSet()))
|
||||
{
|
||||
foundUnreffedTexture = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
} // ObjectCacheUtils
|
||||
|
||||
void ObjectCache::releaseGLObjects(osg::State* state)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
|
||||
ObjectCacheUtils::ContainsUnreffedTextures cut;
|
||||
|
||||
for(ObjectCacheMap::iterator itr = _objectCache.begin();
|
||||
itr != _objectCache.end();
|
||||
++itr)
|
||||
)
|
||||
{
|
||||
ObjectCacheMap::iterator curr_itr = itr;
|
||||
|
||||
// get object and advance iterator to next item
|
||||
osg::Object* object = itr->second.first.get();
|
||||
|
||||
bool needToRemoveEntry = cut.check(itr->second.first.get());
|
||||
|
||||
object->releaseGLObjects(state);
|
||||
|
||||
++itr;
|
||||
|
||||
if (needToRemoveEntry)
|
||||
{
|
||||
_objectCache.erase(curr_itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user