From 08dd2294cf50d9282134bcf968d9f2eb0e3abd67 Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Tue, 13 Jan 2015 17:52:38 -0700 Subject: Can compile "loader" and "layers" on Windows and Linux ... These directories build and are partially turned-on on Windows, using the "tri" demo (follow-on commit) and a "NULL driver" that was created out of the sample/Intel driver. The GetProcAddress() is not yet finding symbols in the NULL driver. For now: - "C:\Windows\System32" is the default XGL driver directory. The getenv() isn't yet working. I suggest creating your own #define in order to point to where a driver is. - In order to recognize a Windows driver, we must look at both its prefix and suffix (i.e. it is named "XGL_*.dll", e.g. "XGL_i965.dll). - We autogenerate Windows ".def" files for the layers. Additional info is: - This is necessary in order for a DLL to export symbols that can be queried using GetProcAddress(). We can't use the normal Windows approach of declaring these functions using "__declspec(dllexport)", because these functions are declared in "xgl.h". - This involves adding and running the new "xgl-win-def-file-generate.py" file. - NOTE: Layers don't have the xglInitAndEnumerateGpus() entrypoint, just the xglGetProcAddr() entrypoint (and now the xglEnumerateLayers() entrypoint). Generating them is pretty simple. NOTE: In order to build on a 64-bit Windows 7/8 system, I did the following: - Install VisualStudio 2013 Professional - Install CMake from: http://www.cmake.org/cmake/resources/software.html - I let it add itself to the system PATH environment variable. - Install Python 3 from: https://www.python.org/downloads - I let it add itself to the system PATH environment variable. - Obtain the Git repository, checkout the "ian-150127-WinBuild" branch. - Using a Cygwin shell: I did the following: - "cd" to the top-level directory (i.e. the one that contains the ".git" directory). - "mkdir _out64" - "cd _out64" - "cmake -G "Visual Studio 12 Win64" .." - At this point, I used WindowsExplorer to open the "XGL.sln" file. I can build. CMake causes the build shortcut to be "Ctrl-Shift-B" instead of the normal "F7". I had to right-click the "ALL_BUILD" project, go to Properties->Debugging and change the debug Command and Working Directory to point to "tri.exe" and where the executable are. At this point, I can debug (using the normal "F5" shortcut). --- loader/loader.c | 227 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 151 insertions(+), 76 deletions(-) (limited to 'loader/loader.c') diff --git a/loader/loader.c b/loader/loader.c index 0aa29406..c4cdce02 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -34,11 +34,12 @@ #include #include +#if defined(WIN32) +#include "dirent_on_windows.h" +#else // WIN32 #include -#include -#include -#include -#include +#endif // WIN32 +#include "loader_platform.h" #include "table_ops.h" #include "loader.h" @@ -48,7 +49,7 @@ struct loader_instance { }; struct loader_layers { - void *lib_handle; + loader_platform_dl_handle lib_handle; char name[256]; }; @@ -79,7 +80,7 @@ struct loader_msg_callback { }; struct loader_scanned_icds { - void *handle; + loader_platform_dl_handle handle; xglGetProcAddrType GetProcAddr; xglCreateInstanceType CreateInstance; xglDestroyInstanceType DestroyInstance; @@ -105,6 +106,7 @@ static struct { bool break_on_warning; } loader; + static XGL_RESULT loader_msg_callback_add(XGL_DBG_MSG_CALLBACK_FUNCTION func, void *data) { @@ -206,7 +208,7 @@ static void loader_log(XGL_DBG_MSG_TYPE msg_type, int32_t msg_code, static void loader_icd_destroy(struct loader_icd *icd) { - dlclose(icd->scanned_icds->handle); + loader_platform_close_library(icd->scanned_icds->handle); free(icd); } @@ -296,20 +298,21 @@ static struct loader_icd *loader_icd_add(struct loader_instance *ptr_inst, static void loader_scanned_icd_add(const char *filename) { - void *handle; + loader_platform_dl_handle handle; void *fp_gpa, *fp_enumerate, *fp_create_inst, *fp_destroy_inst; struct loader_scanned_icds *new_node; - handle = dlopen(filename, RTLD_LAZY); + // Used to call: dlopen(filename, RTLD_LAZY); + handle = loader_platform_open_library(filename); if (!handle) { - loader_log(XGL_DBG_MSG_WARNING, 0, dlerror()); + loader_log(XGL_DBG_MSG_WARNING, 0, loader_platform_open_library_error(filename)); return; } #define LOOKUP(func_ptr, func) do { \ - func_ptr = (xgl ##func## Type) dlsym(handle, "xgl" #func); \ + func_ptr = (xgl ##func## Type) loader_platform_get_proc_address(handle, "xgl" #func); \ if (!func_ptr) { \ - loader_log(XGL_DBG_MSG_WARNING, 0, dlerror()); \ + loader_log(XGL_DBG_MSG_WARNING, 0, loader_platform_get_proc_address_error("xgl" #func)); \ return; \ } \ } while (0) @@ -335,12 +338,50 @@ static void loader_scanned_icd_add(const char *filename) loader.scanned_icd_list = new_node; } +#if defined(WIN32) + +#define PATH_SEPERATOR ';' +#define DIRECTORY_SYMBOL "\\" +#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 "C:\\Windows\\System32" +// TODO/TBD: Is this an appropriate prefix for Windows? +#define XGL_DRIVER_LIBRARY_PREFIX "XGL_" +#define XGL_DRIVER_LIBRARY_PREFIX_LEN 4 +// TODO/TBD: Is this an appropriate suffix for Windows? +#define XGL_LAYER_LIBRARY_PREFIX "XGLLayer" +#define XGL_LAYER_LIBRARY_PREFIX_LEN 8 +#define XGL_LIBRARY_SUFFIX ".dll" +#define XGL_LIBRARY_SUFFIX_LEN 4 +#endif // DEFAULT_XGL_DRIVERS_PATH +#ifndef DEFAULT_XGL_LAYERS_PATH +// TODO: Is this a good default location? +#define DEFAULT_XGL_LAYERS_PATH "C:\\Windows\\System32" +#endif // DEFAULT_XGL_LAYERS_PATH + +#else // WIN32 + +#define PATH_SEPERATOR ':' +#define DIRECTORY_SYMBOL "/" #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" +#define XGL_DRIVER_LIBRARY_PREFIX "libXGL_" +#define XGL_DRIVER_LIBRARY_PREFIX_LEN 7 +#define XGL_LAYER_LIBRARY_PREFIX "libXGLLayer" +#define XGL_LAYER_LIBRARY_PREFIX_LEN 11 +#define XGL_LIBRARY_SUFFIX ".so" +#define XGL_LIBRARY_SUFFIX_LEN 3 +#endif // DEFAULT_XGL_DRIVERS_PATH +#ifndef DEFAULT_XGL_LAYERS_PATH +// TODO: Are these good default locations? +#define DEFAULT_XGL_LAYERS_PATH ".:/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl" #endif +#endif // WIN32 + /** * Try to \c loader_icd_scan XGL driver(s). * @@ -361,15 +402,19 @@ static void loader_icd_scan(void) int len; libPaths = NULL; +#if !defined(WIN32) if (geteuid() == getuid()) { - /* don't allow setuid apps to use LIBXGL_DRIVERS_PATH */ + /* Don't allow setuid apps to use LIBXGL_DRIVERS_PATH */ +#endif // WIN32 libPaths = getenv("LIBXGL_DRIVERS_PATH"); +#if !defined(WIN32) } +#endif // WIN32 if (libPaths == NULL) libPaths = DEFAULT_XGL_DRIVERS_PATH; for (p = libPaths; *p; p = next) { - next = strchr(p, ':'); + next = strchr(p, PATH_SEPERATOR); if (next == NULL) { len = strlen(p); next = p + len; @@ -381,16 +426,28 @@ static void loader_icd_scan(void) next++; } + // TODO/TBD: Do we want to do this on Windows, or just let Windows take + // care of its own search path (which it apparently has)? sysdir = opendir(p); if (sysdir) { dent = readdir(sysdir); while (dent) { - /* look for ICDs starting with "libXGL_" */ - if (!strncmp(dent->d_name, "libXGL_", 7)) { - snprintf(icd_library, 1024, "%s/%s",p,dent->d_name); - - loader_scanned_icd_add(icd_library); - } + /* Look for ICDs starting with XGL_DRIVER_LIBRARY_PREFIX and + * ending with XGL_LIBRARY_SUFFIX + */ + if (!strncmp(dent->d_name, + XGL_DRIVER_LIBRARY_PREFIX, + XGL_DRIVER_LIBRARY_PREFIX_LEN)) { + int nlen = strlen(dent->d_name); + const char *suf = dent->d_name + nlen - XGL_LIBRARY_SUFFIX_LEN; + if ((nlen > XGL_LIBRARY_SUFFIX_LEN) && + !strncmp(suf, + XGL_LIBRARY_SUFFIX, + XGL_LIBRARY_SUFFIX_LEN)) { + snprintf(icd_library, 1024, "%s" DIRECTORY_SYMBOL "%s", p,dent->d_name); + loader_scanned_icd_add(icd_library); + } + } dent = readdir(sysdir); } @@ -398,14 +455,9 @@ static void loader_icd_scan(void) } } - loader.icds_scanned = true; } -#ifndef DEFAULT_XGL_LAYERS_PATH -// TODO: Are these good default locations? -#define DEFAULT_XGL_LAYERS_PATH ".:/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl" -#endif static void layer_lib_scan_path(const char * libInPaths) { @@ -423,11 +475,15 @@ static void layer_lib_scan_path(const char * libInPaths) p = libInPaths; } else { +#if !defined(WIN32) if (geteuid() == getuid()) { +#endif // WIN32 p = getenv("LIBXGL_LAYERS_PATH"); if (p != NULL) len = strlen(p); +#if !defined(WIN32) } +#endif // WIN32 } if (len == 0) { @@ -456,7 +512,7 @@ static void layer_lib_scan_path(const char * libInPaths) loader.scanned_layer_count = 0; for (p = libPaths; *p; p = next) { - next = strchr(p, ':'); + next = strchr(p, PATH_SEPERATOR); if (next == NULL) { len = strlen(p); next = p + len; @@ -471,25 +527,37 @@ static void layer_lib_scan_path(const char * libInPaths) if (curdir) { dent = readdir(curdir); while (dent) { - /* look for wrappers starting with "libXGLlayer" */ - if (!strncmp(dent->d_name, "libXGLLayer", strlen("libXGLLayer"))) { - void * handle; - snprintf(temp_str, sizeof(temp_str), "%s/%s",p,dent->d_name); - if ((handle = dlopen(temp_str, RTLD_LAZY)) == NULL) { - dent = readdir(curdir); - continue; - } - if (loader.scanned_layer_count == MAX_LAYER_LIBRARIES) { - loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: max layer libraries exceed", temp_str); - break; - } - if ((loader.scanned_layer_names[loader.scanned_layer_count] = malloc(strlen(temp_str) + 1)) == NULL) { - loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: out of memory", temp_str); - break; - } - strcpy(loader.scanned_layer_names[loader.scanned_layer_count], temp_str); - loader.scanned_layer_count++; - dlclose(handle); + /* Look for layers starting with XGL_LAYER_LIBRARY_PREFIX and + * ending with XGL_LIBRARY_SUFFIX + */ + if (!strncmp(dent->d_name, + XGL_LAYER_LIBRARY_PREFIX, + XGL_LAYER_LIBRARY_PREFIX_LEN)) { + int nlen = strlen(dent->d_name); + const char *suf = dent->d_name + nlen - XGL_LIBRARY_SUFFIX_LEN; + if ((nlen > XGL_LIBRARY_SUFFIX_LEN) && + !strncmp(suf, + XGL_LIBRARY_SUFFIX, + XGL_LIBRARY_SUFFIX_LEN)) { + loader_platform_dl_handle handle; + snprintf(temp_str, sizeof(temp_str), "%s" DIRECTORY_SYMBOL "%s",p,dent->d_name); + // Used to call: dlopen(temp_str, RTLD_LAZY) + if ((handle = loader_platform_open_library(temp_str)) == NULL) { + dent = readdir(curdir); + continue; + } + if (loader.scanned_layer_count == MAX_LAYER_LIBRARIES) { + loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: max layer libraries exceed", temp_str); + break; + } + if ((loader.scanned_layer_names[loader.scanned_layer_count] = malloc(strlen(temp_str) + 1)) == NULL) { + loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: out of memory", temp_str); + break; + } + strcpy(loader.scanned_layer_names[loader.scanned_layer_count], temp_str); + loader.scanned_layer_count++; + loader_platform_close_library(handle); + } } dent = readdir(curdir); @@ -556,8 +624,9 @@ static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, s obj = &(icd->layer_libs[gpu_index][i]); strncpy(obj->name, (char *) pLayerNames[i].layer_name, sizeof(obj->name) - 1); obj->name[sizeof(obj->name) - 1] = '\0'; - if ((obj->lib_handle = dlopen(pLayerNames[i].lib_name, RTLD_LAZY | RTLD_DEEPBIND)) == NULL) { - loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to open layer library %s got error %d", pLayerNames[i].lib_name, dlerror()); + // Used to call: dlopen(pLayerNames[i].lib_name, RTLD_LAZY | RTLD_DEEPBIND) + if ((obj->lib_handle = loader_platform_open_library(pLayerNames[i].lib_name)) == NULL) { + loader_log(XGL_DBG_MSG_ERROR, 0, loader_platform_open_library_error(pLayerNames[i].lib_name)); continue; } else { loader_log(XGL_DBG_MSG_UNKNOWN, 0, "Inserting layer %s from library %s", pLayerNames[i].layer_name, pLayerNames[i].lib_name); @@ -570,7 +639,7 @@ static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, s static bool find_layer_name(struct loader_icd *icd, uint32_t gpu_index, const char * layer_name, const char **lib_name) { - void *handle; + loader_platform_dl_handle handle; xglEnumerateLayersType fpEnumerateLayers; char layer_buf[16][256]; char * layers[16]; @@ -580,14 +649,17 @@ static bool find_layer_name(struct loader_icd *icd, uint32_t gpu_index, const ch for (unsigned int j = 0; j < loader.scanned_layer_count; j++) { *lib_name = loader.scanned_layer_names[j]; - if ((handle = dlopen(*lib_name, RTLD_LAZY)) == NULL) + // Used to call: dlopen(*lib_name, RTLD_LAZY) + if ((handle = loader_platform_open_library(*lib_name)) == NULL) continue; - if ((fpEnumerateLayers = dlsym(handle, "xglEnumerateLayers")) == NULL) { - //use default layer name based on library name libXGLLayer.so + if ((fpEnumerateLayers = (xglEnumerateLayersType) loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) { char * lib_str = malloc(strlen(*lib_name) + 1 + strlen(layer_name)); - snprintf(lib_str, strlen(*lib_name) + strlen(layer_name), "libXGLLayer%s.so", layer_name); - dlclose(handle); - if (!strcmp(basename(*lib_name), lib_str)) { + //use default layer name + snprintf(lib_str, strlen(*lib_name) + strlen(layer_name), + XGL_DRIVER_LIBRARY_PREFIX "%s" XGL_LIBRARY_SUFFIX, + layer_name); + loader_platform_close_library(handle); + if (!strcmp(*lib_name, lib_str)) { free(lib_str); return true; } @@ -598,16 +670,16 @@ static bool find_layer_name(struct loader_icd *icd, uint32_t gpu_index, const ch } else { size_t cnt; - fpEnumerateLayers(NULL, 16, 256, &cnt, layers, (void *) icd->gpus + gpu_index); + fpEnumerateLayers(NULL, 16, 256, &cnt, layers, (char *) icd->gpus + gpu_index); for (unsigned int i = 0; i < cnt; i++) { if (!strcmp((char *) layers[i], layer_name)) { - dlclose(handle); + loader_platform_close_library(handle); return true; } } } - dlclose(handle); + loader_platform_close_library(handle); } return false; @@ -630,7 +702,7 @@ static uint32_t loader_get_layer_env(struct loader_icd *icd, uint32_t gpu_index, while (p && *p && count < MAX_LAYER_LIBRARIES) { const char *lib_name = NULL; - next = strchr(p, ':'); + next = strchr(p, PATH_SEPERATOR); if (next == NULL) { len = strlen(p); next = p + len; @@ -717,7 +789,7 @@ static void loader_deactivate_layer(const struct loader_instance *instance) for (uint32_t i = 0; i < icd->layer_count[j]; i++) { libs = &(icd->layer_libs[j][i]); if (libs->lib_handle) - dlclose(libs->lib_handle); + loader_platform_close_library(libs->lib_handle); libs->lib_handle = NULL; } if (icd->wrappedGpus[j]) @@ -763,8 +835,8 @@ extern uint32_t loader_activate_layers(XGL_PHYSICAL_GPU gpu, const XGL_DEVICE_CR char funcStr[256]; snprintf(funcStr, 256, "%sGetProcAddr",icd->layer_libs[gpu_index][i].name); - if ((nextGPA = dlsym(icd->layer_libs[gpu_index][i].lib_handle, funcStr)) == NULL) - nextGPA = dlsym(icd->layer_libs[gpu_index][i].lib_handle, "xglGetProcAddr"); + if ((nextGPA = (xglGetProcAddrType) loader_platform_get_proc_address(icd->layer_libs[gpu_index][i].lib_handle, funcStr)) == NULL) + nextGPA = (xglGetProcAddrType) loader_platform_get_proc_address(icd->layer_libs[gpu_index][i].lib_handle, "xglGetProcAddr"); if (!nextGPA) { loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to find xglGetProcAddr in layer %s", icd->layer_libs[gpu_index][i].name); continue; @@ -803,17 +875,18 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglCreateInstance( const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_INSTANCE* pInstance) { - static pthread_once_t once_icd = PTHREAD_ONCE_INIT; - static pthread_once_t once_layer = PTHREAD_ONCE_INIT; + static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd); + static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer); struct loader_instance *ptr_instance = NULL; struct loader_scanned_icds *scanned_icds; struct loader_icd *icd; XGL_RESULT res; - pthread_once(&once_icd, loader_icd_scan); + /* Scan/discover all ICD libraries in a single-threaded manner */ + loader_platform_thread_once(&once_icd, loader_icd_scan); - /* get layer libraries */ - pthread_once(&once_layer, layer_lib_scan); + /* get layer libraries in a single-threaded manner */ + loader_platform_thread_once(&once_layer, layer_lib_scan); ptr_instance = (struct loader_instance*) malloc(sizeof(struct loader_instance)); if (ptr_instance == NULL) { @@ -967,8 +1040,9 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateGpus( LOADER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const char * pName) { - if (gpu == NULL) + if (gpu == NULL) { return NULL; + } XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu; XGL_LAYER_DISPATCH_TABLE * disp_table = * (XGL_LAYER_DISPATCH_TABLE **) gpuw->baseObject; void *addr; @@ -992,7 +1066,7 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t uint32_t count = 0; char *lib_name; struct loader_icd *icd = loader_get_icd((const XGL_BASE_LAYER_OBJECT *) gpu, &gpu_index); - void *handle; + loader_platform_dl_handle handle; xglEnumerateLayersType fpEnumerateLayers; char layer_buf[16][256]; char * layers[16]; @@ -1008,16 +1082,17 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t for (unsigned int j = 0; j < loader.scanned_layer_count && count < maxLayerCount; j++) { lib_name = loader.scanned_layer_names[j]; - if ((handle = dlopen(lib_name, RTLD_LAZY)) == NULL) + // Used to call: dlopen(*lib_name, RTLD_LAZY) + if ((handle = loader_platform_open_library(lib_name)) == NULL) continue; - if ((fpEnumerateLayers = dlsym(handle, "xglEnumerateLayers")) == NULL) { - //use default layer name based on library name libXGLLayer.so + if ((fpEnumerateLayers = loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) { + //use default layer name based on library name XGL_LAYER_LIBRARY_PREFIX.XGL_LIBRARY_SUFFIX char *pEnd, *cpyStr; int siz; - dlclose(handle); + loader_platform_close_library(handle); lib_name = basename(lib_name); pEnd = strrchr(lib_name, '.'); - siz = pEnd - lib_name - strlen("libXGLLayer") + 1; + siz = pEnd - lib_name - strlen(XGL_LAYER_LIBRARY_PREFIX) + 1; if (pEnd == NULL || siz <= 0) continue; cpyStr = malloc(siz); @@ -1025,7 +1100,7 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t free(cpyStr); continue; } - strncpy(cpyStr, lib_name + strlen("libXGLLayer"), siz); + strncpy(cpyStr, lib_name + strlen(XGL_LAYER_LIBRARY_PREFIX), siz); cpyStr[siz - 1] = '\0'; if (siz > maxStringSize) siz = maxStringSize; @@ -1039,8 +1114,8 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t uint32_t n; XGL_RESULT res; n = (maxStringSize < 256) ? maxStringSize : 256; - res = fpEnumerateLayers(NULL, 16, n, &cnt, layers, (void *) icd->gpus + gpu_index); - dlclose(handle); + res = fpEnumerateLayers(NULL, 16, n, &cnt, layers, (char *) icd->gpus + gpu_index); + loader_platform_close_library(handle); if (res != XGL_SUCCESS) continue; if (cnt + count > maxLayerCount) -- cgit v1.2.3