diff options
Diffstat (limited to 'loader/loader.c')
| -rw-r--r-- | loader/loader.c | 112 |
1 files changed, 83 insertions, 29 deletions
diff --git a/loader/loader.c b/loader/loader.c index 4e5f231f..86087a2a 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -24,10 +24,14 @@ #include <stdio.h> #include <stdlib.h> +#include <dirent.h> #include <stdarg.h> #include <stdbool.h> #include <string.h> +#include <sys/syscall.h> +#include <unistd.h> + #include <dlfcn.h> #include <pthread.h> @@ -36,6 +40,8 @@ #include "loader.generated" +typedef XGL_RESULT (*LoadT)(); +typedef XGL_RESULT (*UnloadT)(); typedef XGL_RESULT (XGLAPI *InitAndEnumerateGpusT)(const XGL_APPLICATION_INFO* pAppInfo, const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_UINT maxGpus, XGL_UINT* pGpuCount, XGL_PHYSICAL_GPU* pGpus); typedef XGL_RESULT (XGLAPI *DbgRegisterMsgCallbackT)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, XGL_VOID* pUserData); typedef XGL_RESULT (XGLAPI *DbgUnregisterMsgCallbackT)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback); @@ -44,6 +50,8 @@ typedef XGL_RESULT (XGLAPI *DbgSetGlobalOptionT)(XGL_INT dbgOption, XGL_SIZE dat struct loader_icd { void *handle; + LoadT Load; + UnloadT Unload; InitAndEnumerateGpusT InitAndEnumerateGpus; DbgRegisterMsgCallbackT DbgRegisterMsgCallback; DbgUnregisterMsgCallbackT DbgUnregisterMsgCallback; @@ -171,6 +179,7 @@ static void loader_log(XGL_DBG_MSG_TYPE msg_type, XGL_INT msg_code, static void loader_icd_destroy(struct loader_icd *icd) { + icd->Unload(); dlclose(icd->handle); free(icd); } @@ -199,6 +208,8 @@ loader_icd_create(const char *filename) return NULL; \ } \ } while (0) + LOOKUP(icd, Load); + LOOKUP(icd, Unload); LOOKUP(icd, InitAndEnumerateGpus); LOOKUP(icd, DbgRegisterMsgCallback); LOOKUP(icd, DbgUnregisterMsgCallback); @@ -255,36 +266,79 @@ static XGL_RESULT loader_icd_set_global_options(const struct loader_icd *icd) return XGL_SUCCESS; } -static void -loader_icd_scan(void) -{ - /* XXX How to discover ICDs? */ - static const char *filenames[] = { - "libmesaxgl.so", - "libintelxgl.so", - "libxgl.so", - }; - int i; - - for (i = 0; i < sizeof(filenames) / sizeof(filenames[0]); i++) { - struct loader_icd *icd; - - icd = loader_icd_create(filenames[i]); - if (!icd) { - continue; - } - - if (loader_icd_set_global_options(icd) != XGL_SUCCESS || - loader_icd_register_msg_callbacks(icd) != XGL_SUCCESS) { - loader_log(XGL_DBG_MSG_WARNING, 0, - "%s ignored: failed to migrate settings", filenames[i]); - loader_icd_destroy(icd); - continue; - } +#ifndef DEFAULT_XGL_DRIVERS_PATH +// TODO: Is this a good default location? +// Need to search for both 32bit and 64bit ICDs +#define DEFAULT_XGL_DRIVERS_PATH "/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl" +#endif - /* prepend to the list */ - icd->next = loader.icds; - loader.icds = icd; +/** + * Try to \c loader_icd_scan XGL driver(s). + * + * This function scans the default system path or path + * specified by the \c LIBXGL_DRIVERS_PATH environment variable in + * order to find loadable XGL ICDs with the name of libXGL_*. + * + * \returns + * void; but side effect is to set loader_icd_scanned to true + */ +static void loader_icd_scan(void) +{ + const char *libPaths, *p, *next; + DIR *sysdir; + struct dirent *dent; + char icd_library[1024]; + int len; + + libPaths = NULL; + if (geteuid() == getuid()) { + /* don't allow setuid apps to use LIBXGL_DRIVERS_PATH */ + libPaths = getenv("LIBXGL_DRIVERS_PATH"); + } + if (libPaths == NULL) + libPaths = DEFAULT_XGL_DRIVERS_PATH; + + for (p = libPaths; *p; p = next) { + next = strchr(p, ':'); + if (next == NULL) { + len = strlen(p); + next = p + len; + } + else { + len = next - p; + next++; + } + + sysdir = opendir(p); + if (sysdir) { + dent = readdir(sysdir); + while (dent) { + /* look for ICDs starting with "libXGL_" */ + if (!strncmp(dent->d_name, "libXGL_", 7)) { + struct loader_icd *icd; + + snprintf(icd_library, 1024, "%s/%s",p,dent->d_name); + + icd = loader_icd_create(icd_library); + if (icd) { + if (XGL_SUCCESS == icd->Load() && + XGL_SUCCESS == loader_icd_set_global_options(icd) && + XGL_SUCCESS == loader_icd_register_msg_callbacks(icd)) { + /* prepend to the list */ + icd->next = loader.icds; + loader.icds = icd; + } else { + loader_log(XGL_DBG_MSG_WARNING, 0, + "%s ignored: failed to migrate settings", icd_library); + loader_icd_destroy(icd); + } + } + } + + dent = readdir(sysdir); + } + closedir(sysdir); + } } /* we have nothing to log anymore */ |
