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