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