egl: include egldefines.h
[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 }