summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/egl
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2010-05-05 18:27:29 +0800
committerChia-I Wu <[email protected]>2010-05-08 14:54:13 +0800
commit2773f888dc9cde61dedf1b004e35efcc72ca9240 (patch)
treea7f1631e82e8e908cdf402a75b3521ec2505b000 /src/gallium/state_trackers/egl
parente8ba2812e6995d1ec95c972a1b48ac29a99531dd (diff)
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.
Diffstat (limited to 'src/gallium/state_trackers/egl')
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c9
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_st.c180
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_st.h7
3 files changed, 157 insertions, 39 deletions
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 3ab72dce2f3..5c6fe97922a 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -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);
}
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 97445478684..1df57d07774 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
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h
index c82681a22d8..ee53799b029 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_st.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h
@@ -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);