aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llvolumemgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmath/llvolumemgr.cpp')
-rw-r--r--linden/indra/llmath/llvolumemgr.cpp314
1 files changed, 314 insertions, 0 deletions
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 @@
1/**
2 * @file llvolumemgr.cpp
3 *
4 * Copyright (c) 2002-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28
29#include "llvolumemgr.h"
30#include "llvolume.h"
31
32
33//#define DEBUG_VOLUME
34
35LLVolumeMgr* gVolumeMgr = 0;
36
37const F32 BASE_THRESHOLD = 0.03f;
38
39//static
40F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
41 2*BASE_THRESHOLD,
42 8*BASE_THRESHOLD,
43 100*BASE_THRESHOLD};
44
45//static
46F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
47
48//============================================================================
49//static
50void LLVolumeMgr::initClass()
51{
52 gVolumeMgr = new LLVolumeMgr();
53}
54
55//static
56BOOL LLVolumeMgr::cleanupClass()
57{
58 BOOL res = FALSE;
59 if (gVolumeMgr) {
60 res = gVolumeMgr->cleanup();
61 delete gVolumeMgr;
62 gVolumeMgr = 0;
63 }
64 return res;
65}
66
67//============================================================================
68
69LLVolumeMgr::LLVolumeMgr()
70{
71 mDataMutex = new LLMutex(gAPRPoolp);
72// mNumVolumes = 0;
73}
74
75LLVolumeMgr::~LLVolumeMgr()
76{
77 cleanup();
78 delete mDataMutex;
79}
80
81BOOL LLVolumeMgr::cleanup()
82{
83 #ifdef DEBUG_VOLUME
84 {
85 lldebugs << "LLVolumeMgr::cleanup()" << llendl;
86 }
87 #endif
88 BOOL no_refs = TRUE;
89 mDataMutex->lock();
90 for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
91 end = mVolumeLODGroups.end();
92 iter != end; iter++)
93 {
94 LLVolumeLODGroup *volgroupp = iter->second;
95 if (volgroupp->getNumRefs() != 1)
96 {
97 llwarns << "Volume group " << volgroupp << " has "
98 << volgroupp->getNumRefs() << " remaining refs" << llendl;
99 llwarns << volgroupp->getParams() << llendl;
100 no_refs = FALSE;
101 }
102 volgroupp->unref();// this );
103 }
104 mVolumeLODGroups.clear();
105 mDataMutex->unlock();
106 return no_refs;
107}
108
109LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail)
110{
111 LLVolumeLODGroup* volgroupp;
112 mDataMutex->lock();
113 volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
114 if( iter == mVolumeLODGroups.end() )
115 {
116 volgroupp = new LLVolumeLODGroup(volume_params);
117 const LLVolumeParams* params = &(volgroupp->getParams());
118 mVolumeLODGroups[params] = volgroupp;
119 volgroupp->ref(); // initial reference
120 }
121 else
122 {
123 volgroupp = iter->second;
124 }
125 volgroupp->ref();// this );
126 mDataMutex->unlock();
127 // mNumVolumes++;
128 #ifdef DEBUG_VOLUME
129 {
130 lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl;
131 }
132 #endif
133 return volgroupp->getLOD(detail);
134}
135
136void LLVolumeMgr::cleanupVolume(LLVolume *volumep)
137{
138 if (volumep->isUnique())
139 {
140 // TomY: Don't need to manage this volume. It is a unique instance.
141 return;
142 }
143 LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams());
144 mDataMutex->lock();
145 volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
146 if( iter == mVolumeLODGroups.end() )
147 {
148 llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
149 mDataMutex->unlock();
150 return;
151 }
152 else
153 {
154 LLVolumeLODGroup* volgroupp = iter->second;
155
156 volgroupp->derefLOD(volumep);
157 volgroupp->unref();// this );
158 if (volgroupp->getNumRefs() == 1)
159 {
160 mVolumeLODGroups.erase(params);
161 volgroupp->unref();// this );
162 }
163 // mNumVolumes--;
164 }
165 mDataMutex->unlock();
166
167 #ifdef DEBUG_VOLUME
168 {
169 lldebugs << "LLVolumeMgr::cleanupVolume() " << (*this) << llendl;
170 }
171 #endif
172}
173
174void LLVolumeMgr::dump()
175{
176 F32 avg = 0.f;
177 mDataMutex->lock();
178 for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
179 end = mVolumeLODGroups.end();
180 iter != end; iter++)
181 {
182 LLVolumeLODGroup *volgroupp = iter->second;
183 avg += volgroupp->dump();
184 }
185 int count = (int)mVolumeLODGroups.size();
186 avg = count ? avg / (F32)count : 0.0f;
187 mDataMutex->unlock();
188 llinfos << "Average usage of LODs " << avg << llendl;
189}
190
191std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
192{
193 s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
194
195 S32 total_refs = 0;
196 volume_mgr.mDataMutex->lock();
197
198 LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin();
199 LLVolumeMgr::volume_lod_group_map_iter end = volume_mgr.mVolumeLODGroups.end();
200 for ( ; iter != end; ++iter)
201 {
202 LLVolumeLODGroup *volgroupp = iter->second;
203 total_refs += volgroupp->getNumRefs();
204 s << ", " << (*volgroupp);
205 }
206
207 volume_mgr.mDataMutex->unlock();
208
209 s << ", total_refs=" << total_refs << " }";
210 return s;
211}
212
213LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
214{
215 S32 i;
216 mParams = params;
217
218 for (i = 0; i < NUM_LODS; i++)
219 {
220 mLODRefs[i] = 0;
221 mVolumeLODs[i] = NULL;
222 mAccessCount[i] = 0;
223 }
224}
225
226LLVolumeLODGroup::~LLVolumeLODGroup()
227{
228 S32 i;
229 for (i = 0; i < NUM_LODS; i++)
230 {
231 delete mVolumeLODs[i];
232 mVolumeLODs[i] = NULL;
233 }
234}
235
236
237LLVolume * LLVolumeLODGroup::getLOD(const S32 detail)
238{
239 llassert(detail >=0 && detail < NUM_LODS);
240 mAccessCount[detail]++;
241 mLODRefs[detail]++;
242 if (!mVolumeLODs[detail])
243 {
244 mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]);
245 }
246 return mVolumeLODs[detail];
247}
248
249BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
250{
251 S32 i;
252 for (i = 0; i < NUM_LODS; i++)
253 {
254 if (mVolumeLODs[i] == volumep)
255 {
256 mLODRefs[i]--;
257 if (!mLODRefs[i])
258 {
259 mVolumeLODs[i] = NULL;
260 }
261 return TRUE;
262 }
263 }
264 llerrs << "Deref of non-matching LOD in volume LOD group" << llendl;
265 return FALSE;
266}
267
268S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
269{
270 S32 i = 0;
271 while (i < (NUM_LODS - 1))
272 {
273 if (tan_angle <= mDetailThresholds[i])
274 {
275 return i;
276 }
277 i++;
278 }
279 return NUM_LODS - 1;
280}
281
282F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
283{
284 return mDetailScales[detail];
285}
286
287F32 LLVolumeLODGroup::dump()
288{
289 char dump_str[255];
290 F32 usage = 0.f;
291 for (S32 i = 0; i < NUM_LODS; i++)
292 {
293 if (mAccessCount[i] > 0)
294 {
295 usage += 1.f;
296 }
297 }
298 usage = usage / (F32)NUM_LODS;
299
300 sprintf(dump_str, "%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
301
302 llinfos << dump_str << llendl;
303 return usage;
304}
305
306std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
307{
308 s << "{ numRefs=" << volgroup.getNumRefs();
309 s << ", mParams=" << volgroup.mParams;
310 s << " }";
311
312 return s;
313}
314