From 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:46 -0500 Subject: Second Life viewer sources 1.13.2.12 --- linden/indra/llmath/llvolumemgr.cpp | 314 ++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 linden/indra/llmath/llvolumemgr.cpp (limited to 'linden/indra/llmath/llvolumemgr.cpp') diff --git a/linden/indra/llmath/llvolumemgr.cpp b/linden/indra/llmath/llvolumemgr.cpp new file mode 100644 index 0000000..6b6182a --- /dev/null +++ b/linden/indra/llmath/llvolumemgr.cpp @@ -0,0 +1,314 @@ +/** + * @file llvolumemgr.cpp + * + * Copyright (c) 2002-2007, Linden Research, Inc. + * + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#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; +} + -- cgit v1.1