Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/display/graphicsPipeSelection.cxx

Go to the documentation of this file.
00001 // Filename: graphicsPipeSelection.cxx
00002 // Created by:  drose (15Aug02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "graphicsPipeSelection.h"
00020 #include "mutexHolder.h"
00021 #include "string_utils.h"
00022 #include "filename.h"
00023 #include "load_dso.h"
00024 #include "config_display.h"
00025 
00026 GraphicsPipeSelection *GraphicsPipeSelection::_global_ptr = NULL;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: GraphicsPipeSelection::Constructor
00030 //       Access: Protected
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 GraphicsPipeSelection::
00034 GraphicsPipeSelection() {
00035   // Get the set of modules named in the various aux-display Configrc
00036   // variables.  We'll want to know this when we call load_modules()
00037   // later.
00038   Config::ConfigTable::Symbol disp;
00039   config_display.GetAll("aux-display", disp);
00040 
00041   Config::ConfigTable::Symbol::iterator ci;
00042   for (ci = disp.begin(); ci != disp.end(); ++ci) {
00043     _display_modules.insert((*ci).Val());
00044   }
00045 
00046   // Also get the name of the default module from the load-display
00047   // variable.  We get this explicitly from Configrc now (instead of
00048   // retrieving it in config_display), in case this constructor is
00049   // running at static init time.
00050   string load_display = config_display.GetString("load-display", "");
00051   load_display = trim_right(load_display);
00052   size_t space = load_display.rfind(' ');
00053   if (space != string::npos) {
00054     // If there's a space, it indicates the name of the GraphicsPipe
00055     // class to prefer.
00056     _default_pipe_name = load_display.substr(space + 1);
00057     load_display = trim_right(load_display.substr(0, space));
00058   }
00059 
00060   // Everything else is the name of the .dll (or .so) file to load.
00061   _default_display_module = load_display;
00062 
00063   if (_default_display_module == "*") {
00064     // '*' or empty string is the key for all display modules.
00065     _default_display_module = string();
00066 
00067   } else if (!_default_display_module.empty()) {
00068     _display_modules.insert(_default_display_module);
00069   }
00070 
00071   _default_module_loaded = false;
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: GraphicsPipeSelection::Destructor
00076 //       Access: Protected
00077 //  Description:
00078 ////////////////////////////////////////////////////////////////////
00079 GraphicsPipeSelection::
00080 ~GraphicsPipeSelection() {
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: GraphicsPipeSelection::get_num_pipe_types
00085 //       Access: Published
00086 //  Description: Returns the number of different types of
00087 //               GraphicsPipes that are available to create through
00088 //               this interface.
00089 ////////////////////////////////////////////////////////////////////
00090 int GraphicsPipeSelection::
00091 get_num_pipe_types() const {
00092   load_default_module();
00093 
00094   int result;
00095   {
00096     MutexHolder holder(_lock);
00097     result = _pipe_types.size();
00098   }
00099   return result;
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: GraphicsPipeSelection::get_pipe_type
00104 //       Access: Published
00105 //  Description: Returns the nth type of GraphicsPipe available
00106 //               through this interface.
00107 ////////////////////////////////////////////////////////////////////
00108 TypeHandle GraphicsPipeSelection::
00109 get_pipe_type(int n) const {
00110   load_default_module();
00111 
00112   TypeHandle result;
00113   {
00114     MutexHolder holder(_lock);
00115     if (n >= 0 && n < (int)_pipe_types.size()) {
00116       result = _pipe_types[n]._type;
00117     }
00118   }
00119   return result;
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: GraphicsPipeSelection::print_pipe_types
00124 //       Access: Published
00125 //  Description: Writes a list of the currently known GraphicsPipe
00126 //               types to nout, for the user's information.
00127 ////////////////////////////////////////////////////////////////////
00128 void GraphicsPipeSelection::
00129 print_pipe_types() const {
00130   load_default_module();
00131 
00132   MutexHolder holder(_lock);
00133   nout << "Known pipe types:" << endl;
00134   PipeTypes::const_iterator pi;
00135   for (pi = _pipe_types.begin(); pi != _pipe_types.end(); ++pi) {
00136     const PipeType &pipe_type = (*pi);
00137     nout << "  " << pipe_type._type << "\n";
00138   }
00139   if (_display_modules.empty()) {
00140     nout << "(all display modules loaded.)\n";
00141   } else {
00142     nout << "(" << _display_modules.size() 
00143          << " aux display modules not yet loaded.)\n";
00144   }
00145 }
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 //     Function: GraphicsPipeSelection::make_pipe
00149 //       Access: Published
00150 //  Description: Creates a new GraphicsPipe of the indicated type (or
00151 //               a type more specific than the indicated type, if
00152 //               necessary) and returns it.  Returns NULL if the type
00153 //               cannot be matched.
00154 ////////////////////////////////////////////////////////////////////
00155 PT(GraphicsPipe) GraphicsPipeSelection::
00156 make_pipe(TypeHandle type) {
00157   load_default_module();
00158 
00159   MutexHolder holder(_lock);
00160   PipeTypes::const_iterator ti;
00161 
00162   // First, look for an exact match of the requested type.
00163   for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00164     const PipeType &ptype = (*ti);
00165     if (ptype._type == type) {
00166       // Here's an exact match.
00167       PT(GraphicsPipe) pipe = (*ptype._constructor)();
00168       if (pipe != (GraphicsPipe *)NULL) {
00169         return pipe;
00170       }
00171     }
00172   }
00173 
00174   // Now look for a more-specific type.
00175   for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00176     const PipeType &ptype = (*ti);
00177     if (ptype._type.is_derived_from(type)) {
00178       // Here's an approximate match.
00179       PT(GraphicsPipe) pipe = (*ptype._constructor)();
00180       if (pipe != (GraphicsPipe *)NULL) {
00181         return pipe;
00182       }
00183     }
00184   }
00185 
00186   // Couldn't find a matching pipe type.
00187   return NULL;
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: GraphicsPipeSelection::make_default_pipe
00192 //       Access: Published
00193 //  Description: Creates a new GraphicsPipe of some arbitrary type.
00194 //               The user may specify a preference using the Configrc
00195 //               file; otherwise, one will be chosen arbitrarily.
00196 ////////////////////////////////////////////////////////////////////
00197 PT(GraphicsPipe) GraphicsPipeSelection::
00198 make_default_pipe() {
00199   load_default_module();
00200 
00201   MutexHolder holder(_lock);
00202   PipeTypes::const_iterator ti;
00203 
00204   if (!_default_pipe_name.empty()) {
00205     // First, look for an exact match of the default type name from
00206     // the Configrc file (excepting case and hyphen/underscore).
00207     for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00208       const PipeType &ptype = (*ti);
00209       if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
00210         // Here's an exact match.
00211         PT(GraphicsPipe) pipe = (*ptype._constructor)();
00212         if (pipe != (GraphicsPipe *)NULL) {
00213           return pipe;
00214         }
00215       }
00216     }
00217     
00218     // No match; look for a substring match.
00219     string preferred_name = downcase(_default_pipe_name);
00220     for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00221       const PipeType &ptype = (*ti);
00222       string ptype_name = downcase(ptype._type.get_name());
00223       if (ptype_name.find(preferred_name) != string::npos) {
00224         // Here's a substring match.
00225         PT(GraphicsPipe) pipe = (*ptype._constructor)();
00226         if (pipe != (GraphicsPipe *)NULL) {
00227           return pipe;
00228         }
00229       }
00230     }
00231   }
00232     
00233   // Couldn't find a matching pipe type; choose one arbitrarily. 
00234   for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00235     const PipeType &ptype = (*ti);
00236     PT(GraphicsPipe) pipe = (*ptype._constructor)();
00237     if (pipe != (GraphicsPipe *)NULL) {
00238       return pipe;
00239     }
00240   }
00241 
00242   // Nothing.  Probably the list was empty.
00243   return NULL;
00244 }
00245 
00246 ////////////////////////////////////////////////////////////////////
00247 //     Function: GraphicsPipeSelection::load_aux_modules
00248 //       Access: Published
00249 //  Description: Loads all the modules named in the aux-display
00250 //               Configrc variable, making as many graphics pipes as
00251 //               possible available.
00252 ////////////////////////////////////////////////////////////////////
00253 void GraphicsPipeSelection::
00254 load_aux_modules() {
00255   DisplayModules::iterator di;
00256   for (di = _display_modules.begin(); di != _display_modules.end(); ++di) {
00257     load_named_module(*di);
00258   }
00259 
00260   _display_modules.clear();
00261   _default_module_loaded = true;
00262 }
00263 
00264 ////////////////////////////////////////////////////////////////////
00265 //     Function: GraphicsPipeSelection::add_pipe_type
00266 //       Access: Public
00267 //  Description: Adds a new kind of GraphicsPipe to the list of
00268 //               available pipes for creation.  Normally, this is
00269 //               called at static init type by the various shared
00270 //               libraries as they are linked in.  Returns true on
00271 //               success, false on failure.
00272 ////////////////////////////////////////////////////////////////////
00273 bool GraphicsPipeSelection::
00274 add_pipe_type(TypeHandle type, PipeConstructorFunc *func) {
00275   if (!type.is_derived_from(GraphicsPipe::get_class_type())) {
00276     display_cat.warning()
00277       << "Attempt to register " << type << " as a GraphicsPipe type.\n";
00278     return false;
00279   }
00280   
00281   // First, make sure we don't already have a GraphicsPipe of this
00282   // type.
00283   MutexHolder holder(_lock);
00284   PipeTypes::const_iterator ti;
00285   for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00286     const PipeType &ptype = (*ti);
00287     if (ptype._type == type) {
00288       display_cat.warning()
00289         << "Attempt to register GraphicsPipe type " << type
00290         << " more than once.\n";
00291       return false;
00292     }
00293   }
00294 
00295   // Ok, now add a new entry.
00296   _pipe_types.push_back(PipeType(type, func));
00297 
00298   return true;
00299 }
00300 
00301 
00302 ////////////////////////////////////////////////////////////////////
00303 //     Function: GraphicsPipeSelection::do_load_default_module
00304 //       Access: Private
00305 //  Description: Loads the particular display module listed in the
00306 //               load-display Configrc variable, which should default
00307 //               the default pipe time.  If this string is empty or
00308 //               "*", loads all modules named in aux-display.
00309 ////////////////////////////////////////////////////////////////////
00310 void GraphicsPipeSelection::
00311 do_load_default_module() {
00312   _default_module_loaded = true;
00313 
00314   if (_default_display_module.empty()) {
00315     load_aux_modules();
00316     return;
00317   }
00318 
00319   load_named_module(_default_display_module);
00320   _display_modules.erase(_default_display_module);
00321 }
00322 
00323 ////////////////////////////////////////////////////////////////////
00324 //     Function: GraphicsPipeSelection::load_named_module
00325 //       Access: Private
00326 //  Description: Loads the indicated display module by looking for a
00327 //               matching .dll or .so file.
00328 ////////////////////////////////////////////////////////////////////
00329 void GraphicsPipeSelection::
00330 load_named_module(const string &name) {
00331   Filename dlname = Filename::dso_filename("lib" + name + ".so");
00332   display_cat.info()
00333     << "loading display module: " << dlname.to_os_specific() << endl;
00334   void *tmp = load_dso(dlname);
00335   if (tmp == (void *)NULL) {
00336     display_cat.info()
00337       << "Unable to load: " << load_dso_error() << endl;
00338   }
00339 }

Generated on Fri May 2 00:36:28 2003 for Panda by doxygen1.3