Panda3D
|
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 }