diff options
Diffstat (limited to 'linden/indra/llmath/llvolumemgr.cpp')
-rw-r--r-- | linden/indra/llmath/llvolumemgr.cpp | 314 |
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 | |||
35 | LLVolumeMgr* gVolumeMgr = 0; | ||
36 | |||
37 | const F32 BASE_THRESHOLD = 0.03f; | ||
38 | |||
39 | //static | ||
40 | F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD, | ||
41 | 2*BASE_THRESHOLD, | ||
42 | 8*BASE_THRESHOLD, | ||
43 | 100*BASE_THRESHOLD}; | ||
44 | |||
45 | //static | ||
46 | F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; | ||
47 | |||
48 | //============================================================================ | ||
49 | //static | ||
50 | void LLVolumeMgr::initClass() | ||
51 | { | ||
52 | gVolumeMgr = new LLVolumeMgr(); | ||
53 | } | ||
54 | |||
55 | //static | ||
56 | BOOL 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 | |||
69 | LLVolumeMgr::LLVolumeMgr() | ||
70 | { | ||
71 | mDataMutex = new LLMutex(gAPRPoolp); | ||
72 | // mNumVolumes = 0; | ||
73 | } | ||
74 | |||
75 | LLVolumeMgr::~LLVolumeMgr() | ||
76 | { | ||
77 | cleanup(); | ||
78 | delete mDataMutex; | ||
79 | } | ||
80 | |||
81 | BOOL 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 | |||
109 | LLVolume *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 | |||
136 | void 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 | |||
174 | void 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 | |||
191 | std::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 | |||
213 | LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms) | ||
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 | |||
226 | LLVolumeLODGroup::~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 | |||
237 | LLVolume * 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 | |||
249 | BOOL 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 | |||
268 | S32 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 | |||
282 | F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail) | ||
283 | { | ||
284 | return mDetailScales[detail]; | ||
285 | } | ||
286 | |||
287 | F32 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 | |||
306 | std::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 | |||