Panda3D
 All Classes Functions Variables Enumerations
shaderPool.cxx
1 // Filename: shaderPool.cxx
2 // Created by: aignacio (Mar06)
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 #include "shaderPool.h"
16 #include "config_util.h"
17 #include "config_express.h"
18 #include "virtualFileSystem.h"
19 #include "loader.h"
20 #include "shader.h"
21 #include "string_utils.h"
22 
23 ShaderPool *ShaderPool::_global_ptr = (ShaderPool *)NULL;
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: ShaderPool::write
27 // Access: Published, Static
28 // Description: Lists the contents of the shader pool to the
29 // indicated output stream.
30 ////////////////////////////////////////////////////////////////////
31 void ShaderPool::
32 write(ostream &out) {
33  get_ptr()->ns_list_contents(out);
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: ShaderPool::ns_has_shader
38 // Access: Private
39 // Description: The nonstatic implementation of has_shader().
40 ////////////////////////////////////////////////////////////////////
41 bool ShaderPool::
42 ns_has_shader(const Filename &orig_filename) {
43  Filename filename;
44  resolve_filename(filename, orig_filename);
45 
46  LightMutexHolder holder(_lock);
47  Shaders::const_iterator ti;
48  ti = _shaders.find(filename);
49  if (ti != _shaders.end()) {
50  // This shader was previously loaded.
51  return true;
52  }
53 
54  return false;
55 }
56 
57 ////////////////////////////////////////////////////////////////////
58 // Function: ShaderPool::ns_load_shader
59 // Access: Private
60 // Description: The nonstatic implementation of load_shader().
61 ////////////////////////////////////////////////////////////////////
62 CPT(Shader) ShaderPool::
63 ns_load_shader(const Filename &orig_filename) {
64  Filename filename;
65  resolve_filename(filename, orig_filename);
66 
67  {
68  LightMutexHolder holder(_lock);
69 
70  Shaders::const_iterator ti;
71  ti = _shaders.find(filename);
72  if (ti != _shaders.end()) {
73  // This shader was previously loaded.
74  return (*ti).second;
75  }
76  }
77 
78  // The shader was not found in the pool.
79  gobj_cat.info()
80  << "Loading shader " << filename << "\n";
81 
82  Shader::ShaderLanguage lang = Shader::SL_none;
83 
84  // Do some guesswork to see if we can figure out the shader language
85  // from the file extension. This is really just guesswork - there are
86  // no standardized extensions for shaders, especially for GLSL.
87  // These are the ones that appear to be closest to "standard".
88  string ext = downcase(filename.get_extension());
89  if (ext == "cg" || ext == "sha") {
90  // "sha" is for historical reasons.
91  lang = Shader::SL_Cg;
92 
93  } else if (ext == "glsl" || ext == "vert" || ext == "frag" ||
94  ext == "geom" || ext == "tesc" || ext == "tese" ||
95  ext == "comp") {
96  lang = Shader::SL_GLSL;
97  }
98 
99  PT(Shader) shader = Shader::load(filename, lang);
100  if (shader == (Shader *)NULL) {
101  // This shader was not found or could not be read.
102  return NULL;
103  }
104 
105  {
106  LightMutexHolder holder(_lock);
107 
108  // Now try again. Someone may have loaded the shader in another
109  // thread.
110  Shaders::const_iterator ti;
111  ti = _shaders.find(filename);
112  if (ti != _shaders.end()) {
113  // This shader was previously loaded.
114  return (*ti).second;
115  }
116 
117  _shaders[filename] = shader;
118  }
119 
120  return shader;
121 }
122 
123 ////////////////////////////////////////////////////////////////////
124 // Function: ShaderPool::ns_add_shader
125 // Access: Private
126 // Description: The nonstatic implementation of add_shader().
127 ////////////////////////////////////////////////////////////////////
128 void ShaderPool::
129 ns_add_shader(const Filename &orig_filename, Shader *shader) {
130  Filename filename;
131  resolve_filename(filename, orig_filename);
132 
133  LightMutexHolder holder(_lock);
134  // We blow away whatever shader was there previously, if any.
135  _shaders[filename] = shader;
136 }
137 
138 ////////////////////////////////////////////////////////////////////
139 // Function: ShaderPool::ns_release_shader
140 // Access: Private
141 // Description: The nonstatic implementation of release_shader().
142 ////////////////////////////////////////////////////////////////////
143 void ShaderPool::
144 ns_release_shader(const Filename &filename) {
145  LightMutexHolder holder(_lock);
146 
147  Shaders::iterator ti;
148  ti = _shaders.find(filename);
149  if (ti != _shaders.end()) {
150  _shaders.erase(ti);
151  }
152 }
153 
154 ////////////////////////////////////////////////////////////////////
155 // Function: ShaderPool::ns_release_all_shaders
156 // Access: Private
157 // Description: The nonstatic implementation of release_all_shaders().
158 ////////////////////////////////////////////////////////////////////
159 void ShaderPool::
160 ns_release_all_shaders() {
161  LightMutexHolder holder(_lock);
162 
163  _shaders.clear();
164 }
165 
166 ////////////////////////////////////////////////////////////////////
167 // Function: ShaderPool::ns_garbage_collect
168 // Access: Private
169 // Description: The nonstatic implementation of garbage_collect().
170 ////////////////////////////////////////////////////////////////////
171 int ShaderPool::
172 ns_garbage_collect() {
173  LightMutexHolder holder(_lock);
174 
175  int num_released = 0;
176  Shaders new_set;
177 
178  Shaders::iterator ti;
179  for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) {
180  CPT(Shader) shader = (*ti).second;
181  if (shader->get_ref_count() == 1) {
182 /*
183  if (shader_cat.is_debug()) {
184  shader_cat.debug()
185  << "Releasing " << (*ti).first << "\n";
186  }
187 */
188  num_released++;
189  } else {
190  new_set.insert(new_set.end(), *ti);
191  }
192  }
193 
194  _shaders.swap(new_set);
195  return num_released;
196 }
197 
198 ////////////////////////////////////////////////////////////////////
199 // Function: ShaderPool::ns_list_contents
200 // Access: Private
201 // Description: The nonstatic implementation of list_contents().
202 ////////////////////////////////////////////////////////////////////
203 void ShaderPool::
204 ns_list_contents(ostream &out) const {
205  LightMutexHolder holder(_lock);
206 
207  out << _shaders.size() << " shaders:\n";
208  Shaders::const_iterator ti;
209  for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) {
210  CPT(Shader) shader = (*ti).second;
211  out << " " << (*ti).first
212  << " (count = " << shader->get_ref_count() << ")\n";
213  }
214 }
215 
216 
217 ////////////////////////////////////////////////////////////////////
218 // Function: ShaderPool::resolve_filename
219 // Access: Private
220 // Description: Searches for the indicated filename along the
221 // model path.
222 ////////////////////////////////////////////////////////////////////
223 void ShaderPool::
224 resolve_filename(Filename &new_filename, const Filename &orig_filename) {
225  new_filename = orig_filename;
227  vfs->resolve_filename(new_filename, get_model_path());
228 }
229 
230 ////////////////////////////////////////////////////////////////////
231 // Function: ShaderPool::get_ptr
232 // Access: Private, Static
233 // Description: Initializes and/or returns the global pointer to the
234 // one ShaderPool object in the system.
235 ////////////////////////////////////////////////////////////////////
236 ShaderPool *ShaderPool::
237 get_ptr() {
238  if (_global_ptr == (ShaderPool *)NULL) {
239  _global_ptr = new ShaderPool;
240  }
241  return _global_ptr;
242 }
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS&#39;s file system.
Definition: shader.h:50
This is the preferred interface for loading shaders for the TextNode system.
Definition: shaderPool.h:31
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
Similar to MutexHolder, but for a light mutex.
static void write(ostream &out)
Lists the contents of the shader pool to the indicated output stream.
Definition: shaderPool.cxx:32
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
string get_extension() const
Returns the file extension.
Definition: filename.I:477