OSDN Git Service

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