egldriver.c revision 848b8605
1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2008 VMware, Inc. 4848b8605Smrg * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5848b8605Smrg * Copyright 2010-2011 LunarG, Inc. 6848b8605Smrg * All Rights Reserved. 7848b8605Smrg * 8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9848b8605Smrg * copy of this software and associated documentation files (the 10848b8605Smrg * "Software"), to deal in the Software without restriction, including 11848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 12848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 13848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 14848b8605Smrg * the following conditions: 15848b8605Smrg * 16848b8605Smrg * The above copyright notice and this permission notice (including the 17848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 18848b8605Smrg * of the Software. 19848b8605Smrg * 20848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26848b8605Smrg * DEALINGS IN THE SOFTWARE. 27848b8605Smrg * 28848b8605Smrg **************************************************************************/ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg/** 32848b8605Smrg * Functions for choosing and opening/loading device drivers. 33848b8605Smrg */ 34848b8605Smrg 35848b8605Smrg 36848b8605Smrg#include <assert.h> 37848b8605Smrg#include <string.h> 38848b8605Smrg#include <stdio.h> 39848b8605Smrg#include <stdlib.h> 40848b8605Smrg 41848b8605Smrg#include "eglstring.h" 42848b8605Smrg#include "egldefines.h" 43848b8605Smrg#include "egldisplay.h" 44848b8605Smrg#include "egldriver.h" 45848b8605Smrg#include "egllog.h" 46848b8605Smrg#include "eglmutex.h" 47848b8605Smrg 48848b8605Smrg#if defined(_EGL_OS_UNIX) 49848b8605Smrg#include <dlfcn.h> 50848b8605Smrg#include <sys/types.h> 51848b8605Smrg#include <dirent.h> 52848b8605Smrg#include <unistd.h> 53848b8605Smrg#endif 54848b8605Smrg 55848b8605Smrg 56848b8605Smrgtypedef struct _egl_module { 57848b8605Smrg char *Path; 58848b8605Smrg _EGLMain_t BuiltIn; 59848b8605Smrg void *Handle; 60848b8605Smrg _EGLDriver *Driver; 61848b8605Smrg} _EGLModule; 62848b8605Smrg 63848b8605Smrgstatic _EGLMutex _eglModuleMutex = _EGL_MUTEX_INITIALIZER; 64848b8605Smrgstatic _EGLArray *_eglModules; 65848b8605Smrg 66848b8605Smrgconst struct { 67848b8605Smrg const char *name; 68848b8605Smrg _EGLMain_t main; 69848b8605Smrg} _eglBuiltInDrivers[] = { 70848b8605Smrg#ifdef _EGL_BUILT_IN_DRIVER_GALLIUM 71848b8605Smrg { "egl_gallium", _eglBuiltInDriverGALLIUM }, 72848b8605Smrg#endif 73848b8605Smrg#ifdef _EGL_BUILT_IN_DRIVER_DRI2 74848b8605Smrg { "egl_dri2", _eglBuiltInDriverDRI2 }, 75848b8605Smrg#endif 76848b8605Smrg { NULL, NULL } 77848b8605Smrg}; 78848b8605Smrg 79848b8605Smrg/** 80848b8605Smrg * Wrappers for dlopen/dlclose() 81848b8605Smrg */ 82848b8605Smrg#if defined(_EGL_OS_WINDOWS) 83848b8605Smrg 84848b8605Smrg 85848b8605Smrgtypedef HMODULE lib_handle; 86848b8605Smrg 87848b8605Smrgstatic HMODULE 88848b8605Smrgopen_library(const char *filename) 89848b8605Smrg{ 90848b8605Smrg return LoadLibrary(filename); 91848b8605Smrg} 92848b8605Smrg 93848b8605Smrgstatic void 94848b8605Smrgclose_library(HMODULE lib) 95848b8605Smrg{ 96848b8605Smrg FreeLibrary(lib); 97848b8605Smrg} 98848b8605Smrg 99848b8605Smrg 100848b8605Smrgstatic const char * 101848b8605Smrglibrary_suffix(void) 102848b8605Smrg{ 103848b8605Smrg return ".dll"; 104848b8605Smrg} 105848b8605Smrg 106848b8605Smrg 107848b8605Smrg#elif defined(_EGL_OS_UNIX) 108848b8605Smrg 109848b8605Smrg 110848b8605Smrgtypedef void * lib_handle; 111848b8605Smrg 112848b8605Smrgstatic void * 113848b8605Smrgopen_library(const char *filename) 114848b8605Smrg{ 115848b8605Smrg return dlopen(filename, RTLD_LAZY); 116848b8605Smrg} 117848b8605Smrg 118848b8605Smrgstatic void 119848b8605Smrgclose_library(void *lib) 120848b8605Smrg{ 121848b8605Smrg dlclose(lib); 122848b8605Smrg} 123848b8605Smrg 124848b8605Smrg 125848b8605Smrgstatic const char * 126848b8605Smrglibrary_suffix(void) 127848b8605Smrg{ 128848b8605Smrg return ".so"; 129848b8605Smrg} 130848b8605Smrg 131848b8605Smrg 132848b8605Smrg#endif 133848b8605Smrg 134848b8605Smrg 135848b8605Smrg/** 136848b8605Smrg * Open the named driver and find its bootstrap function: _eglMain(). 137848b8605Smrg */ 138848b8605Smrgstatic _EGLMain_t 139848b8605Smrg_eglOpenLibrary(const char *driverPath, lib_handle *handle) 140848b8605Smrg{ 141848b8605Smrg lib_handle lib; 142848b8605Smrg _EGLMain_t mainFunc = NULL; 143848b8605Smrg const char *error = "unknown error"; 144848b8605Smrg 145848b8605Smrg assert(driverPath); 146848b8605Smrg 147848b8605Smrg _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath); 148848b8605Smrg lib = open_library(driverPath); 149848b8605Smrg 150848b8605Smrg#if defined(_EGL_OS_WINDOWS) 151848b8605Smrg /* XXX untested */ 152848b8605Smrg if (lib) 153848b8605Smrg mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain"); 154848b8605Smrg#elif defined(_EGL_OS_UNIX) 155848b8605Smrg if (lib) { 156848b8605Smrg union { 157848b8605Smrg _EGLMain_t func; 158848b8605Smrg void *ptr; 159848b8605Smrg } tmp = { NULL }; 160848b8605Smrg /* direct cast gives a warning when compiled with -pedantic */ 161848b8605Smrg tmp.ptr = dlsym(lib, "_eglMain"); 162848b8605Smrg mainFunc = tmp.func; 163848b8605Smrg if (!mainFunc) 164848b8605Smrg error = dlerror(); 165848b8605Smrg } 166848b8605Smrg else { 167848b8605Smrg error = dlerror(); 168848b8605Smrg } 169848b8605Smrg#endif 170848b8605Smrg 171848b8605Smrg if (!lib) { 172848b8605Smrg _eglLog(_EGL_WARNING, "Could not open driver %s (%s)", 173848b8605Smrg driverPath, error); 174848b8605Smrg return NULL; 175848b8605Smrg } 176848b8605Smrg 177848b8605Smrg if (!mainFunc) { 178848b8605Smrg _eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)", 179848b8605Smrg driverPath, error); 180848b8605Smrg if (lib) 181848b8605Smrg close_library(lib); 182848b8605Smrg return NULL; 183848b8605Smrg } 184848b8605Smrg 185848b8605Smrg *handle = lib; 186848b8605Smrg return mainFunc; 187848b8605Smrg} 188848b8605Smrg 189848b8605Smrg 190848b8605Smrg/** 191848b8605Smrg * Load a module and create the driver object. 192848b8605Smrg */ 193848b8605Smrgstatic EGLBoolean 194848b8605Smrg_eglLoadModule(_EGLModule *mod) 195848b8605Smrg{ 196848b8605Smrg _EGLMain_t mainFunc; 197848b8605Smrg lib_handle lib; 198848b8605Smrg _EGLDriver *drv; 199848b8605Smrg 200848b8605Smrg if (mod->Driver) 201848b8605Smrg return EGL_TRUE; 202848b8605Smrg 203848b8605Smrg if (mod->BuiltIn) { 204848b8605Smrg lib = (lib_handle) NULL; 205848b8605Smrg mainFunc = mod->BuiltIn; 206848b8605Smrg } 207848b8605Smrg else { 208848b8605Smrg mainFunc = _eglOpenLibrary(mod->Path, &lib); 209848b8605Smrg if (!mainFunc) 210848b8605Smrg return EGL_FALSE; 211848b8605Smrg } 212848b8605Smrg 213848b8605Smrg drv = mainFunc(NULL); 214848b8605Smrg if (!drv) { 215848b8605Smrg if (lib) 216848b8605Smrg close_library(lib); 217848b8605Smrg return EGL_FALSE; 218848b8605Smrg } 219848b8605Smrg 220848b8605Smrg if (!drv->Name) { 221848b8605Smrg _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", mod->Path); 222848b8605Smrg drv->Name = "UNNAMED"; 223848b8605Smrg } 224848b8605Smrg 225848b8605Smrg mod->Handle = (void *) lib; 226848b8605Smrg mod->Driver = drv; 227848b8605Smrg 228848b8605Smrg return EGL_TRUE; 229848b8605Smrg} 230848b8605Smrg 231848b8605Smrg 232848b8605Smrg/** 233848b8605Smrg * Unload a module. 234848b8605Smrg */ 235848b8605Smrgstatic void 236848b8605Smrg_eglUnloadModule(_EGLModule *mod) 237848b8605Smrg{ 238848b8605Smrg#if defined(_EGL_OS_UNIX) 239848b8605Smrg /* destroy the driver */ 240848b8605Smrg if (mod->Driver && mod->Driver->Unload) 241848b8605Smrg mod->Driver->Unload(mod->Driver); 242848b8605Smrg 243848b8605Smrg /* 244848b8605Smrg * XXX At this point (atexit), the module might be the last reference to 245848b8605Smrg * libEGL. Closing the module might unmap libEGL and give problems. 246848b8605Smrg */ 247848b8605Smrg#if 0 248848b8605Smrg if (mod->Handle) 249848b8605Smrg close_library(mod->Handle); 250848b8605Smrg#endif 251848b8605Smrg#elif defined(_EGL_OS_WINDOWS) 252848b8605Smrg /* XXX Windows unloads DLLs before atexit */ 253848b8605Smrg#endif 254848b8605Smrg 255848b8605Smrg mod->Driver = NULL; 256848b8605Smrg mod->Handle = NULL; 257848b8605Smrg} 258848b8605Smrg 259848b8605Smrg 260848b8605Smrg/** 261848b8605Smrg * Add a module to the module array. 262848b8605Smrg */ 263848b8605Smrgstatic _EGLModule * 264848b8605Smrg_eglAddModule(const char *path) 265848b8605Smrg{ 266848b8605Smrg _EGLModule *mod; 267848b8605Smrg EGLint i; 268848b8605Smrg 269848b8605Smrg if (!_eglModules) { 270848b8605Smrg _eglModules = _eglCreateArray("Module", 8); 271848b8605Smrg if (!_eglModules) 272848b8605Smrg return NULL; 273848b8605Smrg } 274848b8605Smrg 275848b8605Smrg /* find duplicates */ 276848b8605Smrg for (i = 0; i < _eglModules->Size; i++) { 277848b8605Smrg mod = _eglModules->Elements[i]; 278848b8605Smrg if (strcmp(mod->Path, path) == 0) 279848b8605Smrg return mod; 280848b8605Smrg } 281848b8605Smrg 282848b8605Smrg /* allocate a new one */ 283848b8605Smrg mod = calloc(1, sizeof(*mod)); 284848b8605Smrg if (mod) { 285848b8605Smrg mod->Path = _eglstrdup(path); 286848b8605Smrg if (!mod->Path) { 287848b8605Smrg free(mod); 288848b8605Smrg mod = NULL; 289848b8605Smrg } 290848b8605Smrg } 291848b8605Smrg if (mod) { 292848b8605Smrg _eglAppendArray(_eglModules, (void *) mod); 293848b8605Smrg _eglLog(_EGL_DEBUG, "added %s to module array", mod->Path); 294848b8605Smrg } 295848b8605Smrg 296848b8605Smrg return mod; 297848b8605Smrg} 298848b8605Smrg 299848b8605Smrg 300848b8605Smrg/** 301848b8605Smrg * Free a module. 302848b8605Smrg */ 303848b8605Smrgstatic void 304848b8605Smrg_eglFreeModule(void *module) 305848b8605Smrg{ 306848b8605Smrg _EGLModule *mod = (_EGLModule *) module; 307848b8605Smrg 308848b8605Smrg _eglUnloadModule(mod); 309848b8605Smrg free(mod->Path); 310848b8605Smrg free(mod); 311848b8605Smrg} 312848b8605Smrg 313848b8605Smrg 314848b8605Smrg/** 315848b8605Smrg * A loader function for use with _eglPreloadForEach. The loader data is the 316848b8605Smrg * filename of the driver. This function stops on the first valid driver. 317848b8605Smrg */ 318848b8605Smrgstatic EGLBoolean 319848b8605Smrg_eglLoaderFile(const char *dir, size_t len, void *loader_data) 320848b8605Smrg{ 321848b8605Smrg char path[1024]; 322848b8605Smrg const char *filename = (const char *) loader_data; 323848b8605Smrg size_t flen = strlen(filename); 324848b8605Smrg 325848b8605Smrg /* make a full path */ 326848b8605Smrg if (len + flen + 2 > sizeof(path)) 327848b8605Smrg return EGL_TRUE; 328848b8605Smrg if (len) { 329848b8605Smrg memcpy(path, dir, len); 330848b8605Smrg path[len++] = '/'; 331848b8605Smrg } 332848b8605Smrg memcpy(path + len, filename, flen); 333848b8605Smrg len += flen; 334848b8605Smrg path[len] = '\0'; 335848b8605Smrg 336848b8605Smrg if (library_suffix()) { 337848b8605Smrg const char *suffix = library_suffix(); 338848b8605Smrg size_t slen = strlen(suffix); 339848b8605Smrg const char *p; 340848b8605Smrg EGLBoolean need_suffix; 341848b8605Smrg 342848b8605Smrg p = filename + flen - slen; 343848b8605Smrg need_suffix = (p < filename || strcmp(p, suffix) != 0); 344848b8605Smrg if (need_suffix) { 345848b8605Smrg /* overflow */ 346848b8605Smrg if (len + slen + 1 > sizeof(path)) 347848b8605Smrg return EGL_TRUE; 348848b8605Smrg strcpy(path + len, suffix); 349848b8605Smrg } 350848b8605Smrg } 351848b8605Smrg 352848b8605Smrg#if defined(_EGL_OS_UNIX) 353848b8605Smrg /* check if the file exists */ 354848b8605Smrg if (access(path, F_OK)) 355848b8605Smrg return EGL_TRUE; 356848b8605Smrg#endif 357848b8605Smrg 358848b8605Smrg _eglAddModule(path); 359848b8605Smrg 360848b8605Smrg return EGL_TRUE; 361848b8605Smrg} 362848b8605Smrg 363848b8605Smrg 364848b8605Smrg/** 365848b8605Smrg * Run the callback function on each driver directory. 366848b8605Smrg * 367848b8605Smrg * The process may end prematurely if the callback function returns false. 368848b8605Smrg */ 369848b8605Smrgstatic void 370848b8605Smrg_eglPreloadForEach(const char *search_path, 371848b8605Smrg EGLBoolean (*loader)(const char *, size_t, void *), 372848b8605Smrg void *loader_data) 373848b8605Smrg{ 374848b8605Smrg const char *cur, *next; 375848b8605Smrg size_t len; 376848b8605Smrg 377848b8605Smrg cur = search_path; 378848b8605Smrg while (cur) { 379848b8605Smrg next = strchr(cur, ':'); 380848b8605Smrg len = (next) ? next - cur : strlen(cur); 381848b8605Smrg 382848b8605Smrg if (!loader(cur, len, loader_data)) 383848b8605Smrg break; 384848b8605Smrg 385848b8605Smrg cur = (next) ? next + 1 : NULL; 386848b8605Smrg } 387848b8605Smrg} 388848b8605Smrg 389848b8605Smrg 390848b8605Smrg/** 391848b8605Smrg * Return a list of colon-separated driver directories. 392848b8605Smrg */ 393848b8605Smrgstatic const char * 394848b8605Smrg_eglGetSearchPath(void) 395848b8605Smrg{ 396848b8605Smrg static char search_path[1024]; 397848b8605Smrg 398848b8605Smrg#if defined(_EGL_OS_UNIX) || defined(_EGL_OS_WINDOWS) 399848b8605Smrg if (search_path[0] == '\0') { 400848b8605Smrg char *buf = search_path; 401848b8605Smrg size_t len = sizeof(search_path); 402848b8605Smrg EGLBoolean use_env; 403848b8605Smrg char dir_sep; 404848b8605Smrg int ret; 405848b8605Smrg 406848b8605Smrg#if defined(_EGL_OS_UNIX) 407848b8605Smrg use_env = (geteuid() == getuid() && getegid() == getgid()); 408848b8605Smrg dir_sep = '/'; 409848b8605Smrg#else 410848b8605Smrg use_env = EGL_TRUE; 411848b8605Smrg dir_sep = '\\'; 412848b8605Smrg#endif 413848b8605Smrg 414848b8605Smrg if (use_env) { 415848b8605Smrg char *p; 416848b8605Smrg 417848b8605Smrg /* extract the dirname from EGL_DRIVER */ 418848b8605Smrg p = getenv("EGL_DRIVER"); 419848b8605Smrg if (p && strchr(p, dir_sep)) { 420848b8605Smrg ret = _eglsnprintf(buf, len, "%s", p); 421848b8605Smrg if (ret > 0 && ret < len) { 422848b8605Smrg p = strrchr(buf, dir_sep); 423848b8605Smrg *p++ = ':'; 424848b8605Smrg 425848b8605Smrg len -= p - buf; 426848b8605Smrg buf = p; 427848b8605Smrg } 428848b8605Smrg } 429848b8605Smrg 430848b8605Smrg /* append EGL_DRIVERS_PATH */ 431848b8605Smrg p = getenv("EGL_DRIVERS_PATH"); 432848b8605Smrg if (p) { 433848b8605Smrg ret = _eglsnprintf(buf, len, "%s:", p); 434848b8605Smrg if (ret > 0 && ret < len) { 435848b8605Smrg buf += ret; 436848b8605Smrg len -= ret; 437848b8605Smrg } 438848b8605Smrg } 439848b8605Smrg } 440848b8605Smrg else { 441848b8605Smrg _eglLog(_EGL_DEBUG, 442848b8605Smrg "ignore EGL_DRIVERS_PATH for setuid/setgid binaries"); 443848b8605Smrg } 444848b8605Smrg 445848b8605Smrg ret = _eglsnprintf(buf, len, "%s", _EGL_DRIVER_SEARCH_DIR); 446848b8605Smrg if (ret < 0 || ret >= len) 447848b8605Smrg search_path[0] = '\0'; 448848b8605Smrg 449848b8605Smrg _eglLog(_EGL_DEBUG, "EGL search path is %s", search_path); 450848b8605Smrg } 451848b8605Smrg#endif /* defined(_EGL_OS_UNIX) || defined(_EGL_OS_WINDOWS) */ 452848b8605Smrg 453848b8605Smrg return search_path; 454848b8605Smrg} 455848b8605Smrg 456848b8605Smrg 457848b8605Smrg/** 458848b8605Smrg * Add the user driver to the module array. 459848b8605Smrg * 460848b8605Smrg * The user driver is specified by EGL_DRIVER. 461848b8605Smrg */ 462848b8605Smrgstatic EGLBoolean 463848b8605Smrg_eglAddUserDriver(void) 464848b8605Smrg{ 465848b8605Smrg const char *search_path = _eglGetSearchPath(); 466848b8605Smrg char *env; 467848b8605Smrg size_t name_len = 0; 468848b8605Smrg 469848b8605Smrg env = getenv("EGL_DRIVER"); 470848b8605Smrg#if defined(_EGL_OS_UNIX) 471848b8605Smrg if (env && strchr(env, '/')) { 472848b8605Smrg search_path = ""; 473848b8605Smrg if ((geteuid() != getuid() || getegid() != getgid())) { 474848b8605Smrg _eglLog(_EGL_DEBUG, 475848b8605Smrg "ignore EGL_DRIVER for setuid/setgid binaries"); 476848b8605Smrg env = NULL; 477848b8605Smrg } 478848b8605Smrg } 479848b8605Smrg else if (env) { 480848b8605Smrg char *suffix = strchr(env, '.'); 481848b8605Smrg name_len = (suffix) ? suffix - env : strlen(env); 482848b8605Smrg } 483848b8605Smrg#else 484848b8605Smrg if (env) 485848b8605Smrg name_len = strlen(env); 486848b8605Smrg#endif /* _EGL_OS_UNIX */ 487848b8605Smrg 488848b8605Smrg /* 489848b8605Smrg * Try built-in drivers first if we know the driver name. This makes sure 490848b8605Smrg * we do not load the outdated external driver that is still on the 491848b8605Smrg * filesystem. 492848b8605Smrg */ 493848b8605Smrg if (name_len) { 494848b8605Smrg _EGLModule *mod; 495848b8605Smrg EGLint i; 496848b8605Smrg 497848b8605Smrg for (i = 0; _eglBuiltInDrivers[i].name; i++) { 498848b8605Smrg if (strlen(_eglBuiltInDrivers[i].name) == name_len && 499848b8605Smrg !strncmp(_eglBuiltInDrivers[i].name, env, name_len)) { 500848b8605Smrg mod = _eglAddModule(env); 501848b8605Smrg if (mod) 502848b8605Smrg mod->BuiltIn = _eglBuiltInDrivers[i].main; 503848b8605Smrg 504848b8605Smrg return EGL_TRUE; 505848b8605Smrg } 506848b8605Smrg } 507848b8605Smrg } 508848b8605Smrg 509848b8605Smrg /* otherwise, treat env as a path */ 510848b8605Smrg if (env) { 511848b8605Smrg _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env); 512848b8605Smrg 513848b8605Smrg return EGL_TRUE; 514848b8605Smrg } 515848b8605Smrg 516848b8605Smrg return EGL_FALSE; 517848b8605Smrg} 518848b8605Smrg 519848b8605Smrg 520848b8605Smrg/** 521848b8605Smrg * Add egl_gallium to the module array. 522848b8605Smrg */ 523848b8605Smrgstatic void 524848b8605Smrg_eglAddGalliumDriver(void) 525848b8605Smrg{ 526848b8605Smrg#ifndef _EGL_BUILT_IN_DRIVER_GALLIUM 527848b8605Smrg void *external = (void *) "egl_gallium"; 528848b8605Smrg _eglPreloadForEach(_eglGetSearchPath(), _eglLoaderFile, external); 529848b8605Smrg#endif 530848b8605Smrg} 531848b8605Smrg 532848b8605Smrg 533848b8605Smrg/** 534848b8605Smrg * Add built-in drivers to the module array. 535848b8605Smrg */ 536848b8605Smrgstatic void 537848b8605Smrg_eglAddBuiltInDrivers(void) 538848b8605Smrg{ 539848b8605Smrg _EGLModule *mod; 540848b8605Smrg EGLint i; 541848b8605Smrg 542848b8605Smrg for (i = 0; _eglBuiltInDrivers[i].name; i++) { 543848b8605Smrg mod = _eglAddModule(_eglBuiltInDrivers[i].name); 544848b8605Smrg if (mod) 545848b8605Smrg mod->BuiltIn = _eglBuiltInDrivers[i].main; 546848b8605Smrg } 547848b8605Smrg} 548848b8605Smrg 549848b8605Smrg 550848b8605Smrg/** 551848b8605Smrg * Add drivers to the module array. Drivers will be loaded as they are matched 552848b8605Smrg * to displays. 553848b8605Smrg */ 554848b8605Smrgstatic EGLBoolean 555848b8605Smrg_eglAddDrivers(void) 556848b8605Smrg{ 557848b8605Smrg if (_eglModules) 558848b8605Smrg return EGL_TRUE; 559848b8605Smrg 560848b8605Smrg if (!_eglAddUserDriver()) { 561848b8605Smrg /* 562848b8605Smrg * Add other drivers only when EGL_DRIVER is not set. The order here 563848b8605Smrg * decides the priorities. 564848b8605Smrg */ 565848b8605Smrg _eglAddGalliumDriver(); 566848b8605Smrg _eglAddBuiltInDrivers(); 567848b8605Smrg } 568848b8605Smrg 569848b8605Smrg return (_eglModules != NULL); 570848b8605Smrg} 571848b8605Smrg 572848b8605Smrg 573848b8605Smrg/** 574848b8605Smrg * A helper function for _eglMatchDriver. It finds the first driver that can 575848b8605Smrg * initialize the display and return. 576848b8605Smrg */ 577848b8605Smrgstatic _EGLDriver * 578848b8605Smrg_eglMatchAndInitialize(_EGLDisplay *dpy) 579848b8605Smrg{ 580848b8605Smrg _EGLDriver *drv = NULL; 581848b8605Smrg EGLint i = 0; 582848b8605Smrg 583848b8605Smrg if (!_eglAddDrivers()) { 584848b8605Smrg _eglLog(_EGL_WARNING, "failed to find any driver"); 585848b8605Smrg return NULL; 586848b8605Smrg } 587848b8605Smrg 588848b8605Smrg if (dpy->Driver) { 589848b8605Smrg drv = dpy->Driver; 590848b8605Smrg /* no re-matching? */ 591848b8605Smrg if (!drv->API.Initialize(drv, dpy)) 592848b8605Smrg drv = NULL; 593848b8605Smrg return drv; 594848b8605Smrg } 595848b8605Smrg 596848b8605Smrg while (i < _eglModules->Size) { 597848b8605Smrg _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i]; 598848b8605Smrg 599848b8605Smrg if (!_eglLoadModule(mod)) { 600848b8605Smrg /* remove invalid modules */ 601848b8605Smrg _eglEraseArray(_eglModules, i, _eglFreeModule); 602848b8605Smrg continue; 603848b8605Smrg } 604848b8605Smrg 605848b8605Smrg if (mod->Driver->API.Initialize(mod->Driver, dpy)) { 606848b8605Smrg drv = mod->Driver; 607848b8605Smrg break; 608848b8605Smrg } 609848b8605Smrg else { 610848b8605Smrg i++; 611848b8605Smrg } 612848b8605Smrg } 613848b8605Smrg 614848b8605Smrg return drv; 615848b8605Smrg} 616848b8605Smrg 617848b8605Smrg 618848b8605Smrg/** 619848b8605Smrg * Match a display to a driver. The display is initialized unless test_only is 620848b8605Smrg * true. The matching is done by finding the first driver that can initialize 621848b8605Smrg * the display. 622848b8605Smrg */ 623848b8605Smrg_EGLDriver * 624848b8605Smrg_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only) 625848b8605Smrg{ 626848b8605Smrg _EGLDriver *best_drv; 627848b8605Smrg 628848b8605Smrg assert(!dpy->Initialized); 629848b8605Smrg 630848b8605Smrg _eglLockMutex(&_eglModuleMutex); 631848b8605Smrg 632848b8605Smrg /* set options */ 633848b8605Smrg dpy->Options.TestOnly = test_only; 634848b8605Smrg dpy->Options.UseFallback = EGL_FALSE; 635848b8605Smrg 636848b8605Smrg best_drv = _eglMatchAndInitialize(dpy); 637848b8605Smrg if (!best_drv) { 638848b8605Smrg dpy->Options.UseFallback = EGL_TRUE; 639848b8605Smrg best_drv = _eglMatchAndInitialize(dpy); 640848b8605Smrg } 641848b8605Smrg 642848b8605Smrg _eglUnlockMutex(&_eglModuleMutex); 643848b8605Smrg 644848b8605Smrg if (best_drv) { 645848b8605Smrg _eglLog(_EGL_DEBUG, "the best driver is %s%s", 646848b8605Smrg best_drv->Name, (test_only) ? " (test only) " : ""); 647848b8605Smrg if (!test_only) { 648848b8605Smrg dpy->Driver = best_drv; 649848b8605Smrg dpy->Initialized = EGL_TRUE; 650848b8605Smrg } 651848b8605Smrg } 652848b8605Smrg 653848b8605Smrg return best_drv; 654848b8605Smrg} 655848b8605Smrg 656848b8605Smrg 657848b8605Smrg__eglMustCastToProperFunctionPointerType 658848b8605Smrg_eglGetDriverProc(const char *procname) 659848b8605Smrg{ 660848b8605Smrg EGLint i; 661848b8605Smrg _EGLProc proc = NULL; 662848b8605Smrg 663848b8605Smrg if (!_eglModules) { 664848b8605Smrg /* load the driver for the default display */ 665848b8605Smrg EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 666848b8605Smrg _EGLDisplay *dpy = _eglLookupDisplay(egldpy); 667848b8605Smrg if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE)) 668848b8605Smrg return NULL; 669848b8605Smrg } 670848b8605Smrg 671848b8605Smrg for (i = 0; i < _eglModules->Size; i++) { 672848b8605Smrg _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i]; 673848b8605Smrg 674848b8605Smrg if (!mod->Driver) 675848b8605Smrg break; 676848b8605Smrg proc = mod->Driver->API.GetProcAddress(mod->Driver, procname); 677848b8605Smrg if (proc) 678848b8605Smrg break; 679848b8605Smrg } 680848b8605Smrg 681848b8605Smrg return proc; 682848b8605Smrg} 683848b8605Smrg 684848b8605Smrg 685848b8605Smrg/** 686848b8605Smrg * Unload all drivers. 687848b8605Smrg */ 688848b8605Smrgvoid 689848b8605Smrg_eglUnloadDrivers(void) 690848b8605Smrg{ 691848b8605Smrg /* this is called at atexit time */ 692848b8605Smrg if (_eglModules) { 693848b8605Smrg _eglDestroyArray(_eglModules, _eglFreeModule); 694848b8605Smrg _eglModules = NULL; 695848b8605Smrg } 696848b8605Smrg} 697848b8605Smrg 698848b8605Smrg 699848b8605Smrg/** 700848b8605Smrg * Invoke a callback function on each EGL search path. 701848b8605Smrg * 702848b8605Smrg * The first argument of the callback function is the name of the search path. 703848b8605Smrg * The second argument is the length of the name. 704848b8605Smrg */ 705848b8605Smrgvoid 706848b8605Smrg_eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *), 707848b8605Smrg void *callback_data) 708848b8605Smrg{ 709848b8605Smrg const char *search_path = _eglGetSearchPath(); 710848b8605Smrg _eglPreloadForEach(search_path, callback, callback_data); 711848b8605Smrg} 712