diff options
author | Eric Anholt <[email protected]> | 2018-11-15 13:54:49 -0800 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2018-11-16 17:49:17 -0800 |
commit | d971a4230d54069c996bca78b6ed6a6a23377821 (patch) | |
tree | 2d9c29c0c0df5405a0bad5b2c7860bcc614069a2 /src/loader | |
parent | cc198157382a988590b0288d287281139c5f73e6 (diff) |
loader: Factor out the common driver opening logic from each loader.
I copied the code from egl_dri2.c, but the functionality was equivalent
between all the loaders other than their particular environment variables.
v2: Drop the logging function equivalent to loader_default_logger()
(requested by Eric, Emil). Move the SCons workaround across. Drop
the now-unused driGetDriverExtensions() declaration that was lost in a
rebase.
Reviewed-by: Eric Engestrom <[email protected]> (v1)
Reviewed-by: Emil Velikov <[email protected]> (v1)
Diffstat (limited to 'src/loader')
-rw-r--r-- | src/loader/Makefile.am | 1 | ||||
-rw-r--r-- | src/loader/SConscript | 2 | ||||
-rw-r--r-- | src/loader/loader.c | 90 | ||||
-rw-r--r-- | src/loader/loader.h | 7 | ||||
-rw-r--r-- | src/loader/meson.build | 4 |
5 files changed, 103 insertions, 1 deletions
diff --git a/src/loader/Makefile.am b/src/loader/Makefile.am index 76252564281..3c22e0ae7e6 100644 --- a/src/loader/Makefile.am +++ b/src/loader/Makefile.am @@ -28,6 +28,7 @@ noinst_LTLIBRARIES = libloader.la AM_CPPFLAGS = \ -I$(top_builddir)/src/util/ \ -DUSE_DRICONF \ + -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \ $(DEFINES) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/drm-uapi \ diff --git a/src/loader/SConscript b/src/loader/SConscript index f70654f43ae..6a315642c2c 100644 --- a/src/loader/SConscript +++ b/src/loader/SConscript @@ -12,6 +12,8 @@ if env['drm']: env.PkgUseModules('DRM') env.Append(CPPDEFINES = ['HAVE_LIBDRM']) +env.Append(CPPDEFINES = ['DEFAULT_DRIVER_DIR=\\"/usr/local/lib/dri\\"']) + # parse Makefile.sources sources = env.ParseSourceList('Makefile.sources', 'LOADER_C_FILES') diff --git a/src/loader/loader.c b/src/loader/loader.c index 041a59212be..05140b6d18f 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -26,6 +26,7 @@ * Rob Clark <[email protected]> */ +#include <dlfcn.h> #include <errno.h> #include <fcntl.h> #include <sys/stat.h> @@ -35,6 +36,7 @@ #include <string.h> #include <unistd.h> #include <stdlib.h> +#include <sys/param.h> #ifdef MAJOR_IN_MKDEV #include <sys/mkdev.h> #endif @@ -510,3 +512,91 @@ loader_get_extensions_name(const char *driver_name) return name; } + +/** + * Opens a DRI driver using its driver name, returning the __DRIextension + * entrypoints. + * + * \param driverName - a name like "i965", "radeon", "nouveau", etc. + * \param out_driver - Address where the dlopen() return value will be stored. + * \param search_path_vars - NULL-terminated list of env vars that can be used + * to override the DEFAULT_DRIVER_DIR search path. + */ +const struct __DRIextensionRec ** +loader_open_driver(const char *driver_name, + void **out_driver_handle, + const char **search_path_vars) +{ + char path[PATH_MAX], *search_paths, *next, *end; + char *get_extensions_name; + const struct __DRIextensionRec **extensions = NULL; + const struct __DRIextensionRec **(*get_extensions)(void); + + search_paths = NULL; + if (geteuid() == getuid() && search_path_vars) { + for (int i = 0; search_path_vars[i] != NULL; i++) { + search_paths = getenv(search_path_vars[i]); + if (search_paths) + break; + } + } + if (search_paths == NULL) + search_paths = DEFAULT_DRIVER_DIR; + + void *driver = NULL; + end = search_paths + strlen(search_paths); + for (char *p = search_paths; p < end; p = next + 1) { + int len; + next = strchr(p, ':'); + if (next == NULL) + next = end; + + len = next - p; +#if GLX_USE_TLS + snprintf(path, sizeof(path), "%.*s/tls/%s_dri.so", len, p, driver_name); + driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); +#endif + if (driver == NULL) { + snprintf(path, sizeof(path), "%.*s/%s_dri.so", len, p, driver_name); + driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); + if (driver == NULL) + log_(_LOADER_DEBUG, "MESA-LOADER: failed to open %s: %s\n", + path, dlerror()); + } + /* not need continue to loop all paths once the driver is found */ + if (driver != NULL) + break; + } + + if (driver == NULL) { + log_(_LOADER_WARNING, "MESA-LOADER: failed to open %s (search paths %s)\n", + driver_name, search_paths); + *out_driver_handle = NULL; + return NULL; + } + + log_(_LOADER_DEBUG, "MESA-LOADER: dlopen(%s)\n", path); + + get_extensions_name = loader_get_extensions_name(driver_name); + if (get_extensions_name) { + get_extensions = dlsym(driver, get_extensions_name); + if (get_extensions) { + extensions = get_extensions(); + } else { + log_(_LOADER_DEBUG, "MESA-LOADER: driver does not expose %s(): %s\n", + get_extensions_name, dlerror()); + } + free(get_extensions_name); + } + + if (!extensions) + extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + log_(_LOADER_WARNING, + "MESA-LOADER: driver exports no extensions (%s)\n", dlerror()); + dlclose(driver); + } + + *out_driver_handle = driver; + return extensions; +} diff --git a/src/loader/loader.h b/src/loader/loader.h index 7b4dd01144f..779ec44b75d 100644 --- a/src/loader/loader.h +++ b/src/loader/loader.h @@ -33,6 +33,8 @@ extern "C" { #endif +struct __DRIextensionRec; + /* Helpers to figure out driver and device name, eg. from pci-id, etc. */ int @@ -47,6 +49,11 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id); char * loader_get_driver_for_fd(int fd); +const struct __DRIextensionRec ** +loader_open_driver(const char *driver_name, + void **out_driver_handle, + const char **search_path_vars); + char * loader_get_device_name_for_fd(int fd); diff --git a/src/loader/meson.build b/src/loader/meson.build index 76fcae2cb44..e280ba41cc2 100644 --- a/src/loader/meson.build +++ b/src/loader/meson.build @@ -39,7 +39,9 @@ libloader = static_library( 'loader', ['loader.c', 'loader.h', 'pci_id_driver_map.c', 'pci_id_driver_map.h', xmlpool_options_h], - c_args : [c_vis_args, '-DUSE_DRICONF'], + c_args : [c_vis_args, '-DUSE_DRICONF', + '-DDEFAULT_DRIVER_DIR="@0@"'.format(dri_search_path), +], include_directories : [inc_include, inc_src, inc_util], dependencies : [dep_libdrm, dep_thread], build_by_default : false, |