OSDN Git Service

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