summaryrefslogtreecommitdiff
path: root/indra/llmath/llvolumemgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmath/llvolumemgr.cpp')
-rw-r--r--indra/llmath/llvolumemgr.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp
new file mode 100644
index 0000000000..54be916c12
--- /dev/null
+++ b/indra/llmath/llvolumemgr.cpp
@@ -0,0 +1,295 @@
+/**
+ * @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 &params)
+{
+ 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;
+}
+