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"
23 #if defined(_EGL_PLATFORM_POSIX)
25 #include <sys/types.h>
31 * Wrappers for dlopen/dlclose()
33 #if defined(_EGL_PLATFORM_WINDOWS)
36 /* XXX Need to decide how to do dynamic name lookup on Windows */
37 static const char DefaultDriverName
[] = "TBD";
39 typedef HMODULE lib_handle
;
42 open_library(const char *filename
)
44 return LoadLibrary(filename
);
48 close_library(HMODULE lib
)
61 #elif defined(_EGL_PLATFORM_POSIX)
64 static const char DefaultDriverName
[] = "egl_softpipe";
66 typedef void * lib_handle
;
69 open_library(const char *filename
)
71 return dlopen(filename
, RTLD_LAZY
);
75 close_library(void *lib
)
88 #else /* _EGL_PLATFORM_NO_OS */
90 static const char DefaultDriverName
[] = "builtin";
92 typedef void *lib_handle
;
95 open_library(const char *filename
)
97 return (void *) filename
;
101 close_library(void *lib
)
116 #define NUM_PROBE_CACHE_SLOTS 8
118 EGLint keys
[NUM_PROBE_CACHE_SLOTS
];
119 const void *values
[NUM_PROBE_CACHE_SLOTS
];
124 * Open the named driver and find its bootstrap function: _eglMain().
127 _eglOpenLibrary(const char *driverPath
, lib_handle
*handle
)
130 _EGLMain_t mainFunc
= NULL
;
131 const char *error
= "unknown error";
135 _eglLog(_EGL_DEBUG
, "dlopen(%s)", driverPath
);
136 lib
= open_library(driverPath
);
138 #if defined(_EGL_PLATFORM_WINDOWS)
141 mainFunc
= (_EGLMain_t
) GetProcAddress(lib
, "_eglMain");
142 #elif defined(_EGL_PLATFORM_POSIX)
144 mainFunc
= (_EGLMain_t
) dlsym(lib
, "_eglMain");
151 #else /* _EGL_PLATFORM_NO_OS */
152 /* must be the default driver name */
153 if (strcmp(driverPath
, DefaultDriverName
) == 0)
154 mainFunc
= (_EGLMain_t
) _eglMain
;
156 error
= "not builtin driver";
160 _eglLog(_EGL_WARNING
, "Could not open driver %s (%s)",
162 if (!getenv("EGL_DRIVER"))
163 _eglLog(_EGL_WARNING
,
164 "The driver can be overridden by setting EGL_DRIVER");
169 _eglLog(_EGL_WARNING
, "_eglMain not found in %s (%s)",
182 * Load the named driver.
185 _eglLoadDriver(const char *path
, const char *args
)
189 _EGLDriver
*drv
= NULL
;
191 mainFunc
= _eglOpenLibrary(path
, &lib
);
195 drv
= mainFunc(args
);
203 _eglLog(_EGL_WARNING
, "Driver loaded from %s has no name", path
);
204 drv
->Name
= "UNNAMED";
207 drv
->Path
= _eglstrdup(path
);
208 drv
->Args
= (args
) ? _eglstrdup(args
) : NULL
;
209 if (!drv
->Path
|| (args
&& !drv
->Args
)) {
211 free((char *) drv
->Path
);
213 free((char *) drv
->Args
);
220 drv
->LibHandle
= lib
;
227 * Match a display to a preloaded driver.
229 * The matching is done by finding the driver with the highest score.
232 _eglMatchDriver(_EGLDisplay
*dpy
)
234 _EGLDriver
*best_drv
= NULL
;
235 EGLint best_score
= -1, i
;
237 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
238 _EGLDriver
*drv
= _eglGlobal
.Drivers
[i
];
241 score
= (drv
->Probe
) ? drv
->Probe(drv
, dpy
) : 0;
242 if (score
> best_score
) {
244 _eglLog(_EGL_DEBUG
, "driver %s has higher score than %s",
245 drv
->Name
, best_drv
->Name
);
261 * Open a preloaded driver.
264 _eglOpenDriver(_EGLDisplay
*dpy
)
266 _EGLDriver
*drv
= _eglMatchDriver(dpy
);
272 * Close a preloaded driver.
275 _eglCloseDriver(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
282 * Preload a user driver.
284 * A user driver can be specified by EGL_DRIVER.
287 _eglPreloadUserDriver(void)
289 #if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS)
292 const char *suffix
, *p
;
294 env
= getenv("EGL_DRIVER");
299 suffix
= library_suffix();
301 /* append suffix if there isn't */
302 p
= strrchr(path
, '.');
304 size_t len
= strlen(path
);
305 char *tmp
= malloc(len
+ strlen(suffix
) + 2);
307 memcpy(tmp
, path
, len
);
310 strcat(tmp
+ len
, suffix
);
316 drv
= _eglLoadDriver(path
, NULL
);
322 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
325 #else /* _EGL_PLATFORM_POSIX || _EGL_PLATFORM_WINDOWS */
332 * Preload display drivers.
334 * Display drivers are a set of drivers that support a certain display system.
335 * The display system may be specified by EGL_DISPLAY.
337 * FIXME This makes libEGL a memory hog if an user driver is not specified and
338 * there are many display drivers.
341 _eglPreloadDisplayDrivers(void)
343 #if defined(_EGL_PLATFORM_POSIX)
344 const char *dpy
, *suffix
;
345 char path
[1024], prefix
[32];
347 struct dirent
*dirent
;
349 dpy
= getenv("EGL_DISPLAY");
351 dpy
= _EGL_DEFAULT_DISPLAY
;
355 snprintf(prefix
, sizeof(prefix
), "egl_%s_", dpy
);
356 suffix
= library_suffix();
358 dirp
= opendir(_EGL_DRIVER_SEARCH_DIR
);
362 while ((dirent
= readdir(dirp
))) {
366 /* match the prefix */
367 if (strncmp(dirent
->d_name
, prefix
, strlen(prefix
)) != 0)
370 /* match the suffix */
371 p
= strrchr(dirent
->d_name
, '.');
372 if ((p
&& !suffix
) || (!p
&& suffix
))
374 else if (p
&& suffix
&& strcmp(p
+ 1, suffix
) != 0)
377 snprintf(path
, sizeof(path
),
378 _EGL_DRIVER_SEARCH_DIR
"/%s", dirent
->d_name
);
380 drv
= _eglLoadDriver(path
, NULL
);
382 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
387 return (_eglGlobal
.NumDrivers
> 0);
388 #else /* _EGL_PLATFORM_POSIX */
395 * Preload the default driver.
398 _eglPreloadDefaultDriver(void)
402 const char *suffix
= library_suffix();
405 snprintf(path
, sizeof(path
), "%s.%s", DefaultDriverName
, suffix
);
407 snprintf(path
, sizeof(path
), DefaultDriverName
);
409 drv
= _eglLoadDriver(path
, NULL
);
413 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
422 * This function loads the driver modules and creates the corresponding
423 * _EGLDriver objects.
426 _eglPreloadDrivers(void)
430 /* already preloaded */
431 if (_eglGlobal
.NumDrivers
)
434 loaded
= (_eglPreloadUserDriver() ||
435 _eglPreloadDisplayDrivers() ||
436 _eglPreloadDefaultDriver());
443 * Unload preloaded drivers.
446 _eglUnloadDrivers(void)
449 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
450 _EGLDriver
*drv
= _eglGlobal
.Drivers
[i
];
451 lib_handle handle
= drv
->LibHandle
;
454 free((char *) drv
->Path
);
456 free((char *) drv
->Args
);
463 close_library(handle
);
464 _eglGlobal
.Drivers
[i
] = NULL
;
467 _eglGlobal
.NumDrivers
= 0;
472 * Plug all the available fallback routines into the given driver's
476 _eglInitDriverFallbacks(_EGLDriver
*drv
)
478 /* If a pointer is set to NULL, then the device driver _really_ has
481 drv
->API
.Initialize
= NULL
;
482 drv
->API
.Terminate
= NULL
;
484 drv
->API
.GetConfigs
= _eglGetConfigs
;
485 drv
->API
.ChooseConfig
= _eglChooseConfig
;
486 drv
->API
.GetConfigAttrib
= _eglGetConfigAttrib
;
488 drv
->API
.CreateContext
= _eglCreateContext
;
489 drv
->API
.DestroyContext
= _eglDestroyContext
;
490 drv
->API
.MakeCurrent
= _eglMakeCurrent
;
491 drv
->API
.QueryContext
= _eglQueryContext
;
493 drv
->API
.CreateWindowSurface
= _eglCreateWindowSurface
;
494 drv
->API
.CreatePixmapSurface
= _eglCreatePixmapSurface
;
495 drv
->API
.CreatePbufferSurface
= _eglCreatePbufferSurface
;
496 drv
->API
.DestroySurface
= _eglDestroySurface
;
497 drv
->API
.QuerySurface
= _eglQuerySurface
;
498 drv
->API
.SurfaceAttrib
= _eglSurfaceAttrib
;
499 drv
->API
.BindTexImage
= _eglBindTexImage
;
500 drv
->API
.ReleaseTexImage
= _eglReleaseTexImage
;
501 drv
->API
.SwapInterval
= _eglSwapInterval
;
502 drv
->API
.SwapBuffers
= _eglSwapBuffers
;
503 drv
->API
.CopyBuffers
= _eglCopyBuffers
;
505 drv
->API
.QueryString
= _eglQueryString
;
506 drv
->API
.WaitClient
= _eglWaitClient
;
507 drv
->API
.WaitNative
= _eglWaitNative
;
509 #ifdef EGL_MESA_screen_surface
510 drv
->API
.ChooseModeMESA
= _eglChooseModeMESA
;
511 drv
->API
.GetModesMESA
= _eglGetModesMESA
;
512 drv
->API
.GetModeAttribMESA
= _eglGetModeAttribMESA
;
513 drv
->API
.GetScreensMESA
= _eglGetScreensMESA
;
514 drv
->API
.CreateScreenSurfaceMESA
= _eglCreateScreenSurfaceMESA
;
515 drv
->API
.ShowScreenSurfaceMESA
= _eglShowScreenSurfaceMESA
;
516 drv
->API
.ScreenPositionMESA
= _eglScreenPositionMESA
;
517 drv
->API
.QueryScreenMESA
= _eglQueryScreenMESA
;
518 drv
->API
.QueryScreenSurfaceMESA
= _eglQueryScreenSurfaceMESA
;
519 drv
->API
.QueryScreenModeMESA
= _eglQueryScreenModeMESA
;
520 drv
->API
.QueryModeStringMESA
= _eglQueryModeStringMESA
;
521 #endif /* EGL_MESA_screen_surface */
523 #ifdef EGL_VERSION_1_2
524 drv
->API
.CreatePbufferFromClientBuffer
= _eglCreatePbufferFromClientBuffer
;
525 #endif /* EGL_VERSION_1_2 */
531 * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
532 * are supported on the system by looking for standard library names.
539 #if defined(_EGL_PLATFORM_WINDOWS)
540 /* XXX not sure about these names */
541 const char *es1_libname
= "libGLESv1_CM.dll";
542 const char *es2_libname
= "libGLESv2.dll";
543 const char *gl_libname
= "OpenGL32.dll";
544 const char *vg_libname
= "libOpenVG.dll";
545 #elif defined(_EGL_PLATFORM_POSIX)
546 const char *es1_libname
= "libGLESv1_CM.so";
547 const char *es2_libname
= "libGLESv2.so";
548 const char *gl_libname
= "libGL.so";
549 const char *vg_libname
= "libOpenVG.so";
550 #else /* _EGL_PLATFORM_NO_OS */
551 const char *es1_libname
= NULL
;
552 const char *es2_libname
= NULL
;
553 const char *gl_libname
= NULL
;
554 const char *vg_libname
= NULL
;
557 if ((lib
= open_library(es1_libname
))) {
559 mask
|= EGL_OPENGL_ES_BIT
;
562 if ((lib
= open_library(es2_libname
))) {
564 mask
|= EGL_OPENGL_ES2_BIT
;
567 if ((lib
= open_library(gl_libname
))) {
569 mask
|= EGL_OPENGL_BIT
;
572 if ((lib
= open_library(vg_libname
))) {
574 mask
|= EGL_OPENVG_BIT
;
582 * Set the probe cache at the given key.
584 * A key, instead of a _EGLDriver, is used to allow the probe cache to be share
585 * by multiple drivers.
588 _eglSetProbeCache(EGLint key
, const void *val
)
592 for (idx
= 0; idx
< NUM_PROBE_CACHE_SLOTS
; idx
++) {
593 if (!_eglProbeCache
.keys
[idx
] || _eglProbeCache
.keys
[idx
] == key
)
597 assert(idx
< NUM_PROBE_CACHE_SLOTS
);
599 _eglProbeCache
.keys
[idx
] = key
;
600 _eglProbeCache
.values
[idx
] = val
;
605 * Return the probe cache at the given key.
608 _eglGetProbeCache(EGLint key
)
612 for (idx
= 0; idx
< NUM_PROBE_CACHE_SLOTS
; idx
++) {
613 if (!_eglProbeCache
.keys
[idx
] || _eglProbeCache
.keys
[idx
] == key
)
617 return (idx
< NUM_PROBE_CACHE_SLOTS
&& _eglProbeCache
.keys
[idx
] == key
) ?
618 _eglProbeCache
.values
[idx
] : NULL
;