Preliminary work on support for a texture object pool that is designed to help manage resources down the GPU more tightly.
This commit is contained in:
@@ -80,6 +80,10 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs)
|
||||
_numHttpDatabaseThreadsHint = vs._numHttpDatabaseThreadsHint;
|
||||
|
||||
_application = vs._application;
|
||||
|
||||
_maxTexturePoolSize = vs._maxTexturePoolSize;
|
||||
_maxVBOPoolSize = vs._maxVBOPoolSize;
|
||||
_maxFBOPoolSize = vs._maxFBOPoolSize;
|
||||
}
|
||||
|
||||
void DisplaySettings::merge(const DisplaySettings& vs)
|
||||
@@ -103,6 +107,10 @@ void DisplaySettings::merge(const DisplaySettings& vs)
|
||||
if (vs._numHttpDatabaseThreadsHint>_numHttpDatabaseThreadsHint) _numHttpDatabaseThreadsHint = vs._numHttpDatabaseThreadsHint;
|
||||
|
||||
if (_application.empty()) _application = vs._application;
|
||||
|
||||
if (vs._maxTexturePoolSize>_maxTexturePoolSize) _maxTexturePoolSize = vs._maxTexturePoolSize;
|
||||
if (vs._maxVBOPoolSize>_maxVBOPoolSize) _maxVBOPoolSize = vs._maxVBOPoolSize;
|
||||
if (vs._maxFBOPoolSize>_maxFBOPoolSize) _maxFBOPoolSize = vs._maxFBOPoolSize;
|
||||
}
|
||||
|
||||
void DisplaySettings::setDefaults()
|
||||
@@ -147,6 +155,10 @@ void DisplaySettings::setDefaults()
|
||||
|
||||
_numDatabaseThreadsHint = 2;
|
||||
_numHttpDatabaseThreadsHint = 1;
|
||||
|
||||
_maxTexturePoolSize = 0;
|
||||
_maxVBOPoolSize = 0;
|
||||
_maxFBOPoolSize = 0;
|
||||
}
|
||||
|
||||
void DisplaySettings::setMaxNumberOfGraphicsContexts(unsigned int num)
|
||||
@@ -186,6 +198,9 @@ static ApplicationUsageProxy DisplaySetting_e14(ApplicationUsage::ENVIRONMENTAL_
|
||||
static ApplicationUsageProxy DisplaySetting_e15(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_NUM_DATABASE_THREADS <int>","Set the hint for the total number of threads to set up in the DatabasePager.");
|
||||
static ApplicationUsageProxy DisplaySetting_e16(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_NUM_HTTP_DATABASE_THREADS <int>","Set the hint for the total number of threads dedicated to http requests to set up in the DatabasePager.");
|
||||
static ApplicationUsageProxy DisplaySetting_e17(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MULTI_SAMPLES <int>","Set the hint for the number of samples to use when multi-sampling.");
|
||||
static ApplicationUsageProxy DisplaySetting_e18(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TEXTURE_POOL_SIZE <int>","Set the hint size of texture pool to manage.");
|
||||
static ApplicationUsageProxy DisplaySetting_e19(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_VBO_POOL_SIZE <int>","Set the hint size of vertex buffer object pool to manage.");
|
||||
static ApplicationUsageProxy DisplaySetting_e20(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FBO_POOL_SIZE <int>","Set the hint size of frame buffer object pool to manage.");
|
||||
|
||||
void DisplaySettings::readEnvironmentalVariables()
|
||||
{
|
||||
@@ -382,6 +397,21 @@ void DisplaySettings::readEnvironmentalVariables()
|
||||
{
|
||||
_numMultiSamples = atoi(ptr);
|
||||
}
|
||||
|
||||
if( (ptr = getenv("OSG_TEXTURE_POOL_SIZE")) != 0)
|
||||
{
|
||||
_maxTexturePoolSize = atoi(ptr);
|
||||
}
|
||||
|
||||
if( (ptr = getenv("OSG_VBO_POOL_SIZE")) != 0)
|
||||
{
|
||||
_maxVBOPoolSize = atoi(ptr);
|
||||
}
|
||||
|
||||
if( (ptr = getenv("OSG_FBO_POOL_SIZE")) != 0)
|
||||
{
|
||||
_maxFBOPoolSize = atoi(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySettings::readCommandLine(ArgumentParser& arguments)
|
||||
@@ -468,4 +498,12 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments)
|
||||
|
||||
while(arguments.read("--num-db-threads",_numDatabaseThreadsHint)) {}
|
||||
while(arguments.read("--num-http-threads",_numHttpDatabaseThreadsHint)) {}
|
||||
|
||||
while(arguments.read("--texture-pool-size",_maxTexturePoolSize)) {}
|
||||
while(arguments.read("--vbo-pool-size",_maxVBOPoolSize)) {}
|
||||
while(arguments.read("--fbo-pool-size",_maxFBOPoolSize)) {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -496,12 +496,12 @@ void FrameBufferAttachment::createRequiredTexturesAndApplyGenerateMipMap(State &
|
||||
if (_ximpl->textureTarget.valid())
|
||||
{
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
if (!tobj || tobj->_id == 0)
|
||||
if (!tobj || tobj->id() == 0)
|
||||
{
|
||||
_ximpl->textureTarget->compileGLObjects(state);
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
}
|
||||
if (!tobj || tobj->_id == 0)
|
||||
if (!tobj || tobj->id() == 0)
|
||||
return;
|
||||
|
||||
Texture::FilterMode minFilter = _ximpl->textureTarget->getFilter(Texture::MIN_FILTER);
|
||||
@@ -526,13 +526,13 @@ void FrameBufferAttachment::attach(State &state, GLenum target, GLenum attachmen
|
||||
if (_ximpl->textureTarget.valid())
|
||||
{
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
if (!tobj || tobj->_id == 0)
|
||||
if (!tobj || tobj->id() == 0)
|
||||
{
|
||||
_ximpl->textureTarget->compileGLObjects(state);
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
|
||||
}
|
||||
if (!tobj || tobj->_id == 0)
|
||||
if (!tobj || tobj->id() == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -543,22 +543,22 @@ void FrameBufferAttachment::attach(State &state, GLenum target, GLenum attachmen
|
||||
ext->glFramebufferRenderbufferEXT(target, attachment_point, GL_RENDERBUFFER_EXT, _ximpl->renderbufferTarget->getObjectID(contextID, ext));
|
||||
break;
|
||||
case Pimpl::TEXTURE1D:
|
||||
ext->glFramebufferTexture1DEXT(target, attachment_point, GL_TEXTURE_1D, tobj->_id, _ximpl->level);
|
||||
ext->glFramebufferTexture1DEXT(target, attachment_point, GL_TEXTURE_1D, tobj->id(), _ximpl->level);
|
||||
break;
|
||||
case Pimpl::TEXTURE2D:
|
||||
ext->glFramebufferTexture2DEXT(target, attachment_point, GL_TEXTURE_2D, tobj->_id, _ximpl->level);
|
||||
ext->glFramebufferTexture2DEXT(target, attachment_point, GL_TEXTURE_2D, tobj->id(), _ximpl->level);
|
||||
break;
|
||||
case Pimpl::TEXTURE3D:
|
||||
ext->glFramebufferTexture3DEXT(target, attachment_point, GL_TEXTURE_3D, tobj->_id, _ximpl->level, _ximpl->zoffset);
|
||||
ext->glFramebufferTexture3DEXT(target, attachment_point, GL_TEXTURE_3D, tobj->id(), _ximpl->level, _ximpl->zoffset);
|
||||
break;
|
||||
case Pimpl::TEXTURE2DARRAY:
|
||||
ext->glFramebufferTextureLayerEXT(target, attachment_point, tobj->_id, _ximpl->level, _ximpl->zoffset);
|
||||
ext->glFramebufferTextureLayerEXT(target, attachment_point, tobj->id(), _ximpl->level, _ximpl->zoffset);
|
||||
break;
|
||||
case Pimpl::TEXTURERECT:
|
||||
ext->glFramebufferTexture2DEXT(target, attachment_point, GL_TEXTURE_RECTANGLE, tobj->_id, 0);
|
||||
ext->glFramebufferTexture2DEXT(target, attachment_point, GL_TEXTURE_RECTANGLE, tobj->id(), 0);
|
||||
break;
|
||||
case Pimpl::TEXTURECUBE:
|
||||
ext->glFramebufferTexture2DEXT(target, attachment_point, GL_TEXTURE_CUBE_MAP_POSITIVE_X + _ximpl->cubeMapFace, tobj->_id, _ximpl->level);
|
||||
ext->glFramebufferTexture2DEXT(target, attachment_point, GL_TEXTURE_CUBE_MAP_POSITIVE_X + _ximpl->cubeMapFace, tobj->id(), _ximpl->level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,10 @@ State::State():
|
||||
|
||||
_glMaxTextureCoords = 1;
|
||||
_glMaxTextureUnits = 1;
|
||||
|
||||
_maxTexturePoolSize = 0;
|
||||
_maxVBOPoolSize = 0;
|
||||
_maxFBOPoolSize = 0;
|
||||
}
|
||||
|
||||
State::~State()
|
||||
@@ -220,6 +224,24 @@ void State::setInitialViewMatrix(const osg::RefMatrix* matrix)
|
||||
_initialInverseViewMatrix.invert(*_initialViewMatrix);
|
||||
}
|
||||
|
||||
void State::setMaxTexturePoolSize(unsigned int size)
|
||||
{
|
||||
_maxTexturePoolSize = size;
|
||||
osg::notify(osg::NOTICE)<<"_maxTexturePoolSize="<<_maxTexturePoolSize<<std::endl;
|
||||
}
|
||||
|
||||
void State::setMaxVBOPoolSize(unsigned int size)
|
||||
{
|
||||
_maxVBOPoolSize = size;
|
||||
osg::notify(osg::NOTICE)<<"_maxVBOPoolSize="<<_maxVBOPoolSize<<std::endl;
|
||||
}
|
||||
|
||||
void State::setMaxFBOPoolSize(unsigned int size)
|
||||
{
|
||||
_maxFBOPoolSize = size;
|
||||
osg::notify(osg::NOTICE)<<"_maxFBOPoolSize="<<_maxFBOPoolSize<<std::endl;
|
||||
}
|
||||
|
||||
void State::pushStateSet(const StateSet* dstate)
|
||||
{
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
#ifndef GL_TEXTURE_WRAP_R
|
||||
#define GL_TEXTURE_WRAP_R 0x8072
|
||||
#endif
|
||||
@@ -54,24 +52,538 @@ namespace osg {
|
||||
|
||||
ApplicationUsageProxy Texture_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_TEXTURE_SIZE","Set the maximum size of textures.");
|
||||
|
||||
class TextureObjectManager : public osg::Referenced
|
||||
typedef buffered_value< ref_ptr<Texture::Extensions> > BufferedExtensions;
|
||||
static BufferedExtensions s_extensions;
|
||||
|
||||
unsigned int s_minimumNumberOfTextureObjectsToRetainInCache = 0;
|
||||
|
||||
void Texture::setMinimumNumberOfTextureObjectsToRetainInCache(unsigned int minimum)
|
||||
{
|
||||
s_minimumNumberOfTextureObjectsToRetainInCache = minimum;
|
||||
}
|
||||
|
||||
unsigned int Texture::getMinimumNumberOfTextureObjectsToRetainInCache()
|
||||
{
|
||||
return s_minimumNumberOfTextureObjectsToRetainInCache;
|
||||
}
|
||||
|
||||
|
||||
#define USE_NEW_TEXTURE_POOL 0
|
||||
|
||||
void Texture::TextureObject::bind()
|
||||
{
|
||||
glBindTexture( _profile._target, _id);
|
||||
if (_set) _set->moveToBack(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// New texture object manager
|
||||
//
|
||||
Texture::TextureObjectSet::TextureObjectSet(TextureObjectManager* parent, const TextureProfile& profile):
|
||||
_parent(parent),
|
||||
_contextID(parent->getContextID()),
|
||||
_profile(profile),
|
||||
_numOfTextureObjects(0),
|
||||
_head(0),
|
||||
_tail(0)
|
||||
{
|
||||
}
|
||||
|
||||
Texture::TextureObjectSet::~TextureObjectSet()
|
||||
{
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<"TextureObjectSet::~TextureObjectSet(), _numOfTextureObjects="<<_numOfTextureObjects<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _orphanedTextureObjects = "<<_orphanedTextureObjects.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _head = "<<_head<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _tail = "<<_tail<<std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Texture::TextureObjectSet::checkConsistency() const
|
||||
{
|
||||
// return true;
|
||||
|
||||
// osg::notify(osg::NOTICE)<<"TextureObjectSet::checkConsistency()"<<std::endl;
|
||||
// check consistency of linked list.
|
||||
unsigned int numInList = 0;
|
||||
Texture::TextureObject* to = _head;
|
||||
while(to!=0)
|
||||
{
|
||||
++numInList;
|
||||
|
||||
if (to->_next)
|
||||
{
|
||||
if ((to->_next)->_previous != to)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error (to->_next)->_previous != to "<<std::endl;
|
||||
throw "Error (to->_next)->_previous != to ";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_tail != to)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error _trail != to"<<std::endl;
|
||||
throw "Error _trail != to";
|
||||
}
|
||||
}
|
||||
|
||||
to = to->_next;
|
||||
}
|
||||
|
||||
unsigned int totalNumber = numInList + _orphanedTextureObjects.size();
|
||||
if (totalNumber != _numOfTextureObjects)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error numInList + _orphanedTextureObjects.size() != _numOfTextureObjects"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" numInList = "<<numInList<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _orphanedTextureObjects.size() = "<<_orphanedTextureObjects.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _pendingOrphanedTextureObjects.size() = "<<_pendingOrphanedTextureObjects.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _numOfTextureObjects = "<<_numOfTextureObjects<<std::endl;
|
||||
throw "Error numInList + _orphanedTextureObjects.size() != _numOfTextureObjects";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::handlePendingOrphandedTextureObjects()
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<"handlePendingOrphandedTextureObjects()"<<_pendingOrphanedTextureObjects.size()<<std::endl;
|
||||
|
||||
if (_pendingOrphanedTextureObjects.empty()) return;
|
||||
|
||||
for(TextureObjectList::iterator itr = _pendingOrphanedTextureObjects.begin();
|
||||
itr != _pendingOrphanedTextureObjects.end();
|
||||
++itr)
|
||||
{
|
||||
TextureObject* to = itr->get();
|
||||
|
||||
_orphanedTextureObjects.push_back(to);
|
||||
|
||||
if (to->_previous!=0)
|
||||
{
|
||||
(to->_previous)->_next = to->_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 'to' was head so assign _head to the next in list
|
||||
_head = to->_next;
|
||||
}
|
||||
|
||||
if (to->_next!=0)
|
||||
{
|
||||
(to->_next)->_previous = to->_previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 'to' was tail so assing tail to the previous in list
|
||||
_tail = to->_previous;
|
||||
}
|
||||
|
||||
// reset the 'to' list pointers as it's no longer in the active list.
|
||||
to->_next = 0;
|
||||
to->_previous = 0;
|
||||
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<" HPOTO after _head = "<<_head<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" HPOTO after _tail = "<<_tail<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" HPOTO after to->_previous = "<<to->_previous<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" HPOTO after to->_next = "<<to->_next<<std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
_pendingOrphanedTextureObjects.clear();
|
||||
|
||||
checkConsistency();
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::flushAllDeletedTextureObjects()
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
handlePendingOrphandedTextureObjects();
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
for(TextureObjectList::iterator itr = _orphanedTextureObjects.begin();
|
||||
itr != _orphanedTextureObjects.end();
|
||||
++itr)
|
||||
{
|
||||
|
||||
GLuint id = (*itr)->id();
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Deleting textureobject id="<<id<<std::endl;
|
||||
|
||||
glDeleteTextures( 1L, &id);
|
||||
}
|
||||
_numOfTextureObjects -= _orphanedTextureObjects.size();
|
||||
_orphanedTextureObjects.clear();
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::discardAllDeletedTextureObjects()
|
||||
{
|
||||
_numOfTextureObjects -= _orphanedTextureObjects.size();
|
||||
|
||||
// just clear the list as there is nothing else we can do with them when discarding them
|
||||
_pendingOrphanedTextureObjects.clear();
|
||||
_orphanedTextureObjects.clear();
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::flushDeletedTextureObjects(double currentTime, double& availableTime)
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<"Texture::TextureObjectSet::flushDeletedTextureObjects(..) Not properly implemented yet"<<std::endl;
|
||||
|
||||
flushAllDeletedTextureObjects();
|
||||
}
|
||||
|
||||
Texture::TextureObject* Texture::TextureObjectSet::takeOrGenerate(Texture* texture)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
if (!_pendingOrphanedTextureObjects.empty()) handlePendingOrphandedTextureObjects();
|
||||
|
||||
// see if we can recyle TextureObject from the orphane list
|
||||
if (!_orphanedTextureObjects.empty())
|
||||
{
|
||||
// take front of orphaned list.
|
||||
ref_ptr<TextureObject> to = _orphanedTextureObjects.front();
|
||||
|
||||
// remove from orphan list.
|
||||
_orphanedTextureObjects.pop_front();
|
||||
|
||||
// assign to new texture
|
||||
to->setTexture(texture);
|
||||
|
||||
// place at back of active list
|
||||
addToBack(to.get());
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Reusing orhpahned TextureObject, _numOfTextureObjects="<<_numOfTextureObjects<<std::endl;
|
||||
|
||||
return to.release();
|
||||
}
|
||||
|
||||
// see if we can reuse TextureObject by taking the least recently used active TextureObject
|
||||
if ((_parent->getTexturePoolSize()!=0) &&
|
||||
(_numOfTextureObjects > _parent->getTexturePoolSize()) &&
|
||||
(_numOfTextureObjects>1) &&
|
||||
(_head != 0))
|
||||
{
|
||||
ref_ptr<TextureObject> to = _head;
|
||||
|
||||
ref_ptr<Texture> original_texture = to->getTexture();
|
||||
|
||||
if (original_texture.valid())
|
||||
{
|
||||
original_texture->setTextureObject(_contextID,0);
|
||||
osg::notify(osg::NOTICE)<<"Reusing an active TextureObject "<<to.get()<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Reusing a recently orphaned active TextureObject "<<to.get()<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
moveToBack(to.get());
|
||||
|
||||
// assign to new texture
|
||||
to->setTexture(texture);
|
||||
|
||||
return to.release();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// no TextureObjects available to recyle so have to create one from scratch
|
||||
//
|
||||
GLuint id;
|
||||
glGenTextures( 1L, &id );
|
||||
|
||||
TextureObject* to = new Texture::TextureObject(const_cast<Texture*>(texture),id,_profile);
|
||||
to->_set = this;
|
||||
++_numOfTextureObjects;
|
||||
|
||||
addToBack(to);
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Created new TextureObject, _numOfTextureObjects "<<_numOfTextureObjects<<std::endl;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::moveToBack(Texture::TextureObject* to)
|
||||
{
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<"TextureObjectSet::moveToBack("<<to<<")"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before _head = "<<_head<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before _tail = "<<_tail<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before to->_previous = "<<to->_previous<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before to->_next = "<<to->_next<<std::endl;
|
||||
#endif
|
||||
|
||||
// nothing to do if we are already tail
|
||||
if (to==_tail) return;
|
||||
|
||||
// if no tail exists then assign 'to' as tail and head
|
||||
if (_tail==0)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error ***************** Should not get here !!!!!!!!!"<<std::endl;
|
||||
_head = to;
|
||||
_tail = to;
|
||||
return;
|
||||
}
|
||||
|
||||
if (to->_next==0)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error ***************** Should not get here either !!!!!!!!!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (to->_previous)
|
||||
{
|
||||
(to->_previous)->_next = to->_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 'to' is the head, so moving it to the back will mean we need a new head
|
||||
if (to->_next)
|
||||
{
|
||||
_head = to->_next;
|
||||
}
|
||||
}
|
||||
|
||||
(to->_next)->_previous = to->_previous;
|
||||
|
||||
_tail->_next = to;
|
||||
|
||||
to->_previous = _tail;
|
||||
to->_next = 0;
|
||||
|
||||
_tail = to;
|
||||
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<" m2B after _head = "<<_head<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" m2B after _tail = "<<_tail<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" m2B after to->_previous = "<<to->_previous<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" m2B after to->_next = "<<to->_next<<std::endl;
|
||||
#endif
|
||||
checkConsistency();
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::addToBack(Texture::TextureObject* to)
|
||||
{
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<"TextureObjectSet::addToBack("<<to<<")"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before _head = "<<_head<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before _tail = "<<_tail<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before to->_previous = "<<to->_previous<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" before to->_next = "<<to->_next<<std::endl;
|
||||
#endif
|
||||
|
||||
if (to->_previous !=0 || to->_next !=0)
|
||||
{
|
||||
moveToBack(to);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_tail) _tail->_next = to;
|
||||
to->_previous = _tail;
|
||||
|
||||
if (!_head) _head = to;
|
||||
_tail = to;
|
||||
}
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<" a2B after _head = "<<_head<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" a2B after _tail = "<<_tail<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" a2B after to->_previous = "<<to->_previous<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" a2B after to->_next = "<<to->_next<<std::endl;
|
||||
#endif
|
||||
checkConsistency();
|
||||
}
|
||||
|
||||
void Texture::TextureObjectSet::orphan(Texture::TextureObject* to)
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<"TextureObjectSet::orphan("<<to<<")"<<std::endl;
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
// disconnect from original texture
|
||||
to->setTexture(0);
|
||||
|
||||
// add orphan 'to' to the pending list of orphans, these will then be
|
||||
// handled in the handlePendingOrphandedTextureObjects() where the TO's
|
||||
// will be removed from the active list, and then placed in the orhpanTextureObject
|
||||
// list. This double buffered approach to handling orphaned TO's is used
|
||||
// to avoid having to mutex the process of appling active TO's.
|
||||
_pendingOrphanedTextureObjects.push_back(to);
|
||||
|
||||
#if 0
|
||||
osg::notify(osg::NOTICE)<<"TextureObjectSet::orphan("<<to<<") _pendingOrphanedTextureObjects.size()="<<_pendingOrphanedTextureObjects.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" _orphanedTextureObjects.size()="<<_orphanedTextureObjects.size()<<std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int Texture::TextureObjectSet::size() const
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Texture::TextureObjectSet::size() Not implemented yet"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Texture::TextureObjectManager::TextureObjectManager(unsigned int contextID):
|
||||
_contextID(contextID),
|
||||
_texturePoolSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::setTexturePoolSize(unsigned int size)
|
||||
{
|
||||
_texturePoolSize = size;
|
||||
}
|
||||
|
||||
|
||||
Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(const Texture* texture, GLenum target)
|
||||
{
|
||||
return generateTextureObject(texture, target, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(const Texture* texture,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLsizei depth,
|
||||
GLint border)
|
||||
{
|
||||
Texture::TextureProfile profile(target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
osg::ref_ptr<Texture::TextureObjectSet>& tos = _textureSetMap[profile];
|
||||
if (!tos) tos = new Texture::TextureObjectSet(this, profile);
|
||||
return tos->takeOrGenerate(const_cast<Texture*>(texture));
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::handlePendingOrphandedTextureObjects()
|
||||
{
|
||||
for(TextureSetMap::iterator itr = _textureSetMap.begin();
|
||||
itr != _textureSetMap.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr).second->handlePendingOrphandedTextureObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::flushAllDeletedTextureObjects()
|
||||
{
|
||||
for(TextureSetMap::iterator itr = _textureSetMap.begin();
|
||||
itr != _textureSetMap.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr).second->flushAllDeletedTextureObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::discardAllDeletedTextureObjects()
|
||||
{
|
||||
for(TextureSetMap::iterator itr = _textureSetMap.begin();
|
||||
itr != _textureSetMap.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr).second->discardAllDeletedTextureObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::flushDeletedTextureObjects(double currentTime, double& availableTime)
|
||||
{
|
||||
for(TextureSetMap::iterator itr = _textureSetMap.begin();
|
||||
(itr != _textureSetMap.end()) && (availableTime > 0.0);
|
||||
++itr)
|
||||
{
|
||||
(*itr).second->flushDeletedTextureObjects(currentTime, availableTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::releaseTextureObject(Texture::TextureObject* to)
|
||||
{
|
||||
if (to->_set) to->_set->orphan(to);
|
||||
else osg::notify(osg::NOTICE)<<"TextureObjectManager::releaseTextureObject(Texture::TextureObject* to) Not implemented yet"<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
#if USE_NEW_TEXTURE_POOL
|
||||
|
||||
Texture::TextureObject* Texture::generateTextureObject(const Texture* texture, unsigned int contextID, GLenum target)
|
||||
{
|
||||
return getTextureObjectManager(contextID)->generateTextureObject(texture, target);
|
||||
}
|
||||
|
||||
Texture::TextureObject* Texture::generateTextureObject(const Texture* texture, unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLsizei depth,
|
||||
GLint border)
|
||||
{
|
||||
return getTextureObjectManager(contextID)->generateTextureObject(texture,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Original texture object manager
|
||||
//
|
||||
class OriginalTextureObjectManager : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
TextureObjectManager():
|
||||
OriginalTextureObjectManager():
|
||||
_expiryDelay(0.0)
|
||||
{
|
||||
// printf("Constructing TextureObjectManager\n");
|
||||
// printf("Constructing OriginalTextureObjectManager\n");
|
||||
}
|
||||
|
||||
~TextureObjectManager()
|
||||
~OriginalTextureObjectManager()
|
||||
{
|
||||
// printf("Destructing TextureObjectManager\n");
|
||||
// printf("Destructing OriginalTextureObjectManager\n");
|
||||
}
|
||||
|
||||
virtual Texture::TextureObject* generateTextureObject(unsigned int contextID,GLenum target);
|
||||
virtual Texture::TextureObject* generateTextureObject(Texture* texture, unsigned int contextID,GLenum target);
|
||||
|
||||
virtual Texture::TextureObject* generateTextureObject(unsigned int contextID,
|
||||
virtual Texture::TextureObject* generateTextureObject(Texture* texture, unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -80,7 +592,7 @@ public:
|
||||
GLsizei depth,
|
||||
GLint border);
|
||||
|
||||
virtual Texture::TextureObject* reuseTextureObject(unsigned int contextID,
|
||||
virtual Texture::TextureObject* reuseTextureObject(Texture* texture, unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -89,7 +601,7 @@ public:
|
||||
GLsizei depth,
|
||||
GLint border);
|
||||
|
||||
inline Texture::TextureObject* reuseOrGenerateTextureObject(unsigned int contextID,
|
||||
inline Texture::TextureObject* reuseOrGenerateTextureObject(Texture* texture, unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -98,15 +610,11 @@ public:
|
||||
GLsizei depth,
|
||||
GLint border)
|
||||
{
|
||||
Texture::TextureObject* to = reuseTextureObject(contextID,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
Texture::TextureObject* to = reuseTextureObject(texture, contextID,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
if (to) return to;
|
||||
else return generateTextureObject(contextID,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
else return generateTextureObject(texture, contextID,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
}
|
||||
|
||||
void addTextureObjects(Texture::TextureObjectListMap& toblm);
|
||||
|
||||
void addTextureObjectsFrom(Texture& texture);
|
||||
|
||||
void flushAllTextureObjects(unsigned int contextID);
|
||||
|
||||
void discardAllTextureObjects(unsigned int contextID);
|
||||
@@ -120,46 +628,32 @@ public:
|
||||
/** How long to keep unused texture objects before deletion. */
|
||||
double _expiryDelay;
|
||||
|
||||
Texture::TextureObjectListMap _textureObjectListMap;
|
||||
typedef osg::buffered_object<Texture::TextureObjectList> TextureObjectListMap;
|
||||
TextureObjectListMap _textureObjectListMap;
|
||||
|
||||
// mutex to keep access serialized.
|
||||
OpenThreads::Mutex _mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
unsigned int Texture::s_numberTextureReusedLastInLastFrame = 0;
|
||||
unsigned int Texture::s_numberNewTextureInLastFrame = 0;
|
||||
unsigned int Texture::s_numberDeletedTextureInLastFrame = 0;
|
||||
|
||||
unsigned int s_minimumNumberOfTextureObjectsToRetainInCache = 0;
|
||||
|
||||
typedef buffered_value< ref_ptr<Texture::Extensions> > BufferedExtensions;
|
||||
static BufferedExtensions s_extensions;
|
||||
static ref_ptr<OriginalTextureObjectManager> s_textureObjectManager = new OriginalTextureObjectManager;
|
||||
|
||||
static ref_ptr<TextureObjectManager> s_textureObjectManager = new TextureObjectManager;
|
||||
|
||||
void Texture::setMinimumNumberOfTextureObjectsToRetainInCache(unsigned int minimum)
|
||||
{
|
||||
s_minimumNumberOfTextureObjectsToRetainInCache = minimum;
|
||||
}
|
||||
|
||||
unsigned int Texture::getMinimumNumberOfTextureObjectsToRetainInCache()
|
||||
{
|
||||
return s_minimumNumberOfTextureObjectsToRetainInCache;
|
||||
}
|
||||
|
||||
Texture::TextureObject* TextureObjectManager::generateTextureObject(unsigned int /*contextID*/,GLenum target)
|
||||
Texture::TextureObject* OriginalTextureObjectManager::generateTextureObject(Texture* texture, unsigned int /*contextID*/,GLenum target)
|
||||
{
|
||||
GLuint id;
|
||||
glGenTextures( 1L, &id );
|
||||
|
||||
return new Texture::TextureObject(id,target);
|
||||
return new Texture::TextureObject(texture, id,target);
|
||||
}
|
||||
|
||||
static int s_number = 0;
|
||||
|
||||
Texture::TextureObject* TextureObjectManager::generateTextureObject(unsigned int /*contextID*/,
|
||||
Texture::TextureObject* OriginalTextureObjectManager::generateTextureObject(Texture* texture, unsigned int /*contextID*/,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -176,10 +670,10 @@ Texture::TextureObject* TextureObjectManager::generateTextureObject(unsigned int
|
||||
GLuint id;
|
||||
glGenTextures( 1L, &id );
|
||||
|
||||
return new Texture::TextureObject(id,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
return new Texture::TextureObject(texture, id,target,numMipmapLevels,internalFormat,width,height,depth,border);
|
||||
}
|
||||
|
||||
Texture::TextureObject* TextureObjectManager::reuseTextureObject(unsigned int contextID,
|
||||
Texture::TextureObject* OriginalTextureObjectManager::reuseTextureObject(Texture* texture, unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -205,6 +699,8 @@ Texture::TextureObject* TextureObjectManager::reuseTextureObject(unsigned int co
|
||||
|
||||
++Texture::s_numberTextureReusedLastInLastFrame;
|
||||
|
||||
textureObject->setTexture(texture);
|
||||
|
||||
return textureObject;
|
||||
}
|
||||
}
|
||||
@@ -212,27 +708,7 @@ Texture::TextureObject* TextureObjectManager::reuseTextureObject(unsigned int co
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TextureObjectManager::addTextureObjects(Texture::TextureObjectListMap& toblm)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
for(unsigned int i=0; i< toblm.size(); ++i)
|
||||
{
|
||||
Texture::TextureObjectList& tol = _textureObjectListMap[i];
|
||||
tol.insert(tol.end(),toblm[i].begin(),toblm[i].end());
|
||||
}
|
||||
}
|
||||
|
||||
void TextureObjectManager::addTextureObjectsFrom(Texture& texture)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
texture.takeTextureObjects(_textureObjectListMap);
|
||||
}
|
||||
|
||||
void TextureObjectManager::flushAllTextureObjects(unsigned int contextID)
|
||||
void OriginalTextureObjectManager::flushAllTextureObjects(unsigned int contextID)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
@@ -245,12 +721,13 @@ void TextureObjectManager::flushAllTextureObjects(unsigned int contextID)
|
||||
++itr)
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<" deleting texture object "<<(*itr)->_id<<std::endl;
|
||||
glDeleteTextures( 1L, &((*itr)->_id));
|
||||
GLuint id = (*itr)->id();
|
||||
glDeleteTextures( 1L, &id);
|
||||
}
|
||||
tol.clear();
|
||||
}
|
||||
|
||||
void TextureObjectManager::discardAllTextureObjects(unsigned int contextID)
|
||||
void OriginalTextureObjectManager::discardAllTextureObjects(unsigned int contextID)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
@@ -258,7 +735,7 @@ void TextureObjectManager::discardAllTextureObjects(unsigned int contextID)
|
||||
tol.clear();
|
||||
}
|
||||
|
||||
void TextureObjectManager::flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime)
|
||||
void OriginalTextureObjectManager::flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime)
|
||||
{
|
||||
// if no time available don't try to flush objects.
|
||||
if (availableTime<=0.0) return;
|
||||
@@ -282,7 +759,7 @@ void TextureObjectManager::flushTextureObjects(unsigned int contextID,double cur
|
||||
itr!=tol.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->_timeStamp==0.0) (*itr)->_timeStamp=currentTime;
|
||||
if ((*itr)->getTimeStamp()==0.0) (*itr)->setTimeStamp(currentTime);
|
||||
}
|
||||
|
||||
double expiryTime = currentTime-_expiryDelay;
|
||||
@@ -291,12 +768,13 @@ void TextureObjectManager::flushTextureObjects(unsigned int contextID,double cur
|
||||
itr!=tol.end() && elapsedTime<availableTime && tol.size()>s_minimumNumberOfTextureObjectsToRetainInCache && numObjectsDeleted<maxNumObjectsToDelete;
|
||||
)
|
||||
{
|
||||
if ((*itr)->_timeStamp<=expiryTime)
|
||||
if ((*itr)->getTimeStamp()<=expiryTime)
|
||||
{
|
||||
--s_number;
|
||||
++Texture::s_numberDeletedTextureInLastFrame;
|
||||
|
||||
glDeleteTextures( 1L, &((*itr)->_id));
|
||||
GLuint id = (*itr)->id();
|
||||
glDeleteTextures( 1L, &id);
|
||||
itr = tol.erase(itr);
|
||||
++numTexturesDeleted;
|
||||
++numObjectsDeleted;
|
||||
@@ -315,19 +793,19 @@ void TextureObjectManager::flushTextureObjects(unsigned int contextID,double cur
|
||||
}
|
||||
|
||||
|
||||
static TextureObjectManager* getTextureObjectManager()
|
||||
static OriginalTextureObjectManager* getOriginalTextureObjectManager()
|
||||
{
|
||||
return s_textureObjectManager.get();
|
||||
}
|
||||
|
||||
|
||||
Texture::TextureObject* Texture::generateTextureObject(unsigned int contextID,GLenum target)
|
||||
Texture::TextureObject* Texture::generateTextureObject(const Texture* texture, unsigned int contextID,GLenum target)
|
||||
{
|
||||
if (getTextureObjectManager()) return getTextureObjectManager()->generateTextureObject(contextID,target);
|
||||
if (getOriginalTextureObjectManager()) return getOriginalTextureObjectManager()->generateTextureObject(const_cast<osg::Texture*>(texture),contextID,target);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
Texture::TextureObject* Texture::generateTextureObject(unsigned int contextID,
|
||||
Texture::TextureObject* Texture::generateTextureObject(const Texture* texture, unsigned int contextID,
|
||||
GLenum target,
|
||||
GLint numMipmapLevels,
|
||||
GLenum internalFormat,
|
||||
@@ -336,8 +814,9 @@ Texture::TextureObject* Texture::generateTextureObject(unsigned int contextID,
|
||||
GLsizei depth,
|
||||
GLint border)
|
||||
{
|
||||
if (getTextureObjectManager())
|
||||
return getTextureObjectManager()->reuseOrGenerateTextureObject(contextID,
|
||||
if (getOriginalTextureObjectManager())
|
||||
return getOriginalTextureObjectManager()->reuseOrGenerateTextureObject(const_cast<osg::Texture*>(texture),
|
||||
contextID,
|
||||
target,
|
||||
numMipmapLevels,
|
||||
internalFormat,
|
||||
@@ -351,19 +830,32 @@ Texture::TextureObject* Texture::generateTextureObject(unsigned int contextID,
|
||||
|
||||
void Texture::flushAllDeletedTextureObjects(unsigned int contextID)
|
||||
{
|
||||
if (getTextureObjectManager()) getTextureObjectManager()->flushAllTextureObjects(contextID);
|
||||
if (getOriginalTextureObjectManager()) getOriginalTextureObjectManager()->flushAllTextureObjects(contextID);
|
||||
}
|
||||
|
||||
void Texture::discardAllDeletedTextureObjects(unsigned int contextID)
|
||||
{
|
||||
if (getTextureObjectManager()) getTextureObjectManager()->discardAllTextureObjects(contextID);
|
||||
if (getOriginalTextureObjectManager()) getOriginalTextureObjectManager()->discardAllTextureObjects(contextID);
|
||||
}
|
||||
|
||||
void Texture::flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availbleTime)
|
||||
{
|
||||
if (getTextureObjectManager()) getTextureObjectManager()->flushTextureObjects(contextID, currentTime, availbleTime);
|
||||
if (getOriginalTextureObjectManager()) getOriginalTextureObjectManager()->flushTextureObjects(contextID, currentTime, availbleTime);
|
||||
}
|
||||
|
||||
void Texture::releaseTextureObject(unsigned int contextID, Texture::TextureObject* to)
|
||||
{
|
||||
if (getOriginalTextureObjectManager())
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getOriginalTextureObjectManager()->_mutex);
|
||||
getOriginalTextureObjectManager()->_textureObjectListMap[contextID].push_back(to);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Texture::Texture():
|
||||
_wrap_s(CLAMP),
|
||||
_wrap_t(CLAMP),
|
||||
@@ -526,20 +1018,14 @@ void Texture::setMaxAnisotropy(float anis)
|
||||
/** Force a recompile on next apply() of associated OpenGL texture objects.*/
|
||||
void Texture::dirtyTextureObject()
|
||||
{
|
||||
if (getTextureObjectManager()) getTextureObjectManager()->addTextureObjectsFrom(*this);
|
||||
}
|
||||
|
||||
void Texture::takeTextureObjects(Texture::TextureObjectListMap& toblm)
|
||||
{
|
||||
for(unsigned int i = 0; i<_textureObjectBuffer.size();++i)
|
||||
for(unsigned int i=0; i<_textureObjectBuffer.size();++i)
|
||||
{
|
||||
if (_textureObjectBuffer[i].valid())
|
||||
if (_textureObjectBuffer[i].valid())
|
||||
{
|
||||
//notify(INFO) << "releasing texture "<<toblm[i].size()<<std::endl;
|
||||
toblm[i].push_back(_textureObjectBuffer[i]);
|
||||
Texture::releaseTextureObject(i, _textureObjectBuffer[i].get());
|
||||
_textureObjectBuffer[i] = 0;
|
||||
}
|
||||
}
|
||||
_textureObjectBuffer.setAllElementsTo(0);
|
||||
}
|
||||
|
||||
void Texture::dirtyTextureParameters()
|
||||
@@ -1482,7 +1968,7 @@ void Texture::mipmapAfterTexImage(State& state, GenerateMipmapMode beforeResult)
|
||||
if (textureObject)
|
||||
{
|
||||
osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(contextID, true);
|
||||
fbo_ext->glGenerateMipmapEXT(textureObject->_target);
|
||||
fbo_ext->glGenerateMipmapEXT(textureObject->target());
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1520,7 +2006,7 @@ void Texture::generateMipmap(State& state) const
|
||||
if (fbo_ext->glGenerateMipmapEXT)
|
||||
{
|
||||
textureObject->bind();
|
||||
fbo_ext->glGenerateMipmapEXT(textureObject->_target);
|
||||
fbo_ext->glGenerateMipmapEXT(textureObject->target());
|
||||
|
||||
// inform state that this texture is the current one bound.
|
||||
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
|
||||
@@ -1533,14 +2019,6 @@ void Texture::generateMipmap(State& state) const
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Static map to manage the deletion of texture objects are the right time.
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
void Texture::compileGLObjects(State& state) const
|
||||
{
|
||||
apply(state);
|
||||
@@ -1560,11 +2038,10 @@ void Texture::releaseGLObjects(State* state) const
|
||||
else
|
||||
{
|
||||
unsigned int contextID = state->getContextID();
|
||||
if (_textureObjectBuffer[contextID].valid() && getTextureObjectManager())
|
||||
if (_textureObjectBuffer[contextID].valid())
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getTextureObjectManager()->_mutex);
|
||||
|
||||
getTextureObjectManager()->_textureObjectListMap[contextID].push_back(_textureObjectBuffer[contextID]);
|
||||
Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get());
|
||||
|
||||
_textureObjectBuffer[contextID] = 0;
|
||||
}
|
||||
}
|
||||
@@ -1800,3 +2277,4 @@ void Texture::Extensions::glGetCompressedTexImage(GLenum target, GLint level, GL
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,7 +150,7 @@ void Texture1D::apply(State& state) const
|
||||
{
|
||||
|
||||
// we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object.
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_1D);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID, GL_TEXTURE_1D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -171,7 +171,7 @@ void Texture1D::apply(State& state) const
|
||||
{
|
||||
|
||||
// we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object.
|
||||
textureObject = generateTextureObject(contextID,GL_TEXTURE_1D);
|
||||
textureObject = generateTextureObject(this, contextID,GL_TEXTURE_1D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -196,7 +196,7 @@ void Texture1D::apply(State& state) const
|
||||
else if ( (_textureWidth!=0) && (_internalFormat!=0) )
|
||||
{
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_1D,_numMipmapLevels,_internalFormat,_textureWidth,1,1,0);
|
||||
this,contextID,GL_TEXTURE_1D,_numMipmapLevels,_internalFormat,_textureWidth,1,1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -378,7 +378,7 @@ void Texture1D::copyTexImage1D(State& state, int x, int y, int width)
|
||||
_min_filter = LINEAR;
|
||||
_mag_filter = LINEAR;
|
||||
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_1D);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_1D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ void Texture2D::apply(State& state) const
|
||||
else if (_subloadCallback.valid())
|
||||
{
|
||||
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_2D);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_2D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -199,7 +199,7 @@ void Texture2D::apply(State& state) const
|
||||
computeRequiredTextureDimensions(state,*image,_textureWidth, _textureHeight, _numMipmapLevels);
|
||||
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
this, contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -223,7 +223,10 @@ void Texture2D::apply(State& state) const
|
||||
// update the modified tag to show that it is upto date.
|
||||
getModifiedCount(contextID) = image->getModifiedCount();
|
||||
|
||||
if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded() && image->getDataVariance()==STATIC)
|
||||
if (state.getMaxTexturePoolSize()==0 &&
|
||||
_unrefImageDataAfterApply &&
|
||||
areAllTextureObjectsLoaded() &&
|
||||
image->getDataVariance()==STATIC)
|
||||
{
|
||||
Texture2D* non_const_this = const_cast<Texture2D*>(this);
|
||||
non_const_this->_image = 0;
|
||||
@@ -239,7 +242,7 @@ void Texture2D::apply(State& state) const
|
||||
else if ( (_textureWidth!=0) && (_textureHeight!=0) && (_internalFormat!=0) )
|
||||
{
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
this, contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -312,7 +315,7 @@ void Texture2D::copyTexImage2D(State& state, int x, int y, int width, int height
|
||||
|
||||
// switch off mip-mapping.
|
||||
//
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_2D);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_2D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ void Texture2DArray::apply(State& state) const
|
||||
else if (_subloadCallback.valid())
|
||||
{
|
||||
// generate texture (i.e. glGenTexture) and apply parameters
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID, GL_TEXTURE_2D_ARRAY_EXT);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID, GL_TEXTURE_2D_ARRAY_EXT);
|
||||
textureObject->bind();
|
||||
applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT, state);
|
||||
_subloadCallback->load(*this,state);
|
||||
@@ -275,7 +275,7 @@ void Texture2DArray::apply(State& state) const
|
||||
|
||||
// create texture object
|
||||
textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
this, contextID,GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
|
||||
// bind texture
|
||||
textureObject->bind();
|
||||
@@ -325,7 +325,7 @@ void Texture2DArray::apply(State& state) const
|
||||
{
|
||||
// generate texture
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID, GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
this, contextID, GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
|
||||
textureObject->bind();
|
||||
applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
|
||||
|
||||
@@ -232,7 +232,7 @@ void Texture3D::apply(State& state) const
|
||||
else if (_subloadCallback.valid())
|
||||
{
|
||||
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_3D);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_3D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -258,7 +258,7 @@ void Texture3D::apply(State& state) const
|
||||
// compute the dimensions of the texture.
|
||||
computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _textureDepth,_numMipmapLevels);
|
||||
|
||||
textureObject = generateTextureObject(contextID,GL_TEXTURE_3D);
|
||||
textureObject = generateTextureObject(this, contextID,GL_TEXTURE_3D);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -284,7 +284,7 @@ void Texture3D::apply(State& state) const
|
||||
else if ( (_textureWidth!=0) && (_textureHeight!=0) && (_textureDepth!=0) && (_internalFormat!=0) )
|
||||
{
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_3D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
this, contextID,GL_TEXTURE_3D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ void TextureCubeMap::apply(State& state) const
|
||||
}
|
||||
else if (_subloadCallback.valid())
|
||||
{
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_CUBE_MAP);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_CUBE_MAP);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -261,7 +261,7 @@ void TextureCubeMap::apply(State& state) const
|
||||
}
|
||||
|
||||
textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
this, contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -304,7 +304,7 @@ void TextureCubeMap::apply(State& state) const
|
||||
else if ( (_textureWidth!=0) && (_textureHeight!=0) && (_internalFormat!=0) )
|
||||
{
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
this, contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ void TextureRectangle::apply(State& state) const
|
||||
else if (_subloadCallback.valid())
|
||||
{
|
||||
// we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object.
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID,GL_TEXTURE_RECTANGLE);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_RECTANGLE);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -212,7 +212,7 @@ void TextureRectangle::apply(State& state) const
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex);
|
||||
|
||||
// we don't have a applyTexImage1D_subload yet so can't reuse.. so just generate a new texture object.
|
||||
textureObject = generateTextureObject(contextID,GL_TEXTURE_RECTANGLE);
|
||||
textureObject = generateTextureObject(this, contextID,GL_TEXTURE_RECTANGLE);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -235,7 +235,7 @@ void TextureRectangle::apply(State& state) const
|
||||
else if ( (_textureWidth!=0) && (_textureHeight!=0) && (_internalFormat!=0) )
|
||||
{
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_RECTANGLE,0,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
this, contextID,GL_TEXTURE_RECTANGLE,0,_internalFormat,_textureWidth,_textureHeight,1,0);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
@@ -460,8 +460,7 @@ void TextureRectangle::copyTexImage2D(State& state, int x, int y, int width, int
|
||||
|
||||
// switch off mip-mapping.
|
||||
//
|
||||
_textureObjectBuffer[contextID] = textureObject =
|
||||
generateTextureObject(contextID,GL_TEXTURE_RECTANGLE);
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(this, contextID,GL_TEXTURE_RECTANGLE);
|
||||
|
||||
textureObject->bind();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user