aboutsummaryrefslogtreecommitdiffstats
path: root/src/loader
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-11-15 13:54:49 -0800
committerEric Anholt <[email protected]>2018-11-16 17:49:17 -0800
commitd971a4230d54069c996bca78b6ed6a6a23377821 (patch)
tree2d9c29c0c0df5405a0bad5b2c7860bcc614069a2 /src/loader
parentcc198157382a988590b0288d287281139c5f73e6 (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.am1
-rw-r--r--src/loader/SConscript2
-rw-r--r--src/loader/loader.c90
-rw-r--r--src/loader/loader.h7
-rw-r--r--src/loader/meson.build4
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,