Panda3D
 All Classes Functions Variables Enumerations
textureStagePool.cxx
00001 // Filename: textureStagePool.cxx
00002 // Created by:  drose (03May10)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 
00016 #include "textureStagePool.h"
00017 #include "config_gobj.h"
00018 #include "mutexHolder.h"
00019 #include "configVariableEnum.h"
00020 
00021 TextureStagePool *TextureStagePool::_global_ptr = (TextureStagePool *)NULL;
00022 
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: TextureStagePool::write
00026 //       Access: Published, Static
00027 //  Description: Lists the contents of the TextureStage pool to the
00028 //               indicated output stream.
00029 ////////////////////////////////////////////////////////////////////
00030 void TextureStagePool::
00031 write(ostream &out) {
00032   get_global_ptr()->ns_list_contents(out);
00033 }
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: TextureStagePool::Constructor
00037 //       Access: Private
00038 //  Description: The constructor is not intended to be called
00039 //               directly; there's only supposed to be one TextureStagePool
00040 //               in the universe and it constructs itself.
00041 ////////////////////////////////////////////////////////////////////
00042 TextureStagePool::
00043 TextureStagePool() {
00044   ConfigVariableEnum<Mode> texture_stage_pool_mode
00045     ("texture-stage-pool-mode", M_none,
00046      PRC_DESC("Defines the initial value of TextureStagePool::set_mode().  "
00047               "Set this to 'none' to disable the use of the TextureStagePool, "
00048               "to 'name' to group TextureStages by name only, or 'unique' "
00049               "to group together only identical TextureStages."));
00050   _mode = texture_stage_pool_mode.get_value();
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: TextureStagePool::ns_get_stage
00055 //       Access: Public
00056 //  Description: The nonstatic implementation of get_stage().
00057 ////////////////////////////////////////////////////////////////////
00058 TextureStage *TextureStagePool::
00059 ns_get_stage(TextureStage *temp) {
00060   MutexHolder holder(_lock);
00061 
00062   switch (_mode) {
00063   case M_none:
00064     return temp;
00065 
00066   case M_name:
00067     {
00068       StagesByName::iterator ni = _stages_by_name.find(temp->get_name());
00069       if (ni == _stages_by_name.end()) {
00070         ni = _stages_by_name.insert(StagesByName::value_type(temp->get_name(), temp)).first;
00071       } else {
00072         if ((*ni).first != (*ni).second->get_name()) {
00073           // The pointer no longer matches the original name.  Save a
00074           // new one.
00075           (*ni).second = temp;
00076         }
00077       }
00078       return (*ni).second;
00079     }
00080 
00081   case M_unique:
00082     {
00083       CPT(TextureStage) cpttemp = temp;
00084       StagesByProperties::iterator si = _stages_by_properties.find(cpttemp);
00085       if (si == _stages_by_properties.end()) {
00086         si = _stages_by_properties.insert(StagesByProperties::value_type(new TextureStage(*temp), temp)).first;
00087       } else {
00088         if (*(*si).first != *(*si).second) {
00089           // The pointer no longer matches its original value.  Save a new
00090           // one.
00091           (*si).second = temp;
00092         }
00093       }
00094       return (*si).second;
00095     }
00096   }
00097 
00098   return NULL;
00099 }
00100 
00101 ////////////////////////////////////////////////////////////////////
00102 //     Function: TextureStagePool::ns_release_stage
00103 //       Access: Private
00104 //  Description: The nonstatic implementation of release_stage().
00105 ////////////////////////////////////////////////////////////////////
00106 void TextureStagePool::
00107 ns_release_stage(TextureStage *temp) {
00108   MutexHolder holder(_lock);
00109 
00110   switch (_mode) {
00111   case M_none:
00112     break;
00113 
00114   case M_name:
00115     _stages_by_name.erase(temp->get_name());
00116     break;
00117 
00118   case M_unique:
00119     {
00120       CPT(TextureStage) cpttemp = temp;
00121       _stages_by_properties.erase(cpttemp);
00122     }
00123     break;
00124   }
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: TextureStagePool::ns_release_all_stages
00129 //       Access: Private
00130 //  Description: The nonstatic implementation of release_all_stages().
00131 ////////////////////////////////////////////////////////////////////
00132 void TextureStagePool::
00133 ns_release_all_stages() {
00134   MutexHolder holder(_lock);
00135 
00136   _stages_by_name.clear();
00137   _stages_by_properties.clear();
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: TextureStagePool::ns_set_mode
00142 //       Access: Private
00143 //  Description: 
00144 ////////////////////////////////////////////////////////////////////
00145 void TextureStagePool::
00146 ns_set_mode(TextureStagePool::Mode mode) {
00147   MutexHolder holder(_lock);
00148 
00149   if (_mode != mode) {
00150     _stages_by_name.clear();
00151     _stages_by_properties.clear();
00152     _mode = mode;
00153   }
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: TextureStagePool::ns_get_mode
00158 //       Access: Private
00159 //  Description: 
00160 ////////////////////////////////////////////////////////////////////
00161 TextureStagePool::Mode TextureStagePool::
00162 ns_get_mode() {
00163   MutexHolder holder(_lock);
00164 
00165   return _mode;
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: TextureStagePool::ns_garbage_collect
00170 //       Access: Private
00171 //  Description: The nonstatic implementation of garbage_collect().
00172 ////////////////////////////////////////////////////////////////////
00173 int TextureStagePool::
00174 ns_garbage_collect() {
00175   MutexHolder holder(_lock);
00176 
00177   switch (_mode) {
00178   case M_none:
00179     return 0;
00180 
00181   case M_name:
00182     {
00183       int num_released = 0;
00184       StagesByName new_set;
00185       
00186       StagesByName::iterator ni;
00187       for (ni = _stages_by_name.begin(); ni != _stages_by_name.end(); ++ni) {
00188         const string &name = (*ni).first;
00189         TextureStage *ts2 = (*ni).second;
00190         if (name != ts2->get_name() || ts2->get_ref_count() == 1) {
00191           if (gobj_cat.is_debug()) {
00192             gobj_cat.debug()
00193               << "Releasing " << name << "\n";
00194           }
00195           ++num_released;
00196         } else {
00197           new_set.insert(new_set.end(), *ni);
00198         }
00199       }
00200       
00201       _stages_by_name.swap(new_set);
00202       return num_released;
00203     }
00204 
00205   case M_unique:
00206     {
00207       int num_released = 0;
00208       StagesByProperties new_set;
00209       
00210       StagesByProperties::iterator si;
00211       for (si = _stages_by_properties.begin(); si != _stages_by_properties.end(); ++si) {
00212         const TextureStage *ts1 = (*si).first;
00213         TextureStage *ts2 = (*si).second;
00214         if ((*ts1) != (*ts2) || ts2->get_ref_count() == 1) {
00215           if (gobj_cat.is_debug()) {
00216             gobj_cat.debug()
00217               << "Releasing " << *ts1 << "\n";
00218           }
00219           ++num_released;
00220         } else {
00221           new_set.insert(new_set.end(), *si);
00222         }
00223       }
00224       
00225       _stages_by_properties.swap(new_set);
00226       return num_released;
00227     }
00228   }
00229 
00230   return 0;
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: TextureStagePool::ns_list_contents
00235 //       Access: Private
00236 //  Description: The nonstatic implementation of list_contents().
00237 ////////////////////////////////////////////////////////////////////
00238 void TextureStagePool::
00239 ns_list_contents(ostream &out) const {
00240   MutexHolder holder(_lock);
00241 
00242   out << "TextureStagePool in mode " << _mode << "\n";
00243 
00244   switch (_mode) {
00245   case M_none:
00246     break;
00247 
00248   case M_name:
00249     {
00250       out << _stages_by_name.size() << " TextureStages:\n";
00251       StagesByName::const_iterator ni;
00252       for (ni = _stages_by_name.begin(); ni != _stages_by_name.end(); ++ni) {
00253         const string &name = (*ni).first;
00254         TextureStage *ts2 = (*ni).second;
00255         out << "  " << name
00256             << " (count = " << ts2->get_ref_count() << ")\n";
00257       }
00258     }
00259     break;
00260 
00261   case M_unique:
00262     {
00263       out << _stages_by_properties.size() << " TextureStages:\n";
00264       StagesByProperties::const_iterator si;
00265       for (si = _stages_by_properties.begin(); si != _stages_by_properties.end(); ++si) {
00266         const TextureStage *ts1 = (*si).first;
00267         TextureStage *ts2 = (*si).second;
00268         out << "  " << *ts1
00269             << " (count = " << ts2->get_ref_count() << ")\n";
00270       }
00271     }
00272     break;
00273   }
00274 }
00275 
00276 ////////////////////////////////////////////////////////////////////
00277 //     Function: TextureStagePool::get_global_ptr
00278 //       Access: Private, Static
00279 //  Description: Initializes and/or returns the global pointer to the
00280 //               one TextureStagePool object in the system.
00281 ////////////////////////////////////////////////////////////////////
00282 TextureStagePool *TextureStagePool::
00283 get_global_ptr() {
00284   if (_global_ptr == (TextureStagePool *)NULL) {
00285     _global_ptr = new TextureStagePool;
00286   }
00287   return _global_ptr;
00288 }
00289 
00290 ////////////////////////////////////////////////////////////////////
00291 //     Function: TextureStagePool::Mode output operator
00292 //  Description: 
00293 ////////////////////////////////////////////////////////////////////
00294 ostream &
00295 operator << (ostream &out, TextureStagePool::Mode mode) {
00296   switch (mode) {
00297   case TextureStagePool::M_none:
00298     return out << "none";
00299 
00300   case TextureStagePool::M_name:
00301     return out << "name";
00302 
00303   case TextureStagePool::M_unique:
00304     return out << "unique";
00305   }
00306 
00307   return out << "**invalid mode (" << (int)mode << ")**";
00308 }
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: TextureStagePool::Mode input operator
00312 //  Description: 
00313 ////////////////////////////////////////////////////////////////////
00314 istream &
00315 operator >> (istream &in, TextureStagePool::Mode &mode) {
00316   string word;
00317   in >> word;
00318 
00319   if (cmp_nocase(word, "none") == 0) {
00320     mode = TextureStagePool::M_none;
00321   } else if (cmp_nocase(word, "name") == 0) {
00322     mode = TextureStagePool::M_name;
00323   } else if (cmp_nocase(word, "unique") == 0) {
00324     mode = TextureStagePool::M_unique;
00325 
00326   } else {
00327     gobj_cat->error() << "Invalid TextureStagePool mode value: " << word << "\n";
00328     mode = TextureStagePool::M_none;
00329   }
00330 
00331   return in;
00332 }
 All Classes Functions Variables Enumerations