egl: Remove unnecessary headers.
[mesa.git] / src / egl / main / egldriver.c
1 /**
2 * Functions for choosing and opening/loading device drivers.
3 */
4
5
6 #include <assert.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "eglconfig.h"
11 #include "eglcontext.h"
12 #include "egldefines.h"
13 #include "egldisplay.h"
14 #include "egldriver.h"
15 #include "eglglobals.h"
16 #include "egllog.h"
17 #include "eglmisc.h"
18 #include "eglmode.h"
19 #include "eglscreen.h"
20 #include "eglstring.h"
21 #include "eglsurface.h"
22 #include "eglimage.h"
23
24 #if defined(_EGL_PLATFORM_POSIX)
25 #include <dlfcn.h>
26 #include <sys/types.h>
27 #include <dirent.h>
28 #endif
29
30
31 /**
32 * Wrappers for dlopen/dlclose()
33 */
34 #if defined(_EGL_PLATFORM_WINDOWS)
35
36
37 /* XXX Need to decide how to do dynamic name lookup on Windows */
38 static const char DefaultDriverName[] = "TBD";
39
40 typedef HMODULE lib_handle;
41
42 static HMODULE
43 open_library(const char *filename)
44 {
45 return LoadLibrary(filename);
46 }
47
48 static void
49 close_library(HMODULE lib)
50 {
51 FreeLibrary(lib);
52 }
53
54
55 static const char *
56 library_suffix(void)
57 {
58 return "dll";
59 }
60
61
62 static EGLBoolean
63 make_library_path(char *buf, unsigned int size, const char *name)
64 {
65 EGLBoolean need_suffix;
66 const char *suffix = ".dll";
67 int ret;
68
69 need_suffix = (strchr(name, '.') == NULL);
70 ret = snprintf(buf, size, "%s%s", name, (need_suffix) ? suffix : "");
71
72 return ((unsigned int) ret < size);
73 }
74
75
76 #elif defined(_EGL_PLATFORM_POSIX)
77
78
79 static const char DefaultDriverName[] = "egl_glx";
80
81 typedef void * lib_handle;
82
83 static void *
84 open_library(const char *filename)
85 {
86 return dlopen(filename, RTLD_LAZY);
87 }
88
89 static void
90 close_library(void *lib)
91 {
92 dlclose(lib);
93 }
94
95
96 static const char *
97 library_suffix(void)
98 {
99 return "so";
100 }
101
102
103 static EGLBoolean
104 make_library_path(char *buf, unsigned int size, const char *name)
105 {
106 EGLBoolean need_dir, need_suffix;
107 const char *suffix = ".so";
108 int ret;
109
110 need_dir = (strchr(name, '/') == NULL);
111 need_suffix = (strchr(name, '.') == NULL);
112
113 ret = snprintf(buf, size, "%s%s%s",
114 (need_dir) ? _EGL_DRIVER_SEARCH_DIR"/" : "", name,
115 (need_suffix) ? suffix : "");
116
117 return ((unsigned int) ret < size);
118 }
119
120
121 #else /* _EGL_PLATFORM_NO_OS */
122
123 static const char DefaultDriverName[] = "builtin";
124
125 typedef void *lib_handle;
126
127 static INLINE void *
128 open_library(const char *filename)
129 {
130 return (void *) filename;
131 }
132
133 static INLINE void
134 close_library(void *lib)
135 {
136 }
137
138
139 static const char *
140 library_suffix(void)
141 {
142 return NULL;
143 }
144
145
146 static EGLBoolean
147 make_library_path(char *buf, unsigned int size, const char *name)
148 {
149 int ret = snprintf(buf, size, name);
150 return ((unsigned int) ret < size);
151 }
152
153
154 #endif
155
156
157 #define NUM_PROBE_CACHE_SLOTS 8
158 static struct {
159 EGLint keys[NUM_PROBE_CACHE_SLOTS];
160 const void *values[NUM_PROBE_CACHE_SLOTS];
161 } _eglProbeCache;
162
163
164 /**
165 * Open the named driver and find its bootstrap function: _eglMain().
166 */
167 static _EGLMain_t
168 _eglOpenLibrary(const char *driverPath, lib_handle *handle)
169 {
170 lib_handle lib;
171 _EGLMain_t mainFunc = NULL;
172 const char *error = "unknown error";
173
174 assert(driverPath);
175
176 _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
177 lib = open_library(driverPath);
178
179 #if defined(_EGL_PLATFORM_WINDOWS)
180 /* XXX untested */
181 if (lib)
182 mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
183 #elif defined(_EGL_PLATFORM_POSIX)
184 if (lib) {
185 mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
186 if (!mainFunc)
187 error = dlerror();
188 }
189 else {
190 error = dlerror();
191 }
192 #else /* _EGL_PLATFORM_NO_OS */
193 /* must be the default driver name */
194 if (strcmp(driverPath, DefaultDriverName) == 0)
195 mainFunc = (_EGLMain_t) _eglMain;
196 else
197 error = "not builtin driver";
198 #endif
199
200 if (!lib) {
201 _eglLog(_EGL_WARNING, "Could not open driver %s (%s)",
202 driverPath, error);
203 if (!getenv("EGL_DRIVER"))
204 _eglLog(_EGL_WARNING,
205 "The driver can be overridden by setting EGL_DRIVER");
206 return NULL;
207 }
208
209 if (!mainFunc) {
210 _eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)",
211 driverPath, error);
212 if (lib)
213 close_library(lib);
214 return NULL;
215 }
216
217 *handle = lib;
218 return mainFunc;
219 }
220
221
222 /**
223 * Load the named driver.
224 */
225 static _EGLDriver *
226 _eglLoadDriver(const char *path, const char *args)
227 {
228 _EGLMain_t mainFunc;
229 lib_handle lib;
230 _EGLDriver *drv = NULL;
231
232 mainFunc = _eglOpenLibrary(path, &lib);
233 if (!mainFunc)
234 return NULL;
235
236 drv = mainFunc(args);
237 if (!drv) {
238 if (lib)
239 close_library(lib);
240 return NULL;
241 }
242
243 if (!drv->Name) {
244 _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path);
245 drv->Name = "UNNAMED";
246 }
247
248 drv->Path = _eglstrdup(path);
249 drv->Args = (args) ? _eglstrdup(args) : NULL;
250 if (!drv->Path || (args && !drv->Args)) {
251 if (drv->Path)
252 free((char *) drv->Path);
253 if (drv->Args)
254 free((char *) drv->Args);
255 drv->Unload(drv);
256 if (lib)
257 close_library(lib);
258 return NULL;
259 }
260
261 drv->LibHandle = lib;
262
263 return drv;
264 }
265
266
267 /**
268 * Match a display to a preloaded driver.
269 *
270 * The matching is done by finding the driver with the highest score.
271 */
272 _EGLDriver *
273 _eglMatchDriver(_EGLDisplay *dpy)
274 {
275 _EGLDriver *best_drv = NULL;
276 EGLint best_score = -1, i;
277
278 for (i = 0; i < _eglGlobal.NumDrivers; i++) {
279 _EGLDriver *drv = _eglGlobal.Drivers[i];
280 EGLint score;
281
282 score = (drv->Probe) ? drv->Probe(drv, dpy) : 0;
283 if (score > best_score) {
284 if (best_drv) {
285 _eglLog(_EGL_DEBUG, "driver %s has higher score than %s",
286 drv->Name, best_drv->Name);
287 }
288
289 best_drv = drv;
290 best_score = score;
291 /* perfect match */
292 if (score >= 100)
293 break;
294 }
295 }
296
297 return best_drv;
298 }
299
300
301 /**
302 * Preload a user driver.
303 *
304 * A user driver can be specified by EGL_DRIVER.
305 */
306 static EGLBoolean
307 _eglPreloadUserDriver(void)
308 {
309 #if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS)
310 _EGLDriver *drv;
311 char path[1024];
312 char *env;
313
314 env = getenv("EGL_DRIVER");
315 if (!env)
316 return EGL_FALSE;
317
318 if (!make_library_path(path, sizeof(path), env))
319 return EGL_FALSE;
320
321 drv = _eglLoadDriver(path, NULL);
322 if (!drv) {
323 _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver");
324 return EGL_FALSE;
325 }
326
327 _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
328
329 return EGL_TRUE;
330 #else /* _EGL_PLATFORM_POSIX || _EGL_PLATFORM_WINDOWS */
331 return EGL_FALSE;
332 #endif
333 }
334
335
336 /**
337 * Preload display drivers.
338 *
339 * Display drivers are a set of drivers that support a certain display system.
340 * The display system may be specified by EGL_DISPLAY.
341 *
342 * FIXME This makes libEGL a memory hog if an user driver is not specified and
343 * there are many display drivers.
344 */
345 static EGLBoolean
346 _eglPreloadDisplayDrivers(void)
347 {
348 #if defined(_EGL_PLATFORM_POSIX)
349 const char *dpy, *suffix;
350 char path[1024], prefix[32];
351 DIR *dirp;
352 struct dirent *dirent;
353
354 dpy = getenv("EGL_DISPLAY");
355 if (!dpy || !dpy[0])
356 dpy = _EGL_DEFAULT_DISPLAY;
357 if (!dpy || !dpy[0])
358 return EGL_FALSE;
359
360 snprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
361 suffix = library_suffix();
362
363 dirp = opendir(_EGL_DRIVER_SEARCH_DIR);
364 if (!dirp)
365 return EGL_FALSE;
366
367 while ((dirent = readdir(dirp))) {
368 _EGLDriver *drv;
369 const char *p;
370
371 /* match the prefix */
372 if (strncmp(dirent->d_name, prefix, strlen(prefix)) != 0)
373 continue;
374
375 /* match the suffix */
376 p = strrchr(dirent->d_name, '.');
377 if ((p && !suffix) || (!p && suffix))
378 continue;
379 else if (p && suffix && strcmp(p + 1, suffix) != 0)
380 continue;
381
382 snprintf(path, sizeof(path),
383 _EGL_DRIVER_SEARCH_DIR"/%s", dirent->d_name);
384
385 drv = _eglLoadDriver(path, NULL);
386 if (drv)
387 _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
388 }
389
390 closedir(dirp);
391
392 return (_eglGlobal.NumDrivers > 0);
393 #else /* _EGL_PLATFORM_POSIX */
394 return EGL_FALSE;
395 #endif
396 }
397
398
399 /**
400 * Preload the default driver.
401 */
402 static EGLBoolean
403 _eglPreloadDefaultDriver(void)
404 {
405 _EGLDriver *drv;
406 char path[1024];
407
408 if (!make_library_path(path, sizeof(path), DefaultDriverName))
409 return EGL_FALSE;
410
411 drv = _eglLoadDriver(path, NULL);
412 if (!drv)
413 return EGL_FALSE;
414
415 _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
416
417 return EGL_TRUE;
418 }
419
420
421 /**
422 * Preload drivers.
423 *
424 * This function loads the driver modules and creates the corresponding
425 * _EGLDriver objects.
426 */
427 EGLBoolean
428 _eglPreloadDrivers(void)
429 {
430 EGLBoolean loaded;
431
432 /* already preloaded */
433 if (_eglGlobal.NumDrivers)
434 return EGL_TRUE;
435
436 loaded = (_eglPreloadUserDriver() ||
437 _eglPreloadDisplayDrivers() ||
438 _eglPreloadDefaultDriver());
439
440 return loaded;
441 }
442
443
444 /**
445 * Unload preloaded drivers.
446 */
447 void
448 _eglUnloadDrivers(void)
449 {
450 EGLint i;
451 for (i = 0; i < _eglGlobal.NumDrivers; i++) {
452 _EGLDriver *drv = _eglGlobal.Drivers[i];
453 lib_handle handle = drv->LibHandle;
454
455 if (drv->Path)
456 free((char *) drv->Path);
457 if (drv->Args)
458 free((char *) drv->Args);
459
460 /* destroy driver */
461 if (drv->Unload)
462 drv->Unload(drv);
463
464 if (handle)
465 close_library(handle);
466 _eglGlobal.Drivers[i] = NULL;
467 }
468
469 _eglGlobal.NumDrivers = 0;
470 }
471
472
473 /**
474 * Plug all the available fallback routines into the given driver's
475 * dispatch table.
476 */
477 void
478 _eglInitDriverFallbacks(_EGLDriver *drv)
479 {
480 /* If a pointer is set to NULL, then the device driver _really_ has
481 * to implement it.
482 */
483 drv->API.Initialize = NULL;
484 drv->API.Terminate = NULL;
485
486 drv->API.GetConfigs = _eglGetConfigs;
487 drv->API.ChooseConfig = _eglChooseConfig;
488 drv->API.GetConfigAttrib = _eglGetConfigAttrib;
489
490 drv->API.CreateContext = _eglCreateContext;
491 drv->API.DestroyContext = _eglDestroyContext;
492 drv->API.MakeCurrent = _eglMakeCurrent;
493 drv->API.QueryContext = _eglQueryContext;
494
495 drv->API.CreateWindowSurface = _eglCreateWindowSurface;
496 drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
497 drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
498 drv->API.DestroySurface = _eglDestroySurface;
499 drv->API.QuerySurface = _eglQuerySurface;
500 drv->API.SurfaceAttrib = _eglSurfaceAttrib;
501 drv->API.BindTexImage = _eglBindTexImage;
502 drv->API.ReleaseTexImage = _eglReleaseTexImage;
503 drv->API.SwapInterval = _eglSwapInterval;
504 drv->API.SwapBuffers = _eglSwapBuffers;
505 drv->API.CopyBuffers = _eglCopyBuffers;
506
507 drv->API.QueryString = _eglQueryString;
508 drv->API.WaitClient = _eglWaitClient;
509 drv->API.WaitNative = _eglWaitNative;
510
511 #ifdef EGL_MESA_screen_surface
512 drv->API.ChooseModeMESA = _eglChooseModeMESA;
513 drv->API.GetModesMESA = _eglGetModesMESA;
514 drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
515 drv->API.GetScreensMESA = _eglGetScreensMESA;
516 drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
517 drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
518 drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
519 drv->API.QueryScreenMESA = _eglQueryScreenMESA;
520 drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
521 drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
522 drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
523 #endif /* EGL_MESA_screen_surface */
524
525 #ifdef EGL_VERSION_1_2
526 drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
527 #endif /* EGL_VERSION_1_2 */
528
529 #ifdef EGL_KHR_image_base
530 drv->API.CreateImageKHR = _eglCreateImageKHR;
531 drv->API.DestroyImageKHR = _eglDestroyImageKHR;
532 #endif /* EGL_KHR_image_base */
533 }
534
535
536 /**
537 * Set the probe cache at the given key.
538 *
539 * A key, instead of a _EGLDriver, is used to allow the probe cache to be share
540 * by multiple drivers.
541 */
542 void
543 _eglSetProbeCache(EGLint key, const void *val)
544 {
545 EGLint idx;
546
547 for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
548 if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
549 break;
550 }
551 assert(key > 0);
552 assert(idx < NUM_PROBE_CACHE_SLOTS);
553
554 _eglProbeCache.keys[idx] = key;
555 _eglProbeCache.values[idx] = val;
556 }
557
558
559 /**
560 * Return the probe cache at the given key.
561 */
562 const void *
563 _eglGetProbeCache(EGLint key)
564 {
565 EGLint idx;
566
567 for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
568 if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
569 break;
570 }
571
572 return (idx < NUM_PROBE_CACHE_SLOTS && _eglProbeCache.keys[idx] == key) ?
573 _eglProbeCache.values[idx] : NULL;
574 }