Move all the EGL API function pointers into a new _egl_api struct.
[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 /* EGL_MESA_screen */
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.ShowSurfaceMESA = _eglShowSurfaceMESA;
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 }
197
198
199 /**
200 * Examine the individual extension enable/disable flags and recompute
201 * the driver's Extensions string.
202 */
203 static void
204 UpdateExtensionsString(_EGLDriver *drv)
205 {
206 drv->Extensions[0] = 0;
207
208 if (drv->MESA_screen_surface)
209 strcat(drv->Extensions, "EGL_MESA_screen_surface ");
210 if (drv->MESA_copy_context)
211 strcat(drv->Extensions, "EGL_MESA_copy_context ");
212 assert(strlen(drv->Extensions) < MAX_EXTENSIONS_LEN);
213 }
214
215
216
217 const char *
218 _eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
219 {
220 (void) drv;
221 (void) dpy;
222 switch (name) {
223 case EGL_VENDOR:
224 return "Mesa Project";
225 case EGL_VERSION:
226 return "1.0";
227 case EGL_EXTENSIONS:
228 UpdateExtensionsString(drv);
229 return drv->Extensions;
230 default:
231 _eglError(EGL_BAD_PARAMETER, "eglQueryString");
232 return NULL;
233 }
234 }
235
236
237 EGLBoolean
238 _eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
239 {
240 /* just a placeholder */
241 (void) drv;
242 (void) dpy;
243 return EGL_TRUE;
244 }
245
246
247 EGLBoolean
248 _eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
249 {
250 /* just a placeholder */
251 (void) drv;
252 (void) dpy;
253 (void) engine;
254 return EGL_TRUE;
255 }