OSDN Git Service

Merge commit 'origin/master' into gallium-0.2
[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  * XXX this function is totally subject change!!!
119  *
120  *
121  * Determine/return the name of the driver to use for the given _EGLDisplay.
122  *
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).
125  *
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".
130  *
131  * Whatever follows ':' is copied and put into dpy->DriverArgs.
132  *
133  * The caller may free() the returned string.
134  */
135 const char *
136 _eglChooseDriver(_EGLDisplay *dpy)
137 {
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;
142 #else
143    const char *displayString = (const char *) dpy->NativeDisplay;
144 #endif
145    const char *driverName = NULL;
146
147    (void) DefaultDriverName;
148
149 #if defined(_EGL_PLATFORM_X)
150    /* First, if the EGL_DRIVER env var is set, use that */
151    driverName = getenv("EGL_DRIVER");
152    if (driverName)
153       return _eglstrdup(driverName);
154 #endif
155
156 #if 0
157    if (!displayString) {
158       /* choose a default */
159       displayString = DefaultDriverName;
160    }
161 #endif
162    /* extract default DriverArgs = whatever follows ':' */
163    if (displayString &&
164        (displayString[0] == '!' ||
165         displayString[0] == ':')) {
166       const char *args = strchr(displayString, ':');
167       if (args)
168          dpy->DriverArgs = _eglstrdup(args + 1);
169    }
170
171    /* determine driver name now */
172    if (displayString && displayString[0] == ':' &&
173        (displayString[1] >= '0' && displayString[1] <= '9') &&
174        !displayString[2]) {
175       int card = atoi(displayString + 1);
176       driverName = _eglChooseDRMDriver(card);
177    }
178    else if (displayString && displayString[0] == '!') {
179       /* use user-specified driver name */
180       driverName = _eglstrdup(displayString + 1);
181       /* truncate driverName at ':' if present */
182       {
183          char *args = strchr(driverName, ':');
184          if (args) {
185             *args = 0;
186          }
187       }
188    }
189    else 
190    {
191       /* NativeDisplay is not a string! */
192 #if defined(_EGL_PLATFORM_X)
193       driverName = _xeglChooseDriver(dpy);
194 #else
195       driverName = DefaultDriverName;
196 #endif
197    }
198
199    return driverName;
200 }
201
202
203 /**
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
206  * been determined.
207  *
208  * \return  new _EGLDriver object.
209  */
210 _EGLDriver *
211 _eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args)
212 {
213    _EGLDriver *drv;
214    _EGLMain_t mainFunc;
215    lib_handle lib;
216    char driverFilename[1000];
217
218    assert(driverName);
219
220 #if defined(_EGL_PLATFORM_WINDOWS)
221 /* Use static linking on Windows for now */
222 #ifdef WINDOWS_STATIC_LINK
223    lib = 0;
224    mainFunc = (_EGLMain_t)_eglMain;
225 #else
226    /* XXX untested */
227    sprintf(driverFilename, "%s.dll", driverName);
228    _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
229    lib = open_library(driverFilename);
230    if (!lib) {
231       _eglLog(_EGL_WARNING, "Could not open %s",
232               driverFilename);
233       return NULL;
234    }
235    mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
236 #endif
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);
242    if (!lib) {
243       _eglLog(_EGL_WARNING, "Could not open %s (%s)",
244               driverFilename, dlerror());
245       return NULL;
246    }
247    mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
248 #endif
249
250    if (!mainFunc) {
251       _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
252       close_library(lib);
253       return NULL;
254    }
255
256    drv = mainFunc(dpy, args);
257    if (!drv) {
258       close_library(lib);
259       return NULL;
260    }
261
262    /* with a recurvise open you want the inner most handle */
263    if (!drv->LibHandle) {
264       drv->LibHandle = lib;
265    }
266    else {
267       close_library(lib);
268    }
269
270    /* update the global notion of supported APIs */
271    _eglGlobal.ClientAPIsMask |= drv->ClientAPIsMask;
272
273    _eglSaveDriver(drv);
274
275    return drv;
276 }
277
278
279 EGLBoolean
280 _eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
281 {
282    void *handle = drv->LibHandle;
283    EGLBoolean b;
284
285    _eglLog(_EGL_DEBUG, "Closing %s", drv->Name);
286
287    /*
288     * XXX check for currently bound context/surfaces and delete them?
289     */
290
291    b = drv->API.Terminate(drv, dpy);
292
293    close_library(handle);
294
295    return b;
296 }
297
298
299 /**
300  * Save the given driver pointer in the list of all known drivers.
301  */
302 void
303 _eglSaveDriver(_EGLDriver *drv)
304 {
305    _eglGlobal.Drivers[ _eglGlobal.NumDrivers++ ] = drv;
306 }
307
308
309 /**
310  * Given a display handle, return the _EGLDriver for that display.
311  */
312 _EGLDriver *
313 _eglLookupDriver(EGLDisplay dpy)
314 {
315    _EGLDisplay *d = _eglLookupDisplay(dpy);
316    if (d)
317       return d->Driver;
318    else
319       return NULL;
320 }
321
322
323 /**
324  * Plug all the available fallback routines into the given driver's
325  * dispatch table.
326  */
327 void
328 _eglInitDriverFallbacks(_EGLDriver *drv)
329 {
330    /* If a pointer is set to NULL, then the device driver _really_ has
331     * to implement it.
332     */
333    drv->API.Initialize = NULL;
334    drv->API.Terminate = NULL;
335
336    drv->API.GetConfigs = _eglGetConfigs;
337    drv->API.ChooseConfig = _eglChooseConfig;
338    drv->API.GetConfigAttrib = _eglGetConfigAttrib;
339
340    drv->API.CreateContext = _eglCreateContext;
341    drv->API.DestroyContext = _eglDestroyContext;
342    drv->API.MakeCurrent = _eglMakeCurrent;
343    drv->API.QueryContext = _eglQueryContext;
344
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;
356
357    drv->API.QueryString = _eglQueryString;
358    drv->API.WaitGL = _eglWaitGL;
359    drv->API.WaitNative = _eglWaitNative;
360
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 */
374
375 #ifdef EGL_VERSION_1_2
376    drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
377 #endif /* EGL_VERSION_1_2 */
378 }
379
380
381
382 /**
383  * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
384  * are supported on the system by looking for standard library names.
385  */
386 EGLint
387 _eglFindAPIs(void)
388 {
389    EGLint mask = 0x0;
390    lib_handle lib;
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";
402 #endif
403
404    if ((lib = open_library(es1_libname))) {
405       close_library(lib);
406       mask |= EGL_OPENGL_ES_BIT;
407    }
408
409    if ((lib = open_library(es2_libname))) {
410       close_library(lib);
411       mask |= EGL_OPENGL_ES2_BIT;
412    }
413
414    if ((lib = open_library(gl_libname))) {
415       close_library(lib);
416       mask |= EGL_OPENGL_BIT;
417    }
418
419    if ((lib = open_library(vg_libname))) {
420       close_library(lib);
421       mask |= EGL_OPENVG_BIT;
422    }
423
424    return mask;
425 }