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_X)
26 #elif defined(_EGL_PLATFORM_WINDOWS)
27 /* Use static linking on Windows for now */
28 #define WINDOWS_STATIC_LINK
32 * Wrappers for dlopen/dlclose()
34 #if defined(_EGL_PLATFORM_WINDOWS)
35 #ifdef WINDOWS_STATIC_LINK
36 static const char *DefaultDriverName
= "Windows EGL Static Library";
38 /* XXX Need to decide how to do dynamic name lookup on Windows */
39 static const char *DefaultDriverName
= "TBD";
41 static const char *SysFS
= NULL
;
42 typedef HMODULE lib_handle
;
45 open_library(const char *filename
)
47 #ifdef WINDOWS_STATIC_LINK
50 return LoadLibrary(filename
);
55 close_library(HMODULE lib
)
57 #ifdef WINDOWS_STATIC_LINK
63 #elif defined(_EGL_PLATFORM_X)
64 static const char *DefaultDriverName
= ":0";
65 static const char *SysFS
= "/sys/class";
67 typedef void * lib_handle
;
70 open_library(const char *filename
)
72 return dlopen(filename
, RTLD_LAZY
);
76 close_library(void *lib
)
84 * Given a card number, use sysfs to determine the DRI driver name.
87 _eglChooseDRMDriver(int card
)
90 return _eglstrdup("libEGLdri");
92 char path
[2000], driverName
[2000];
96 snprintf(path
, sizeof(path
), "%s/drm/card%d/dri_library_name", SysFS
, card
);
102 fgets(driverName
, sizeof(driverName
), f
);
105 if ((length
= strlen(driverName
)) > 1) {
106 /* remove the trailing newline from sysfs */
107 driverName
[length
- 1] = '\0';
108 strncat(driverName
, "_dri", sizeof(driverName
));
109 return _eglstrdup(driverName
);
119 * XXX this function is totally subject change!!!
122 * Determine/return the path of the driver to use for the given native display.
124 * Try to be clever and determine if nativeDisplay is an Xlib Display
125 * ptr or a string (naming a driver or screen number, etc).
127 * If the first character is ':' we interpret it as a screen or card index
128 * number (i.e. ":0" or ":1", etc)
129 * Else if the first character is '!' we interpret it as specific driver name
130 * (i.e. "!r200" or "!i830".
132 * Whatever follows ':' is interpreted as arguments.
134 * The caller may free() the returned strings.
137 _eglChooseDriver(_EGLDisplay
*dpy
, char **argsRet
)
140 const char *args
= NULL
;
142 path
= getenv("EGL_DRIVER");
144 path
= _eglstrdup(path
);
146 #if defined(_EGL_PLATFORM_X)
147 (void) DefaultDriverName
;
149 if (!path
&& dpy
->NativeDisplay
) {
150 const char *dpyString
= (const char *) dpy
->NativeDisplay
;
152 /* parse the display string */
153 if (dpyString
[0] == '!' || dpyString
[0] == ':') {
154 if (dpyString
[0] == '!') {
155 path
= _eglstrdup(dpyString
);
156 p
= strchr(path
, ':');
160 p
= strchr(dpyString
, ':');
166 if (!path
&& p
[0] >= '0' && p
[0] <= '9' && !p
[1]) {
168 path
= (char *) _eglChooseDRMDriver(card
);
174 path
= (char *) _xeglChooseDriver(dpy
);
177 #elif defined(_EGL_PLATFORM_WINDOWS)
179 path
= _eglstrdup(DefaultDriverName
);
180 #endif /* _EGL_PLATFORM_X */
183 *argsRet
= (args
) ? _eglstrdup(args
) : NULL
;
190 * Open the named driver and find its bootstrap function: _eglMain().
193 _eglOpenLibrary(const char *driverName
, lib_handle
*handle
)
197 char driverFilename
[1000];
201 #if defined(_EGL_PLATFORM_WINDOWS)
202 /* Use static linking on Windows for now */
203 #ifdef WINDOWS_STATIC_LINK
205 mainFunc
= (_EGLMain_t
)_eglMain
;
208 sprintf(driverFilename
, "%s.dll", driverName
);
209 _eglLog(_EGL_DEBUG
, "dlopen(%s)", driverFilename
);
210 lib
= open_library(driverFilename
);
212 _eglLog(_EGL_WARNING
, "Could not open %s",
216 mainFunc
= (_EGLMain_t
) GetProcAddress(lib
, "_eglMain");
218 #elif defined(_EGL_PLATFORM_X)
219 /* XXX also prepend a directory path??? */
220 sprintf(driverFilename
, "%s.so", driverName
);
221 _eglLog(_EGL_DEBUG
, "dlopen(%s)", driverFilename
);
222 lib
= open_library(driverFilename
);
224 _eglLog(_EGL_WARNING
, "Could not open %s (%s)",
225 driverFilename
, dlerror());
228 mainFunc
= (_EGLMain_t
) dlsym(lib
, "_eglMain");
232 _eglLog(_EGL_WARNING
, "_eglMain not found in %s", driverFilename
);
244 * Load the named driver. The path and args passed will be
245 * owned by the driver and freed.
248 _eglLoadDriver(_EGLDisplay
*dpy
, char *path
, char *args
)
252 _EGLDriver
*drv
= NULL
;
254 mainFunc
= _eglOpenLibrary(path
, &lib
);
258 drv
= mainFunc(dpy
, args
);
266 _eglLog(_EGL_WARNING
, "Driver loaded from %s has no name", path
);
267 drv
->Name
= "UNNAMED";
272 drv
->LibHandle
= lib
;
279 * Match a display to a preloaded driver.
282 _eglMatchDriver(_EGLDisplay
*dpy
)
284 _EGLDriver
*defaultDriver
= NULL
;
287 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
288 _EGLDriver
*drv
= _eglGlobal
.Drivers
[i
];
290 /* display specifies a driver */
291 if (dpy
->DriverName
) {
292 if (strcmp(dpy
->DriverName
, drv
->Name
) == 0)
295 else if (drv
->Probe
) {
296 if (drv
->Probe(drv
, dpy
))
305 return defaultDriver
;
310 * Load a driver and save it.
313 _eglPreloadDriver(_EGLDisplay
*dpy
)
319 path
= _eglChooseDriver(dpy
, &args
);
323 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
324 drv
= _eglGlobal
.Drivers
[i
];
325 if (strcmp(drv
->Path
, path
) == 0) {
326 _eglLog(_EGL_DEBUG
, "Driver %s is already preloaded",
335 drv
= _eglLoadDriver(dpy
, path
, args
);
339 /* update the global notion of supported APIs */
340 _eglGlobal
.ClientAPIsMask
|= drv
->ClientAPIsMask
;
342 _eglGlobal
.Drivers
[_eglGlobal
.NumDrivers
++] = drv
;
349 * Open a preloaded driver.
352 _eglOpenDriver(_EGLDisplay
*dpy
)
354 _EGLDriver
*drv
= _eglMatchDriver(dpy
);
360 * Close a preloaded driver.
363 _eglCloseDriver(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
365 _eglReleaseDisplayResources(drv
, dpy
);
366 drv
->API
.Terminate(drv
, dpy
);
372 * Unload preloaded drivers.
375 _eglUnloadDrivers(void)
378 for (i
= 0; i
< _eglGlobal
.NumDrivers
; i
++) {
379 _EGLDriver
*drv
= _eglGlobal
.Drivers
[i
];
380 lib_handle handle
= drv
->LibHandle
;
383 free((char *) drv
->Path
);
385 free((char *) drv
->Args
);
392 close_library(handle
);
393 _eglGlobal
.Drivers
[i
] = NULL
;
396 _eglGlobal
.NumDrivers
= 0;
401 * Given a display handle, return the _EGLDriver for that display.
404 _eglLookupDriver(EGLDisplay dpy
)
406 _EGLDisplay
*d
= _eglLookupDisplay(dpy
);
415 * Plug all the available fallback routines into the given driver's
419 _eglInitDriverFallbacks(_EGLDriver
*drv
)
421 /* If a pointer is set to NULL, then the device driver _really_ has
424 drv
->API
.Initialize
= NULL
;
425 drv
->API
.Terminate
= NULL
;
427 drv
->API
.GetConfigs
= _eglGetConfigs
;
428 drv
->API
.ChooseConfig
= _eglChooseConfig
;
429 drv
->API
.GetConfigAttrib
= _eglGetConfigAttrib
;
431 drv
->API
.CreateContext
= _eglCreateContext
;
432 drv
->API
.DestroyContext
= _eglDestroyContext
;
433 drv
->API
.MakeCurrent
= _eglMakeCurrent
;
434 drv
->API
.QueryContext
= _eglQueryContext
;
436 drv
->API
.CreateWindowSurface
= _eglCreateWindowSurface
;
437 drv
->API
.CreatePixmapSurface
= _eglCreatePixmapSurface
;
438 drv
->API
.CreatePbufferSurface
= _eglCreatePbufferSurface
;
439 drv
->API
.DestroySurface
= _eglDestroySurface
;
440 drv
->API
.QuerySurface
= _eglQuerySurface
;
441 drv
->API
.SurfaceAttrib
= _eglSurfaceAttrib
;
442 drv
->API
.BindTexImage
= _eglBindTexImage
;
443 drv
->API
.ReleaseTexImage
= _eglReleaseTexImage
;
444 drv
->API
.SwapInterval
= _eglSwapInterval
;
445 drv
->API
.SwapBuffers
= _eglSwapBuffers
;
446 drv
->API
.CopyBuffers
= _eglCopyBuffers
;
448 drv
->API
.QueryString
= _eglQueryString
;
449 drv
->API
.WaitGL
= _eglWaitGL
;
450 drv
->API
.WaitNative
= _eglWaitNative
;
452 #ifdef EGL_MESA_screen_surface
453 drv
->API
.ChooseModeMESA
= _eglChooseModeMESA
;
454 drv
->API
.GetModesMESA
= _eglGetModesMESA
;
455 drv
->API
.GetModeAttribMESA
= _eglGetModeAttribMESA
;
456 drv
->API
.GetScreensMESA
= _eglGetScreensMESA
;
457 drv
->API
.CreateScreenSurfaceMESA
= _eglCreateScreenSurfaceMESA
;
458 drv
->API
.ShowScreenSurfaceMESA
= _eglShowScreenSurfaceMESA
;
459 drv
->API
.ScreenPositionMESA
= _eglScreenPositionMESA
;
460 drv
->API
.QueryScreenMESA
= _eglQueryScreenMESA
;
461 drv
->API
.QueryScreenSurfaceMESA
= _eglQueryScreenSurfaceMESA
;
462 drv
->API
.QueryScreenModeMESA
= _eglQueryScreenModeMESA
;
463 drv
->API
.QueryModeStringMESA
= _eglQueryModeStringMESA
;
464 #endif /* EGL_MESA_screen_surface */
466 #ifdef EGL_VERSION_1_2
467 drv
->API
.CreatePbufferFromClientBuffer
= _eglCreatePbufferFromClientBuffer
;
468 #endif /* EGL_VERSION_1_2 */
474 * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
475 * are supported on the system by looking for standard library names.
482 #if defined(_EGL_PLATFORM_WINDOWS)
483 /* XXX not sure about these names */
484 const char *es1_libname
= "libGLESv1_CM.dll";
485 const char *es2_libname
= "libGLESv2.dll";
486 const char *gl_libname
= "OpenGL32.dll";
487 const char *vg_libname
= "libOpenVG.dll";
488 #elif defined(_EGL_PLATFORM_X)
489 const char *es1_libname
= "libGLESv1_CM.so";
490 const char *es2_libname
= "libGLESv2.so";
491 const char *gl_libname
= "libGL.so";
492 const char *vg_libname
= "libOpenVG.so";
495 if ((lib
= open_library(es1_libname
))) {
497 mask
|= EGL_OPENGL_ES_BIT
;
500 if ((lib
= open_library(es2_libname
))) {
502 mask
|= EGL_OPENGL_ES2_BIT
;
505 if ((lib
= open_library(gl_libname
))) {
507 mask
|= EGL_OPENGL_BIT
;
510 if ((lib
= open_library(vg_libname
))) {
512 mask
|= EGL_OPENVG_BIT
;