Panda3D
textureStagePool.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file textureStagePool.cxx
10  * @author drose
11  * @date 2010-05-03
12  */
13 
14 #include "textureStagePool.h"
15 #include "config_gobj.h"
16 #include "mutexHolder.h"
17 #include "configVariableEnum.h"
18 #include "string_utils.h"
19 
20 using std::istream;
21 using std::ostream;
22 using std::string;
23 
24 TextureStagePool *TextureStagePool::_global_ptr = nullptr;
25 
26 
27 /**
28  * Lists the contents of the TextureStage pool to the indicated output stream.
29  */
31 write(ostream &out) {
32  get_global_ptr()->ns_list_contents(out);
33 }
34 
35 /**
36  * The constructor is not intended to be called directly; there's only
37  * supposed to be one TextureStagePool in the universe and it constructs
38  * itself.
39  */
40 TextureStagePool::
41 TextureStagePool() {
42  ConfigVariableEnum<Mode> texture_stage_pool_mode
43  ("texture-stage-pool-mode", M_none,
44  PRC_DESC("Defines the initial value of TextureStagePool::set_mode(). "
45  "Set this to 'none' to disable the use of the TextureStagePool, "
46  "to 'name' to group TextureStages by name only, or 'unique' "
47  "to group together only identical TextureStages."));
48  _mode = texture_stage_pool_mode.get_value();
49 }
50 
51 /**
52  * The nonstatic implementation of get_stage().
53  */
54 TextureStage *TextureStagePool::
55 ns_get_stage(TextureStage *temp) {
56  MutexHolder holder(_lock);
57 
58  switch (_mode) {
59  case M_none:
60  return temp;
61 
62  case M_name:
63  {
64  StagesByName::iterator ni = _stages_by_name.find(temp->get_name());
65  if (ni == _stages_by_name.end()) {
66  ni = _stages_by_name.insert(StagesByName::value_type(temp->get_name(), temp)).first;
67  } else {
68  if ((*ni).first != (*ni).second->get_name()) {
69  // The pointer no longer matches the original name. Save a new one.
70  (*ni).second = temp;
71  }
72  }
73  return (*ni).second;
74  }
75 
76  case M_unique:
77  {
78  CPT(TextureStage) cpttemp = temp;
79  StagesByProperties::iterator si = _stages_by_properties.find(cpttemp);
80  if (si == _stages_by_properties.end()) {
81  si = _stages_by_properties.insert(StagesByProperties::value_type(new TextureStage(*temp), temp)).first;
82  } else {
83  if (*(*si).first != *(*si).second) {
84  // The pointer no longer matches its original value. Save a new
85  // one.
86  (*si).second = temp;
87  }
88  }
89  return (*si).second;
90  }
91  }
92 
93  return nullptr;
94 }
95 
96 /**
97  * The nonstatic implementation of release_stage().
98  */
99 void TextureStagePool::
100 ns_release_stage(TextureStage *temp) {
101  MutexHolder holder(_lock);
102 
103  switch (_mode) {
104  case M_none:
105  break;
106 
107  case M_name:
108  _stages_by_name.erase(temp->get_name());
109  break;
110 
111  case M_unique:
112  {
113  CPT(TextureStage) cpttemp = temp;
114  _stages_by_properties.erase(cpttemp);
115  }
116  break;
117  }
118 }
119 
120 /**
121  * The nonstatic implementation of release_all_stages().
122  */
123 void TextureStagePool::
124 ns_release_all_stages() {
125  MutexHolder holder(_lock);
126 
127  _stages_by_name.clear();
128  _stages_by_properties.clear();
129 }
130 
131 /**
132  *
133  */
134 void TextureStagePool::
135 ns_set_mode(TextureStagePool::Mode mode) {
136  MutexHolder holder(_lock);
137 
138  if (_mode != mode) {
139  _stages_by_name.clear();
140  _stages_by_properties.clear();
141  _mode = mode;
142  }
143 }
144 
145 /**
146  *
147  */
148 TextureStagePool::Mode TextureStagePool::
149 ns_get_mode() {
150  MutexHolder holder(_lock);
151 
152  return _mode;
153 }
154 
155 /**
156  * The nonstatic implementation of garbage_collect().
157  */
158 int TextureStagePool::
159 ns_garbage_collect() {
160  MutexHolder holder(_lock);
161 
162  switch (_mode) {
163  case M_none:
164  return 0;
165 
166  case M_name:
167  {
168  int num_released = 0;
169  StagesByName new_set;
170 
171  StagesByName::iterator ni;
172  for (ni = _stages_by_name.begin(); ni != _stages_by_name.end(); ++ni) {
173  const string &name = (*ni).first;
174  TextureStage *ts2 = (*ni).second;
175  if (name != ts2->get_name() || ts2->get_ref_count() == 1) {
176  if (gobj_cat.is_debug()) {
177  gobj_cat.debug()
178  << "Releasing " << name << "\n";
179  }
180  ++num_released;
181  } else {
182  new_set.insert(new_set.end(), *ni);
183  }
184  }
185 
186  _stages_by_name.swap(new_set);
187  return num_released;
188  }
189 
190  case M_unique:
191  {
192  int num_released = 0;
193  StagesByProperties new_set;
194 
195  StagesByProperties::iterator si;
196  for (si = _stages_by_properties.begin(); si != _stages_by_properties.end(); ++si) {
197  const TextureStage *ts1 = (*si).first;
198  TextureStage *ts2 = (*si).second;
199  if ((*ts1) != (*ts2) || ts2->get_ref_count() == 1) {
200  if (gobj_cat.is_debug()) {
201  gobj_cat.debug()
202  << "Releasing " << *ts1 << "\n";
203  }
204  ++num_released;
205  } else {
206  new_set.insert(new_set.end(), *si);
207  }
208  }
209 
210  _stages_by_properties.swap(new_set);
211  return num_released;
212  }
213  }
214 
215  return 0;
216 }
217 
218 /**
219  * The nonstatic implementation of list_contents().
220  */
221 void TextureStagePool::
222 ns_list_contents(ostream &out) const {
223  MutexHolder holder(_lock);
224 
225  out << "TextureStagePool in mode " << _mode << "\n";
226 
227  switch (_mode) {
228  case M_none:
229  break;
230 
231  case M_name:
232  {
233  out << _stages_by_name.size() << " TextureStages:\n";
234  StagesByName::const_iterator ni;
235  for (ni = _stages_by_name.begin(); ni != _stages_by_name.end(); ++ni) {
236  const string &name = (*ni).first;
237  TextureStage *ts2 = (*ni).second;
238  out << " " << name
239  << " (count = " << ts2->get_ref_count() << ")\n";
240  }
241  }
242  break;
243 
244  case M_unique:
245  {
246  out << _stages_by_properties.size() << " TextureStages:\n";
247  StagesByProperties::const_iterator si;
248  for (si = _stages_by_properties.begin(); si != _stages_by_properties.end(); ++si) {
249  const TextureStage *ts1 = (*si).first;
250  TextureStage *ts2 = (*si).second;
251  out << " " << *ts1
252  << " (count = " << ts2->get_ref_count() << ")\n";
253  }
254  }
255  break;
256  }
257 }
258 
259 /**
260  * Initializes and/or returns the global pointer to the one TextureStagePool
261  * object in the system.
262  */
263 TextureStagePool *TextureStagePool::
264 get_global_ptr() {
265  if (_global_ptr == nullptr) {
266  _global_ptr = new TextureStagePool;
267  }
268  return _global_ptr;
269 }
270 
271 /**
272  *
273  */
274 ostream &
275 operator << (ostream &out, TextureStagePool::Mode mode) {
276  switch (mode) {
277  case TextureStagePool::M_none:
278  return out << "none";
279 
280  case TextureStagePool::M_name:
281  return out << "name";
282 
283  case TextureStagePool::M_unique:
284  return out << "unique";
285  }
286 
287  return out << "**invalid mode (" << (int)mode << ")**";
288 }
289 
290 /**
291  *
292  */
293 istream &
294 operator >> (istream &in, TextureStagePool::Mode &mode) {
295  string word;
296  in >> word;
297 
298  if (cmp_nocase(word, "none") == 0) {
299  mode = TextureStagePool::M_none;
300  } else if (cmp_nocase(word, "name") == 0) {
301  mode = TextureStagePool::M_name;
302  } else if (cmp_nocase(word, "unique") == 0) {
303  mode = TextureStagePool::M_unique;
304 
305  } else {
306  gobj_cat->error() << "Invalid TextureStagePool mode value: " << word << "\n";
307  mode = TextureStagePool::M_none;
308  }
309 
310  return in;
311 }
MutexHolder
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_gobj.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
textureStagePool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureStagePool::write
static void write(std::ostream &out)
Lists the contents of the TextureStage pool to the indicated output stream.
Definition: textureStagePool.cxx:31
TextureStage::get_name
get_name
Returns the name of this texture stage.
Definition: textureStage.h:190
ConfigVariableEnum
This class specializes ConfigVariable as an enumerated type.
Definition: configVariableEnum.h:31
configVariableEnum.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureStagePool
The TextureStagePool (there is only one in the universe) serves to unify different pointers to the sa...
Definition: textureStagePool.h:32
mutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureStage
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
ReferenceCount::get_ref_count
get_ref_count
Returns the current reference count.
Definition: referenceCount.h:53