diff options
Diffstat (limited to 'indra/llmath/llvolumemgr.cpp')
-rw-r--r-- | indra/llmath/llvolumemgr.cpp | 816 |
1 files changed, 408 insertions, 408 deletions
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 06794fd23f..f796fbf551 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -1,408 +1,408 @@ -/** - * @file llvolumemgr.cpp - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llvolumemgr.h" -#include "llvolume.h" - - -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}; - - -//============================================================================ - -LLVolumeMgr::LLVolumeMgr() -: mDataMutex(NULL) -{ - // the LLMutex magic interferes with easy unit testing, - // so you now must manually call useMutex() to use it - //mDataMutex = new LLMutex(); -} - -LLVolumeMgr::~LLVolumeMgr() -{ - cleanup(); - - delete mDataMutex; - mDataMutex = NULL; -} - -bool LLVolumeMgr::cleanup() -{ - bool no_refs = true; - if (mDataMutex) - { - mDataMutex->lock(); - } - for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), - end = mVolumeLODGroups.end(); - iter != end; iter++) - { - LLVolumeLODGroup *volgroupp = iter->second; - if (!volgroupp->cleanupRefs()) - { - no_refs = false; - } - delete volgroupp; - } - mVolumeLODGroups.clear(); - if (mDataMutex) - { - mDataMutex->unlock(); - } - return no_refs; -} - -// Always only ever store the results of refVolume in a LLPointer -// Note however that LLVolumeLODGroup that contains the volume -// also holds a LLPointer so the volume will only go away after -// anything holding the volume and the LODGroup are destroyed -LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 lod) -{ - LLVolumeLODGroup* volgroupp; - if (mDataMutex) - { - mDataMutex->lock(); - } - volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); - if( iter == mVolumeLODGroups.end() ) - { - volgroupp = createNewGroup(volume_params); - } - else - { - volgroupp = iter->second; - } - if (mDataMutex) - { - mDataMutex->unlock(); - } - return volgroupp->refLOD(lod); -} - -// virtual -LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const -{ - LLVolumeLODGroup* volgroupp = NULL; - if (mDataMutex) - { - mDataMutex->lock(); - } - volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params); - if( iter != mVolumeLODGroups.end() ) - { - volgroupp = iter->second; - } - if (mDataMutex) - { - mDataMutex->unlock(); - } - return volgroupp; -} - -void LLVolumeMgr::unrefVolume(LLVolume *volumep) -{ - if (volumep->isUnique()) - { - // TomY: Don't need to manage this volume. It is a unique instance. - return; - } - const LLVolumeParams* params = &(volumep->getParams()); - if (mDataMutex) - { - mDataMutex->lock(); - } - volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); - if( iter == mVolumeLODGroups.end() ) - { - LL_ERRS() << "Warning! Tried to cleanup unknown volume type! " << *params << LL_ENDL; - if (mDataMutex) - { - mDataMutex->unlock(); - } - return; - } - else - { - LLVolumeLODGroup* volgroupp = iter->second; - - volgroupp->derefLOD(volumep); - if (volgroupp->getNumRefs() == 0) - { - mVolumeLODGroups.erase(params); - delete volgroupp; - } - } - if (mDataMutex) - { - mDataMutex->unlock(); - } - -} - -// protected -void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup) -{ - mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup; -} - -// protected -LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params) -{ - LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params); - insertGroup(volgroup); - return volgroup; -} - -// virtual -void LLVolumeMgr::dump() -{ - F32 avg = 0.f; - if (mDataMutex) - { - 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; - if (mDataMutex) - { - mDataMutex->unlock(); - } - LL_INFOS() << "Average usage of LODs " << avg << LL_ENDL; -} - -void LLVolumeMgr::useMutex() -{ - if (!mDataMutex) - { - mDataMutex = new LLMutex(); - } -} - -std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) -{ - s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; - - S32 total_refs = 0; - if (volume_mgr.mDataMutex) - { - volume_mgr.mDataMutex->lock(); - } - - for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin(); - iter != volume_mgr.mVolumeLODGroups.end(); ++iter) - { - LLVolumeLODGroup *volgroupp = iter->second; - total_refs += volgroupp->getNumRefs(); - s << ", " << (*volgroupp); - } - - if (volume_mgr.mDataMutex) - { - volume_mgr.mDataMutex->unlock(); - } - - s << ", total_refs=" << total_refs << " }"; - return s; -} - -LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms) - : mVolumeParams(params), - mRefs(0) -{ - for (S32 i = 0; i < NUM_LODS; i++) - { - mLODRefs[i] = 0; - mAccessCount[i] = 0; - } -} - -LLVolumeLODGroup::~LLVolumeLODGroup() -{ - for (S32 i = 0; i < NUM_LODS; i++) - { - llassert_always(mLODRefs[i] == 0); - } -} - -// Called from LLVolumeMgr::cleanup -bool LLVolumeLODGroup::cleanupRefs() -{ - bool res = true; - if (mRefs != 0) - { - LL_WARNS() << "Volume group has remaining refs:" << getNumRefs() << LL_ENDL; - mRefs = 0; - for (S32 i = 0; i < NUM_LODS; i++) - { - if (mLODRefs[i] > 0) - { - LL_WARNS() << " LOD " << i << " refs = " << mLODRefs[i] << LL_ENDL; - mLODRefs[i] = 0; - mVolumeLODs[i] = NULL; - } - } - LL_WARNS() << *getVolumeParams() << LL_ENDL; - res = false; - } - return res; -} - -LLVolume* LLVolumeLODGroup::refLOD(const S32 lod) -{ - llassert(lod >=0 && lod < NUM_LODS); - mAccessCount[lod]++; - - mRefs++; - if (mVolumeLODs[lod].isNull()) - { - mVolumeLODs[lod] = new LLVolume(mVolumeParams, mDetailScales[lod]); - } - mLODRefs[lod]++; - return mVolumeLODs[lod]; -} - -bool LLVolumeLODGroup::derefLOD(LLVolume *volumep) -{ - llassert_always(mRefs > 0); - mRefs--; - for (S32 i = 0; i < NUM_LODS; i++) - { - if (mVolumeLODs[i] == volumep) - { - llassert_always(mLODRefs[i] > 0); - mLODRefs[i]--; -#if 0 // SJB: Possible opt: keep other lods around - if (!mLODRefs[i]) - { - mVolumeLODs[i] = NULL; - } -#endif - return true; - } - } - LL_ERRS() << "Deref of non-matching LOD in volume LOD group" << LL_ENDL; - 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; -} - -void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher) -{ - S32 detail = getDetailFromTan(tan_angle); - - if (detail > 0) - { - to_lower = tan_angle - mDetailThresholds[detail]; - } - else - { - to_lower = 1024.f*1024.f; - } - - if (detail < NUM_LODS-1) - { - to_higher = mDetailThresholds[detail+1] - tan_angle; - } - else - { - to_higher = 1024.f*1024.f; - } -} - -F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail) -{ - return mDetailScales[detail]; -} - -S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail) -{ - for (S32 i = 1; i < 4; i++) - { - if (mDetailScales[i] > detail) - { - return i-1; - } - } - - return 3; -} - -F32 LLVolumeLODGroup::dump() -{ - F32 usage = 0.f; - for (S32 i = 0; i < NUM_LODS; i++) - { - if (mAccessCount[i] > 0) - { - usage += 1.f; - } - } - usage = usage / (F32)NUM_LODS; - - std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]); - - LL_INFOS() << dump_str << LL_ENDL; - return usage; -} - -std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup) -{ - s << "{ numRefs=" << volgroup.getNumRefs(); - s << ", mParams=" << volgroup.getVolumeParams(); - s << " }"; - - return s; -} - +/**
+ * @file llvolumemgr.cpp
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llvolumemgr.h"
+#include "llvolume.h"
+
+
+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};
+
+
+//============================================================================
+
+LLVolumeMgr::LLVolumeMgr()
+: mDataMutex(NULL)
+{
+ // the LLMutex magic interferes with easy unit testing,
+ // so you now must manually call useMutex() to use it
+ //mDataMutex = new LLMutex();
+}
+
+LLVolumeMgr::~LLVolumeMgr()
+{
+ cleanup();
+
+ delete mDataMutex;
+ mDataMutex = NULL;
+}
+
+bool LLVolumeMgr::cleanup()
+{
+ bool no_refs = true;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
+ end = mVolumeLODGroups.end();
+ iter != end; iter++)
+ {
+ LLVolumeLODGroup *volgroupp = iter->second;
+ if (!volgroupp->cleanupRefs())
+ {
+ no_refs = false;
+ }
+ delete volgroupp;
+ }
+ mVolumeLODGroups.clear();
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return no_refs;
+}
+
+// Always only ever store the results of refVolume in a LLPointer
+// Note however that LLVolumeLODGroup that contains the volume
+// also holds a LLPointer so the volume will only go away after
+// anything holding the volume and the LODGroup are destroyed
+LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 lod)
+{
+ LLVolumeLODGroup* volgroupp;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
+ if( iter == mVolumeLODGroups.end() )
+ {
+ volgroupp = createNewGroup(volume_params);
+ }
+ else
+ {
+ volgroupp = iter->second;
+ }
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return volgroupp->refLOD(lod);
+}
+
+// virtual
+LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const
+{
+ LLVolumeLODGroup* volgroupp = NULL;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params);
+ if( iter != mVolumeLODGroups.end() )
+ {
+ volgroupp = iter->second;
+ }
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return volgroupp;
+}
+
+void LLVolumeMgr::unrefVolume(LLVolume *volumep)
+{
+ if (volumep->isUnique())
+ {
+ // TomY: Don't need to manage this volume. It is a unique instance.
+ return;
+ }
+ const LLVolumeParams* params = &(volumep->getParams());
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
+ if( iter == mVolumeLODGroups.end() )
+ {
+ LL_ERRS() << "Warning! Tried to cleanup unknown volume type! " << *params << LL_ENDL;
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return;
+ }
+ else
+ {
+ LLVolumeLODGroup* volgroupp = iter->second;
+
+ volgroupp->derefLOD(volumep);
+ if (volgroupp->getNumRefs() == 0)
+ {
+ mVolumeLODGroups.erase(params);
+ delete volgroupp;
+ }
+ }
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+
+}
+
+// protected
+void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup)
+{
+ mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup;
+}
+
+// protected
+LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params)
+{
+ LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params);
+ insertGroup(volgroup);
+ return volgroup;
+}
+
+// virtual
+void LLVolumeMgr::dump()
+{
+ F32 avg = 0.f;
+ if (mDataMutex)
+ {
+ 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;
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ LL_INFOS() << "Average usage of LODs " << avg << LL_ENDL;
+}
+
+void LLVolumeMgr::useMutex()
+{
+ if (!mDataMutex)
+ {
+ mDataMutex = new LLMutex();
+ }
+}
+
+std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
+{
+ s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
+
+ S32 total_refs = 0;
+ if (volume_mgr.mDataMutex)
+ {
+ volume_mgr.mDataMutex->lock();
+ }
+
+ for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin();
+ iter != volume_mgr.mVolumeLODGroups.end(); ++iter)
+ {
+ LLVolumeLODGroup *volgroupp = iter->second;
+ total_refs += volgroupp->getNumRefs();
+ s << ", " << (*volgroupp);
+ }
+
+ if (volume_mgr.mDataMutex)
+ {
+ volume_mgr.mDataMutex->unlock();
+ }
+
+ s << ", total_refs=" << total_refs << " }";
+ return s;
+}
+
+LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms)
+ : mVolumeParams(params),
+ mRefs(0)
+{
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ mLODRefs[i] = 0;
+ mAccessCount[i] = 0;
+ }
+}
+
+LLVolumeLODGroup::~LLVolumeLODGroup()
+{
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ llassert_always(mLODRefs[i] == 0);
+ }
+}
+
+// Called from LLVolumeMgr::cleanup
+bool LLVolumeLODGroup::cleanupRefs()
+{
+ bool res = true;
+ if (mRefs != 0)
+ {
+ LL_WARNS() << "Volume group has remaining refs:" << getNumRefs() << LL_ENDL;
+ mRefs = 0;
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ if (mLODRefs[i] > 0)
+ {
+ LL_WARNS() << " LOD " << i << " refs = " << mLODRefs[i] << LL_ENDL;
+ mLODRefs[i] = 0;
+ mVolumeLODs[i] = NULL;
+ }
+ }
+ LL_WARNS() << *getVolumeParams() << LL_ENDL;
+ res = false;
+ }
+ return res;
+}
+
+LLVolume* LLVolumeLODGroup::refLOD(const S32 lod)
+{
+ llassert(lod >=0 && lod < NUM_LODS);
+ mAccessCount[lod]++;
+
+ mRefs++;
+ if (mVolumeLODs[lod].isNull())
+ {
+ mVolumeLODs[lod] = new LLVolume(mVolumeParams, mDetailScales[lod]);
+ }
+ mLODRefs[lod]++;
+ return mVolumeLODs[lod];
+}
+
+bool LLVolumeLODGroup::derefLOD(LLVolume *volumep)
+{
+ llassert_always(mRefs > 0);
+ mRefs--;
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ if (mVolumeLODs[i] == volumep)
+ {
+ llassert_always(mLODRefs[i] > 0);
+ mLODRefs[i]--;
+#if 0 // SJB: Possible opt: keep other lods around
+ if (!mLODRefs[i])
+ {
+ mVolumeLODs[i] = NULL;
+ }
+#endif
+ return true;
+ }
+ }
+ LL_ERRS() << "Deref of non-matching LOD in volume LOD group" << LL_ENDL;
+ 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;
+}
+
+void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher)
+{
+ S32 detail = getDetailFromTan(tan_angle);
+
+ if (detail > 0)
+ {
+ to_lower = tan_angle - mDetailThresholds[detail];
+ }
+ else
+ {
+ to_lower = 1024.f*1024.f;
+ }
+
+ if (detail < NUM_LODS-1)
+ {
+ to_higher = mDetailThresholds[detail+1] - tan_angle;
+ }
+ else
+ {
+ to_higher = 1024.f*1024.f;
+ }
+}
+
+F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
+{
+ return mDetailScales[detail];
+}
+
+S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail)
+{
+ for (S32 i = 1; i < 4; i++)
+ {
+ if (mDetailScales[i] > detail)
+ {
+ return i-1;
+ }
+ }
+
+ return 3;
+}
+
+F32 LLVolumeLODGroup::dump()
+{
+ F32 usage = 0.f;
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ if (mAccessCount[i] > 0)
+ {
+ usage += 1.f;
+ }
+ }
+ usage = usage / (F32)NUM_LODS;
+
+ std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
+
+ LL_INFOS() << dump_str << LL_ENDL;
+ return usage;
+}
+
+std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
+{
+ s << "{ numRefs=" << volgroup.getNumRefs();
+ s << ", mParams=" << volgroup.getVolumeParams();
+ s << " }";
+
+ return s;
+}
+
|