*/
#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"
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