mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-30 00:40:25 +01:00
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:
parent
e8ba2812e6
commit
2773f888dc
3 changed files with 156 additions and 38 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue