1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**************************************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2010-2011 LunarG, Inc.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All Rights Reserved.
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sub license, and/or sell copies of the Software, and to
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial portions
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software.
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE.
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **************************************************************************/
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Functions for choosing and opening/loading device drivers.
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <assert.h>
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <string.h>
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h>
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h>
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "eglstring.h"
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "egldefines.h"
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "egldisplay.h"
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "egldriver.h"
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "egllog.h"
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "eglmutex.h"
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_UNIX)
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <dlfcn.h>
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <sys/types.h>
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <dirent.h>
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <unistd.h>
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtypedef struct _egl_module {
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   char *Path;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLMain_t BuiltIn;
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *Handle;
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLDriver *Driver;
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} _EGLModule;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic _EGL_DECLARE_MUTEX(_eglModuleMutex);
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic _EGLArray *_eglModules;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst struct {
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *name;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLMain_t main;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} _eglBuiltInDrivers[] = {
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef _EGL_BUILT_IN_DRIVER_GALLIUM
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   { "egl_gallium", _eglBuiltInDriverGALLIUM },
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef _EGL_BUILT_IN_DRIVER_DRI2
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   { "egl_dri2", _eglBuiltInDriverDRI2 },
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef _EGL_BUILT_IN_DRIVER_GLX
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   { "egl_glx", _eglBuiltInDriverGLX },
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   { NULL, NULL }
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Wrappers for dlopen/dlclose()
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_WINDOWS)
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtypedef HMODULE lib_handle;
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic HMODULE
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgopen_library(const char *filename)
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return LoadLibrary(filename);
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclose_library(HMODULE lib)
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FreeLibrary(lib);
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglibrary_suffix(void)
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return ".dll";
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(_EGL_OS_UNIX)
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtypedef void * lib_handle;
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void *
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgopen_library(const char *filename)
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return dlopen(filename, RTLD_LAZY);
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclose_library(void *lib)
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dlclose(lib);
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglibrary_suffix(void)
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return ".so";
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Open the named driver and find its bootstrap function: _eglMain().
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic _EGLMain_t
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglOpenLibrary(const char *driverPath, lib_handle *handle)
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   lib_handle lib;
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLMain_t mainFunc = NULL;
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *error = "unknown error";
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(driverPath);
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   lib = open_library(driverPath);
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_WINDOWS)
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* XXX untested */
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (lib)
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(_EGL_OS_UNIX)
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (lib) {
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      union {
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _EGLMain_t func;
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         void *ptr;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } tmp = { NULL };
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* direct cast gives a warning when compiled with -pedantic */
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp.ptr = dlsym(lib, "_eglMain");
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mainFunc = tmp.func;
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!mainFunc)
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         error = dlerror();
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      error = dlerror();
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!lib) {
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_WARNING, "Could not open driver %s (%s)",
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              driverPath, error);
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!mainFunc) {
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)",
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              driverPath, error);
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (lib)
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         close_library(lib);
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *handle = lib;
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return mainFunc;
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Load a module and create the driver object.
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic EGLBoolean
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglLoadModule(_EGLModule *mod)
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLMain_t mainFunc;
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   lib_handle lib;
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLDriver *drv;
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mod->Driver)
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return EGL_TRUE;
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mod->BuiltIn) {
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      lib = (lib_handle) NULL;
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mainFunc = mod->BuiltIn;
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mainFunc = _eglOpenLibrary(mod->Path, &lib);
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!mainFunc)
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return EGL_FALSE;
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   drv = mainFunc(NULL);
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!drv) {
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (lib)
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         close_library(lib);
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return EGL_FALSE;
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!drv->Name) {
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", mod->Path);
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      drv->Name = "UNNAMED";
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mod->Handle = (void *) lib;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mod->Driver = drv;
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return EGL_TRUE;
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Unload a module.
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglUnloadModule(_EGLModule *mod)
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_UNIX)
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* destroy the driver */
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mod->Driver && mod->Driver->Unload)
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mod->Driver->Unload(mod->Driver);
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * XXX At this point (atexit), the module might be the last reference to
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * libEGL.  Closing the module might unmap libEGL and give problems.
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mod->Handle)
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      close_library(mod->Handle);
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(_EGL_OS_WINDOWS)
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* XXX Windows unloads DLLs before atexit */
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mod->Driver = NULL;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mod->Handle = NULL;
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Add a module to the module array.
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic _EGLModule *
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglAddModule(const char *path)
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLModule *mod;
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   EGLint i;
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!_eglModules) {
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglModules = _eglCreateArray("Module", 8);
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!_eglModules)
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return NULL;
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* find duplicates */
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < _eglModules->Size; i++) {
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mod = _eglModules->Elements[i];
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(mod->Path, path) == 0)
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return mod;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* allocate a new one */
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mod = calloc(1, sizeof(*mod));
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mod) {
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mod->Path = _eglstrdup(path);
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!mod->Path) {
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         free(mod);
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         mod = NULL;
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mod) {
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglAppendArray(_eglModules, (void *) mod);
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_DEBUG, "added %s to module array", mod->Path);
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return mod;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Free a module.
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglFreeModule(void *module)
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLModule *mod = (_EGLModule *) module;
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglUnloadModule(mod);
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(mod->Path);
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(mod);
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A loader function for use with _eglPreloadForEach.  The loader data is the
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * filename of the driver.   This function stops on the first valid driver.
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic EGLBoolean
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglLoaderFile(const char *dir, size_t len, void *loader_data)
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   char path[1024];
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *filename = (const char *) loader_data;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   size_t flen = strlen(filename);
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* make a full path */
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (len + flen + 2 > sizeof(path))
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return EGL_TRUE;
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (len) {
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      memcpy(path, dir, len);
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path[len++] = '/';
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(path + len, filename, flen);
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   len += flen;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path[len] = '\0';
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (library_suffix()) {
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const char *suffix = library_suffix();
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      size_t slen = strlen(suffix);
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const char *p;
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      EGLBoolean need_suffix;
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = filename + flen - slen;
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      need_suffix = (p < filename || strcmp(p, suffix) != 0);
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (need_suffix) {
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* overflow */
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (len + slen + 1 > sizeof(path))
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return EGL_TRUE;
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         strcpy(path + len, suffix);
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_UNIX)
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* check if the file exists */
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (access(path, F_OK))
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return EGL_TRUE;
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglAddModule(path);
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return EGL_TRUE;
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Run the callback function on each driver directory.
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The process may end prematurely if the callback function returns false.
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglPreloadForEach(const char *search_path,
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   EGLBoolean (*loader)(const char *, size_t, void *),
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   void *loader_data)
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *cur, *next;
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   size_t len;
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   cur = search_path;
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while (cur) {
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      next = strchr(cur, ':');
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      len = (next) ? next - cur : strlen(cur);
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!loader(cur, len, loader_data))
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      cur = (next) ? next + 1 : NULL;
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Return a list of colon-separated driver directories.
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglGetSearchPath(void)
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   static char search_path[1024];
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_UNIX) || defined(_EGL_OS_WINDOWS)
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (search_path[0] == '\0') {
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      char *buf = search_path;
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      size_t len = sizeof(search_path);
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      EGLBoolean use_env;
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      char dir_sep;
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int ret;
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_UNIX)
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      use_env = (geteuid() == getuid() && getegid() == getgid());
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dir_sep = '/';
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      use_env = EGL_TRUE;
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dir_sep = '\\';
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (use_env) {
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         char *p;
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* extract the dirname from EGL_DRIVER */
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p = getenv("EGL_DRIVER");
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (p && strchr(p, dir_sep)) {
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ret = _eglsnprintf(buf, len, "%s", p);
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (ret > 0 && ret < len) {
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               p = strrchr(buf, dir_sep);
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               *p++ = ':';
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               len -= p - buf;
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               buf = p;
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* append EGL_DRIVERS_PATH */
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p = getenv("EGL_DRIVERS_PATH");
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (p) {
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ret = _eglsnprintf(buf, len, "%s:", p);
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (ret > 0 && ret < len) {
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               buf += ret;
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               len -= ret;
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _eglLog(_EGL_DEBUG,
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               "ignore EGL_DRIVERS_PATH for setuid/setgid binaries");
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ret = _eglsnprintf(buf, len, "%s", _EGL_DRIVER_SEARCH_DIR);
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ret < 0 || ret >= len)
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         search_path[0] = '\0';
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_DEBUG, "EGL search path is %s", search_path);
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif /* defined(_EGL_OS_UNIX) || defined(_EGL_OS_WINDOWS) */
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return search_path;
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Add the user driver to the module array.
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The user driver is specified by EGL_DRIVER.
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic EGLBoolean
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglAddUserDriver(void)
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *search_path = _eglGetSearchPath();
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   char *env;
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   size_t name_len = 0;
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   env = getenv("EGL_DRIVER");
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_EGL_OS_UNIX)
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (env && strchr(env, '/')) {
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      search_path = "";
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((geteuid() != getuid() || getegid() != getgid())) {
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _eglLog(_EGL_DEBUG,
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               "ignore EGL_DRIVER for setuid/setgid binaries");
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         env = NULL;
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (env) {
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      char *suffix = strchr(env, '.');
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      name_len = (suffix) ? suffix - env : strlen(env);
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (env)
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      name_len = strlen(env);
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif /* _EGL_OS_UNIX */
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Try built-in drivers first if we know the driver name.  This makes sure
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * we do not load the outdated external driver that is still on the
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * filesystem.
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (name_len) {
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _EGLModule *mod;
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      EGLint i;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; _eglBuiltInDrivers[i].name; i++) {
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (strlen(_eglBuiltInDrivers[i].name) == name_len &&
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             !strncmp(_eglBuiltInDrivers[i].name, env, name_len)) {
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            mod = _eglAddModule(env);
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (mod)
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               mod->BuiltIn = _eglBuiltInDrivers[i].main;
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return EGL_TRUE;
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* otherwise, treat env as a path */
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (env) {
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return EGL_TRUE;
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return EGL_FALSE;
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Add egl_gallium to the module array.
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglAddGalliumDriver(void)
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef _EGL_BUILT_IN_DRIVER_GALLIUM
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *external = (void *) "egl_gallium";
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglPreloadForEach(_eglGetSearchPath(), _eglLoaderFile, external);
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Add built-in drivers to the module array.
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglAddBuiltInDrivers(void)
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLModule *mod;
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   EGLint i;
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; _eglBuiltInDrivers[i].name; i++) {
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mod = _eglAddModule(_eglBuiltInDrivers[i].name);
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (mod)
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         mod->BuiltIn = _eglBuiltInDrivers[i].main;
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Add drivers to the module array.  Drivers will be loaded as they are matched
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to displays.
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic EGLBoolean
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglAddDrivers(void)
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (_eglModules)
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return EGL_TRUE;
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!_eglAddUserDriver()) {
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /*
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * Add other drivers only when EGL_DRIVER is not set.  The order here
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * decides the priorities.
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglAddGalliumDriver();
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglAddBuiltInDrivers();
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (_eglModules != NULL);
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A helper function for _eglMatchDriver.  It finds the first driver that can
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * initialize the display and return.
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic _EGLDriver *
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglMatchAndInitialize(_EGLDisplay *dpy)
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLDriver *drv = NULL;
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   EGLint i = 0;
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!_eglAddDrivers()) {
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_WARNING, "failed to find any driver");
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (dpy->Driver) {
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      drv = dpy->Driver;
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no re-matching? */
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!drv->API.Initialize(drv, dpy))
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         drv = NULL;
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return drv;
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while (i < _eglModules->Size) {
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!_eglLoadModule(mod)) {
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* remove invalid modules */
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _eglEraseArray(_eglModules, i, _eglFreeModule);
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         drv = mod->Driver;
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         i++;
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return drv;
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Match a display to a driver.  The display is initialized unless test_only is
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * true.  The matching is done by finding the first driver that can initialize
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the display.
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_EGLDriver *
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLDriver *best_drv;
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(!dpy->Initialized);
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglLockMutex(&_eglModuleMutex);
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* set options */
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dpy->Options.TestOnly = test_only;
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dpy->Options.UseFallback = EGL_FALSE;
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   best_drv = _eglMatchAndInitialize(dpy);
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!best_drv) {
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dpy->Options.UseFallback = EGL_TRUE;
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      best_drv = _eglMatchAndInitialize(dpy);
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglUnlockMutex(&_eglModuleMutex);
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (best_drv) {
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglLog(_EGL_DEBUG, "the best driver is %s%s",
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            best_drv->Name, (test_only) ? " (test only) " : "");
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!test_only) {
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         dpy->Driver = best_drv;
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         dpy->Initialized = EGL_TRUE;
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return best_drv;
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org__eglMustCastToProperFunctionPointerType
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglGetDriverProc(const char *procname)
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   EGLint i;
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _EGLProc proc = NULL;
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!_eglModules) {
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* load the driver for the default display */
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return NULL;
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < _eglModules->Size; i++) {
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!mod->Driver)
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (proc)
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return proc;
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Unload all drivers.
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglUnloadDrivers(void)
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* this is called at atexit time */
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (_eglModules) {
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglDestroyArray(_eglModules, _eglFreeModule);
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _eglModules = NULL;
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Invoke a callback function on each EGL search path.
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The first argument of the callback function is the name of the search path.
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The second argument is the length of the name.
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      void *callback_data)
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *search_path = _eglGetSearchPath();
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _eglPreloadForEach(search_path, callback, callback_data);
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
715