296 lines
6.1 KiB
C++
296 lines
6.1 KiB
C++
/**
|
|
* @file llvolumemgr.cpp
|
|
*
|
|
* Copyright (c) 2002-$CurrentYear$, Linden Research, Inc.
|
|
* $License$
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
|
|
#include "llvolumemgr.h"
|
|
#include "llvolume.h"
|
|
|
|
|
|
//#define DEBUG_VOLUME
|
|
|
|
LLVolumeMgr* gVolumeMgr = 0;
|
|
|
|
const F32 BASE_THRESHOLD = 0.03f;
|
|
|
|
//static
|
|
F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
|
|
2*BASE_THRESHOLD,
|
|
8*BASE_THRESHOLD,
|
|
100*BASE_THRESHOLD};
|
|
|
|
//static
|
|
F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
|
|
|
|
//============================================================================
|
|
//static
|
|
void LLVolumeMgr::initClass()
|
|
{
|
|
gVolumeMgr = new LLVolumeMgr();
|
|
}
|
|
|
|
//static
|
|
BOOL LLVolumeMgr::cleanupClass()
|
|
{
|
|
BOOL res = FALSE;
|
|
if (gVolumeMgr) {
|
|
res = gVolumeMgr->cleanup();
|
|
delete gVolumeMgr;
|
|
gVolumeMgr = 0;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
//============================================================================
|
|
|
|
LLVolumeMgr::LLVolumeMgr()
|
|
{
|
|
mDataMutex = new LLMutex(gAPRPoolp);
|
|
// mNumVolumes = 0;
|
|
}
|
|
|
|
LLVolumeMgr::~LLVolumeMgr()
|
|
{
|
|
cleanup();
|
|
delete mDataMutex;
|
|
}
|
|
|
|
BOOL LLVolumeMgr::cleanup()
|
|
{
|
|
#ifdef DEBUG_VOLUME
|
|
{
|
|
lldebugs << "LLVolumeMgr::cleanup()" << llendl;
|
|
}
|
|
#endif
|
|
BOOL no_refs = TRUE;
|
|
mDataMutex->lock();
|
|
for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
|
|
end = mVolumeLODGroups.end();
|
|
iter != end; iter++)
|
|
{
|
|
LLVolumeLODGroup *volgroupp = iter->second;
|
|
if (volgroupp->getNumRefs() != 1)
|
|
{
|
|
llwarns << "Volume group " << volgroupp << " has "
|
|
<< volgroupp->getNumRefs() << " remaining refs" << llendl;
|
|
llwarns << volgroupp->getParams() << llendl;
|
|
no_refs = FALSE;
|
|
}
|
|
volgroupp->unref();// this );
|
|
}
|
|
mVolumeLODGroups.clear();
|
|
mDataMutex->unlock();
|
|
return no_refs;
|
|
}
|
|
|
|
LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail)
|
|
{
|
|
LLVolumeLODGroup* volgroupp;
|
|
mDataMutex->lock();
|
|
volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
|
|
if( iter == mVolumeLODGroups.end() )
|
|
{
|
|
volgroupp = new LLVolumeLODGroup(volume_params);
|
|
const LLVolumeParams* params = &(volgroupp->getParams());
|
|
mVolumeLODGroups[params] = volgroupp;
|
|
volgroupp->ref(); // initial reference
|
|
}
|
|
else
|
|
{
|
|
volgroupp = iter->second;
|
|
}
|
|
volgroupp->ref();// this );
|
|
mDataMutex->unlock();
|
|
// mNumVolumes++;
|
|
#ifdef DEBUG_VOLUME
|
|
{
|
|
lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl;
|
|
}
|
|
#endif
|
|
return volgroupp->getLOD(detail);
|
|
}
|
|
|
|
void LLVolumeMgr::cleanupVolume(LLVolume *volumep)
|
|
{
|
|
if (volumep->isUnique())
|
|
{
|
|
// TomY: Don't need to manage this volume. It is a unique instance.
|
|
return;
|
|
}
|
|
LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams());
|
|
mDataMutex->lock();
|
|
volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
|
|
if( iter == mVolumeLODGroups.end() )
|
|
{
|
|
llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
|
|
mDataMutex->unlock();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
LLVolumeLODGroup* volgroupp = iter->second;
|
|
|
|
volgroupp->derefLOD(volumep);
|
|
volgroupp->unref();// this );
|
|
if (volgroupp->getNumRefs() == 1)
|
|
{
|
|
mVolumeLODGroups.erase(params);
|
|
volgroupp->unref();// this );
|
|
}
|
|
// mNumVolumes--;
|
|
}
|
|
mDataMutex->unlock();
|
|
|
|
#ifdef DEBUG_VOLUME
|
|
{
|
|
lldebugs << "LLVolumeMgr::cleanupVolume() " << (*this) << llendl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void LLVolumeMgr::dump()
|
|
{
|
|
F32 avg = 0.f;
|
|
mDataMutex->lock();
|
|
for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
|
|
end = mVolumeLODGroups.end();
|
|
iter != end; iter++)
|
|
{
|
|
LLVolumeLODGroup *volgroupp = iter->second;
|
|
avg += volgroupp->dump();
|
|
}
|
|
int count = (int)mVolumeLODGroups.size();
|
|
avg = count ? avg / (F32)count : 0.0f;
|
|
mDataMutex->unlock();
|
|
llinfos << "Average usage of LODs " << avg << llendl;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
|
|
{
|
|
s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
|
|
|
|
S32 total_refs = 0;
|
|
volume_mgr.mDataMutex->lock();
|
|
|
|
LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin();
|
|
LLVolumeMgr::volume_lod_group_map_iter end = volume_mgr.mVolumeLODGroups.end();
|
|
for ( ; iter != end; ++iter)
|
|
{
|
|
LLVolumeLODGroup *volgroupp = iter->second;
|
|
total_refs += volgroupp->getNumRefs();
|
|
s << ", " << (*volgroupp);
|
|
}
|
|
|
|
volume_mgr.mDataMutex->unlock();
|
|
|
|
s << ", total_refs=" << total_refs << " }";
|
|
return s;
|
|
}
|
|
|
|
LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms)
|
|
{
|
|
S32 i;
|
|
mParams = params;
|
|
|
|
for (i = 0; i < NUM_LODS; i++)
|
|
{
|
|
mLODRefs[i] = 0;
|
|
mVolumeLODs[i] = NULL;
|
|
mAccessCount[i] = 0;
|
|
}
|
|
}
|
|
|
|
LLVolumeLODGroup::~LLVolumeLODGroup()
|
|
{
|
|
S32 i;
|
|
for (i = 0; i < NUM_LODS; i++)
|
|
{
|
|
delete mVolumeLODs[i];
|
|
mVolumeLODs[i] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
LLVolume * LLVolumeLODGroup::getLOD(const S32 detail)
|
|
{
|
|
llassert(detail >=0 && detail < NUM_LODS);
|
|
mAccessCount[detail]++;
|
|
mLODRefs[detail]++;
|
|
if (!mVolumeLODs[detail])
|
|
{
|
|
mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]);
|
|
}
|
|
return mVolumeLODs[detail];
|
|
}
|
|
|
|
BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
|
|
{
|
|
S32 i;
|
|
for (i = 0; i < NUM_LODS; i++)
|
|
{
|
|
if (mVolumeLODs[i] == volumep)
|
|
{
|
|
mLODRefs[i]--;
|
|
if (!mLODRefs[i])
|
|
{
|
|
mVolumeLODs[i] = NULL;
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
llerrs << "Deref of non-matching LOD in volume LOD group" << llendl;
|
|
return FALSE;
|
|
}
|
|
|
|
S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
|
|
{
|
|
S32 i = 0;
|
|
while (i < (NUM_LODS - 1))
|
|
{
|
|
if (tan_angle <= mDetailThresholds[i])
|
|
{
|
|
return i;
|
|
}
|
|
i++;
|
|
}
|
|
return NUM_LODS - 1;
|
|
}
|
|
|
|
F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
|
|
{
|
|
return mDetailScales[detail];
|
|
}
|
|
|
|
F32 LLVolumeLODGroup::dump()
|
|
{
|
|
char dump_str[255];
|
|
F32 usage = 0.f;
|
|
for (S32 i = 0; i < NUM_LODS; i++)
|
|
{
|
|
if (mAccessCount[i] > 0)
|
|
{
|
|
usage += 1.f;
|
|
}
|
|
}
|
|
usage = usage / (F32)NUM_LODS;
|
|
|
|
sprintf(dump_str, "%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
|
|
|
|
llinfos << dump_str << llendl;
|
|
return usage;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
|
|
{
|
|
s << "{ numRefs=" << volgroup.getNumRefs();
|
|
s << ", mParams=" << volgroup.mParams;
|
|
s << " }";
|
|
|
|
return s;
|
|
}
|
|
|