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);
288 * XXX check for currently bound context/surfaces and delete them?
291 b = drv->API.Terminate(drv, dpy);
293 close_library(handle);
300 * Save the given driver pointer in the list of all known drivers.
303 _eglSaveDriver(_EGLDriver *drv)
305 _eglGlobal.Drivers[ _eglGlobal.NumDrivers++ ] = drv;
310 * Given a display handle, return the _EGLDriver for that display.
313 _eglLookupDriver(EGLDisplay dpy)
315 _EGLDisplay *d = _eglLookupDisplay(dpy);
324 * Plug all the available fallback routines into the given driver's
328 _eglInitDriverFallbacks(_EGLDriver *drv)
330 /* If a pointer is set to NULL, then the device driver _really_ has
333 drv->API.Initialize = NULL;
334 drv->API.Terminate = NULL;
336 drv->API.GetConfigs = _eglGetConfigs;
337 drv->API.ChooseConfig = _eglChooseConfig;
338 drv->API.GetConfigAttrib = _eglGetConfigAttrib;
340 drv->API.CreateContext = _eglCreateContext;
341 drv->API.DestroyContext = _eglDestroyContext;
342 drv->API.MakeCurrent = _eglMakeCurrent;
343 drv->API.QueryContext = _eglQueryContext;
345 drv->API.CreateWindowSurface = _eglCreateWindowSurface;
346 drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
347 drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
348 drv->API.DestroySurface = _eglDestroySurface;
349 drv->API.QuerySurface = _eglQuerySurface;
350 drv->API.SurfaceAttrib = _eglSurfaceAttrib;
351 drv->API.BindTexImage = _eglBindTexImage;
352 drv->API.ReleaseTexImage = _eglReleaseTexImage;
353 drv->API.SwapInterval = _eglSwapInterval;
354 drv->API.SwapBuffers = _eglSwapBuffers;
355 drv->API.CopyBuffers = _eglCopyBuffers;
357 drv->API.QueryString = _eglQueryString;
358 drv->API.WaitGL = _eglWaitGL;
359 drv->API.WaitNative = _eglWaitNative;
361 #ifdef EGL_MESA_screen_surface
362 drv->API.ChooseModeMESA = _eglChooseModeMESA;
363 drv->API.GetModesMESA = _eglGetModesMESA;
364 drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
365 drv->API.GetScreensMESA = _eglGetScreensMESA;
366 drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
367 drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
368 drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
369 drv->API.QueryScreenMESA = _eglQueryScreenMESA;
370 drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
371 drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
372 drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
373 #endif /* EGL_MESA_screen_surface */
375 #ifdef EGL_VERSION_1_2
376 drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
377 #endif /* EGL_VERSION_1_2 */
383 * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
384 * are supported on the system by looking for standard library names.
391 #if defined(_EGL_PLATFORM_WINDOWS)
392 /* XXX not sure about these names */
393 const char *es1_libname = "libGLESv1_CM.dll";
394 const char *es2_libname = "libGLESv2.dll";
395 const char *gl_libname = "OpenGL32.dll";
396 const char *vg_libname = "libOpenVG.dll";
397 #elif defined(_EGL_PLATFORM_X)
398 const char *es1_libname = "libGLESv1_CM.so";
399 const char *es2_libname = "libGLESv2.so";
400 const char *gl_libname = "libGL.so";
401 const char *vg_libname = "libOpenVG.so";
404 if ((lib = open_library(es1_libname))) {
406 mask |= EGL_OPENGL_ES_BIT;
409 if ((lib = open_library(es2_libname))) {
411 mask |= EGL_OPENGL_ES2_BIT;
414 if ((lib = open_library(gl_libname))) {
416 mask |= EGL_OPENGL_BIT;
419 if ((lib = open_library(vg_libname))) {
421 mask |= EGL_OPENVG_BIT;