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