llvolumemgr.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 
00033 #include "llvolumemgr.h"
00034 #include "llvolume.h"
00035 
00036 
00037 //#define DEBUG_VOLUME
00038 
00039 LLVolumeMgr* gVolumeMgr = 0;
00040 
00041 const F32 BASE_THRESHOLD = 0.03f;
00042 
00043 //static
00044 F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
00045                                                                                                          2*BASE_THRESHOLD,
00046                                                                                                          8*BASE_THRESHOLD,
00047                                                                                                          100*BASE_THRESHOLD};
00048 
00049 //static
00050 F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
00051 
00052 //============================================================================
00053 //static
00054 void LLVolumeMgr::initClass()
00055 {
00056         gVolumeMgr = new LLVolumeMgr();
00057 }
00058 
00059 //static
00060 BOOL LLVolumeMgr::cleanupClass()
00061 {
00062         BOOL res = FALSE;
00063         if (gVolumeMgr) {
00064                 res = gVolumeMgr->cleanup();
00065                 delete gVolumeMgr;
00066                 gVolumeMgr = 0;
00067         }
00068         return res;
00069 }
00070 
00071 //============================================================================
00072 
00073 LLVolumeMgr::LLVolumeMgr()
00074 {
00075         mDataMutex = new LLMutex(gAPRPoolp);
00076 //      mNumVolumes = 0;
00077 }
00078 
00079 LLVolumeMgr::~LLVolumeMgr()
00080 {
00081         cleanup();
00082         delete mDataMutex;
00083 }
00084 
00085 BOOL LLVolumeMgr::cleanup()
00086 {
00087         #ifdef DEBUG_VOLUME
00088         {
00089                 lldebugs << "LLVolumeMgr::cleanup()" << llendl;
00090         }
00091         #endif
00092         BOOL no_refs = TRUE;
00093         mDataMutex->lock();
00094         for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
00095                          end = mVolumeLODGroups.end();
00096                  iter != end; iter++)
00097         {
00098                 LLVolumeLODGroup *volgroupp = iter->second;
00099                 if (volgroupp->getNumRefs() != 1)
00100                 {
00101                         llwarns << "Volume group " << volgroupp << " has " 
00102                                         << volgroupp->getNumRefs() << " remaining refs" << llendl;
00103                         llwarns << volgroupp->getParams() << llendl;
00104                         no_refs = FALSE;
00105                 }
00106                 volgroupp->unref();// this );
00107         }
00108         mVolumeLODGroups.clear();
00109         mDataMutex->unlock();
00110         return no_refs;
00111 }
00112 
00113 LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail)
00114 {
00115         LLVolumeLODGroup* volgroupp;
00116         mDataMutex->lock();
00117         volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
00118         if( iter == mVolumeLODGroups.end() )
00119         {
00120                 volgroupp = new LLVolumeLODGroup(volume_params);
00121                 const LLVolumeParams* params = &(volgroupp->getParams());
00122                 mVolumeLODGroups[params] = volgroupp;
00123                 volgroupp->ref(); // initial reference
00124         }
00125         else
00126         {
00127                 volgroupp = iter->second;
00128         }
00129         volgroupp->ref();// this );
00130         mDataMutex->unlock();
00131         //      mNumVolumes++;
00132         #ifdef DEBUG_VOLUME
00133         {
00134                 lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl;
00135         }
00136         #endif
00137         return volgroupp->getLOD(detail);
00138 }
00139 
00140 void LLVolumeMgr::cleanupVolume(LLVolume *volumep)
00141 {
00142         if (volumep->isUnique())
00143         {
00144                 // TomY: Don't need to manage this volume. It is a unique instance.
00145                 return;
00146         }
00147         LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams());
00148         mDataMutex->lock();
00149         volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
00150         if( iter == mVolumeLODGroups.end() )
00151         {
00152                 llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
00153                 mDataMutex->unlock();
00154                 return;
00155         }
00156         else
00157         {
00158                 LLVolumeLODGroup* volgroupp = iter->second;
00159 
00160                 volgroupp->derefLOD(volumep);
00161                 volgroupp->unref();// this );
00162                 if (volgroupp->getNumRefs() == 1)
00163                 {
00164                         mVolumeLODGroups.erase(params);
00165                         volgroupp->unref();// this );
00166                 }
00167                 //      mNumVolumes--;
00168         }
00169         mDataMutex->unlock();
00170 
00171         #ifdef DEBUG_VOLUME
00172         {
00173                 lldebugs << "LLVolumeMgr::cleanupVolume() " << (*this) << llendl;
00174         }
00175         #endif
00176 }
00177 
00178 void LLVolumeMgr::dump()
00179 {
00180         F32 avg = 0.f;
00181         mDataMutex->lock();
00182         for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
00183                          end = mVolumeLODGroups.end();
00184                  iter != end; iter++)
00185         {
00186                 LLVolumeLODGroup *volgroupp = iter->second;
00187                 avg += volgroupp->dump();
00188         }
00189         int count = (int)mVolumeLODGroups.size();
00190         avg = count ? avg / (F32)count : 0.0f;
00191         mDataMutex->unlock();
00192         llinfos << "Average usage of LODs " << avg << llendl;
00193 }
00194 
00195 std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
00196 {
00197         s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
00198 
00199         S32 total_refs = 0;
00200         volume_mgr.mDataMutex->lock();
00201 
00202         LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin();
00203         LLVolumeMgr::volume_lod_group_map_iter end  = volume_mgr.mVolumeLODGroups.end();
00204         for ( ; iter != end; ++iter)
00205         {
00206                 LLVolumeLODGroup *volgroupp = iter->second;
00207                 total_refs += volgroupp->getNumRefs();
00208                 s << ", " << (*volgroupp);
00209         }
00210 
00211         volume_mgr.mDataMutex->unlock();
00212 
00213         s << ", total_refs=" << total_refs << " }";
00214         return s;
00215 }
00216 
00217 LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
00218 {
00219         S32 i;
00220         mParams = params;
00221 
00222         for (i = 0; i < NUM_LODS; i++)
00223         {
00224                 mLODRefs[i] = 0;
00225                 mVolumeLODs[i] = NULL;
00226                 mAccessCount[i] = 0;
00227         }
00228 }
00229 
00230 LLVolumeLODGroup::~LLVolumeLODGroup()
00231 {
00232         S32 i;
00233         for (i = 0; i < NUM_LODS; i++)
00234         {
00235                 delete mVolumeLODs[i];
00236                 mVolumeLODs[i] = NULL;
00237         }
00238 }
00239 
00240 
00241 LLVolume * LLVolumeLODGroup::getLOD(const S32 detail)
00242 {
00243         llassert(detail >=0 && detail < NUM_LODS);
00244         mAccessCount[detail]++;
00245         mLODRefs[detail]++;
00246         if (!mVolumeLODs[detail])
00247         {
00248                 mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]);
00249         }
00250         return mVolumeLODs[detail];
00251 }
00252 
00253 BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
00254 {
00255         S32 i;
00256         for (i = 0; i < NUM_LODS; i++)
00257         {
00258                 if (mVolumeLODs[i] == volumep)
00259                 {
00260                         mLODRefs[i]--;
00261                         if (!mLODRefs[i])
00262                         {
00263                                 mVolumeLODs[i] = NULL;
00264                         }
00265                         return TRUE;
00266                 }
00267         }
00268         llerrs << "Deref of non-matching LOD in volume LOD group" << llendl;
00269         return FALSE;
00270 }
00271 
00272 S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
00273 {
00274         S32 i = 0;
00275         while (i < (NUM_LODS - 1))
00276         {
00277                 if (tan_angle <= mDetailThresholds[i])
00278                 {
00279                         return i;
00280                 }
00281                 i++;
00282         }
00283         return NUM_LODS - 1;
00284 }
00285 
00286 F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
00287 {
00288         return mDetailScales[detail];
00289 }
00290 
00291 F32 LLVolumeLODGroup::dump()
00292 {
00293         char dump_str[255];             /* Flawfinder: ignore */
00294         F32 usage = 0.f;
00295         for (S32 i = 0; i < NUM_LODS; i++)
00296         {
00297                 if (mAccessCount[i] > 0)
00298                 {
00299                         usage += 1.f;
00300                 }
00301         }
00302         usage = usage / (F32)NUM_LODS;
00303 
00304         snprintf(dump_str, sizeof(dump_str), "%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);    /* Flawfinder: ignore */
00305 
00306         llinfos << dump_str << llendl;
00307         return usage;
00308 }
00309 
00310 std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
00311 {
00312         s << "{ numRefs=" << volgroup.getNumRefs();
00313         s << ", mParams=" << volgroup.mParams;
00314         s << " }";
00315          
00316         return s;
00317 }
00318 

Generated on Thu Jul 1 06:09:41 2010 for Second Life Viewer by  doxygen 1.4.7