OSDN Git Service

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