llvolumemgr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llvolumemgr.cpp
  3.  *
  4.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2002-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21.  * 
  22.  * By copying, modifying or distributing this software, you acknowledge
  23.  * that you have read and understood your obligations described above,
  24.  * and agree to abide by those obligations.
  25.  * 
  26.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28.  * COMPLETENESS OR PERFORMANCE.
  29.  * $/LicenseInfo$
  30.  */
  31. #include "linden_common.h"
  32. #include "llvolumemgr.h"
  33. #include "llmemtype.h"
  34. #include "llvolume.h"
  35. const F32 BASE_THRESHOLD = 0.03f;
  36. //static
  37. F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
  38.  2*BASE_THRESHOLD,
  39.  8*BASE_THRESHOLD,
  40.  100*BASE_THRESHOLD};
  41. //static
  42. F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
  43. //============================================================================
  44. LLVolumeMgr::LLVolumeMgr()
  45. : mDataMutex(NULL)
  46. {
  47. // the LLMutex magic interferes with easy unit testing,
  48. // so you now must manually call useMutex() to use it
  49. //mDataMutex = new LLMutex(gAPRPoolp);
  50. }
  51. LLVolumeMgr::~LLVolumeMgr()
  52. {
  53. cleanup();
  54. delete mDataMutex;
  55. mDataMutex = NULL;
  56. }
  57. BOOL LLVolumeMgr::cleanup()
  58. {
  59. BOOL no_refs = TRUE;
  60. if (mDataMutex)
  61. {
  62. mDataMutex->lock();
  63. }
  64. for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
  65.  end = mVolumeLODGroups.end();
  66.  iter != end; iter++)
  67. {
  68. LLVolumeLODGroup *volgroupp = iter->second;
  69. if (volgroupp->cleanupRefs() == false)
  70. {
  71. no_refs = FALSE;
  72. }
  73.   delete volgroupp;
  74. }
  75. mVolumeLODGroups.clear();
  76. if (mDataMutex)
  77. {
  78. mDataMutex->unlock();
  79. }
  80. return no_refs;
  81. }
  82. // Always only ever store the results of refVolume in a LLPointer
  83. // Note however that LLVolumeLODGroup that contains the volume
  84. //  also holds a LLPointer so the volume will only go away after
  85. //  anything holding the volume and the LODGroup are destroyed
  86. LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 detail)
  87. {
  88. LLVolumeLODGroup* volgroupp;
  89. if (mDataMutex)
  90. {
  91. mDataMutex->lock();
  92. }
  93. volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
  94. if( iter == mVolumeLODGroups.end() )
  95. {
  96. volgroupp = createNewGroup(volume_params);
  97. }
  98. else
  99. {
  100. volgroupp = iter->second;
  101. }
  102. if (mDataMutex)
  103. {
  104. mDataMutex->unlock();
  105. }
  106. return volgroupp->refLOD(detail);
  107. }
  108. // virtual
  109. LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const
  110. {
  111. LLVolumeLODGroup* volgroupp = NULL;
  112. if (mDataMutex)
  113. {
  114. mDataMutex->lock();
  115. }
  116. volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params);
  117. if( iter != mVolumeLODGroups.end() )
  118. {
  119. volgroupp = iter->second;
  120. }
  121. if (mDataMutex)
  122. {
  123. mDataMutex->unlock();
  124. }
  125. return volgroupp;
  126. }
  127. void LLVolumeMgr::unrefVolume(LLVolume *volumep)
  128. {
  129. if (volumep->isUnique())
  130. {
  131. // TomY: Don't need to manage this volume. It is a unique instance.
  132. return;
  133. }
  134. const LLVolumeParams* params = &(volumep->getParams());
  135. if (mDataMutex)
  136. {
  137. mDataMutex->lock();
  138. }
  139. volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
  140. if( iter == mVolumeLODGroups.end() )
  141. {
  142. llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
  143. if (mDataMutex)
  144. {
  145. mDataMutex->unlock();
  146. }
  147. return;
  148. }
  149. else
  150. {
  151. LLVolumeLODGroup* volgroupp = iter->second;
  152. volgroupp->derefLOD(volumep);
  153. if (volgroupp->getNumRefs() == 0)
  154. {
  155. mVolumeLODGroups.erase(params);
  156. delete volgroupp;
  157. }
  158. }
  159. if (mDataMutex)
  160. {
  161. mDataMutex->unlock();
  162. }
  163. }
  164. // protected
  165. void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup)
  166. {
  167. mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup;
  168. }
  169. // protected
  170. LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params)
  171. {
  172. LLMemType m1(LLMemType::MTYPE_VOLUME);
  173. LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params);
  174. insertGroup(volgroup);
  175. return volgroup;
  176. }
  177. // virtual
  178. void LLVolumeMgr::dump()
  179. {
  180. F32 avg = 0.f;
  181. if (mDataMutex)
  182. {
  183. mDataMutex->lock();
  184. }
  185. for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
  186.  end = mVolumeLODGroups.end();
  187.  iter != end; iter++)
  188. {
  189. LLVolumeLODGroup *volgroupp = iter->second;
  190. avg += volgroupp->dump();
  191. }
  192. int count = (int)mVolumeLODGroups.size();
  193. avg = count ? avg / (F32)count : 0.0f;
  194. if (mDataMutex)
  195. {
  196. mDataMutex->unlock();
  197. }
  198. llinfos << "Average usage of LODs " << avg << llendl;
  199. }
  200. void LLVolumeMgr::useMutex()
  201. if (!mDataMutex)
  202. {
  203. mDataMutex = new LLMutex(gAPRPoolp);
  204. }
  205. }
  206. std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
  207. {
  208. s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
  209. S32 total_refs = 0;
  210. if (volume_mgr.mDataMutex)
  211. {
  212. volume_mgr.mDataMutex->lock();
  213. }
  214. for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin();
  215.  iter != volume_mgr.mVolumeLODGroups.end(); ++iter)
  216. {
  217. LLVolumeLODGroup *volgroupp = iter->second;
  218. total_refs += volgroupp->getNumRefs();
  219. s << ", " << (*volgroupp);
  220. }
  221. if (volume_mgr.mDataMutex)
  222. {
  223. volume_mgr.mDataMutex->unlock();
  224. }
  225. s << ", total_refs=" << total_refs << " }";
  226. return s;
  227. }
  228. LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
  229. : mVolumeParams(params),
  230.   mRefs(0)
  231. {
  232. for (S32 i = 0; i < NUM_LODS; i++)
  233. {
  234. mLODRefs[i] = 0;
  235. mAccessCount[i] = 0;
  236. }
  237. }
  238. LLVolumeLODGroup::~LLVolumeLODGroup()
  239. {
  240. for (S32 i = 0; i < NUM_LODS; i++)
  241. {
  242. llassert_always(mLODRefs[i] == 0);
  243. }
  244. }
  245. // Called from LLVolumeMgr::cleanup
  246. bool LLVolumeLODGroup::cleanupRefs()
  247. {
  248. bool res = true;
  249. if (mRefs != 0)
  250. {
  251. llwarns << "Volume group has remaining refs:" << getNumRefs() << llendl;
  252. mRefs = 0;
  253. for (S32 i = 0; i < NUM_LODS; i++)
  254. {
  255. if (mLODRefs[i] > 0)
  256. {
  257. llwarns << " LOD " << i << " refs = " << mLODRefs[i] << llendl;
  258. mLODRefs[i] = 0;
  259. mVolumeLODs[i] = NULL;
  260. }
  261. }
  262. llwarns << *getVolumeParams() << llendl;
  263. res = false;
  264. }
  265. return res;
  266. }
  267. LLVolume* LLVolumeLODGroup::refLOD(const S32 detail)
  268. {
  269. llassert(detail >=0 && detail < NUM_LODS);
  270. mAccessCount[detail]++;
  271. mRefs++;
  272. if (mVolumeLODs[detail].isNull())
  273. {
  274. LLMemType m1(LLMemType::MTYPE_VOLUME);
  275. mVolumeLODs[detail] = new LLVolume(mVolumeParams, mDetailScales[detail]);
  276. }
  277. mLODRefs[detail]++;
  278. return mVolumeLODs[detail];
  279. }
  280. BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
  281. {
  282. llassert_always(mRefs > 0);
  283. mRefs--;
  284. for (S32 i = 0; i < NUM_LODS; i++)
  285. {
  286. if (mVolumeLODs[i] == volumep)
  287. {
  288. llassert_always(mLODRefs[i] > 0);
  289. mLODRefs[i]--;
  290. #if 1 // SJB: Possible opt: keep other lods around
  291. if (!mLODRefs[i])
  292. {
  293. mVolumeLODs[i] = NULL;
  294. }
  295. #endif
  296. return TRUE;
  297. }
  298. }
  299. llerrs << "Deref of non-matching LOD in volume LOD group" << llendl;
  300. return FALSE;
  301. }
  302. S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
  303. {
  304. S32 i = 0;
  305. while (i < (NUM_LODS - 1))
  306. {
  307. if (tan_angle <= mDetailThresholds[i])
  308. {
  309. return i;
  310. }
  311. i++;
  312. }
  313. return NUM_LODS - 1;
  314. }
  315. void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher)
  316. {
  317. S32 detail = getDetailFromTan(tan_angle);
  318. if (detail > 0)
  319. {
  320. to_lower = tan_angle - mDetailThresholds[detail];
  321. }
  322. else
  323. {
  324. to_lower = 1024.f*1024.f;
  325. }
  326. if (detail < NUM_LODS-1)
  327. {
  328. to_higher = mDetailThresholds[detail+1] - tan_angle;
  329. }
  330. else
  331. {
  332. to_higher = 1024.f*1024.f;
  333. }
  334. }
  335. F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
  336. {
  337. return mDetailScales[detail];
  338. }
  339. F32 LLVolumeLODGroup::dump()
  340. {
  341. F32 usage = 0.f;
  342. for (S32 i = 0; i < NUM_LODS; i++)
  343. {
  344. if (mAccessCount[i] > 0)
  345. {
  346. usage += 1.f;
  347. }
  348. }
  349. usage = usage / (F32)NUM_LODS;
  350. std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
  351. llinfos << dump_str << llendl;
  352. return usage;
  353. }
  354. std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
  355. {
  356. s << "{ numRefs=" << volgroup.getNumRefs();
  357. s << ", mParams=" << volgroup.getVolumeParams();
  358. s << " }";
  359.  
  360. return s;
  361. }