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
2f9537c07d
commit
64b5397330
@ -11,6 +11,7 @@
|
|||||||
* OpenSceneGraph Public License for more details.
|
* OpenSceneGraph Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <osg/Texture>
|
||||||
#include <osgDB/ObjectCache>
|
#include <osgDB/ObjectCache>
|
||||||
#include <osgDB/Options>
|
#include <osgDB/Options>
|
||||||
|
|
||||||
@ -188,15 +189,95 @@ void ObjectCache::clear()
|
|||||||
_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)
|
void ObjectCache::releaseGLObjects(osg::State* state)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||||
|
|
||||||
|
ObjectCacheUtils::ContainsUnreffedTextures cut;
|
||||||
|
|
||||||
for(ObjectCacheMap::iterator itr = _objectCache.begin();
|
for(ObjectCacheMap::iterator itr = _objectCache.begin();
|
||||||
itr != _objectCache.end();
|
itr != _objectCache.end();
|
||||||
++itr)
|
)
|
||||||
{
|
{
|
||||||
|
ObjectCacheMap::iterator curr_itr = itr;
|
||||||
|
|
||||||
|
// get object and advance iterator to next item
|
||||||
osg::Object* object = itr->second.first.get();
|
osg::Object* object = itr->second.first.get();
|
||||||
|
|
||||||
|
bool needToRemoveEntry = cut.check(itr->second.first.get());
|
||||||
|
|
||||||
object->releaseGLObjects(state);
|
object->releaseGLObjects(state);
|
||||||
|
|
||||||
|
++itr;
|
||||||
|
|
||||||
|
if (needToRemoveEntry)
|
||||||
|
{
|
||||||
|
_objectCache.erase(curr_itr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user