OSDN Git Service

Merge branch 'mesa_7_5_branch'
[android-x86/external-mesa.git] / src / egl / main / egldriver.c
1 /**
2  * Functions for choosing and opening/loading device drivers.
3  */
4
5
6 #include <assert.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "eglconfig.h"
11 #include "eglcontext.h"
12 #include "egldefines.h"
13 #include "egldisplay.h"
14 #include "egldriver.h"
15 #include "eglglobals.h"
16 #include "egllog.h"
17 #include "eglmisc.h"
18 #include "eglmode.h"
19 #include "eglscreen.h"
20 #include "eglstring.h"
21 #include "eglsurface.h"
22
23 #if defined(_EGL_PLATFORM_X)
24 #include <dlfcn.h>
25 #include "eglx.h"
26 #elif defined(_EGL_PLATFORM_WINDOWS)
27 /* Use static linking on Windows for now */
28 #define WINDOWS_STATIC_LINK
29 #endif
30
31 /**
32  * Wrappers for dlopen/dlclose()
33  */
34 #if defined(_EGL_PLATFORM_WINDOWS)
35 #ifdef WINDOWS_STATIC_LINK
36    static const char *DefaultDriverName = "Windows EGL Static Library";
37 #else
38    /* XXX Need to decide how to do dynamic name lookup on Windows */
39    static const char *DefaultDriverName = "TBD";
40 #endif
41    static const char *SysFS = NULL;
42    typedef HMODULE lib_handle;
43
44    static HMODULE
45    open_library(const char *filename)
46    {
47 #ifdef WINDOWS_STATIC_LINK
48       return 0;
49 #else
50       return LoadLibrary(filename);
51 #endif
52    }
53
54    static void
55    close_library(HMODULE lib)
56    {
57 #ifdef WINDOWS_STATIC_LINK
58 #else
59       FreeLibrary(lib);
60 #endif
61    }
62
63 #elif defined(_EGL_PLATFORM_X)
64    static const char *DefaultDriverName = ":0";
65    static const char *SysFS = "/sys/class";
66
67    typedef void * lib_handle;
68
69    static void *
70    open_library(const char *filename)
71    {
72       return dlopen(filename, RTLD_LAZY);
73    }
74
75    static void
76    close_library(void *lib)
77    {
78       dlclose(lib);
79    }
80    
81 #endif
82
83 /**
84  * Given a card number, use sysfs to determine the DRI driver name.
85  */
86 const char *
87 _eglChooseDRMDriver(int card)
88 {
89 #if 0
90    return _eglstrdup("libEGLdri");
91 #else
92    char path[2000], driverName[2000];
93    FILE *f;
94    int length;
95
96    snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", SysFS, card);
97
98    f = fopen(path, "r");
99    if (!f)
100       return NULL;
101
102    fgets(driverName, sizeof(driverName), f);
103    fclose(f);
104
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);
110    }
111    else {
112       return NULL;
113    }   
114 #endif
115 }
116
117
118 /**
119  * XXX this function is totally subject change!!!
120  *
121  *
122  * Determine/return the path of the driver to use for the given native display.
123  *
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).
126  *
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".
131  *
132  * Whatever follows ':' is interpreted as arguments.
133  *
134  * The caller may free() the returned strings.
135  */
136 static char *
137 _eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
138 {
139    char *path = NULL;
140    const char *args = NULL;
141
142    path = getenv("EGL_DRIVER");
143    if (path)
144       path = _eglstrdup(path);
145
146 #if defined(_EGL_PLATFORM_X)
147    (void) DefaultDriverName;
148
149    if (!path && dpy->NativeDisplay) {
150       const char *dpyString = (const char *) dpy->NativeDisplay;
151       char *p;
152       /* parse the display string */
153       if (dpyString[0] == '!' || dpyString[0] == ':') {
154          if (dpyString[0] == '!') {
155             path = _eglstrdup(dpyString);
156             p = strchr(path, ':');
157             if (p)
158                *p++ = '\0';
159          } else {
160             p = strchr(dpyString, ':');
161             if (p)
162                p++;
163          }
164
165          if (p) {
166             if (!path && p[0] >= '0' && p[0] <= '9' && !p[1]) {
167                int card = atoi(p);
168                path = (char *) _eglChooseDRMDriver(card);
169             }
170             args = p;
171          }
172       }
173       else {
174          path = (char *) _xeglChooseDriver(dpy);
175       }
176    }
177 #elif defined(_EGL_PLATFORM_WINDOWS)
178    if (!path)
179       path = _eglstrdup(DefaultDriverName);
180 #endif /* _EGL_PLATFORM_X */
181
182    if (path && argsRet)
183       *argsRet = (args) ? _eglstrdup(args) : NULL;
184
185    return path;
186 }
187
188
189 /**
190  * Open the named driver and find its bootstrap function: _eglMain().
191  */
192 static _EGLMain_t
193 _eglOpenLibrary(const char *driverName, lib_handle *handle)
194 {
195    _EGLMain_t mainFunc;
196    lib_handle lib;
197    char driverFilename[1000];
198
199    assert(driverName);
200
201 #if defined(_EGL_PLATFORM_WINDOWS)
202 /* Use static linking on Windows for now */
203 #ifdef WINDOWS_STATIC_LINK
204    lib = 0;
205    mainFunc = (_EGLMain_t)_eglMain;
206 #else
207    /* XXX untested */
208    sprintf(driverFilename, "%s.dll", driverName);
209    _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
210    lib = open_library(driverFilename);
211    if (!lib) {
212       _eglLog(_EGL_WARNING, "Could not open %s",
213               driverFilename);
214       return NULL;
215    }
216    mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
217 #endif
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);
223    if (!lib) {
224       _eglLog(_EGL_WARNING, "Could not open %s (%s)",
225               driverFilename, dlerror());
226       return NULL;
227    }
228    mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
229 #endif
230
231    if (!mainFunc) {
232       _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
233       if (lib)
234          close_library(lib);
235       return NULL;
236    }
237
238    *handle = lib;
239    return mainFunc;
240 }
241
242
243 /**
244  * Load the named driver.  The path and args passed will be
245  * owned by the driver and freed.
246  */
247 static _EGLDriver *
248 _eglLoadDriver(char *path, char *args)
249 {
250    _EGLMain_t mainFunc;
251    lib_handle lib;
252    _EGLDriver *drv = NULL;
253
254    mainFunc = _eglOpenLibrary(path, &lib);
255    if (!mainFunc)
256       return NULL;
257
258    drv = mainFunc(args);
259    if (!drv) {
260       if (lib)
261          close_library(lib);
262       return NULL;
263    }
264
265    if (!drv->Name) {
266       _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path);
267       drv->Name = "UNNAMED";
268    }
269
270    drv->Path = path;
271    drv->Args = args;
272    drv->LibHandle = lib;
273
274    return drv;
275 }
276
277
278 /**
279  * Match a display to a preloaded driver.
280  */
281 static _EGLDriver *
282 _eglMatchDriver(_EGLDisplay *dpy)
283 {
284    _EGLDriver *defaultDriver = NULL;
285    EGLint i;
286
287    for (i = 0; i < _eglGlobal.NumDrivers; i++) {
288       _EGLDriver *drv = _eglGlobal.Drivers[i];
289
290       /* display specifies a driver */
291       if (dpy->DriverName) {
292          if (strcmp(dpy->DriverName, drv->Name) == 0)
293             return drv;
294       }
295       else if (drv->Probe) {
296          if (drv->Probe(drv, dpy))
297             return drv;
298       }
299       else {
300          if (!defaultDriver)
301             defaultDriver = drv;
302       }
303    }
304
305    return defaultDriver;
306 }
307
308
309 /**
310  * Load a driver and save it.
311  */
312 const char *
313 _eglPreloadDriver(_EGLDisplay *dpy)
314 {
315    char *path, *args;
316    _EGLDriver *drv;
317    EGLint i;
318
319    path = _eglChooseDriver(dpy, &args);
320    if (!path)
321       return NULL;
322
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",
327                  drv->Name);
328          free(path);
329          if (args)
330             free(args);
331          return drv->Name;
332       }
333    }
334
335    drv = _eglLoadDriver(path, args);
336    if (!drv)
337       return NULL;
338
339    _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
340
341    return drv->Name;
342 }
343
344
345 /**
346  * Open a preloaded driver.
347  */
348 _EGLDriver *
349 _eglOpenDriver(_EGLDisplay *dpy)
350 {
351    _EGLDriver *drv = _eglMatchDriver(dpy);
352    return drv;
353 }
354
355
356 /**
357  * Close a preloaded driver.
358  */
359 EGLBoolean
360 _eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy)
361 {
362    return EGL_TRUE;
363 }
364
365
366 /**
367  * Unload preloaded drivers.
368  */
369 void
370 _eglUnloadDrivers(void)
371 {
372    EGLint i;
373    for (i = 0; i < _eglGlobal.NumDrivers; i++) {
374       _EGLDriver *drv = _eglGlobal.Drivers[i];
375       lib_handle handle = drv->LibHandle;
376
377       if (drv->Path)
378          free((char *) drv->Path);
379       if (drv->Args)
380          free((char *) drv->Args);
381
382       /* destroy driver */
383       if (drv->Unload)
384          drv->Unload(drv);
385
386       if (handle)
387          close_library(handle);
388       _eglGlobal.Drivers[i] = NULL;
389    }
390
391    _eglGlobal.NumDrivers = 0;
392 }
393
394
395 /**
396  * Given a display handle, return the _EGLDriver for that display.
397  */
398 _EGLDriver *
399 _eglLookupDriver(EGLDisplay dpy)
400 {
401    _EGLDisplay *d = _eglLookupDisplay(dpy);
402    if (d)
403       return d->Driver;
404    else
405       return NULL;
406 }
407
408
409 /**
410  * Plug all the available fallback routines into the given driver's
411  * dispatch table.
412  */
413 void
414 _eglInitDriverFallbacks(_EGLDriver *drv)
415 {
416    /* If a pointer is set to NULL, then the device driver _really_ has
417     * to implement it.
418     */
419    drv->API.Initialize = NULL;
420    drv->API.Terminate = NULL;
421
422    drv->API.GetConfigs = _eglGetConfigs;
423    drv->API.ChooseConfig = _eglChooseConfig;
424    drv->API.GetConfigAttrib = _eglGetConfigAttrib;
425
426    drv->API.CreateContext = _eglCreateContext;
427    drv->API.DestroyContext = _eglDestroyContext;
428    drv->API.MakeCurrent = _eglMakeCurrent;
429    drv->API.QueryContext = _eglQueryContext;
430
431    drv->API.CreateWindowSurface = _eglCreateWindowSurface;
432    drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
433    drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
434    drv->API.DestroySurface = _eglDestroySurface;
435    drv->API.QuerySurface = _eglQuerySurface;
436    drv->API.SurfaceAttrib = _eglSurfaceAttrib;
437    drv->API.BindTexImage = _eglBindTexImage;
438    drv->API.ReleaseTexImage = _eglReleaseTexImage;
439    drv->API.SwapInterval = _eglSwapInterval;
440    drv->API.SwapBuffers = _eglSwapBuffers;
441    drv->API.CopyBuffers = _eglCopyBuffers;
442
443    drv->API.QueryString = _eglQueryString;
444    drv->API.WaitGL = _eglWaitGL;
445    drv->API.WaitNative = _eglWaitNative;
446
447 #ifdef EGL_MESA_screen_surface
448    drv->API.ChooseModeMESA = _eglChooseModeMESA; 
449    drv->API.GetModesMESA = _eglGetModesMESA;
450    drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
451    drv->API.GetScreensMESA = _eglGetScreensMESA;
452    drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
453    drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
454    drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
455    drv->API.QueryScreenMESA = _eglQueryScreenMESA;
456    drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
457    drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
458    drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
459 #endif /* EGL_MESA_screen_surface */
460
461 #ifdef EGL_VERSION_1_2
462    drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
463 #endif /* EGL_VERSION_1_2 */
464 }
465
466
467
468 /**
469  * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
470  * are supported on the system by looking for standard library names.
471  */
472 EGLint
473 _eglFindAPIs(void)
474 {
475    EGLint mask = 0x0;
476    lib_handle lib;
477 #if defined(_EGL_PLATFORM_WINDOWS)
478    /* XXX not sure about these names */
479    const char *es1_libname = "libGLESv1_CM.dll";
480    const char *es2_libname = "libGLESv2.dll";
481    const char *gl_libname = "OpenGL32.dll";
482    const char *vg_libname = "libOpenVG.dll";
483 #elif defined(_EGL_PLATFORM_X)
484    const char *es1_libname = "libGLESv1_CM.so";
485    const char *es2_libname = "libGLESv2.so";
486    const char *gl_libname = "libGL.so";
487    const char *vg_libname = "libOpenVG.so";
488 #endif
489
490    if ((lib = open_library(es1_libname))) {
491       close_library(lib);
492       mask |= EGL_OPENGL_ES_BIT;
493    }
494
495    if ((lib = open_library(es2_libname))) {
496       close_library(lib);
497       mask |= EGL_OPENGL_ES2_BIT;
498    }
499
500    if ((lib = open_library(gl_libname))) {
501       close_library(lib);
502       mask |= EGL_OPENGL_BIT;
503    }
504
505    if ((lib = open_library(vg_libname))) {
506       close_library(lib);
507       mask |= EGL_OPENVG_BIT;
508    }
509
510    return mask;
511 }