egl/main: drop support for external egl drivers
[mesa.git] / src / egl / main / egldriver.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31 /**
32 * Functions for choosing and opening/loading device drivers.
33 */
34
35
36 #include <assert.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include "c11/threads.h"
41
42 #include "eglstring.h"
43 #include "egldefines.h"
44 #include "egldisplay.h"
45 #include "egldriver.h"
46 #include "egllog.h"
47
48 #ifdef _EGL_BUILT_IN_DRIVER_HAIKU
49 _EGLDriver* _eglBuiltInDriverHaiku(const char* args);
50 #endif
51
52 typedef struct _egl_module {
53 char *Name;
54 _EGLMain_t BuiltIn;
55 _EGLDriver *Driver;
56 } _EGLModule;
57
58 static mtx_t _eglModuleMutex = _MTX_INITIALIZER_NP;
59 static _EGLArray *_eglModules;
60
61 const struct {
62 const char *name;
63 _EGLMain_t main;
64 } _eglBuiltInDrivers[] = {
65 #ifdef _EGL_BUILT_IN_DRIVER_DRI2
66 { "egl_dri2", _eglBuiltInDriverDRI2 },
67 #endif
68 #ifdef _EGL_BUILT_IN_DRIVER_HAIKU
69 { "egl_haiku", _eglBuiltInDriverHaiku },
70 #endif
71 { NULL, NULL }
72 };
73
74 /**
75 * Load a module and create the driver object.
76 */
77 static EGLBoolean
78 _eglLoadModule(_EGLModule *mod)
79 {
80 _EGLDriver *drv;
81
82 if (mod->Driver)
83 return EGL_TRUE;
84
85 if (!mod->BuiltIn)
86 return EGL_FALSE;
87
88 drv = mod->BuiltIn(NULL);
89 if (!drv || !drv->Name)
90 return EGL_FALSE;
91
92 mod->Driver = drv;
93
94 return EGL_TRUE;
95 }
96
97
98 /**
99 * Unload a module.
100 */
101 static void
102 _eglUnloadModule(_EGLModule *mod)
103 {
104 #if defined(_EGL_OS_UNIX)
105 /* destroy the driver */
106 if (mod->Driver && mod->Driver->Unload)
107 mod->Driver->Unload(mod->Driver);
108
109 #elif defined(_EGL_OS_WINDOWS)
110 /* XXX Windows unloads DLLs before atexit */
111 #endif
112
113 mod->Driver = NULL;
114 }
115
116
117 /**
118 * Add a module to the module array.
119 */
120 static _EGLModule *
121 _eglAddModule(const char *name)
122 {
123 _EGLModule *mod;
124 EGLint i;
125
126 if (!_eglModules) {
127 _eglModules = _eglCreateArray("Module", 8);
128 if (!_eglModules)
129 return NULL;
130 }
131
132 /* find duplicates */
133 for (i = 0; i < _eglModules->Size; i++) {
134 mod = _eglModules->Elements[i];
135 if (strcmp(mod->Name, name) == 0)
136 return mod;
137 }
138
139 /* allocate a new one */
140 mod = calloc(1, sizeof(*mod));
141 if (mod) {
142 mod->Name = _eglstrdup(name);
143 if (!mod->Name) {
144 free(mod);
145 mod = NULL;
146 }
147 }
148 if (mod) {
149 _eglAppendArray(_eglModules, (void *) mod);
150 _eglLog(_EGL_DEBUG, "added %s to module array", mod->Name);
151 }
152
153 return mod;
154 }
155
156
157 /**
158 * Free a module.
159 */
160 static void
161 _eglFreeModule(void *module)
162 {
163 _EGLModule *mod = (_EGLModule *) module;
164
165 _eglUnloadModule(mod);
166 free(mod->Name);
167 free(mod);
168 }
169
170
171 /**
172 * Add the user driver to the module array.
173 *
174 * The user driver is specified by EGL_DRIVER.
175 */
176 static EGLBoolean
177 _eglAddUserDriver(void)
178 {
179 char *env;
180
181 env = getenv("EGL_DRIVER");
182 if (env) {
183 EGLint i;
184
185 for (i = 0; _eglBuiltInDrivers[i].name; i++) {
186 if (!strcmp(_eglBuiltInDrivers[i].name, env)) {
187 _EGLModule *mod = _eglAddModule(env);
188 if (mod)
189 mod->BuiltIn = _eglBuiltInDrivers[i].main;
190
191 return EGL_TRUE;
192 }
193 }
194 }
195
196 return EGL_FALSE;
197 }
198
199
200 /**
201 * Add built-in drivers to the module array.
202 */
203 static void
204 _eglAddBuiltInDrivers(void)
205 {
206 _EGLModule *mod;
207 EGLint i;
208
209 for (i = 0; _eglBuiltInDrivers[i].name; i++) {
210 mod = _eglAddModule(_eglBuiltInDrivers[i].name);
211 if (mod)
212 mod->BuiltIn = _eglBuiltInDrivers[i].main;
213 }
214 }
215
216
217 /**
218 * Add drivers to the module array. Drivers will be loaded as they are matched
219 * to displays.
220 */
221 static EGLBoolean
222 _eglAddDrivers(void)
223 {
224 if (_eglModules)
225 return EGL_TRUE;
226
227 if (!_eglAddUserDriver()) {
228 /*
229 * Add other drivers only when EGL_DRIVER is not set. The order here
230 * decides the priorities.
231 */
232 _eglAddBuiltInDrivers();
233 }
234
235 return (_eglModules != NULL);
236 }
237
238
239 /**
240 * A helper function for _eglMatchDriver. It finds the first driver that can
241 * initialize the display and return.
242 */
243 static _EGLDriver *
244 _eglMatchAndInitialize(_EGLDisplay *dpy)
245 {
246 _EGLDriver *drv = NULL;
247 EGLint i = 0;
248
249 if (!_eglAddDrivers()) {
250 _eglLog(_EGL_WARNING, "failed to find any driver");
251 return NULL;
252 }
253
254 if (dpy->Driver) {
255 drv = dpy->Driver;
256 /* no re-matching? */
257 if (!drv->API.Initialize(drv, dpy))
258 drv = NULL;
259 return drv;
260 }
261
262 while (i < _eglModules->Size) {
263 _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
264
265 if (!_eglLoadModule(mod)) {
266 /* remove invalid modules */
267 _eglEraseArray(_eglModules, i, _eglFreeModule);
268 continue;
269 }
270
271 if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
272 drv = mod->Driver;
273 break;
274 }
275 else {
276 i++;
277 }
278 }
279
280 return drv;
281 }
282
283
284 /**
285 * Match a display to a driver. The display is initialized unless test_only is
286 * true. The matching is done by finding the first driver that can initialize
287 * the display.
288 */
289 _EGLDriver *
290 _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
291 {
292 _EGLDriver *best_drv;
293
294 assert(!dpy->Initialized);
295
296 mtx_lock(&_eglModuleMutex);
297
298 /* set options */
299 dpy->Options.TestOnly = test_only;
300 dpy->Options.UseFallback = EGL_FALSE;
301
302 best_drv = _eglMatchAndInitialize(dpy);
303 if (!best_drv) {
304 dpy->Options.UseFallback = EGL_TRUE;
305 best_drv = _eglMatchAndInitialize(dpy);
306 }
307
308 mtx_unlock(&_eglModuleMutex);
309
310 if (best_drv) {
311 _eglLog(_EGL_DEBUG, "the best driver is %s%s",
312 best_drv->Name, (test_only) ? " (test only) " : "");
313 if (!test_only) {
314 dpy->Driver = best_drv;
315 dpy->Initialized = EGL_TRUE;
316 }
317 }
318
319 return best_drv;
320 }
321
322
323 __eglMustCastToProperFunctionPointerType
324 _eglGetDriverProc(const char *procname)
325 {
326 EGLint i;
327 _EGLProc proc = NULL;
328
329 if (!_eglModules) {
330 /* load the driver for the default display */
331 EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
332 _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
333 if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
334 return NULL;
335 }
336
337 for (i = 0; i < _eglModules->Size; i++) {
338 _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
339
340 if (!mod->Driver)
341 break;
342 proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
343 if (proc)
344 break;
345 }
346
347 return proc;
348 }
349
350
351 /**
352 * Unload all drivers.
353 */
354 void
355 _eglUnloadDrivers(void)
356 {
357 /* this is called at atexit time */
358 if (_eglModules) {
359 _eglDestroyArray(_eglModules, _eglFreeModule);
360 _eglModules = NULL;
361 }
362 }