OSDN Git Service

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