Panda3D
|
00001 // Filename: shaderPool.cxx 00002 // Created by: aignacio (Mar06) 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 #include "shaderPool.h" 00016 #include "config_util.h" 00017 #include "config_express.h" 00018 #include "virtualFileSystem.h" 00019 #include "loader.h" 00020 #include "shader.h" 00021 00022 ShaderPool *ShaderPool::_global_ptr = (ShaderPool *)NULL; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: ShaderPool::write 00026 // Access: Published, Static 00027 // Description: Lists the contents of the shader pool to the 00028 // indicated output stream. 00029 //////////////////////////////////////////////////////////////////// 00030 void ShaderPool:: 00031 write(ostream &out) { 00032 get_ptr()->ns_list_contents(out); 00033 } 00034 00035 //////////////////////////////////////////////////////////////////// 00036 // Function: ShaderPool::ns_has_shader 00037 // Access: Private 00038 // Description: The nonstatic implementation of has_shader(). 00039 //////////////////////////////////////////////////////////////////// 00040 bool ShaderPool:: 00041 ns_has_shader(const Filename &orig_filename) { 00042 Filename filename; 00043 resolve_filename(filename, orig_filename); 00044 00045 LightMutexHolder holder(_lock); 00046 Shaders::const_iterator ti; 00047 ti = _shaders.find(filename); 00048 if (ti != _shaders.end()) { 00049 // This shader was previously loaded. 00050 return true; 00051 } 00052 00053 return false; 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: ShaderPool::ns_load_shader 00058 // Access: Private 00059 // Description: The nonstatic implementation of load_shader(). 00060 //////////////////////////////////////////////////////////////////// 00061 CPT(Shader) ShaderPool:: 00062 ns_load_shader(const Filename &orig_filename) { 00063 Filename filename; 00064 resolve_filename(filename, orig_filename); 00065 00066 { 00067 LightMutexHolder holder(_lock); 00068 00069 Shaders::const_iterator ti; 00070 ti = _shaders.find(filename); 00071 if (ti != _shaders.end()) { 00072 // This shader was previously loaded. 00073 return (*ti).second; 00074 } 00075 } 00076 00077 /* 00078 shader_cat.info() 00079 << "Loading shader " << filename << "\n"; 00080 */ 00081 00082 CPT(Shader) shader; 00083 00084 shader = (CPT(Shader)) NULL; 00085 string extension = filename.get_extension(); 00086 00087 if (extension.empty() || extension == "cg" || extension == "hlsl") { 00088 // this does nothing for now 00089 } 00090 00091 if (shader == (CPT(Shader)) NULL) { 00092 shader = Shader::load (filename); 00093 } 00094 00095 if (shader == (CPT(Shader)) NULL) { 00096 // This shader was not found or could not be read. 00097 return NULL; 00098 } 00099 00100 { 00101 LightMutexHolder holder(_lock); 00102 00103 // Now try again. Someone may have loaded the shader in another 00104 // thread. 00105 Shaders::const_iterator ti; 00106 ti = _shaders.find(filename); 00107 if (ti != _shaders.end()) { 00108 // This shader was previously loaded. 00109 return (*ti).second; 00110 } 00111 00112 _shaders[filename] = shader; 00113 } 00114 00115 return shader; 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: ShaderPool::ns_add_shader 00120 // Access: Private 00121 // Description: The nonstatic implementation of add_shader(). 00122 //////////////////////////////////////////////////////////////////// 00123 void ShaderPool:: 00124 ns_add_shader(const Filename &orig_filename, Shader *shader) { 00125 Filename filename; 00126 resolve_filename(filename, orig_filename); 00127 00128 LightMutexHolder holder(_lock); 00129 // We blow away whatever shader was there previously, if any. 00130 _shaders[filename] = shader; 00131 } 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function: ShaderPool::ns_release_shader 00135 // Access: Private 00136 // Description: The nonstatic implementation of release_shader(). 00137 //////////////////////////////////////////////////////////////////// 00138 void ShaderPool:: 00139 ns_release_shader(const Filename &filename) { 00140 LightMutexHolder holder(_lock); 00141 00142 Shaders::iterator ti; 00143 ti = _shaders.find(filename); 00144 if (ti != _shaders.end()) { 00145 _shaders.erase(ti); 00146 } 00147 } 00148 00149 //////////////////////////////////////////////////////////////////// 00150 // Function: ShaderPool::ns_release_all_shaders 00151 // Access: Private 00152 // Description: The nonstatic implementation of release_all_shaders(). 00153 //////////////////////////////////////////////////////////////////// 00154 void ShaderPool:: 00155 ns_release_all_shaders() { 00156 LightMutexHolder holder(_lock); 00157 00158 _shaders.clear(); 00159 } 00160 00161 //////////////////////////////////////////////////////////////////// 00162 // Function: ShaderPool::ns_garbage_collect 00163 // Access: Private 00164 // Description: The nonstatic implementation of garbage_collect(). 00165 //////////////////////////////////////////////////////////////////// 00166 int ShaderPool:: 00167 ns_garbage_collect() { 00168 LightMutexHolder holder(_lock); 00169 00170 int num_released = 0; 00171 Shaders new_set; 00172 00173 Shaders::iterator ti; 00174 for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) { 00175 CPT(Shader) shader = (*ti).second; 00176 if (shader->get_ref_count() == 1) { 00177 /* 00178 if (shader_cat.is_debug()) { 00179 shader_cat.debug() 00180 << "Releasing " << (*ti).first << "\n"; 00181 } 00182 */ 00183 num_released++; 00184 } else { 00185 new_set.insert(new_set.end(), *ti); 00186 } 00187 } 00188 00189 _shaders.swap(new_set); 00190 return num_released; 00191 } 00192 00193 //////////////////////////////////////////////////////////////////// 00194 // Function: ShaderPool::ns_list_contents 00195 // Access: Private 00196 // Description: The nonstatic implementation of list_contents(). 00197 //////////////////////////////////////////////////////////////////// 00198 void ShaderPool:: 00199 ns_list_contents(ostream &out) const { 00200 LightMutexHolder holder(_lock); 00201 00202 out << _shaders.size() << " shaders:\n"; 00203 Shaders::const_iterator ti; 00204 for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) { 00205 CPT(Shader) shader = (*ti).second; 00206 out << " " << (*ti).first 00207 << " (count = " << shader->get_ref_count() << ")\n"; 00208 } 00209 } 00210 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: ShaderPool::resolve_filename 00214 // Access: Private 00215 // Description: Searches for the indicated filename along the 00216 // model path. 00217 //////////////////////////////////////////////////////////////////// 00218 void ShaderPool:: 00219 resolve_filename(Filename &new_filename, const Filename &orig_filename) { 00220 new_filename = orig_filename; 00221 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00222 vfs->resolve_filename(new_filename, get_model_path()); 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: ShaderPool::get_ptr 00227 // Access: Private, Static 00228 // Description: Initializes and/or returns the global pointer to the 00229 // one ShaderPool object in the system. 00230 //////////////////////////////////////////////////////////////////// 00231 ShaderPool *ShaderPool:: 00232 get_ptr() { 00233 if (_global_ptr == (ShaderPool *)NULL) { 00234 _global_ptr = new ShaderPool; 00235 } 00236 return _global_ptr; 00237 }