llvolumemgr.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 
00033 #include "llvolumemgr.h"
00034 #include "llmemtype.h"
00035 #include "llvolume.h"
00036 
00037 
00038 const F32 BASE_THRESHOLD = 0.03f;
00039 
00040 //static
00041 F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
00042                                                                                                          2*BASE_THRESHOLD,
00043                                                                                                          8*BASE_THRESHOLD,
00044                                                                                                          100*BASE_THRESHOLD};
00045 
00046 //static
00047 F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
00048 
00049 
00050 //============================================================================
00051 
00052 LLVolumeMgr::LLVolumeMgr()
00053 :       mDataMutex(NULL)
00054 {
00055         // the LLMutex magic interferes with easy unit testing,
00056         // so you now must manually call useMutex() to use it
00057         //mDataMutex = new LLMutex(gAPRPoolp);
00058 }
00059 
00060 LLVolumeMgr::~LLVolumeMgr()
00061 {
00062         cleanup();
00063 
00064         delete mDataMutex;
00065         mDataMutex = NULL;
00066 }
00067 
00068 BOOL LLVolumeMgr::cleanup()
00069 {
00070         BOOL no_refs = TRUE;
00071         if (mDataMutex)
00072         {
00073                 mDataMutex->lock();
00074         }
00075         for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
00076                          end = mVolumeLODGroups.end();
00077                  iter != end; iter++)
00078         {
00079                 LLVolumeLODGroup *volgroupp = iter->second;
00080                 if (volgroupp->cleanupRefs() == false)
00081                 {
00082                         no_refs = FALSE;
00083                 }
00084                 delete volgroupp;
00085         }
00086         mVolumeLODGroups.clear();
00087         if (mDataMutex)
00088         {
00089                 mDataMutex->unlock();
00090         }
00091         return no_refs;
00092 }
00093 
00094 // Always only ever store the results of refVolume in a LLPointer
00095 // Note however that LLVolumeLODGroup that contains the volume
00096 //  also holds a LLPointer so the volume will only go away after
00097 //  anything holding the volume and the LODGroup are destroyed
00098 LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 detail)
00099 {
00100         LLVolumeLODGroup* volgroupp;
00101         if (mDataMutex)
00102         {
00103                 mDataMutex->lock();
00104         }
00105         volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
00106         if( iter == mVolumeLODGroups.end() )
00107         {
00108                 volgroupp = createNewGroup(volume_params);
00109         }
00110         else
00111         {
00112                 volgroupp = iter->second;
00113         }
00114         if (mDataMutex)
00115         {
00116                 mDataMutex->unlock();
00117         }
00118         return volgroupp->getLODVolume(detail);
00119 }
00120 
00121 // virtual
00122 LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const
00123 {
00124         LLVolumeLODGroup* volgroupp = NULL;
00125         if (mDataMutex)
00126         {
00127                 mDataMutex->lock();
00128         }
00129         volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params);
00130         if( iter != mVolumeLODGroups.end() )
00131         {
00132                 volgroupp = iter->second;
00133         }
00134         if (mDataMutex)
00135         {
00136                 mDataMutex->unlock();
00137         }
00138         return volgroupp;
00139 }
00140 
00141 void LLVolumeMgr::unrefVolume(LLVolume *volumep)
00142 {
00143         if (volumep->isUnique())
00144         {
00145                 // TomY: Don't need to manage this volume. It is a unique instance.
00146                 return;
00147         }
00148         const LLVolumeParams* params = &(volumep->getParams());
00149         if (mDataMutex)
00150         {
00151                 mDataMutex->lock();
00152         }
00153         volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
00154         if( iter == mVolumeLODGroups.end() )
00155         {
00156                 llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
00157                 if (mDataMutex)
00158                 {
00159                         mDataMutex->unlock();
00160                 }
00161                 return;
00162         }
00163         else
00164         {
00165                 LLVolumeLODGroup* volgroupp = iter->second;
00166 
00167                 volgroupp->derefLOD(volumep);
00168                 if (volgroupp->getNumRefs() == 0)
00169                 {
00170                         mVolumeLODGroups.erase(params);
00171                         delete volgroupp;
00172                 }
00173         }
00174         if (mDataMutex)
00175         {
00176                 mDataMutex->unlock();
00177         }
00178 
00179 }
00180 
00181 // protected
00182 void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup)
00183 {
00184         mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup;
00185 }
00186 
00187 // protected
00188 LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params)
00189 {
00190         LLMemType m1(LLMemType::MTYPE_VOLUME);
00191         LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params);
00192         insertGroup(volgroup);
00193         return volgroup;
00194 }
00195 
00196 // virtual
00197 void LLVolumeMgr::dump()
00198 {
00199         F32 avg = 0.f;
00200         if (mDataMutex)
00201         {
00202                 mDataMutex->lock();
00203         }
00204         for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
00205                          end = mVolumeLODGroups.end();
00206                  iter != end; iter++)
00207         {
00208                 LLVolumeLODGroup *volgroupp = iter->second;
00209                 avg += volgroupp->dump();
00210         }
00211         int count = (int)mVolumeLODGroups.size();
00212         avg = count ? avg / (F32)count : 0.0f;
00213         if (mDataMutex)
00214         {
00215                 mDataMutex->unlock();
00216         }
00217         llinfos << "Average usage of LODs " << avg << llendl;
00218 }
00219 
00220 void LLVolumeMgr::useMutex()
00221 { 
00222         if (!mDataMutex)
00223         {
00224                 mDataMutex = new LLMutex(gAPRPoolp);
00225         }
00226 }
00227 
00228 std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
00229 {
00230         s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
00231 
00232         S32 total_refs = 0;
00233         if (volume_mgr.mDataMutex)
00234         {
00235                 volume_mgr.mDataMutex->lock();
00236         }
00237 
00238         for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin();
00239                  iter != volume_mgr.mVolumeLODGroups.end(); ++iter)
00240         {
00241                 LLVolumeLODGroup *volgroupp = iter->second;
00242                 total_refs += volgroupp->getNumRefs();
00243                 s << ", " << (*volgroupp);
00244         }
00245 
00246         if (volume_mgr.mDataMutex)
00247         {
00248                 volume_mgr.mDataMutex->unlock();
00249         }
00250 
00251         s << ", total_refs=" << total_refs << " }";
00252         return s;
00253 }
00254 
00255 LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
00256         : mVolumeParams(params),
00257           mRefs(0)
00258 {
00259         for (S32 i = 0; i < NUM_LODS; i++)
00260         {
00261                 mLODRefs[i] = 0;
00262                 mAccessCount[i] = 0;
00263         }
00264 }
00265 
00266 LLVolumeLODGroup::~LLVolumeLODGroup()
00267 {
00268         for (S32 i = 0; i < NUM_LODS; i++)
00269         {
00270                 llassert_always(mLODRefs[i] == 0);
00271         }
00272 }
00273 
00274 // Called from LLVolumeMgr::cleanup
00275 bool LLVolumeLODGroup::cleanupRefs()
00276 {
00277         bool res = true;
00278         if (mRefs != 0)
00279         {
00280                 llwarns << "Volume group has remaining refs:" << getNumRefs() << llendl;
00281                 mRefs = 0;
00282                 for (S32 i = 0; i < NUM_LODS; i++)
00283                 {
00284                         if (mLODRefs[i] > 0)
00285                         {
00286                                 llwarns << " LOD " << i << " refs = " << mLODRefs[i] << llendl;
00287                                 mLODRefs[i] = 0;
00288                                 mVolumeLODs[i] = NULL;
00289                         }
00290                 }
00291                 llwarns << *getVolumeParams() << llendl;
00292                 res = false;
00293         }
00294         return res;
00295 }
00296 
00297 LLVolume* LLVolumeLODGroup::getLODVolume(const S32 detail)
00298 {
00299         llassert(detail >=0 && detail < NUM_LODS);
00300         mAccessCount[detail]++;
00301         
00302         mRefs++;
00303         if (mVolumeLODs[detail].isNull())
00304         {
00305                 LLMemType m1(LLMemType::MTYPE_VOLUME);
00306                 mVolumeLODs[detail] = new LLVolume(mVolumeParams, mDetailScales[detail]);
00307         }
00308         mLODRefs[detail]++;
00309         return mVolumeLODs[detail];
00310 }
00311 
00312 BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
00313 {
00314         llassert_always(mRefs > 0);
00315         mRefs--;
00316         for (S32 i = 0; i < NUM_LODS; i++)
00317         {
00318                 if (mVolumeLODs[i] == volumep)
00319                 {
00320                         llassert_always(mLODRefs[i] > 0);
00321                         mLODRefs[i]--;
00322 #if 1 // SJB: Possible opt: keep other lods around
00323                         if (!mLODRefs[i])
00324                         {
00325                                 mVolumeLODs[i] = NULL;
00326                         }
00327 #endif
00328                         return TRUE;
00329                 }
00330         }
00331         llerrs << "Deref of non-matching LOD in volume LOD group" << llendl;
00332         return FALSE;
00333 }
00334 
00335 S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
00336 {
00337         S32 i = 0;
00338         while (i < (NUM_LODS - 1))
00339         {
00340                 if (tan_angle <= mDetailThresholds[i])
00341                 {
00342                         return i;
00343                 }
00344                 i++;
00345         }
00346         return NUM_LODS - 1;
00347 }
00348 
00349 void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher)
00350 {
00351         S32 detail = getDetailFromTan(tan_angle);
00352         
00353         if (detail > 0)
00354         {
00355                 to_lower = tan_angle - mDetailThresholds[detail];
00356         }
00357         else
00358         {
00359                 to_lower = 1024.f*1024.f;
00360         }
00361 
00362         if (detail < NUM_LODS-1)
00363         {
00364                 to_higher = mDetailThresholds[detail+1] - tan_angle;
00365         }
00366         else
00367         {
00368                 to_higher = 1024.f*1024.f;
00369         }
00370 }
00371 
00372 F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
00373 {
00374         return mDetailScales[detail];
00375 }
00376 
00377 F32 LLVolumeLODGroup::dump()
00378 {
00379         char dump_str[255];             /* Flawfinder: ignore */
00380         F32 usage = 0.f;
00381         for (S32 i = 0; i < NUM_LODS; i++)
00382         {
00383                 if (mAccessCount[i] > 0)
00384                 {
00385                         usage += 1.f;
00386                 }
00387         }
00388         usage = usage / (F32)NUM_LODS;
00389 
00390         snprintf(dump_str, sizeof(dump_str), "%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);    /* Flawfinder: ignore */
00391 
00392         llinfos << dump_str << llendl;
00393         return usage;
00394 }
00395 
00396 std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
00397 {
00398         s << "{ numRefs=" << volgroup.getNumRefs();
00399         s << ", mParams=" << volgroup.getVolumeParams();
00400         s << " }";
00401          
00402         return s;
00403 }
00404 

Generated on Fri May 16 08:32:18 2008 for SecondLife by  doxygen 1.5.5