loadAllModules(), etc.

This commit is contained in:
David Rose 2003-01-11 16:46:57 +00:00
parent d33bc6d7b2
commit 62cebed480
8 changed files with 213 additions and 86 deletions

View File

@ -29,12 +29,10 @@
#include "geomNodeContext.h"
#include "geomContext.h"
Configure(config_display);
ConfigureDef(config_display);
NotifyCategoryDef(display, "");
NotifyCategoryDef(gsg, display_cat);
static Config::ConfigTable::Symbol *disp;
ConfigureFn(config_display) {
init_libdisplay();
}
@ -59,20 +57,16 @@ const bool pstats_unused_states = config_display.GetBool("pstats-unused-states",
// system!
const string threading_model = config_display.GetString("threading-model", "");
// Use this to specify a particular pipe you prefer to use, when more
// than one GraphicsPipe is available (for instance, if both GL and DX
// are linked in). This should be the name of the type preferred, or
// a substring unique to the type name.
const string preferred_pipe = config_display.GetString("preferred-pipe", "");
// Use the variable load-display to specifiy the name of the default
// graphics display library or GraphicsPipe to load. It is the name
// of a shared library (or * for all libraries named in aux-display),
// optionally followed by the name of the particular GraphicsPipe
// class to create.
// Also use the variable aux-display to name each of the graphics
// display libraries that are available on a particular platform.
// This variable may be repeated several times.
Config::ConfigTable::Symbol::iterator display_modules_begin(void) {
return disp->begin();
}
Config::ConfigTable::Symbol::iterator display_modules_end(void) {
return disp->end();
}
////////////////////////////////////////////////////////////////////
// Function: init_libdisplay
@ -102,7 +96,4 @@ init_libdisplay() {
TextureContext::init_type();
GeomNodeContext::init_type();
GeomContext::init_type();
disp = new Config::ConfigTable::Symbol;
config_display.GetAll("load-display", *disp);
}

View File

@ -26,6 +26,7 @@
#include <string>
#include "pvector.h"
ConfigureDecl(config_display, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(display, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(gsg, EXPCL_PANDA, EXPTP_PANDA);
@ -33,10 +34,6 @@ extern const bool view_frustum_cull;
extern const bool pstats_unused_states;
extern const string threading_model;
extern const string preferred_pipe;
extern Config::ConfigTable::Symbol::iterator display_modules_begin(void);
extern Config::ConfigTable::Symbol::iterator display_modules_end(void);
extern EXPCL_PANDA void init_libdisplay();

View File

@ -16,3 +16,21 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipe::is_valid
// Access: Published
// Description: Returns false if this pipe is known to be invalid,
// meaning that an attempt to create a GraphicsWindow
// with the pipe will certainly fail. Returns true if
// the pipe is probably valid (is this case, an attempt
// to create a GraphicsWindow should succeed, but might
// still fail).
//
// Use the GraphicsEngine class to create a
// GraphicsWindow on a particular pipe.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsPipe::
is_valid() const {
return _is_valid;
}

View File

@ -29,6 +29,9 @@ TypeHandle GraphicsPipe::_type_handle;
////////////////////////////////////////////////////////////////////
GraphicsPipe::
GraphicsPipe() {
// Initially, we assume the GraphicsPipe is valid. A derived class
// should set this to false if it determines otherwise.
_is_valid = true;
}
////////////////////////////////////////////////////////////////////
@ -38,6 +41,7 @@ GraphicsPipe() {
////////////////////////////////////////////////////////////////////
GraphicsPipe::
GraphicsPipe(const GraphicsPipe &) {
_is_valid = false;
nassertv(false);
}

View File

@ -59,11 +59,18 @@ PUBLISHED:
int get_num_windows() const;
PT(GraphicsWindow) get_window(int n) const;
INLINE bool is_valid() const;
virtual string get_interface_name() const=0;
public:
virtual int get_num_hw_channels();
virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
protected:
// The make_window() interface on GraphicsPipe is protected; don't
// try to call it directly. Instead, use
// GraphicsEngine::make_window() to make a new window on a
// particular pipe.
virtual PT(GraphicsWindow) make_window()=0;
void add_window(GraphicsWindow *window);
@ -73,6 +80,7 @@ protected:
Windows _windows;
Mutex _lock;
bool _is_valid;
public:
static TypeHandle get_class_type() {

View File

@ -16,18 +16,17 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::resolve_modules
// Function: GraphicsPipeSelection::get_num_aux_modules
// Access: Published
// Description: Conditionally calls do_resolve_modules(), if it has
// not been called before.
// Description: Returns the number of display modules that are still
// to be loaded. If this is nonzero, then calling
// load_aux_modules() will likely increase the number of
// GraphicsPipes available.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsPipeSelection::
resolve_modules() const {
if (!_resolved_modules) {
((GraphicsPipeSelection *)this)->do_resolve_modules();
}
INLINE int GraphicsPipeSelection::
get_num_aux_modules() const {
return _display_modules.size();
}
////////////////////////////////////////////////////////////////////
@ -44,6 +43,19 @@ get_global_ptr() {
return _global_ptr;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::load_default_module
// Access: Private
// Description: Conditionally calls do_load_default_module(), if it has
// not been called before.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsPipeSelection::
load_default_module() const {
if (!_default_module_loaded) {
((GraphicsPipeSelection *)this)->do_load_default_module();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::PipeType::Constructor
// Access: Public

View File

@ -32,7 +32,43 @@ GraphicsPipeSelection *GraphicsPipeSelection::_global_ptr = NULL;
////////////////////////////////////////////////////////////////////
GraphicsPipeSelection::
GraphicsPipeSelection() {
_resolved_modules = false;
// Get the set of modules named in the various aux-display Configrc
// variables. We'll want to know this when we call load_modules()
// later.
Config::ConfigTable::Symbol disp;
config_display.GetAll("aux-display", disp);
Config::ConfigTable::Symbol::iterator ci;
for (ci = disp.begin(); ci != disp.end(); ++ci) {
_display_modules.insert((*ci).Val());
}
// Also get the name of the default module from the load-display
// variable. We get this explicitly from Configrc now (instead of
// retrieving it in config_display), in case this constructor is
// running at static init time.
string load_display = config_display.GetString("load-display", "");
load_display = trim_right(load_display);
size_t space = load_display.rfind(' ');
if (space != string::npos) {
// If there's a space, it indicates the name of the GraphicsPipe
// class to prefer.
_default_pipe_name = load_display.substr(space + 1);
load_display = trim_right(load_display.substr(0, space));
}
// Everything else is the name of the .dll (or .so) file to load.
_default_display_module = load_display;
if (_default_display_module == "*") {
// '*' or empty string is the key for all display modules.
_default_display_module = string();
} else if (!_default_display_module.empty()) {
_display_modules.insert(_default_display_module);
}
_default_module_loaded = false;
}
////////////////////////////////////////////////////////////////////
@ -53,7 +89,7 @@ GraphicsPipeSelection::
////////////////////////////////////////////////////////////////////
int GraphicsPipeSelection::
get_num_pipe_types() const {
resolve_modules();
load_default_module();
int result;
{
@ -71,7 +107,7 @@ get_num_pipe_types() const {
////////////////////////////////////////////////////////////////////
TypeHandle GraphicsPipeSelection::
get_pipe_type(int n) const {
resolve_modules();
load_default_module();
TypeHandle result;
{
@ -83,6 +119,31 @@ get_pipe_type(int n) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::print_pipe_types
// Access: Published
// Description: Writes a list of the currently known GraphicsPipe
// types to nout, for the user's information.
////////////////////////////////////////////////////////////////////
void GraphicsPipeSelection::
print_pipe_types() const {
load_default_module();
MutexHolder holder(_lock);
nout << "Known pipe types:" << endl;
PipeTypes::const_iterator pi;
for (pi = _pipe_types.begin(); pi != _pipe_types.end(); ++pi) {
const PipeType &pipe_type = (*pi);
nout << " " << pipe_type._type << "\n";
}
if (_display_modules.empty()) {
nout << "(all display modules loaded.)\n";
} else {
nout << "(" << _display_modules.size()
<< " aux display modules not yet loaded.)\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::make_pipe
// Access: Published
@ -93,7 +154,7 @@ get_pipe_type(int n) const {
////////////////////////////////////////////////////////////////////
PT(GraphicsPipe) GraphicsPipeSelection::
make_pipe(TypeHandle type) {
resolve_modules();
load_default_module();
MutexHolder holder(_lock);
PipeTypes::const_iterator ti;
@ -135,38 +196,40 @@ make_pipe(TypeHandle type) {
////////////////////////////////////////////////////////////////////
PT(GraphicsPipe) GraphicsPipeSelection::
make_default_pipe() {
resolve_modules();
load_default_module();
MutexHolder holder(_lock);
PipeTypes::const_iterator ti;
// First, look for an exact match of the requested type (excepting
// case and hyphen/underscore).
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
const PipeType &ptype = (*ti);
if (cmp_nocase_uh(ptype._type.get_name(), preferred_pipe) == 0) {
// Here's an exact match.
PT(GraphicsPipe) pipe = (*ptype._constructor)();
if (pipe != (GraphicsPipe *)NULL) {
return pipe;
if (!_default_pipe_name.empty()) {
// First, look for an exact match of the requested type (excepting
// case and hyphen/underscore).
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
const PipeType &ptype = (*ti);
if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
// Here's an exact match.
PT(GraphicsPipe) pipe = (*ptype._constructor)();
if (pipe != (GraphicsPipe *)NULL) {
return pipe;
}
}
}
// No match; look for a substring match.
string preferred_name = downcase(_default_pipe_name);
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
const PipeType &ptype = (*ti);
string ptype_name = downcase(ptype._type.get_name());
if (ptype_name.find(preferred_name) != string::npos) {
// Here's a substring match.
PT(GraphicsPipe) pipe = (*ptype._constructor)();
if (pipe != (GraphicsPipe *)NULL) {
return pipe;
}
}
}
}
// No match; look for a substring match.
string preferred_name = downcase(preferred_pipe);
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
const PipeType &ptype = (*ti);
string ptype_name = downcase(ptype._type.get_name());
if (ptype_name.find(preferred_name) != string::npos) {
// Here's a substring match.
PT(GraphicsPipe) pipe = (*ptype._constructor)();
if (pipe != (GraphicsPipe *)NULL) {
return pipe;
}
}
}
// Couldn't find a matching pipe type; choose one arbitrarily.
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
const PipeType &ptype = (*ti);
@ -180,6 +243,24 @@ make_default_pipe() {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::load_aux_modules
// Access: Published
// Description: Loads all the modules named in the aux-display
// Configrc variable, making as many graphics pipes as
// possible available.
////////////////////////////////////////////////////////////////////
void GraphicsPipeSelection::
load_aux_modules() {
DisplayModules::iterator di;
for (di = _display_modules.begin(); di != _display_modules.end(); ++di) {
load_named_module(*di);
}
_display_modules.clear();
_default_module_loaded = true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::add_pipe_type
// Access: Public
@ -217,35 +298,42 @@ add_pipe_type(TypeHandle type, PipeConstructorFunc *func) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::do_resolve_modules
// Function: GraphicsPipeSelection::do_load_default_module
// Access: Private
// Description: Loads the shared objects listed in the load-display
// Configrc variable, which should make all of the
// dynamic GraphicsPipes available.
// Description: Loads the particular display module listed in the
// load-display Configrc variable, which should default
// the default pipe time. If this string is empty or
// "*", loads all modules named in aux-display.
////////////////////////////////////////////////////////////////////
void GraphicsPipeSelection::
do_resolve_modules() {
Config::ConfigTable::Symbol::iterator ci;
do_load_default_module() {
_default_module_loaded = true;
// Build up a set of the modules we've already loaded as we go, so
// we don't attempt to load a given module more than once.
pset<string> already_loaded;
for (ci = display_modules_begin(); ci != display_modules_end(); ++ci) {
string name = (*ci).Val();
if (already_loaded.insert(name).second) {
Filename dlname = Filename::dso_filename("lib" + name + ".so");
display_cat.info()
<< "loading display module: " << dlname.to_os_specific() << endl;
void *tmp = load_dso(dlname);
if (tmp == (void *)NULL) {
display_cat.info()
<< "Unable to load: " << load_dso_error() << endl;
}
}
if (_default_display_module.empty()) {
load_aux_modules();
return;
}
_resolved_modules = true;
load_named_module(_default_display_module);
_display_modules.erase(_default_display_module);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipeSelection::load_named_module
// Access: Private
// Description: Loads the indicated display module by looking for a
// matching .dll or .so file.
////////////////////////////////////////////////////////////////////
void GraphicsPipeSelection::
load_named_module(const string &name) {
Filename dlname = Filename::dso_filename("lib" + name + ".so");
display_cat.info()
<< "loading display module: " << dlname.to_os_specific() << endl;
void *tmp = load_dso(dlname);
if (tmp == (void *)NULL) {
display_cat.info()
<< "Unable to load: " << load_dso_error() << endl;
}
}

View File

@ -51,11 +51,13 @@ protected:
PUBLISHED:
int get_num_pipe_types() const;
TypeHandle get_pipe_type(int n) const;
void print_pipe_types() const;
PT(GraphicsPipe) make_pipe(TypeHandle type);
PT(GraphicsPipe) make_default_pipe();
INLINE void resolve_modules() const;
INLINE int get_num_aux_modules() const;
void load_aux_modules();
INLINE static GraphicsPipeSelection *get_global_ptr();
@ -64,7 +66,9 @@ public:
bool add_pipe_type(TypeHandle type, PipeConstructorFunc *func);
private:
void do_resolve_modules();
INLINE void load_default_module() const;
void do_load_default_module();
void load_named_module(const string &name);
class PipeType {
public:
@ -74,9 +78,14 @@ private:
};
typedef pvector<PipeType> PipeTypes;
PipeTypes _pipe_types;
bool _resolved_modules;
Mutex _lock;
typedef pset<string> DisplayModules;
DisplayModules _display_modules;
string _default_display_module;
string _default_pipe_name;
bool _default_module_loaded;
static GraphicsPipeSelection *_global_ptr;
};