1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright (C) 2010 LunarG Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Chia-I Wu <olv (at) lunarg.com> 27 */ 28 29 #include "dxgi_private.h" 30 #include <stdio.h> 31 extern "C" 32 { 33 #include "state_tracker/drm_driver.h" 34 #include "util/u_dl.h" 35 } 36 #define PIPE_PREFIX "pipe_" 37 38 static const char * 39 get_search_path(void) 40 { 41 static const char *search_path; 42 43 if (!search_path) { 44 static char buffer[1024]; 45 const char *p; 46 int ret; 47 48 p = getenv("DXGI_DRIVERS_PATH"); 49 if(!p) 50 p = getenv("EGL_DRIVERS_PATH"); 51 #ifdef __unix__ 52 if (p && (geteuid() != getuid() || getegid() != getgid())) { 53 p = NULL; 54 } 55 #endif 56 57 if (p) { 58 ret = snprintf(buffer, sizeof(buffer), 59 "%s:%s", p, DXGI_DRIVER_SEARCH_DIR); 60 if (ret > 0 && ret < (int)sizeof(buffer)) 61 search_path = buffer; 62 } 63 } 64 if (!search_path) 65 search_path = DXGI_DRIVER_SEARCH_DIR; 66 67 return search_path; 68 } 69 70 static void 71 for_each_colon_separated(const char *search_path, 72 bool (*loader)(const char *, size_t, void *), 73 void *loader_data) 74 { 75 const char *cur, *next; 76 size_t len; 77 78 cur = search_path; 79 while (cur) { 80 next = strchr(cur, ':'); 81 len = (next) ? next - cur : strlen(cur); 82 83 if (!loader(cur, len, loader_data)) 84 break; 85 86 cur = (next) ? next + 1 : NULL; 87 } 88 } 89 90 void 91 for_each_in_search_path(bool (*callback)(const char *, size_t, void *), 92 void *callback_data) 93 { 94 const char *search_path = get_search_path(); 95 for_each_colon_separated(search_path, callback, callback_data); 96 } 97 98 static struct pipe_module { 99 boolean initialized; 100 char *name; 101 struct util_dl_library *lib; 102 const struct drm_driver_descriptor *drmdd; 103 struct pipe_screen *(*swrast_create_screen)(struct sw_winsys *); 104 } pipe_modules[16]; 105 106 static bool 107 dlopen_pipe_module_cb(const char *dir, size_t len, void *callback_data) 108 { 109 struct pipe_module *pmod = (struct pipe_module *) callback_data; 110 char path[1024]; 111 int ret; 112 113 if (len) { 114 ret = snprintf(path, sizeof(path), 115 "%.*s/" PIPE_PREFIX "%s" UTIL_DL_EXT, len, dir, pmod->name); 116 } 117 else { 118 ret = snprintf(path, sizeof(path), 119 PIPE_PREFIX "%s" UTIL_DL_EXT, pmod->name); 120 } 121 if (ret > 0 && ret < (int)sizeof(path)) { 122 pmod->lib = util_dl_open(path); 123 } 124 125 return !(pmod->lib); 126 } 127 128 static bool 129 load_pipe_module(struct pipe_module *pmod, const char *name) 130 { 131 pmod->name = strdup(name); 132 if (!pmod->name) 133 return FALSE; 134 135 for_each_in_search_path(dlopen_pipe_module_cb, (void *) pmod); 136 if (pmod->lib) { 137 pmod->drmdd = (const struct drm_driver_descriptor *) 138 util_dl_get_proc_address(pmod->lib, "driver_descriptor"); 139 140 /* sanity check on the name */ 141 if (pmod->drmdd && strcmp(pmod->drmdd->name, pmod->name) != 0) 142 pmod->drmdd = NULL; 143 144 /* swrast */ 145 if (pmod->drmdd && !pmod->drmdd->driver_name) { 146 pmod->swrast_create_screen = 147 (struct pipe_screen *(*)(struct sw_winsys *)) 148 util_dl_get_proc_address(pmod->lib, "swrast_create_screen"); 149 if (!pmod->swrast_create_screen) 150 pmod->drmdd = NULL; 151 } 152 153 if (!pmod->drmdd) { 154 util_dl_close(pmod->lib); 155 pmod->lib = NULL; 156 } 157 } 158 159 return (pmod->drmdd != NULL); 160 } 161 162 163 static struct pipe_module * 164 get_pipe_module(const char *name) 165 { 166 struct pipe_module *pmod = NULL; 167 unsigned i; 168 169 if (!name) 170 return NULL; 171 172 for (i = 0; i < sizeof(pipe_modules) / sizeof(pipe_modules[0]); i++) { 173 if (!pipe_modules[i].initialized || 174 strcmp(pipe_modules[i].name, name) == 0) { 175 pmod = &pipe_modules[i]; 176 break; 177 } 178 } 179 if (!pmod) 180 return NULL; 181 182 if (!pmod->initialized) { 183 load_pipe_module(pmod, name); 184 pmod->initialized = TRUE; 185 } 186 187 return pmod; 188 } 189 190 struct native_display; 191 192 struct pipe_screen * 193 dxgi_loader_create_drm_screen(struct native_display* dpy, const char *name, int fd) 194 { 195 struct pipe_module *pmod = get_pipe_module(name); 196 return (pmod && pmod->drmdd && pmod->drmdd->create_screen) ? 197 pmod->drmdd->create_screen(fd) : NULL; 198 } 199 200 struct pipe_screen * 201 dxgi_loader_create_sw_screen(struct native_display* dpy, struct sw_winsys *ws) 202 { 203 struct pipe_module *pmod = get_pipe_module("swrast"); 204 return (pmod && pmod->swrast_create_screen) ? 205 pmod->swrast_create_screen(ws) : NULL; 206 } 207