OSDN Git Service

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