OSDN Git Service

egl: clean-up re-org of the client API state
[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 <dlfcn.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "eglconfig.h"
12 #include "eglcontext.h"
13 #include "egldefines.h"
14 #include "egldisplay.h"
15 #include "egldriver.h"
16 #include "eglglobals.h"
17 #include "egllog.h"
18 #include "eglmisc.h"
19 #include "eglmode.h"
20 #include "eglscreen.h"
21 #include "eglstring.h"
22 #include "eglsurface.h"
23
24 #if defined(_EGL_PLATFORM_X)
25 #include "eglx.h"
26 #elif defined(_EGL_PLATFORM_WINDOWS)
27 /* XXX to do */
28 #elif defined(_EGL_PLATFORM_WINCE)
29 /* XXX to do */
30 #endif
31
32
33 const char *DefaultDriverName = ":0";
34 const char *SysFS = "/sys/class";
35
36
37
38
39 /**
40  * Given a card number, use sysfs to determine the DRI driver name.
41  */
42 static const char *
43 _eglChooseDRMDriver(int card)
44 {
45 #if 0
46    return _eglstrdup("libEGLdri");
47 #else
48    char path[2000], driverName[2000];
49    FILE *f;
50    int length;
51
52    snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", SysFS, card);
53
54    f = fopen(path, "r");
55    if (!f)
56       return NULL;
57
58    fgets(driverName, sizeof(driverName), f);
59    fclose(f);
60
61    if ((length = strlen(driverName)) > 1) {
62       /* remove the trailing newline from sysfs */
63       driverName[length - 1] = '\0';
64       strncat(driverName, "_dri", sizeof(driverName));
65       return _eglstrdup(driverName);
66    }
67    else {
68       return NULL;
69    }   
70 #endif
71 }
72
73
74 /**
75  * Determine/return the name of the driver to use for the given _EGLDisplay.
76  *
77  * Try to be clever and determine if nativeDisplay is an Xlib Display
78  * ptr or a string (naming a driver or screen number, etc).
79  *
80  * If the first character is ':' we interpret it as a screen or card index
81  * number (i.e. ":0" or ":1", etc)
82  * Else if the first character is '!' we interpret it as specific driver name
83  * (i.e. "!r200" or "!i830".
84  *
85  * Whatever follows ':' is copied and put into dpy->DriverArgs.
86  *
87  * The caller may free() the returned string.
88  */
89 const char *
90 _eglChooseDriver(_EGLDisplay *dpy)
91 {
92    const char *displayString = (const char *) dpy->NativeDisplay;
93    const char *driverName = NULL;
94
95    /* First, if the EGL_DRIVER env var is set, use that */
96    driverName = getenv("EGL_DRIVER");
97    if (driverName)
98       return _eglstrdup(driverName);
99
100 #if 0
101    if (!displayString) {
102       /* choose a default */
103       displayString = DefaultDriverName;
104    }
105 #endif
106    /* extract default DriverArgs = whatever follows ':' */
107    if (displayString &&
108        (displayString[0] == '!' ||
109         displayString[0] == ':')) {
110       const char *args = strchr(displayString, ':');
111       if (args)
112          dpy->DriverArgs = _eglstrdup(args + 1);
113    }
114
115    /* determine driver name now */
116    if (displayString && displayString[0] == ':' &&
117        (displayString[1] >= '0' && displayString[1] <= '9') &&
118        !displayString[2]) {
119       int card = atoi(displayString + 1);
120       driverName = _eglChooseDRMDriver(card);
121    }
122    else if (displayString && displayString[0] == '!') {
123       /* use user-specified driver name */
124       driverName = _eglstrdup(displayString + 1);
125       /* truncate driverName at ':' if present */
126       {
127          char *args = strchr(driverName, ':');
128          if (args) {
129             *args = 0;
130          }
131       }
132    }
133    else {
134       /* NativeDisplay is not a string! */
135 #if defined(_EGL_PLATFORM_X)
136       driverName = _xeglChooseDriver(dpy);
137 #elif defined(_EGL_PLATFORM_WINDOWS)
138       /* XXX to do */
139       driverName = _weglChooseDriver(dpy);
140 #elif defined(_EGL_PLATFORM_WINCE)
141       /* XXX to do */
142 #endif
143    }
144
145    return driverName;
146 }
147
148
149 /**
150  * Open/load the named driver and call its bootstrap function: _eglMain().
151  * By the time this function is called, the dpy->DriverName should have
152  * been determined.
153  *
154  * \return  new _EGLDriver object.
155  */
156 _EGLDriver *
157 _eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args)
158 {
159    _EGLDriver *drv;
160    _EGLMain_t mainFunc;
161    void *lib;
162    char driverFilename[1000];
163
164    assert(driverName);
165
166    /* XXX also prepend a directory path??? */
167    sprintf(driverFilename, "%s.so", driverName);
168
169    _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
170    lib = dlopen(driverFilename, RTLD_NOW);
171    if (!lib) {
172       _eglLog(_EGL_WARNING, "Could not open %s (%s)",
173               driverFilename, dlerror());
174       return NULL;
175    }
176
177    mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
178    if (!mainFunc) {
179       _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
180       dlclose(lib);
181       return NULL;
182    }
183
184    drv = mainFunc(dpy, args);
185    if (!drv) {
186       dlclose(lib);
187       return NULL;
188    }
189    /* with a recurvise open you want the inner most handle */
190    if (!drv->LibHandle)
191       drv->LibHandle = lib;
192    else
193       dlclose(lib);
194
195    /* update the global notion of supported APIs */
196    _eglGlobal.ClientAPIsMask |= drv->ClientAPIsMask;
197
198    return drv;
199 }
200
201
202 EGLBoolean
203 _eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
204 {
205    void *handle = drv->LibHandle;
206    EGLBoolean b;
207
208    _eglLog(_EGL_INFO, "Closing driver");
209
210    /*
211     * XXX check for currently bound context/surfaces and delete them?
212     */
213
214    b = drv->API.Terminate(drv, dpy);
215    dlclose(handle);
216    return b;
217 }
218
219
220 /**
221  * Given a display handle, return the _EGLDriver for that display.
222  */
223 _EGLDriver *
224 _eglLookupDriver(EGLDisplay dpy)
225 {
226    _EGLDisplay *d = _eglLookupDisplay(dpy);
227    if (d)
228       return d->Driver;
229    else
230       return NULL;
231 }
232
233
234 /**
235  * Plug all the available fallback routines into the given driver's
236  * dispatch table.
237  */
238 void
239 _eglInitDriverFallbacks(_EGLDriver *drv)
240 {
241    /* If a pointer is set to NULL, then the device driver _really_ has
242     * to implement it.
243     */
244    drv->API.Initialize = NULL;
245    drv->API.Terminate = NULL;
246
247    drv->API.GetConfigs = _eglGetConfigs;
248    drv->API.ChooseConfig = _eglChooseConfig;
249    drv->API.GetConfigAttrib = _eglGetConfigAttrib;
250
251    drv->API.CreateContext = _eglCreateContext;
252    drv->API.DestroyContext = _eglDestroyContext;
253    drv->API.MakeCurrent = _eglMakeCurrent;
254    drv->API.QueryContext = _eglQueryContext;
255
256    drv->API.CreateWindowSurface = _eglCreateWindowSurface;
257    drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
258    drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
259    drv->API.DestroySurface = _eglDestroySurface;
260    drv->API.QuerySurface = _eglQuerySurface;
261    drv->API.SurfaceAttrib = _eglSurfaceAttrib;
262    drv->API.BindTexImage = _eglBindTexImage;
263    drv->API.ReleaseTexImage = _eglReleaseTexImage;
264    drv->API.SwapInterval = _eglSwapInterval;
265    drv->API.SwapBuffers = _eglSwapBuffers;
266    drv->API.CopyBuffers = _eglCopyBuffers;
267
268    drv->API.QueryString = _eglQueryString;
269    drv->API.WaitGL = _eglWaitGL;
270    drv->API.WaitNative = _eglWaitNative;
271
272 #ifdef EGL_MESA_screen_surface
273    drv->API.ChooseModeMESA = _eglChooseModeMESA; 
274    drv->API.GetModesMESA = _eglGetModesMESA;
275    drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
276    drv->API.GetScreensMESA = _eglGetScreensMESA;
277    drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
278    drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
279    drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
280    drv->API.QueryScreenMESA = _eglQueryScreenMESA;
281    drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
282    drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
283    drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
284 #endif /* EGL_MESA_screen_surface */
285
286 #ifdef EGL_VERSION_1_2
287    drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
288 #endif /* EGL_VERSION_1_2 */
289 }