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
);
118 * XXX this function is totally subject change!!!
121 * Determine/return the name of the driver to use for the given _EGLDisplay.
123 * Try to be clever and determine if nativeDisplay is an Xlib Display
124 * ptr or a string (naming a driver or screen number, etc).
126 * If the first character is ':' we interpret it as a screen or card index
127 * number (i.e. ":0" or ":1", etc)
128 * Else if the first character is '!' we interpret it as specific driver name
129 * (i.e. "!r200" or "!i830".
131 * Whatever follows ':' is copied and put into dpy->DriverArgs.
133 * The caller may free() the returned string.
136 _eglChooseDriver(_EGLDisplay
*dpy
)
138 /* Under Windows, the NativeDisplay is an HDC handle, therefore */
139 /* it can't be interpreted as a string or a pointer. */
140 #if defined(_EGL_PLATFORM_WINDOWS)
141 const char *displayString
= NULL
;
143 const char *displayString
= (const char *) dpy
->NativeDisplay
;
145 const char *driverName
= NULL
;
147 (void) DefaultDriverName
;
149 #if defined(_EGL_PLATFORM_X)
150 /* First, if the EGL_DRIVER env var is set, use that */
151 driverName
= getenv("EGL_DRIVER");
153 return _eglstrdup(driverName
);
157 if (!displayString
) {
158 /* choose a default */
159 displayString
= DefaultDriverName
;
162 /* extract default DriverArgs = whatever follows ':' */
164 (displayString
[0] == '!' ||
165 displayString
[0] == ':')) {
166 const char *args
= strchr(displayString
, ':');
168 dpy
->DriverArgs
= _eglstrdup(args
+ 1);
171 /* determine driver name now */
172 if (displayString
&& displayString
[0] == ':' &&
173 (displayString
[1] >= '0' && displayString
[1] <= '9') &&
175 int card
= atoi(displayString
+ 1);
176 driverName
= _eglChooseDRMDriver(card
);
178 else if (displayString
&& displayString
[0] == '!') {
179 /* use user-specified driver name */
180 driverName
= _eglstrdup(displayString
+ 1);
181 /* truncate driverName at ':' if present */
183 char *args
= strchr(driverName
, ':');
191 /* NativeDisplay is not a string! */
192 #if defined(_EGL_PLATFORM_X)
193 driverName
= _xeglChooseDriver(dpy
);
195 driverName
= DefaultDriverName
;
204 * Open/load the named driver and call its bootstrap function: _eglMain().
205 * By the time this function is called, the dpy->DriverName should have
208 * \return new _EGLDriver object.
211 _eglOpenDriver(_EGLDisplay
*dpy
, const char *driverName
, const char *args
)
216 char driverFilename
[1000];
220 #if defined(_EGL_PLATFORM_WINDOWS)
221 /* Use static linking on Windows for now */
222 #ifdef WINDOWS_STATIC_LINK
224 mainFunc
= (_EGLMain_t
)_eglMain
;
227 sprintf(driverFilename
, "%s.dll", driverName
);
228 _eglLog(_EGL_DEBUG
, "dlopen(%s)", driverFilename
);
229 lib
= open_library(driverFilename
);
231 _eglLog(_EGL_WARNING
, "Could not open %s",
235 mainFunc
= (_EGLMain_t
) GetProcAddress(lib
, "_eglMain");
237 #elif defined(_EGL_PLATFORM_X)
238 /* XXX also prepend a directory path??? */
239 sprintf(driverFilename
, "%s.so", driverName
);
240 _eglLog(_EGL_DEBUG
, "dlopen(%s)", driverFilename
);
241 lib
= open_library(driverFilename
);
243 _eglLog(_EGL_WARNING
, "Could not open %s (%s)",
244 driverFilename
, dlerror());
247 mainFunc
= (_EGLMain_t
) dlsym(lib
, "_eglMain");
251 _eglLog(_EGL_WARNING
, "_eglMain not found in %s", driverFilename
);
256 drv
= mainFunc(dpy
, args
);
262 /* with a recurvise open you want the inner most handle */
263 if (!drv
->LibHandle
) {
264 drv
->LibHandle
= lib
;
270 /* update the global notion of supported APIs */
271 _eglGlobal
.ClientAPIsMask
|= drv
->ClientAPIsMask
;
280 _eglCloseDriver(_EGLDriver
*drv
, EGLDisplay dpy
)
282 void *handle
= drv
->LibHandle
;
285 _eglLog(_EGL_DEBUG
, "Closing %s", drv
->Name
);
287 _eglReleaseDisplayResources(drv
, dpy
);
289 b
= drv
->API
.Terminate(drv
, dpy
);
291 close_library(handle
);
298 * Save the given driver pointer in the list of all known drivers.
301 _eglSaveDriver(_EGLDriver
*drv
)
303 _eglGlobal
.Drivers
[ _eglGlobal
.NumDrivers
++ ] = drv
;
308 * Given a display handle, return the _EGLDriver for that display.
311 _eglLookupDriver(EGLDisplay dpy
)
313 _EGLDisplay
*d
= _eglLookupDisplay(dpy
);
322 * Plug all the available fallback routines into the given driver's
326 _eglInitDriverFallbacks(_EGLDriver
*drv
)
328 /* If a pointer is set to NULL, then the device driver _really_ has
331 drv
->API
.Initialize
= NULL
;
332 drv
->API
.Terminate
= NULL
;
334 drv
->API
.GetConfigs
= _eglGetConfigs
;
335 drv
->API
.ChooseConfig
= _eglChooseConfig
;
336 drv
->API
.GetConfigAttrib
= _eglGetConfigAttrib
;
338 drv
->API
.CreateContext
= _eglCreateContext
;
339 drv
->API
.DestroyContext
= _eglDestroyContext
;
340 drv
->API
.MakeCurrent
= _eglMakeCurrent
;
341 drv
->API
.QueryContext
= _eglQueryContext
;
343 drv
->API
.CreateWindowSurface
= _eglCreateWindowSurface
;
344 drv
->API
.CreatePixmapSurface
= _eglCreatePixmapSurface
;
345 drv
->API
.CreatePbufferSurface
= _eglCreatePbufferSurface
;
346 drv
->API
.DestroySurface
= _eglDestroySurface
;
347 drv
->API
.QuerySurface
= _eglQuerySurface
;
348 drv
->API
.SurfaceAttrib
= _eglSurfaceAttrib
;
349 drv
->API
.BindTexImage
= _eglBindTexImage
;
350 drv
->API
.ReleaseTexImage
= _eglReleaseTexImage
;
351 drv
->API
.SwapInterval
= _eglSwapInterval
;
352 drv
->API
.SwapBuffers
= _eglSwapBuffers
;
353 drv
->API
.CopyBuffers
= _eglCopyBuffers
;
355 drv
->API
.QueryString
= _eglQueryString
;
356 drv
->API
.WaitGL
= _eglWaitGL
;
357 drv
->API
.WaitNative
= _eglWaitNative
;
359 #ifdef EGL_MESA_screen_surface
360 drv
->API
.ChooseModeMESA
= _eglChooseModeMESA
;
361 drv
->API
.GetModesMESA
= _eglGetModesMESA
;
362 drv
->API
.GetModeAttribMESA
= _eglGetModeAttribMESA
;
363 drv
->API
.GetScreensMESA
= _eglGetScreensMESA
;
364 drv
->API
.CreateScreenSurfaceMESA
= _eglCreateScreenSurfaceMESA
;
365 drv
->API
.ShowScreenSurfaceMESA
= _eglShowScreenSurfaceMESA
;
366 drv
->API
.ScreenPositionMESA
= _eglScreenPositionMESA
;
367 drv
->API
.QueryScreenMESA
= _eglQueryScreenMESA
;
368 drv
->API
.QueryScreenSurfaceMESA
= _eglQueryScreenSurfaceMESA
;
369 drv
->API
.QueryScreenModeMESA
= _eglQueryScreenModeMESA
;
370 drv
->API
.QueryModeStringMESA
= _eglQueryModeStringMESA
;
371 #endif /* EGL_MESA_screen_surface */
373 #ifdef EGL_VERSION_1_2
374 drv
->API
.CreatePbufferFromClientBuffer
= _eglCreatePbufferFromClientBuffer
;
375 #endif /* EGL_VERSION_1_2 */
381 * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
382 * are supported on the system by looking for standard library names.
389 #if defined(_EGL_PLATFORM_WINDOWS)
390 /* XXX not sure about these names */
391 const char *es1_libname
= "libGLESv1_CM.dll";
392 const char *es2_libname
= "libGLESv2.dll";
393 const char *gl_libname
= "OpenGL32.dll";
394 const char *vg_libname
= "libOpenVG.dll";
395 #elif defined(_EGL_PLATFORM_X)
396 const char *es1_libname
= "libGLESv1_CM.so";
397 const char *es2_libname
= "libGLESv2.so";
398 const char *gl_libname
= "libGL.so";
399 const char *vg_libname
= "libOpenVG.so";
402 if ((lib
= open_library(es1_libname
))) {
404 mask
|= EGL_OPENGL_ES_BIT
;
407 if ((lib
= open_library(es2_libname
))) {
409 mask
|= EGL_OPENGL_ES2_BIT
;
412 if ((lib
= open_library(gl_libname
))) {
414 mask
|= EGL_OPENGL_BIT
;
417 if ((lib
= open_library(vg_libname
))) {
419 mask
|= EGL_OPENVG_BIT
;