00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "graphicsPipeSelection.h"
00016 #include "lightMutexHolder.h"
00017 #include "string_utils.h"
00018 #include "filename.h"
00019 #include "load_dso.h"
00020 #include "config_display.h"
00021 #include "typeRegistry.h"
00022 #include "pset.h"
00023 #include "config_util.h"
00024
00025 #include <algorithm>
00026
00027 GraphicsPipeSelection *GraphicsPipeSelection::_global_ptr = NULL;
00028
00029
00030
00031
00032
00033
00034 GraphicsPipeSelection::
00035 GraphicsPipeSelection() : _lock("GraphicsPipeSelection") {
00036
00037
00038 ConfigVariableString load_display
00039 ("load-display", "*",
00040 PRC_DESC("Specify the name of the default graphics display library or "
00041 "GraphicsPipe to load. It is the name of a shared library (or * for "
00042 "all libraries named in aux-display), optionally followed by the "
00043 "name of the particular GraphicsPipe class to create."));
00044
00045 ConfigVariableList aux_display
00046 ("aux-display",
00047 PRC_DESC("Names each of the graphics display libraries that are available on "
00048 "a particular platform. This variable may be repeated several "
00049 "times. These libraries will be tried one at a time if the library "
00050 "specified by load_display cannot be loaded."));
00051
00052 _default_display_module = load_display.get_word(0);
00053 _default_pipe_name = load_display.get_word(1);
00054
00055 if (_default_display_module == "*") {
00056
00057 _default_display_module = string();
00058
00059 } else if (!_default_display_module.empty()) {
00060 _display_modules.push_back(_default_display_module);
00061 }
00062
00063
00064
00065
00066 int num_aux = aux_display.get_num_unique_values();
00067 for (int i = 0; i < num_aux; i++) {
00068 string name = aux_display.get_unique_value(i);
00069 if (name != _default_display_module) {
00070 _display_modules.push_back(name);
00071 }
00072 }
00073
00074 _default_module_loaded = false;
00075 }
00076
00077
00078
00079
00080
00081
00082 GraphicsPipeSelection::
00083 ~GraphicsPipeSelection() {
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 int GraphicsPipeSelection::
00094 get_num_pipe_types() const {
00095 load_default_module();
00096
00097 int result;
00098 {
00099 LightMutexHolder holder(_lock);
00100 result = _pipe_types.size();
00101 }
00102 return result;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 TypeHandle GraphicsPipeSelection::
00112 get_pipe_type(int n) const {
00113 load_default_module();
00114
00115 TypeHandle result;
00116 {
00117 LightMutexHolder holder(_lock);
00118 if (n >= 0 && n < (int)_pipe_types.size()) {
00119 result = _pipe_types[n]._type;
00120 }
00121 }
00122 return result;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 void GraphicsPipeSelection::
00132 print_pipe_types() const {
00133 load_default_module();
00134
00135 LightMutexHolder holder(_lock);
00136 nout << "Known pipe types:" << endl;
00137 PipeTypes::const_iterator pi;
00138 for (pi = _pipe_types.begin(); pi != _pipe_types.end(); ++pi) {
00139 const PipeType &pipe_type = (*pi);
00140 nout << " " << pipe_type._type << "\n";
00141 }
00142 if (_display_modules.empty()) {
00143 nout << "(all display modules loaded.)\n";
00144 } else {
00145 nout << "(" << _display_modules.size()
00146 << " aux display modules not yet loaded.)\n";
00147 }
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 PT(GraphicsPipe) GraphicsPipeSelection::
00163 make_pipe(const string &type_name, const string &module_name) {
00164 TypeRegistry *type_reg = TypeRegistry::ptr();
00165
00166
00167 TypeHandle type = type_reg->find_type(type_name);
00168
00169
00170 if (type == TypeHandle::none()) {
00171 if (!module_name.empty()) {
00172 load_named_module(module_name);
00173 type = type_reg->find_type(type_name);
00174 }
00175 }
00176
00177
00178 if (type == TypeHandle::none()) {
00179 load_default_module();
00180 type = type_reg->find_type(type_name);
00181 }
00182
00183
00184 if (type == TypeHandle::none()) {
00185 load_aux_modules();
00186 type = type_reg->find_type(type_name);
00187 }
00188
00189 if (type == TypeHandle::none()) {
00190 return NULL;
00191 }
00192
00193 return make_pipe(type);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 PT(GraphicsPipe) GraphicsPipeSelection::
00205 make_pipe(TypeHandle type) {
00206 LightMutexHolder holder(_lock);
00207 PipeTypes::const_iterator ti;
00208
00209
00210 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00211 const PipeType &ptype = (*ti);
00212 if (ptype._type == type) {
00213
00214 PT(GraphicsPipe) pipe = (*ptype._constructor)();
00215 if (pipe != (GraphicsPipe *)NULL) {
00216 return pipe;
00217 }
00218 }
00219 }
00220
00221
00222 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00223 const PipeType &ptype = (*ti);
00224 if (ptype._type.is_derived_from(type)) {
00225
00226 PT(GraphicsPipe) pipe = (*ptype._constructor)();
00227 if (pipe != (GraphicsPipe *)NULL) {
00228 return pipe;
00229 }
00230 }
00231 }
00232
00233
00234 load_default_module();
00235 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00236 const PipeType &ptype = (*ti);
00237 if (ptype._type.is_derived_from(type)) {
00238
00239 PT(GraphicsPipe) pipe = (*ptype._constructor)();
00240 if (pipe != (GraphicsPipe *)NULL) {
00241 return pipe;
00242 }
00243 }
00244 }
00245
00246
00247 return NULL;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257 PT(GraphicsPipe) GraphicsPipeSelection::
00258 make_module_pipe(const string &module_name) {
00259 if (display_cat.is_debug()) {
00260 display_cat.debug()
00261 << "make_module_pipe(" << module_name << ")\n";
00262 }
00263
00264 TypeHandle pipe_type = load_named_module(module_name);
00265 if (pipe_type == TypeHandle::none()) {
00266 return NULL;
00267 }
00268
00269 return make_pipe(pipe_type);
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279 PT(GraphicsPipe) GraphicsPipeSelection::
00280 make_default_pipe() {
00281 load_default_module();
00282
00283 LightMutexHolder holder(_lock);
00284 PipeTypes::const_iterator ti;
00285
00286 if (!_default_pipe_name.empty()) {
00287
00288
00289 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00290 const PipeType &ptype = (*ti);
00291 if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
00292
00293 PT(GraphicsPipe) pipe = (*ptype._constructor)();
00294 if (pipe != (GraphicsPipe *)NULL) {
00295 return pipe;
00296 }
00297 }
00298 }
00299
00300
00301 string preferred_name = downcase(_default_pipe_name);
00302 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00303 const PipeType &ptype = (*ti);
00304 string ptype_name = downcase(ptype._type.get_name());
00305 if (ptype_name.find(preferred_name) != string::npos) {
00306
00307 PT(GraphicsPipe) pipe = (*ptype._constructor)();
00308 if (pipe != (GraphicsPipe *)NULL) {
00309 return pipe;
00310 }
00311 }
00312 }
00313 }
00314
00315
00316
00317 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00318 const PipeType &ptype = (*ti);
00319 PT(GraphicsPipe) pipe = (*ptype._constructor)();
00320 if (pipe != (GraphicsPipe *)NULL) {
00321 return pipe;
00322 }
00323 }
00324
00325
00326 return NULL;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336 void GraphicsPipeSelection::
00337 load_aux_modules() {
00338 DisplayModules::iterator di;
00339 for (di = _display_modules.begin(); di != _display_modules.end(); ++di) {
00340 load_named_module(*di);
00341 }
00342
00343 _display_modules.clear();
00344 _default_module_loaded = true;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 bool GraphicsPipeSelection::
00357 add_pipe_type(TypeHandle type, PipeConstructorFunc *func) {
00358 nassertr(func != NULL, false);
00359
00360 if (!type.is_derived_from(GraphicsPipe::get_class_type())) {
00361 display_cat.warning()
00362 << "Attempt to register " << type << " as a GraphicsPipe type.\n";
00363 return false;
00364 }
00365
00366
00367
00368 LightMutexHolder holder(_lock);
00369 PipeTypes::const_iterator ti;
00370 for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
00371 const PipeType &ptype = (*ti);
00372 if (ptype._type == type) {
00373 display_cat.warning()
00374 << "Attempt to register GraphicsPipe type " << type
00375 << " more than once.\n";
00376 return false;
00377 }
00378 }
00379
00380 if (display_cat.is_debug()) {
00381 display_cat.debug()
00382 << "Registering " << type << " as a GraphicsPipe type.\n";
00383 }
00384
00385
00386 _pipe_types.push_back(PipeType(type, func));
00387
00388 return true;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 void GraphicsPipeSelection::
00401 do_load_default_module() {
00402 if (_default_display_module.empty()) {
00403 load_aux_modules();
00404 return;
00405 }
00406
00407 load_named_module(_default_display_module);
00408
00409 DisplayModules::iterator di =
00410 find(_display_modules.begin(), _display_modules.end(),
00411 _default_display_module);
00412 if (di != _display_modules.end()) {
00413 _display_modules.erase(di);
00414 }
00415
00416 _default_module_loaded = true;
00417
00418 if (_pipe_types.empty()) {
00419
00420
00421 load_aux_modules();
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 TypeHandle GraphicsPipeSelection::
00434 load_named_module(const string &name) {
00435 LightMutexHolder holder(_loaded_modules_lock);
00436
00437 LoadedModules::iterator mi = _loaded_modules.find(name);
00438 if (mi != _loaded_modules.end()) {
00439
00440
00441 return (*mi).second._default_pipe_type;
00442 }
00443
00444
00445 Filename dlname = Filename::dso_filename("lib" + name + ".so");
00446 display_cat.info()
00447 << "loading display module: " << dlname.to_os_specific() << endl;
00448 void *handle = load_dso(get_plugin_path().get_value(), dlname);
00449 if (handle == (void *)NULL) {
00450 display_cat.warning()
00451 << "Unable to load: " << load_dso_error() << endl;
00452 return TypeHandle::none();
00453 }
00454
00455
00456
00457
00458 string symbol_name = "get_pipe_type_" + name;
00459 void *dso_symbol = get_dso_symbol(handle, symbol_name);
00460 if (display_cat.is_debug()) {
00461 display_cat.debug()
00462 << "symbol of " << symbol_name << " = " << dso_symbol << "\n";
00463 }
00464
00465 TypeHandle pipe_type = TypeHandle::none();
00466
00467 if (dso_symbol == (void *)NULL) {
00468
00469 display_cat.warning()
00470 << "Unable to find " << symbol_name << " in " << dlname.get_basename()
00471 << "\n";
00472
00473 } else {
00474
00475
00476
00477 typedef int FuncType();
00478 int pipe_type_index = (*(FuncType *)dso_symbol)();
00479 if (display_cat.is_debug()) {
00480 display_cat.debug()
00481 << "pipe_type_index = " << pipe_type_index << "\n";
00482 }
00483
00484 if (pipe_type_index != 0) {
00485 TypeRegistry *type_reg = TypeRegistry::ptr();
00486 pipe_type = type_reg->find_type_by_id(pipe_type_index);
00487 if (display_cat.is_debug()) {
00488 display_cat.debug()
00489 << "pipe_type = " << pipe_type << "\n";
00490 }
00491 }
00492 }
00493
00494 if (pipe_type == TypeHandle::none()) {
00495
00496
00497
00498
00499 display_cat.warning()
00500 << "No default pipe type available for " << dlname.get_basename()
00501 << "\n";
00502 }
00503
00504 LoadedModule &module = _loaded_modules[name];
00505 module._module_name = name;
00506 module._module_handle = handle;
00507 module._default_pipe_type = pipe_type;
00508
00509 return pipe_type;
00510 }