2 * Functions for choosing and opening/loading device drivers.
10 #include "eglconfig.h"
11 #include "eglcontext.h"
12 #include "egldefines.h"
13 #include "egldisplay.h"
14 #include "egldriver.h"
15 #include "eglglobals.h"
19 #include "eglscreen.h"
20 #include "eglstring.h"
21 #include "eglsurface.h"
24 #if defined(_EGL_PLATFORM_POSIX)
26 #include <sys/types.h>
32 * Wrappers for dlopen/dlclose()
34 #if defined(_EGL_PLATFORM_WINDOWS)
37 /* XXX Need to decide how to do dynamic name lookup on Windows */
38 static const char DefaultDriverName
[] = "TBD";
40 typedef HMODULE lib_handle
;
43 open_library(const char *filename
)
45 return LoadLibrary(filename
);
49 close_library(HMODULE lib
)
63 make_library_path(char *buf
, unsigned int size
, const char *name
)
65 EGLBoolean need_suffix
;
66 const char *suffix
= ".dll";
69 need_suffix
= (strchr(name
, '.') == NULL
);
70 ret
= snprintf(buf
, size
, "%s%s", name
, (need_suffix
) ? suffix
: "");
72 return ((unsigned int) ret
< size
);
76 #elif defined(_EGL_PLATFORM_POSIX)
79 static const char DefaultDriverName
[] = "egl_glx";
81 typedef void * lib_handle
;
84 open_library(const char *filename
)
86 return dlopen(filename
, RTLD_LAZY
);
90 close_library(void *lib
)
104 make_library_path(char *buf
, unsigned int size
, const char *name
)
106 EGLBoolean need_dir
, need_suffix
;
107 const char *suffix
= ".so";
110 need_dir
= (strchr(name
, '/') == NULL
);
111 need_suffix
= (strchr(name
, '.') == NULL
);
113 ret
= snprintf(buf
, size
, "%s%s%s",
114 (need_dir
) ? _EGL_DRIVER_SEARCH_DIR
"/" : "", name
,
115 (need_suffix
) ? suffix
: "");
117 return ((unsigned int) ret
< size
);
121 #else /* _EGL_PLATFORM_NO_OS */
123 static const char DefaultDriverName
[] = "builtin";
125 typedef void *lib_handle
;
128 open_library(const char *filename
)
130 return (void *) filename
;
134 close_library(void *lib
)
147 make_library_path(char *buf
, unsigned int size
, const char *name
)
149 int ret
= snprintf(buf
, size
, name
);
150 return ((unsigned int) ret
< size
);
157 #define NUM_PROBE_CACHE_SLOTS 8
159 EGLint keys
[NUM_PROBE_CACHE_SLOTS
];
160 const void *values
[NUM_PROBE_CACHE_SLOTS
];
165 * Open the named driver and find its bootstrap function: _eglMain().
168 _eglOpenLibrary(const char *driverPath
, lib_handle
*handle
)
171 _EGLMain_t mainFunc
= NULL
;
172 const char *error
= "unknown error";
176 _eglLog(_EGL_DEBUG
, "dlopen(%s)", driverPath
);
177 lib
= open_library(driverPath
);
179 #if defined(_EGL_PLATFORM_WINDOWS)
182 mainFunc
= (_EGLMain_t
) GetProcAddress(lib
, "_eglMain");
183 #elif defined(_EGL_PLATFORM_POSIX)
185 mainFunc
= (_EGLMain_t
) dlsym(lib
, "_eglMain");
192 #else /* _EGL_PLATFORM_NO_OS */
193 /* must be the default driver name */
194 if (strcmp(driverPath
, DefaultDriverName
) == 0)
195 mainFunc
= (_EGLMain_t
) _eglMain
;
197 error
= "not builtin driver";
201 _eglLog(_EGL_WARNING
, "Could not open driver %s (%s)",
203 if (!getenv("EGL_DRIVER"))
204 _eglLog(_EGL_WARNING
,
205 "The driver can be overridden by setting EGL_DRIVER");
210 _eglLog(_EGL_WARNING
, "_eglMain not found in %s (%s)",
223 * Load the named driver.
226 _eglLoadDriver(const char *path
, const char *args
)
230 _EGLDriver
*drv
= NULL
;
232 mainFunc
= _eglOpenLibrary(path
, &lib
);
236 drv
= mainFunc(args
);
244 _eglLog(_EGL_WARNING
, "Driver loaded from %s has no name", path
);
245 drv
->Name
= "UNNAMED";
248 drv
->Path
= _eglstrdup(path
);
249 drv
->Args
= (args
) ? _eglstrdup(args
) : NULL
;
250 if (!drv
->Path
|| (args
&& !drv
->Args
)) {
252 free((char *) drv
->Path
);
254 free((char *) drv
->Args
);
261 drv
->LibHandle
= lib
;
268 * Match a display to a preloaded driver.
270 * The matching is done by finding the driver with the highest score.
273 _eglMatchDriver(_EGLDisplay
*dpy
)
275 _EGLDriver
*best_drv
= NULL
;
276 EGLint best_score
= -1, i
;
278 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
279 _EGLDriver
*drv
= _eglGlobal
.Drivers
[i
];
282 score
= (drv
->Probe
) ? drv
->Probe(drv
, dpy
) : 0;
283 if (score
> best_score
) {
285 _eglLog(_EGL_DEBUG
, "driver %s has higher score than %s",
286 drv
->Name
, best_drv
->Name
);
302 * Open a preloaded driver.
305 _eglOpenDriver(_EGLDisplay
*dpy
)
307 _EGLDriver
*drv
= _eglMatchDriver(dpy
);
313 * Close a preloaded driver.
316 _eglCloseDriver(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
323 * Preload a user driver.
325 * A user driver can be specified by EGL_DRIVER.
328 _eglPreloadUserDriver(void)
330 #if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS)
335 env
= getenv("EGL_DRIVER");
339 if (!make_library_path(path
, sizeof(path
), env
))
342 drv
= _eglLoadDriver(path
, NULL
);
344 _eglLog(_EGL_WARNING
, "EGL_DRIVER is set to an invalid driver");
348 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
351 #else /* _EGL_PLATFORM_POSIX || _EGL_PLATFORM_WINDOWS */
358 * Preload display drivers.
360 * Display drivers are a set of drivers that support a certain display system.
361 * The display system may be specified by EGL_DISPLAY.
363 * FIXME This makes libEGL a memory hog if an user driver is not specified and
364 * there are many display drivers.
367 _eglPreloadDisplayDrivers(void)
369 #if defined(_EGL_PLATFORM_POSIX)
370 const char *dpy
, *suffix
;
371 char path
[1024], prefix
[32];
373 struct dirent
*dirent
;
375 dpy
= getenv("EGL_DISPLAY");
377 dpy
= _EGL_DEFAULT_DISPLAY
;
381 snprintf(prefix
, sizeof(prefix
), "egl_%s_", dpy
);
382 suffix
= library_suffix();
384 dirp
= opendir(_EGL_DRIVER_SEARCH_DIR
);
388 while ((dirent
= readdir(dirp
))) {
392 /* match the prefix */
393 if (strncmp(dirent
->d_name
, prefix
, strlen(prefix
)) != 0)
396 /* match the suffix */
397 p
= strrchr(dirent
->d_name
, '.');
398 if ((p
&& !suffix
) || (!p
&& suffix
))
400 else if (p
&& suffix
&& strcmp(p
+ 1, suffix
) != 0)
403 snprintf(path
, sizeof(path
),
404 _EGL_DRIVER_SEARCH_DIR
"/%s", dirent
->d_name
);
406 drv
= _eglLoadDriver(path
, NULL
);
408 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
413 return (_eglGlobal
.NumDrivers
> 0);
414 #else /* _EGL_PLATFORM_POSIX */
421 * Preload the default driver.
424 _eglPreloadDefaultDriver(void)
429 if (!make_library_path(path
, sizeof(path
), DefaultDriverName
))
432 drv
= _eglLoadDriver(path
, NULL
);
436 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
445 * This function loads the driver modules and creates the corresponding
446 * _EGLDriver objects.
449 _eglPreloadDrivers(void)
453 /* already preloaded */
454 if (_eglGlobal
.NumDrivers
)
457 loaded
= (_eglPreloadUserDriver() ||
458 _eglPreloadDisplayDrivers() ||
459 _eglPreloadDefaultDriver());
466 * Unload preloaded drivers.
469 _eglUnloadDrivers(void)
472 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
473 _EGLDriver
*drv
= _eglGlobal
.Drivers
[i
];
474 lib_handle handle
= drv
->LibHandle
;
477 free((char *) drv
->Path
);
479 free((char *) drv
->Args
);
486 close_library(handle
);
487 _eglGlobal
.Drivers
[i
] = NULL
;
490 _eglGlobal
.NumDrivers
= 0;
495 * Plug all the available fallback routines into the given driver's
499 _eglInitDriverFallbacks(_EGLDriver
*drv
)
501 /* If a pointer is set to NULL, then the device driver _really_ has
504 drv
->API
.Initialize
= NULL
;
505 drv
->API
.Terminate
= NULL
;
507 drv
->API
.GetConfigs
= _eglGetConfigs
;
508 drv
->API
.ChooseConfig
= _eglChooseConfig
;
509 drv
->API
.GetConfigAttrib
= _eglGetConfigAttrib
;
511 drv
->API
.CreateContext
= _eglCreateContext
;
512 drv
->API
.DestroyContext
= _eglDestroyContext
;
513 drv
->API
.MakeCurrent
= _eglMakeCurrent
;
514 drv
->API
.QueryContext
= _eglQueryContext
;
516 drv
->API
.CreateWindowSurface
= _eglCreateWindowSurface
;
517 drv
->API
.CreatePixmapSurface
= _eglCreatePixmapSurface
;
518 drv
->API
.CreatePbufferSurface
= _eglCreatePbufferSurface
;
519 drv
->API
.DestroySurface
= _eglDestroySurface
;
520 drv
->API
.QuerySurface
= _eglQuerySurface
;
521 drv
->API
.SurfaceAttrib
= _eglSurfaceAttrib
;
522 drv
->API
.BindTexImage
= _eglBindTexImage
;
523 drv
->API
.ReleaseTexImage
= _eglReleaseTexImage
;
524 drv
->API
.SwapInterval
= _eglSwapInterval
;
525 drv
->API
.SwapBuffers
= _eglSwapBuffers
;
526 drv
->API
.CopyBuffers
= _eglCopyBuffers
;
528 drv
->API
.QueryString
= _eglQueryString
;
529 drv
->API
.WaitClient
= _eglWaitClient
;
530 drv
->API
.WaitNative
= _eglWaitNative
;
532 #ifdef EGL_MESA_screen_surface
533 drv
->API
.ChooseModeMESA
= _eglChooseModeMESA
;
534 drv
->API
.GetModesMESA
= _eglGetModesMESA
;
535 drv
->API
.GetModeAttribMESA
= _eglGetModeAttribMESA
;
536 drv
->API
.GetScreensMESA
= _eglGetScreensMESA
;
537 drv
->API
.CreateScreenSurfaceMESA
= _eglCreateScreenSurfaceMESA
;
538 drv
->API
.ShowScreenSurfaceMESA
= _eglShowScreenSurfaceMESA
;
539 drv
->API
.ScreenPositionMESA
= _eglScreenPositionMESA
;
540 drv
->API
.QueryScreenMESA
= _eglQueryScreenMESA
;
541 drv
->API
.QueryScreenSurfaceMESA
= _eglQueryScreenSurfaceMESA
;
542 drv
->API
.QueryScreenModeMESA
= _eglQueryScreenModeMESA
;
543 drv
->API
.QueryModeStringMESA
= _eglQueryModeStringMESA
;
544 #endif /* EGL_MESA_screen_surface */
546 #ifdef EGL_VERSION_1_2
547 drv
->API
.CreatePbufferFromClientBuffer
= _eglCreatePbufferFromClientBuffer
;
548 #endif /* EGL_VERSION_1_2 */
550 #ifdef EGL_KHR_image_base
551 drv
->API
.CreateImageKHR
= _eglCreateImageKHR
;
552 drv
->API
.DestroyImageKHR
= _eglDestroyImageKHR
;
553 #endif /* EGL_KHR_image_base */
558 * Set the probe cache at the given key.
560 * A key, instead of a _EGLDriver, is used to allow the probe cache to be share
561 * by multiple drivers.
564 _eglSetProbeCache(EGLint key
, const void *val
)
568 for (idx
= 0; idx
< NUM_PROBE_CACHE_SLOTS
; idx
++) {
569 if (!_eglProbeCache
.keys
[idx
] || _eglProbeCache
.keys
[idx
] == key
)
573 assert(idx
< NUM_PROBE_CACHE_SLOTS
);
575 _eglProbeCache
.keys
[idx
] = key
;
576 _eglProbeCache
.values
[idx
] = val
;
581 * Return the probe cache at the given key.
584 _eglGetProbeCache(EGLint key
)
588 for (idx
= 0; idx
< NUM_PROBE_CACHE_SLOTS
; idx
++) {
589 if (!_eglProbeCache
.keys
[idx
] || _eglProbeCache
.keys
[idx
] == key
)
593 return (idx
< NUM_PROBE_CACHE_SLOTS
&& _eglProbeCache
.keys
[idx
] == key
) ?
594 _eglProbeCache
.values
[idx
] : NULL
;