egl_g3d: Check external modules for client APIs first.

dlopen api_<API>.so before dlopening the process itself in case the
client APIs are implemented in external modules.
This commit is contained in:
Chia-I Wu 2010-05-05 18:27:29 +08:00
parent e8ba2812e6
commit 2773f888dc
3 changed files with 156 additions and 38 deletions

View file

@ -50,8 +50,8 @@ egl_g3d_init_st(_EGLDriver *drv)
if (gdrv->api_mask)
return;
egl_g3d_init_st_apis(gdrv->stapis);
for (i = 0; i < ST_API_COUNT; i++) {
gdrv->stapis[i] = egl_g3d_create_st_api(i);
if (gdrv->stapis[i])
gdrv->api_mask |= egl_g3d_st_api_bit(i);
}
@ -581,13 +581,8 @@ static void
egl_g3d_unload(_EGLDriver *drv)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
EGLint i;
for (i = 0; i < ST_API_COUNT; i++) {
if (gdrv->stapis[i])
gdrv->stapis[i]->destroy(gdrv->stapis[i]);
}
egl_g3d_destroy_st_apis();
egl_g3d_destroy_probe(drv, NULL);
FREE(gdrv);
}

View file

@ -27,8 +27,10 @@
*/
#include "util/u_memory.h"
#include "util/u_string.h"
#include "util/u_inlines.h"
#include "util/u_dl.h"
#include "egldriver.h"
#include "eglimage.h"
#include "eglmutex.h"
@ -46,42 +48,160 @@ egl_g3d_st_manager(struct st_manager *smapi)
return (struct egl_g3d_st_manager *) smapi;
}
struct st_api *
egl_g3d_create_st_api(enum st_api_type api)
{
static struct egl_g3d_st_module {
const char *filename;
struct util_dl_library *lib;
const char *proc_name;
struct st_api * (*proc)(void) = NULL;
struct st_api *stapi;
} egl_g3d_st_modules[ST_API_COUNT];
switch (api) {
case ST_API_OPENGL:
proc_name = ST_CREATE_OPENGL_SYMBOL;
break;
case ST_API_OPENGL_ES1:
proc_name = ST_CREATE_OPENGL_ES1_SYMBOL;
break;
case ST_API_OPENGL_ES2:
proc_name = ST_CREATE_OPENGL_ES2_SYMBOL;
break;
case ST_API_OPENVG:
proc_name = ST_CREATE_OPENVG_SYMBOL;
break;
default:
assert(!"Unknown API Type\n");
return NULL;
static EGLBoolean
egl_g3d_search_path_callback(const char *dir, size_t len, void *callback_data)
{
struct egl_g3d_st_module *stmod =
(struct egl_g3d_st_module *) callback_data;
char path[1024];
int ret;
ret = util_snprintf(path, sizeof(path),
"%.*s/%s", len, dir, stmod->filename);
if (ret > 0 && ret < sizeof(path))
stmod->lib = util_dl_open(path);
return !(stmod->lib);
}
static boolean
egl_g3d_load_st_module(struct egl_g3d_st_module *stmod,
const char *filename, const char *procname)
{
struct st_api *(*create_api)(void);
stmod->filename = filename;
if (stmod->filename)
_eglSearchPathForEach(egl_g3d_search_path_callback, (void *) stmod);
else
stmod->lib = util_dl_open(NULL);
if (stmod->lib) {
create_api = (struct st_api *(*)(void))
util_dl_get_proc_address(stmod->lib, procname);
if (create_api)
stmod->stapi = create_api();
if (!stmod->stapi) {
util_dl_close(stmod->lib);
stmod->lib = NULL;
}
}
lib = util_dl_open(NULL);
if (lib) {
proc = util_dl_get_proc_address(lib, proc_name);
debug_printf("%s: %s %p\n", __func__, proc_name, proc);
util_dl_close(lib);
if (stmod->stapi) {
return TRUE;
}
else {
stmod->filename = NULL;
return FALSE;
}
}
if (!proc)
return NULL;
void
egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT])
{
const char *skip_checks[ST_API_COUNT], *symbols[ST_API_COUNT];
const char *filenames[ST_API_COUNT][4];
struct util_dl_library *self;
int num_needed = 0, api;
return proc();
self = util_dl_open(NULL);
/* collect the necessary data for loading modules */
for (api = 0; api < ST_API_COUNT; api++) {
int count = 0;
switch (api) {
case ST_API_OPENGL:
skip_checks[api] = "glColor4d";
symbols[api] = ST_CREATE_OPENGL_SYMBOL;
filenames[api][count++] = "api_GL.so";
break;
case ST_API_OPENGL_ES1:
skip_checks[api] = "glColor4x";
symbols[api] = ST_CREATE_OPENGL_ES1_SYMBOL;
filenames[api][count++] = "api_GLESv1_CM.so";
filenames[api][count++] = "api_GL.so";
break;
case ST_API_OPENGL_ES2:
skip_checks[api] = "glShaderBinary";
symbols[api] = ST_CREATE_OPENGL_ES2_SYMBOL;
filenames[api][count++] = "api_GLESv2.so";
filenames[api][count++] = "api_GL.so";
break;
case ST_API_OPENVG:
skip_checks[api] = "vgClear";
symbols[api] = ST_CREATE_OPENVG_SYMBOL;
filenames[api][count++]= "api_OpenVG.so";
break;
default:
assert(!"Unknown API Type\n");
skip_checks[api] = NULL;
symbols[api] = NULL;
break;
}
filenames[api][count++]= NULL;
assert(count < Elements(filenames[api]));
/* heuristicically decide if the module is needed */
if (!self || !skip_checks[api] ||
util_dl_get_proc_address(self, skip_checks[api])) {
/* unset so the module is not skipped */
skip_checks[api] = NULL;
num_needed++;
}
}
/* mark all moudles needed if we wrongly decided that none is needed */
if (!num_needed)
memset(skip_checks, 0, sizeof(skip_checks));
if (self)
util_dl_close(self);
for (api = 0; api < ST_API_COUNT; api++) {
struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api];
const char **p;
/* skip the module */
if (skip_checks[api])
continue;
/* try all filenames, including NULL */
for (p = filenames[api]; *p; p++) {
if (egl_g3d_load_st_module(stmod, *p, symbols[api]))
break;
}
if (!stmod->stapi)
egl_g3d_load_st_module(stmod, NULL, symbols[api]);
stapis[api] = stmod->stapi;
}
}
void
egl_g3d_destroy_st_apis(void)
{
int api;
for (api = 0; api < ST_API_COUNT; api++) {
struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api];
if (stmod->stapi) {
stmod->stapi->destroy(stmod->stapi);
stmod->stapi = NULL;
}
if (stmod->lib) {
util_dl_close(stmod->lib);
stmod->lib = NULL;
}
stmod->filename = NULL;
}
}
static boolean

View file

@ -33,8 +33,11 @@
#include "state_tracker/st_api.h"
#include "egltypedefs.h"
struct st_api *
egl_g3d_create_st_api(enum st_api_type api);
void
egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT]);
void
egl_g3d_destroy_st_apis(void);
struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay *dpy);