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 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_ref_count
Returns the current reference count.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_name
Returns the name of this texture stage.
Definition: textureStage.h:188
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The TextureStagePool (there is only one in the universe) serves to unify different pointers to the sa...
This class specializes ConfigVariable as an enumerated type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void write(std::ostream &out)
Lists the contents of the TextureStage pool to the indicated output stream.
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35