/* * Mesa 3-D graphics library * Version: 7.9 * * Copyright (C) 2010 LunarG Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Chia-I Wu */ #include "dxgi_private.h" #include extern "C" { #include "state_tracker/drm_driver.h" #include "util/u_dl.h" } #define PIPE_PREFIX "pipe_" static const char * get_search_path(void) { static const char *search_path; if (!search_path) { static char buffer[1024]; const char *p; int ret; p = getenv("DXGI_DRIVERS_PATH"); if(!p) p = getenv("EGL_DRIVERS_PATH"); #ifdef __unix__ if (p && (geteuid() != getuid() || getegid() != getgid())) { p = NULL; } #endif if (p) { ret = snprintf(buffer, sizeof(buffer), "%s:%s", p, DXGI_DRIVER_SEARCH_DIR); if (ret > 0 && ret < (int)sizeof(buffer)) search_path = buffer; } } if (!search_path) search_path = DXGI_DRIVER_SEARCH_DIR; return search_path; } static void for_each_colon_separated(const char *search_path, bool (*loader)(const char *, size_t, void *), void *loader_data) { const char *cur, *next; size_t len; cur = search_path; while (cur) { next = strchr(cur, ':'); len = (next) ? next - cur : strlen(cur); if (!loader(cur, len, loader_data)) break; cur = (next) ? next + 1 : NULL; } } void for_each_in_search_path(bool (*callback)(const char *, size_t, void *), void *callback_data) { const char *search_path = get_search_path(); for_each_colon_separated(search_path, callback, callback_data); } static struct pipe_module { boolean initialized; char *name; struct util_dl_library *lib; const struct drm_driver_descriptor *drmdd; struct pipe_screen *(*swrast_create_screen)(struct sw_winsys *); } pipe_modules[16]; static bool dlopen_pipe_module_cb(const char *dir, size_t len, void *callback_data) { struct pipe_module *pmod = (struct pipe_module *) callback_data; char path[1024]; int ret; if (len) { ret = snprintf(path, sizeof(path), "%.*s/" PIPE_PREFIX "%s" UTIL_DL_EXT, len, dir, pmod->name); } else { ret = snprintf(path, sizeof(path), PIPE_PREFIX "%s" UTIL_DL_EXT, pmod->name); } if (ret > 0 && ret < (int)sizeof(path)) { pmod->lib = util_dl_open(path); } return !(pmod->lib); } static bool load_pipe_module(struct pipe_module *pmod, const char *name) { pmod->name = strdup(name); if (!pmod->name) return FALSE; for_each_in_search_path(dlopen_pipe_module_cb, (void *) pmod); if (pmod->lib) { pmod->drmdd = (const struct drm_driver_descriptor *) util_dl_get_proc_address(pmod->lib, "driver_descriptor"); /* sanity check on the name */ if (pmod->drmdd && strcmp(pmod->drmdd->name, pmod->name) != 0) pmod->drmdd = NULL; /* swrast */ if (pmod->drmdd && !pmod->drmdd->driver_name) { pmod->swrast_create_screen = (struct pipe_screen *(*)(struct sw_winsys *)) util_dl_get_proc_address(pmod->lib, "swrast_create_screen"); if (!pmod->swrast_create_screen) pmod->drmdd = NULL; } if (!pmod->drmdd) { util_dl_close(pmod->lib); pmod->lib = NULL; } } return (pmod->drmdd != NULL); } static struct pipe_module * get_pipe_module(const char *name) { struct pipe_module *pmod = NULL; unsigned i; if (!name) return NULL; for (i = 0; i < sizeof(pipe_modules) / sizeof(pipe_modules[0]); i++) { if (!pipe_modules[i].initialized || strcmp(pipe_modules[i].name, name) == 0) { pmod = &pipe_modules[i]; break; } } if (!pmod) return NULL; if (!pmod->initialized) { load_pipe_module(pmod, name); pmod->initialized = TRUE; } return pmod; } struct native_display; struct pipe_screen * dxgi_loader_create_drm_screen(struct native_display* dpy, const char *name, int fd) { struct pipe_module *pmod = get_pipe_module(name); return (pmod && pmod->drmdd && pmod->drmdd->create_screen) ? pmod->drmdd->create_screen(fd) : NULL; } struct pipe_screen * dxgi_loader_create_sw_screen(struct native_display* dpy, struct sw_winsys *ws) { struct pipe_module *pmod = get_pipe_module("swrast"); return (pmod && pmod->swrast_create_screen) ? pmod->swrast_create_screen(ws) : NULL; }