egldriver.c revision f36cba6cf3d51a3937d3bb429609d258399751a0
16052af172f0241e6678cd16efac0a0f14f40146cBrian Paul/**
26052af172f0241e6678cd16efac0a0f14f40146cBrian Paul * Functions for choosing and opening/loading device drivers.
36052af172f0241e6678cd16efac0a0f14f40146cBrian Paul */
46052af172f0241e6678cd16efac0a0f14f40146cBrian Paul
56052af172f0241e6678cd16efac0a0f14f40146cBrian Paul
6adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include <assert.h>
711a261ef4f1d4100c46f73ad51e7e4ed57cc1b5eBrian Paul#include <string.h>
8adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include <stdio.h>
90c8908c411c434eda318b41b4f2a370a1e794831Brian Paul#include <stdlib.h>
101e6c10f4be9e36cc052a6b47fb2cb1eae60caa00Chia-I Wu
111e6c10f4be9e36cc052a6b47fb2cb1eae60caa00Chia-I Wu#include "eglstring.h"
12e084fe54f93c9d51df99812b76d3299b0cff57a3Brian Paul#include "egldefines.h"
13adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include "egldisplay.h"
14adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include "egldriver.h"
15b711eb793b68bb0c4561e5e345b76453dfac286bBrian Paul#include "egllog.h"
16f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu#include "eglmutex.h"
17adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul
186f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#if defined(_EGL_OS_UNIX)
196b389b5c2facc431af0ffb21e3a9bcd532765367Brian Paul#include <dlfcn.h>
20b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu#include <sys/types.h>
21b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu#include <dirent.h>
225d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu#include <unistd.h>
23b870bf79b5387f26668285f44ccbf5812ad62e10Jakob Bornecrantz#endif
24adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul
255541988578054345ca70b7ed7972710396e61b44Chia-I Wu
26f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wutypedef struct _egl_module {
27f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   char *Path;
28c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLMain_t BuiltIn;
29f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   void *Handle;
30f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLDriver *Driver;
31f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu} _EGLModule;
32f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
33f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGL_DECLARE_MUTEX(_eglModuleMutex);
34f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGLArray *_eglModules;
35f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
36c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wuconst struct {
37c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   const char *name;
38c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLMain_t main;
39c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu} _eglBuiltInDrivers[] = {
40a8b6b6555c7d6a02a3d095c72ebbdc218bc45cd3Chia-I Wu#ifdef _EGL_BUILT_IN_DRIVER_GALLIUM
41a8b6b6555c7d6a02a3d095c72ebbdc218bc45cd3Chia-I Wu   { "egl_gallium", _eglBuiltInDriverGALLIUM },
42a8b6b6555c7d6a02a3d095c72ebbdc218bc45cd3Chia-I Wu#endif
43c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#ifdef _EGL_BUILT_IN_DRIVER_DRI2
44c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { "egl_dri2", _eglBuiltInDriverDRI2 },
45c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#endif
46c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#ifdef _EGL_BUILT_IN_DRIVER_GLX
47c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { "egl_glx", _eglBuiltInDriverGLX },
48c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#endif
49c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { NULL, NULL }
50c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu};
51f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
52a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul/**
53a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul * Wrappers for dlopen/dlclose()
54a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul */
556f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#if defined(_EGL_OS_WINDOWS)
56a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul
575541988578054345ca70b7ed7972710396e61b44Chia-I Wu
585541988578054345ca70b7ed7972710396e61b44Chia-I Wutypedef HMODULE lib_handle;
595541988578054345ca70b7ed7972710396e61b44Chia-I Wu
605541988578054345ca70b7ed7972710396e61b44Chia-I Wustatic HMODULE
615541988578054345ca70b7ed7972710396e61b44Chia-I Wuopen_library(const char *filename)
625541988578054345ca70b7ed7972710396e61b44Chia-I Wu{
635541988578054345ca70b7ed7972710396e61b44Chia-I Wu   return LoadLibrary(filename);
645541988578054345ca70b7ed7972710396e61b44Chia-I Wu}
655541988578054345ca70b7ed7972710396e61b44Chia-I Wu
665541988578054345ca70b7ed7972710396e61b44Chia-I Wustatic void
675541988578054345ca70b7ed7972710396e61b44Chia-I Wuclose_library(HMODULE lib)
685541988578054345ca70b7ed7972710396e61b44Chia-I Wu{
695541988578054345ca70b7ed7972710396e61b44Chia-I Wu   FreeLibrary(lib);
705541988578054345ca70b7ed7972710396e61b44Chia-I Wu}
715541988578054345ca70b7ed7972710396e61b44Chia-I Wu
72ab0d13dd60c707f2c414fa9fe8e489a9e24a8aeeJonathan White
73b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wustatic const char *
74b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wulibrary_suffix(void)
75b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
765d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   return ".dll";
7721b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu}
7821b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu
7921b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu
806f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#elif defined(_EGL_OS_UNIX)
81a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul
82a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul
835541988578054345ca70b7ed7972710396e61b44Chia-I Wutypedef void * lib_handle;
845541988578054345ca70b7ed7972710396e61b44Chia-I Wu
855541988578054345ca70b7ed7972710396e61b44Chia-I Wustatic void *
865541988578054345ca70b7ed7972710396e61b44Chia-I Wuopen_library(const char *filename)
875541988578054345ca70b7ed7972710396e61b44Chia-I Wu{
885541988578054345ca70b7ed7972710396e61b44Chia-I Wu   return dlopen(filename, RTLD_LAZY);
895541988578054345ca70b7ed7972710396e61b44Chia-I Wu}
905541988578054345ca70b7ed7972710396e61b44Chia-I Wu
915541988578054345ca70b7ed7972710396e61b44Chia-I Wustatic void
925541988578054345ca70b7ed7972710396e61b44Chia-I Wuclose_library(void *lib)
935541988578054345ca70b7ed7972710396e61b44Chia-I Wu{
945541988578054345ca70b7ed7972710396e61b44Chia-I Wu   dlclose(lib);
955541988578054345ca70b7ed7972710396e61b44Chia-I Wu}
965541988578054345ca70b7ed7972710396e61b44Chia-I Wu
97b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
98b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wustatic const char *
99b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wulibrary_suffix(void)
100b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
1015d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   return ".so";
10221b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu}
10321b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu
10421b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu
105a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul#endif
106a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul
1070eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
108adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul/**
1090eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu * Open the named driver and find its bootstrap function: _eglMain().
110adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul */
1110eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wustatic _EGLMain_t
112b1f156f0ecc93e456757fa95497b2af9b045d4deChia-I Wu_eglOpenLibrary(const char *driverPath, lib_handle *handle)
113adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul{
114a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul   lib_handle lib;
1155541988578054345ca70b7ed7972710396e61b44Chia-I Wu   _EGLMain_t mainFunc = NULL;
1165541988578054345ca70b7ed7972710396e61b44Chia-I Wu   const char *error = "unknown error";
117adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul
118b1f156f0ecc93e456757fa95497b2af9b045d4deChia-I Wu   assert(driverPath);
1196052af172f0241e6678cd16efac0a0f14f40146cBrian Paul
120b1f156f0ecc93e456757fa95497b2af9b045d4deChia-I Wu   _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
121b1f156f0ecc93e456757fa95497b2af9b045d4deChia-I Wu   lib = open_library(driverPath);
1225541988578054345ca70b7ed7972710396e61b44Chia-I Wu
1236f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#if defined(_EGL_OS_WINDOWS)
1245541988578054345ca70b7ed7972710396e61b44Chia-I Wu   /* XXX untested */
1255541988578054345ca70b7ed7972710396e61b44Chia-I Wu   if (lib)
1265541988578054345ca70b7ed7972710396e61b44Chia-I Wu      mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
1276f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#elif defined(_EGL_OS_UNIX)
1285541988578054345ca70b7ed7972710396e61b44Chia-I Wu   if (lib) {
129496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu      union {
130496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu         _EGLMain_t func;
131496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu         void *ptr;
132496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu      } tmp = { NULL };
133496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu      /* direct cast gives a warning when compiled with -pedantic */
134496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu      tmp.ptr = dlsym(lib, "_eglMain");
135496724b869d4258a64e8343d3ae66d08bfb19f7bChia-I Wu      mainFunc = tmp.func;
1365541988578054345ca70b7ed7972710396e61b44Chia-I Wu      if (!mainFunc)
1375541988578054345ca70b7ed7972710396e61b44Chia-I Wu         error = dlerror();
1385541988578054345ca70b7ed7972710396e61b44Chia-I Wu   }
1395541988578054345ca70b7ed7972710396e61b44Chia-I Wu   else {
1405541988578054345ca70b7ed7972710396e61b44Chia-I Wu      error = dlerror();
141ab0d13dd60c707f2c414fa9fe8e489a9e24a8aeeJonathan White   }
142ab0d13dd60c707f2c414fa9fe8e489a9e24a8aeeJonathan White#endif
1435541988578054345ca70b7ed7972710396e61b44Chia-I Wu
144485528f2acb69940a7c757638127f716c0cb2654Jon Smirl   if (!lib) {
1455541988578054345ca70b7ed7972710396e61b44Chia-I Wu      _eglLog(_EGL_WARNING, "Could not open driver %s (%s)",
1465541988578054345ca70b7ed7972710396e61b44Chia-I Wu              driverPath, error);
147485528f2acb69940a7c757638127f716c0cb2654Jon Smirl      return NULL;
148485528f2acb69940a7c757638127f716c0cb2654Jon Smirl   }
1496b389b5c2facc431af0ffb21e3a9bcd532765367Brian Paul
150485528f2acb69940a7c757638127f716c0cb2654Jon Smirl   if (!mainFunc) {
1515541988578054345ca70b7ed7972710396e61b44Chia-I Wu      _eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)",
1525541988578054345ca70b7ed7972710396e61b44Chia-I Wu              driverPath, error);
1530eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu      if (lib)
1540eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu         close_library(lib);
155485528f2acb69940a7c757638127f716c0cb2654Jon Smirl      return NULL;
156adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul   }
157485528f2acb69940a7c757638127f716c0cb2654Jon Smirl
1580eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   *handle = lib;
1590eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   return mainFunc;
1600eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
1610eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1620eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1630eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
164f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Load a module and create the driver object.
1650eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu */
166f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic EGLBoolean
167f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglLoadModule(_EGLModule *mod)
1680eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu{
1690eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   _EGLMain_t mainFunc;
1700eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   lib_handle lib;
171f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLDriver *drv;
1720eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
173c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   if (mod->Driver)
174c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      return EGL_TRUE;
175c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu
176c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   if (mod->BuiltIn) {
177c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      lib = (lib_handle) NULL;
178c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      mainFunc = mod->BuiltIn;
179c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   }
180c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   else {
181c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      mainFunc = _eglOpenLibrary(mod->Path, &lib);
182c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      if (!mainFunc)
183c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         return EGL_FALSE;
184c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   }
1850eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
186f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   drv = mainFunc(NULL);
187485528f2acb69940a7c757638127f716c0cb2654Jon Smirl   if (!drv) {
1880eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu      if (lib)
1890eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu         close_library(lib);
190f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      return EGL_FALSE;
191adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul   }
1926b389b5c2facc431af0ffb21e3a9bcd532765367Brian Paul
1930eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   if (!drv->Name) {
194f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", mod->Path);
1950eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu      drv->Name = "UNNAMED";
1966b389b5c2facc431af0ffb21e3a9bcd532765367Brian Paul   }
1970eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
198f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Handle = (void *) lib;
199f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Driver = drv;
200f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
201f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return EGL_TRUE;
202f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
203b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
2040eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
205f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
206f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Unload a module.
207f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
208f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
209f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglUnloadModule(_EGLModule *mod)
210f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
211d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#if defined(_EGL_OS_UNIX)
212f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* destroy the driver */
213f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod->Driver && mod->Driver->Unload)
214f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod->Driver->Unload(mod->Driver);
215d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu
216d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu   /*
217d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu    * XXX At this point (atexit), the module might be the last reference to
218d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu    * libEGL.  Closing the module might unmap libEGL and give problems.
219d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu    */
220d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#if 0
221f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod->Handle)
222f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      close_library(mod->Handle);
223d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#endif
224d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#elif defined(_EGL_OS_WINDOWS)
225d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu   /* XXX Windows unloads DLLs before atexit */
226d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#endif
227f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
228f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Driver = NULL;
229f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Handle = NULL;
2300eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
2310eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
2320eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
2330eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
234f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add a module to the module array.
2350eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu */
236f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGLModule *
237f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddModule(const char *path)
2380eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu{
239f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLModule *mod;
240f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
2410eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
242f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglModules) {
243f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglModules = _eglCreateArray("Module", 8);
244f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!_eglModules)
245f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return NULL;
246f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
247cf22fd5e5b13ccdb02ba0368ea722ede3bbc6de0Chia-I Wu
248f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* find duplicates */
249f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   for (i = 0; i < _eglModules->Size; i++) {
250f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod = _eglModules->Elements[i];
251f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (strcmp(mod->Path, path) == 0)
252f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return mod;
253f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
254f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
255f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* allocate a new one */
256f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod = calloc(1, sizeof(*mod));
257f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod) {
258f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod->Path = _eglstrdup(path);
259f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!mod->Path) {
260f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         free(mod);
261f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         mod = NULL;
2620eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu      }
2630eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   }
264f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod) {
265f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglAppendArray(_eglModules, (void *) mod);
266f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglLog(_EGL_DEBUG, "added %s to module array", mod->Path);
267f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
2680eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
269f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return mod;
270f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
271f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
272f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
273f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
274f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Free a module.
275f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
276f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
277f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglFreeModule(void *module)
278f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
279f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLModule *mod = (_EGLModule *) module;
280f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
281f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _eglUnloadModule(mod);
282f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   free(mod->Path);
283f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   free(mod);
2840eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
2850eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
2860eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
2870eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
2880d089cbb48d099b833768556266114d537c91299Chia-I Wu * A loader function for use with _eglPreloadForEach.  The loader data is the
2895d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu * filename of the driver.   This function stops on the first valid driver.
2905d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu */
2915d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wustatic EGLBoolean
2920d089cbb48d099b833768556266114d537c91299Chia-I Wu_eglLoaderFile(const char *dir, size_t len, void *loader_data)
2935d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu{
2945d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   char path[1024];
2950d089cbb48d099b833768556266114d537c91299Chia-I Wu   const char *filename = (const char *) loader_data;
2965d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   size_t flen = strlen(filename);
2975d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
2985d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   /* make a full path */
2995d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   if (len + flen + 2 > sizeof(path))
3005d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      return EGL_TRUE;
3015d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   if (len) {
3025d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      memcpy(path, dir, len);
3035d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      path[len++] = '/';
3045d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   }
3055d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   memcpy(path + len, filename, flen);
3065d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   len += flen;
3075d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   path[len] = '\0';
3085d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
309f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (library_suffix()) {
3105d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      const char *suffix = library_suffix();
3115d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      size_t slen = strlen(suffix);
3125d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      const char *p;
3135d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      EGLBoolean need_suffix;
3145d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3155d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      p = filename + flen - slen;
3165d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      need_suffix = (p < filename || strcmp(p, suffix) != 0);
317f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (need_suffix) {
318f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         /* overflow */
319f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         if (len + slen + 1 > sizeof(path))
320f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu            return EGL_TRUE;
3215d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu         strcpy(path + len, suffix);
3225d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      }
3235d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   }
324f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
325f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu#if defined(_EGL_OS_UNIX)
326f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* check if the file exists */
327f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (access(path, F_OK))
3285d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      return EGL_TRUE;
329f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu#endif
330f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
331f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _eglAddModule(path);
332f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
333f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return EGL_TRUE;
334f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
335f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
3365d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
337f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
338f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Run the callback function on each driver directory.
3395d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu *
3405d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu * The process may end prematurely if the callback function returns false.
3415d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu */
342f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
3435d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu_eglPreloadForEach(const char *search_path,
3440d089cbb48d099b833768556266114d537c91299Chia-I Wu                   EGLBoolean (*loader)(const char *, size_t, void *),
3450d089cbb48d099b833768556266114d537c91299Chia-I Wu                   void *loader_data)
3465d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu{
3475d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   const char *cur, *next;
3485d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   size_t len;
3495d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3505d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   cur = search_path;
3515d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   while (cur) {
3525d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      next = strchr(cur, ':');
3535d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      len = (next) ? next - cur : strlen(cur);
3545d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
35588af76ce94834d795c11445b1c82b7aa874b87d5Igor Oliveira      if (!loader(cur, len, loader_data))
3565d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu         break;
3575d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3585d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      cur = (next) ? next + 1 : NULL;
3595d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   }
3605d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu}
3615d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3625d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3635d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu/**
3645d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu * Return a list of colon-separated driver directories.
3655d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu */
3665d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wustatic const char *
3675d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu_eglGetSearchPath(void)
3685d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu{
369ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu   static char search_path[1024];
3705d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3716f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#if defined(_EGL_OS_UNIX) || defined(_EGL_OS_WINDOWS)
372ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu   if (search_path[0] == '\0') {
373ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      char *buf = search_path;
374ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      size_t len = sizeof(search_path);
375ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      EGLBoolean use_env;
376ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      char dir_sep;
3775d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      int ret;
3785d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
3796f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#if defined(_EGL_OS_UNIX)
380ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      use_env = (geteuid() == getuid() && getegid() == getgid());
381ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      dir_sep = '/';
382ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu#else
383ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      use_env = EGL_TRUE;
384ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      dir_sep = '\\';
385ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu#endif
386ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu
387ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      if (use_env) {
388ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         char *p;
389ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu
390ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         /* extract the dirname from EGL_DRIVER */
391ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         p = getenv("EGL_DRIVER");
392ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         if (p && strchr(p, dir_sep)) {
393ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu            ret = _eglsnprintf(buf, len, "%s", p);
394ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu            if (ret > 0 && ret < len) {
395ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu               p = strrchr(buf, dir_sep);
396ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu               *p++ = ':';
397ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu
398ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu               len -= p - buf;
399ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu               buf = p;
400ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu            }
401ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         }
402ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu
403ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         /* append EGL_DRIVERS_PATH */
404ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         p = getenv("EGL_DRIVERS_PATH");
405ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         if (p) {
406ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu            ret = _eglsnprintf(buf, len, "%s:", p);
407ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu            if (ret > 0 && ret < len) {
408ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu               buf += ret;
409ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu               len -= ret;
410ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu            }
411ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         }
412ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      }
413ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      else {
4146fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu         _eglLog(_EGL_DEBUG,
4156fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu               "ignore EGL_DRIVERS_PATH for setuid/setgid binaries");
4166fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu      }
4176fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu
418ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      ret = _eglsnprintf(buf, len, "%s", _EGL_DRIVER_SEARCH_DIR);
419ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      if (ret < 0 || ret >= len)
420ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         search_path[0] = '\0';
421ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu
422ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      _eglLog(_EGL_DEBUG, "EGL search path is %s", search_path);
4235d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   }
424ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu#endif /* defined(_EGL_OS_UNIX) || defined(_EGL_OS_WINDOWS) */
4255d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
4265d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   return search_path;
4275d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu}
4285d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
4295d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu
4305d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu/**
431f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add the user driver to the module array.
432b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu *
433f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * The user driver is specified by EGL_DRIVER.
434b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu */
4351e4f412242391000eea3fd28452865c3d27f987dChia-I Wustatic EGLBoolean
436f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddUserDriver(void)
437b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
4385d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu   const char *search_path = _eglGetSearchPath();
43921b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu   char *env;
440f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   size_t name_len = 0;
441b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
442b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu   env = getenv("EGL_DRIVER");
4436f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#if defined(_EGL_OS_UNIX)
4446fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu   if (env && strchr(env, '/')) {
4455d8646c41ff3022692fa9d7f5f1644a2a60641e4Chia-I Wu      search_path = "";
4466fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu      if ((geteuid() != getuid() || getegid() != getgid())) {
4476fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu         _eglLog(_EGL_DEBUG,
4486fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu               "ignore EGL_DRIVER for setuid/setgid binaries");
4496fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu         env = NULL;
4506fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu      }
4516fd8b6a9e22f474117281b00d15c548c29b8197fChia-I Wu   }
452f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   else if (env) {
453f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu      char *suffix = strchr(env, '.');
454f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu      name_len = (suffix) ? suffix - env : strlen(env);
455f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   }
456f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu#else
457f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   if (env)
458f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu      name_len = strlen(env);
4596f690caddcd9afbea6ed3e743b0c95c02c85e5efChia-I Wu#endif /* _EGL_OS_UNIX */
460f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
461f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   /*
462f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu    * Try built-in drivers first if we know the driver name.  This makes sure
463f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu    * we do not load the outdated external driver that is still on the
464f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu    * filesystem.
465f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu    */
466f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   if (name_len) {
467c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      _EGLModule *mod;
468c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      EGLint i;
469c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu
470c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      for (i = 0; _eglBuiltInDrivers[i].name; i++) {
471f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu         if (strlen(_eglBuiltInDrivers[i].name) == name_len &&
472f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu             !strncmp(_eglBuiltInDrivers[i].name, env, name_len)) {
473c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu            mod = _eglAddModule(env);
474c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu            if (mod)
475c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu               mod->BuiltIn = _eglBuiltInDrivers[i].main;
476f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
477f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu            return EGL_TRUE;
478c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         }
479c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      }
480f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   }
481f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
482f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   /* otherwise, treat env as a path */
483f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   if (env) {
484f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu      _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
4851e4f412242391000eea3fd28452865c3d27f987dChia-I Wu
4861e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      return EGL_TRUE;
487c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   }
4881e4f412242391000eea3fd28452865c3d27f987dChia-I Wu
4891e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   return EGL_FALSE;
490f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
491b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
492f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
493f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
49449ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu * Add egl_gallium to the module array.
49549ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu */
49649ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wustatic void
49749ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu_eglAddGalliumDriver(void)
49849ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu{
49949ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu#ifndef _EGL_BUILT_IN_DRIVER_GALLIUM
50049ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu   void *external = (void *) "egl_gallium";
50149ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu   _eglPreloadForEach(_eglGetSearchPath(), _eglLoaderFile, external);
50249ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu#endif
50349ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu}
50449ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu
50549ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu
50649ed5bb28d501cd6751bd59dc25a60a4293bcd75Chia-I Wu/**
507c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu * Add built-in drivers to the module array.
508f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
509f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
510c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu_eglAddBuiltInDrivers(void)
511f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
512c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLModule *mod;
513f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
514f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
515c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   for (i = 0; _eglBuiltInDrivers[i].name; i++) {
516c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      mod = _eglAddModule(_eglBuiltInDrivers[i].name);
517c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      if (mod)
518c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         mod->BuiltIn = _eglBuiltInDrivers[i].main;
51921b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu   }
520f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
521b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
522f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
523f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
524f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add drivers to the module array.  Drivers will be loaded as they are matched
525f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * to displays.
526f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
527f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic EGLBoolean
528f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddDrivers(void)
529f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
530f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (_eglModules)
531f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      return EGL_TRUE;
532f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
5331e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   if (!_eglAddUserDriver()) {
5341e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      /*
5351e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       * Add other drivers only when EGL_DRIVER is not set.  The order here
5361e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       * decides the priorities.
5371e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       */
5381e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglAddGalliumDriver();
5391e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglAddBuiltInDrivers();
5401e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   }
541f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
542f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return (_eglModules != NULL);
543b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu}
544b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
545b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
546b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu/**
547655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * A helper function for _eglMatchDriver.  It finds the first driver that can
548655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * initialize the display and return.
549b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu */
550655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wustatic _EGLDriver *
551655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_eglMatchAndInitialize(_EGLDisplay *dpy)
552b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
553655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _EGLDriver *drv = NULL;
554655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   EGLint i = 0;
5554afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
556f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglAddDrivers()) {
5571e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglLog(_EGL_WARNING, "failed to find any driver");
558655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      return NULL;
5594afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu   }
560b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
561655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   if (dpy->Driver) {
562655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      drv = dpy->Driver;
563655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      /* no re-matching? */
564655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!drv->API.Initialize(drv, dpy))
565655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         drv = NULL;
566655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      return drv;
567655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   }
568b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
569655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   while (i < _eglModules->Size) {
570655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
571655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
572655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!_eglLoadModule(mod)) {
573655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         /* remove invalid modules */
574655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         _eglEraseArray(_eglModules, i, _eglFreeModule);
575655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         continue;
576655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      }
577655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
578655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
579655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         drv = mod->Driver;
580655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         break;
581f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
582f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      else {
583655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         i++;
584f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
585f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
5864afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
587655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   return drv;
588655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu}
589b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
5904afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
591655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu/**
592655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * Match a display to a driver.  The display is initialized unless test_only is
593655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * true.  The matching is done by finding the first driver that can initialize
594655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * the display.
595655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu */
596655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_EGLDriver *
597655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
598655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu{
599655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _EGLDriver *best_drv;
600f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
601655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   assert(!dpy->Initialized);
602f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
603655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _eglLockMutex(&_eglModuleMutex);
604655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
605655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   /* set options */
606655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   dpy->Options.TestOnly = test_only;
607a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   dpy->Options.UseFallback = EGL_FALSE;
608655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
609655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   best_drv = _eglMatchAndInitialize(dpy);
610a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   if (!best_drv) {
611a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu      dpy->Options.UseFallback = EGL_TRUE;
612a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu      best_drv = _eglMatchAndInitialize(dpy);
613a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   }
6140eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
615f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _eglUnlockMutex(&_eglModuleMutex);
616f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
617f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (best_drv) {
618655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      _eglLog(_EGL_DEBUG, "the best driver is %s%s",
619655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu            best_drv->Name, (test_only) ? " (test only) " : "");
620655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!test_only) {
621f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         dpy->Driver = best_drv;
622f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         dpy->Initialized = EGL_TRUE;
623f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
624f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
625f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
626f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return best_drv;
627e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul}
628e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul
629f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
630f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu__eglMustCastToProperFunctionPointerType
631f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglGetDriverProc(const char *procname)
632681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg{
633f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
634f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLProc proc = NULL;
635f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
636f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglModules) {
637f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      /* load the driver for the default display */
638f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
639f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
640f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
641f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return NULL;
642f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
643681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
644f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   for (i = 0; i < _eglModules->Size; i++) {
645f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
646681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
647f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!mod->Driver)
648f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         break;
649f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
650f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (proc)
651afcea9b115cdfa0a6c948784f753d38b43240d25Chia-I Wu         break;
652afcea9b115cdfa0a6c948784f753d38b43240d25Chia-I Wu   }
653681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
654f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return proc;
655f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
656f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
657681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
658f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
659f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Unload all drivers.
660f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
661f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wuvoid
662f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglUnloadDrivers(void)
663f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
664f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* this is called at atexit time */
665f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (_eglModules) {
666f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglDestroyArray(_eglModules, _eglFreeModule);
667f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglModules = NULL;
668f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
669681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg}
670681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
671e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul
672e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul/**
673e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu * Invoke a callback function on each EGL search path.
674e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu *
675e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu * The first argument of the callback function is the name of the search path.
676e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu * The second argument is the length of the name.
677e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu */
678e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wuvoid
679e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu_eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
680e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu                      void *callback_data)
681e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu{
682e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu   const char *search_path = _eglGetSearchPath();
683e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu   _eglPreloadForEach(search_path, callback, callback_data);
684e8ba2812e6995d1ec95c972a1b48ac29a99531ddChia-I Wu}
685