Third-party can put their backend to a directory configured with '--with-gbm-backenddir' and create a /etc/gbm.conf.d/*.conf file which contains the backend so file name to overwrite the default builtin DRI backend.
The /etc/gbm.conf.d/*.conf will be sorted and the backends added will be tried one-by-one until one can successfully create a gbm device. The default DRI backend is tried at last. People can still use GBM_BACKEND to overwrite the backend try order. Signed-off-by: Qiang Yu <qiang...@amd.com> --- configure.ac | 7 +++++ src/gbm/Makefile.am | 1 + src/gbm/main/backend.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 64ace9d..21aea75 100644 --- a/configure.ac +++ b/configure.ac @@ -2201,6 +2201,13 @@ AC_ARG_WITH([d3d-libdir], [D3D_DRIVER_INSTALL_DIR="${libdir}/d3d"]) AC_SUBST([D3D_DRIVER_INSTALL_DIR]) +AC_ARG_WITH([gbm-backenddir], + [AS_HELP_STRING([--with-gbm-backenddir=DIR], + [directory for the GBM backends @<:@${libdir}/gbm@:>@])], + [GBM_BACKEND_DIR="$withval"], + [GBM_BACKEND_DIR='${libdir}/gbm']) +AC_SUBST([GBM_BACKEND_DIR]) + dnl dnl Gallium helper functions dnl diff --git a/src/gbm/Makefile.am b/src/gbm/Makefile.am index e34c1d4..a613005 100644 --- a/src/gbm/Makefile.am +++ b/src/gbm/Makefile.am @@ -39,6 +39,7 @@ libgbm_la_SOURCES += \ AM_CFLAGS += \ -DDEFAULT_DRIVER_DIR='"$(DRI_DRIVER_SEARCH_DIR)"' \ + -DGBM_BACKEND_DIR='"$(GBM_BACKEND_DIR)"' \ $(LIBDRM_CFLAGS) \ $(PTHREADSTUBS_CFLAGS) diff --git a/src/gbm/main/backend.c b/src/gbm/main/backend.c index 37ec9c1..0b89dde 100644 --- a/src/gbm/main/backend.c +++ b/src/gbm/main/backend.c @@ -31,6 +31,10 @@ #include <string.h> #include <limits.h> +#include <dirent.h> +#include <fnmatch.h> +#include <dlfcn.h> + #include "backend.h" #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) @@ -42,12 +46,18 @@ struct backend_desc { const struct gbm_backend *builtin; }; -static const struct backend_desc backends[] = { +static const struct backend_desc builtin_backends[] = { { "gbm_dri.so", &gbm_dri_backend }, }; +#define MAX_BACKENDS 10 +static struct backend_desc backends[MAX_BACKENDS]; +static int num_backends = 0; + +#define CONFIG_DIR "/etc/gbm.conf.d" + static const void * -load_backend(const struct backend_desc *backend) +load_backend(struct backend_desc *backend) { const void *init = NULL; @@ -57,17 +67,28 @@ load_backend(const struct backend_desc *backend) if (backend->builtin) { init = backend->builtin; } + else { + char path[PATH_MAX]; + void *module; + + snprintf(path, PATH_MAX, "%s/%s", GBM_BACKEND_DIR, backend->name); + module = dlopen(path, RTLD_NOW | RTLD_GLOBAL); + if (module) { + backend->builtin = dlsym(module, "gbm_backend"); + init = backend->builtin; + } + } return init; } -static const struct backend_desc * +static struct backend_desc * find_backend(const char *name) { - const struct backend_desc *backend = NULL; + struct backend_desc *backend = NULL; unsigned i; - for (i = 0; i < ARRAY_SIZE(backends); ++i) { + for (i = 0; i < num_backends; ++i) { if (strcmp(backends[i].name, name) == 0) { backend = &backends[i]; break; @@ -77,6 +98,50 @@ find_backend(const char *name) return backend; } +static int +scandir_filter(const struct dirent *ent) +{ + if (ent->d_type != DT_REG && ent->d_type != DT_LNK && + ent->d_type != DT_UNKNOWN) + return 0; + + if (fnmatch("*.conf", ent->d_name, 0)) + return 0; + + return 1; +} + +static void +init_backends(void) +{ + int i, count; + struct dirent **entries = NULL; + + count = scandir(CONFIG_DIR, &entries, scandir_filter, alphasort); + for (i = 0; i < count; i++) { + char path[PATH_MAX]; + FILE *file; + + snprintf(path, PATH_MAX, "%s/%s", CONFIG_DIR, entries[i]->d_name); + if ((file = fopen(path, "r"))) { + while (fgets(path, PATH_MAX, file)) { + int n = strlen(path); + if (path[n - 1] == '\n') + path[n - 1] = '\0'; + if (!fnmatch("*.so", path, 0) && + num_backends < MAX_BACKENDS - ARRAY_SIZE(builtin_backends)) { + backends[num_backends].name = strdup(path); + backends[num_backends++].builtin = NULL; + } + } + fclose(file); + } + } + + memcpy(backends + num_backends, builtin_backends, sizeof(builtin_backends)); + num_backends += ARRAY_SIZE(builtin_backends); +} + struct gbm_device * _gbm_create_device(int fd) { @@ -85,6 +150,9 @@ _gbm_create_device(int fd) unsigned i; const char *b; + if (!num_backends) + init_backends(); + b = getenv("GBM_BACKEND"); if (b) backend = load_backend(find_backend(b)); @@ -92,7 +160,7 @@ _gbm_create_device(int fd) if (backend) dev = backend->create_device(fd); - for (i = 0; i < ARRAY_SIZE(backends) && dev == NULL; ++i) { + for (i = 0; i < num_backends && dev == NULL; ++i) { backend = load_backend(&backends[i]); if (backend == NULL) continue; -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev