From 2773f888dc9cde61dedf1b004e35efcc72ca9240 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 5 May 2010 18:27:29 +0800 Subject: egl_g3d: Check external modules for client APIs first. dlopen api_.so before dlopening the process itself in case the client APIs are implemented in external modules. --- src/gallium/state_trackers/egl/common/egl_g3d_st.c | 180 +++++++++++++++++---- 1 file changed, 150 insertions(+), 30 deletions(-) (limited to 'src/gallium/state_trackers/egl/common/egl_g3d_st.c') diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c index 9744547868..1df57d0777 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -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; - - 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; + struct st_api *stapi; +} egl_g3d_st_modules[ST_API_COUNT]; + +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; + + 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]); - return proc(); + 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 -- cgit v1.2.3