egl: Use _eglPreloadDrivers.
[mesa.git] / src / egl / main / egldisplay.c
1 /**
2 * Functions related to EGLDisplay.
3 */
4
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "eglcontext.h"
9 #include "eglsurface.h"
10 #include "egldisplay.h"
11 #include "egldriver.h"
12 #include "eglglobals.h"
13 #include "eglstring.h"
14 #include "eglmutex.h"
15 #include "egllog.h"
16
17
18 /**
19 * Finish display management.
20 */
21 void
22 _eglFiniDisplay(void)
23 {
24 _EGLDisplay *dpyList, *dpy;
25
26 /* atexit function is called with global mutex locked */
27 dpyList = _eglGlobal.DisplayList;
28 while (dpyList) {
29 /* pop list head */
30 dpy = dpyList;
31 dpyList = dpyList->Next;
32
33 if (dpy->ContextList || dpy->SurfaceList)
34 _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
35
36 free(dpy);
37 }
38 _eglGlobal.DisplayList = NULL;
39 }
40
41
42 /**
43 * If the first character is '!' we interpret it as specific driver name
44 * (i.e. "!r200" or "!i830"). Whatever follows ':' is interpreted as
45 * arguments.
46 *
47 * The caller may free() the returned driver name.
48 */
49 char *
50 _eglSplitDisplayString(const char *dpyString, const char **args)
51 {
52 char *drv, *p;
53
54 if (!dpyString || dpyString[0] != '!')
55 return NULL;
56 drv = _eglstrdup(dpyString + 1);
57 if (!drv)
58 return NULL;
59
60 p = strchr(dpyString, ':');
61 if (p) {
62 drv[p - dpyString] = '\0';
63 p++;
64 }
65 if (args)
66 *args = p;
67
68 return drv;
69 }
70
71
72 /**
73 * Allocate a new _EGLDisplay object for the given nativeDisplay handle.
74 * We'll also try to determine the device driver name at this time.
75 *
76 * Note that nativeDisplay may be an X Display ptr, or a string.
77 */
78 _EGLDisplay *
79 _eglNewDisplay(NativeDisplayType nativeDisplay)
80 {
81 _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
82 if (dpy) {
83 dpy->NativeDisplay = nativeDisplay;
84 }
85 return dpy;
86 }
87
88
89 /**
90 * Link a display to itself and return the handle of the link.
91 * The handle can be passed to client directly.
92 */
93 EGLDisplay
94 _eglLinkDisplay(_EGLDisplay *dpy)
95 {
96 _eglLockMutex(_eglGlobal.Mutex);
97
98 dpy->Next = _eglGlobal.DisplayList;
99 _eglGlobal.DisplayList = dpy;
100
101 _eglUnlockMutex(_eglGlobal.Mutex);
102
103 return (EGLDisplay) dpy;
104 }
105
106
107 /**
108 * Unlink a linked display from itself.
109 * Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
110 */
111 void
112 _eglUnlinkDisplay(_EGLDisplay *dpy)
113 {
114 _EGLDisplay *prev;
115
116 _eglLockMutex(_eglGlobal.Mutex);
117
118 prev = _eglGlobal.DisplayList;
119 if (prev != dpy) {
120 while (prev) {
121 if (prev->Next == dpy)
122 break;
123 prev = prev->Next;
124 }
125 assert(prev);
126 prev->Next = dpy->Next;
127 }
128 else {
129 _eglGlobal.DisplayList = dpy->Next;
130 }
131
132 _eglUnlockMutex(_eglGlobal.Mutex);
133 }
134
135
136 /**
137 * Find the display corresponding to the specified native display id in all
138 * linked displays.
139 */
140 _EGLDisplay *
141 _eglFindDisplay(NativeDisplayType nativeDisplay)
142 {
143 _EGLDisplay *dpy;
144
145 _eglLockMutex(_eglGlobal.Mutex);
146
147 dpy = _eglGlobal.DisplayList;
148 while (dpy) {
149 if (dpy->NativeDisplay == nativeDisplay) {
150 _eglUnlockMutex(_eglGlobal.Mutex);
151 return dpy;
152 }
153 dpy = dpy->Next;
154 }
155
156 _eglUnlockMutex(_eglGlobal.Mutex);
157
158 return NULL;
159 }
160
161
162 /**
163 * Destroy the contexts and surfaces that are linked to the display.
164 */
165 void
166 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
167 {
168 _EGLContext *contexts;
169 _EGLSurface *surfaces;
170
171 contexts = display->ContextList;
172 surfaces = display->SurfaceList;
173
174 while (contexts) {
175 _EGLContext *ctx = contexts;
176 contexts = contexts->Next;
177
178 _eglUnlinkContext(ctx);
179 drv->API.DestroyContext(drv, display, ctx);
180 }
181 assert(!display->ContextList);
182
183 while (surfaces) {
184 _EGLSurface *surf = surfaces;
185 surfaces = surfaces->Next;
186
187 _eglUnlinkSurface(surf);
188 drv->API.DestroySurface(drv, display, surf);
189 }
190 assert(!display->SurfaceList);
191 }
192
193
194 /**
195 * Free all the data hanging of an _EGLDisplay object, but not
196 * the object itself.
197 */
198 void
199 _eglCleanupDisplay(_EGLDisplay *disp)
200 {
201 EGLint i;
202
203 if (disp->Configs) {
204 for (i = 0; i < disp->NumConfigs; i++)
205 free(disp->Configs[i]);
206 free(disp->Configs);
207 disp->Configs = NULL;
208 disp->NumConfigs = 0;
209 }
210
211 /* XXX incomplete */
212 }
213
214
215 /**
216 * Link a context to a display and return the handle of the link.
217 * The handle can be passed to client directly.
218 */
219 EGLContext
220 _eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
221 {
222 ctx->Display = dpy;
223 ctx->Next = dpy->ContextList;
224 dpy->ContextList = ctx;
225 return (EGLContext) ctx;
226 }
227
228
229 /**
230 * Unlink a linked context from its display.
231 * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
232 */
233 void
234 _eglUnlinkContext(_EGLContext *ctx)
235 {
236 _EGLContext *prev;
237
238 prev = ctx->Display->ContextList;
239 if (prev != ctx) {
240 while (prev) {
241 if (prev->Next == ctx)
242 break;
243 prev = prev->Next;
244 }
245 assert(prev);
246 prev->Next = ctx->Next;
247 }
248 else {
249 ctx->Display->ContextList = ctx->Next;
250 }
251
252 ctx->Next = NULL;
253 ctx->Display = NULL;
254 }
255
256
257 /**
258 * Link a surface to a display and return the handle of the link.
259 * The handle can be passed to client directly.
260 */
261 EGLSurface
262 _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
263 {
264 surf->Display = dpy;
265 surf->Next = dpy->SurfaceList;
266 dpy->SurfaceList = surf;
267 return (EGLSurface) surf;
268 }
269
270
271 /**
272 * Unlink a linked surface from its display.
273 * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
274 */
275 void
276 _eglUnlinkSurface(_EGLSurface *surf)
277 {
278 _EGLSurface *prev;
279
280 prev = surf->Display->SurfaceList;
281 if (prev != surf) {
282 while (prev) {
283 if (prev->Next == surf)
284 break;
285 prev = prev->Next;
286 }
287 assert(prev);
288 prev->Next = surf->Next;
289 }
290 else {
291 prev = NULL;
292 surf->Display->SurfaceList = surf->Next;
293 }
294
295 surf->Next = NULL;
296 surf->Display = NULL;
297 }
298
299
300 #ifndef _EGL_SKIP_HANDLE_CHECK
301
302
303 /**
304 * Return EGL_TRUE if the given handle is a valid handle to a display.
305 */
306 EGLBoolean
307 _eglCheckDisplayHandle(EGLDisplay dpy)
308 {
309 _EGLDisplay *cur;
310
311 _eglLockMutex(_eglGlobal.Mutex);
312 cur = _eglGlobal.DisplayList;
313 while (cur) {
314 if (cur == (_EGLDisplay *) dpy)
315 break;
316 cur = cur->Next;
317 }
318 _eglUnlockMutex(_eglGlobal.Mutex);
319 return (cur != NULL);
320 }
321
322
323 /**
324 * Return EGL_TRUE if the given handle is a valid handle to a context.
325 */
326 EGLBoolean
327 _eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
328 {
329 _EGLContext *cur = NULL;
330
331 if (dpy)
332 cur = dpy->ContextList;
333 while (cur) {
334 if (cur == (_EGLContext *) ctx) {
335 assert(cur->Display == dpy);
336 break;
337 }
338 cur = cur->Next;
339 }
340 return (cur != NULL);
341 }
342
343
344 /**
345 * Return EGL_TRUE if the given handle is a valid handle to a surface.
346 */
347 EGLBoolean
348 _eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
349 {
350 _EGLSurface *cur = NULL;
351
352 if (dpy)
353 cur = dpy->SurfaceList;
354 while (cur) {
355 if (cur == (_EGLSurface *) surf) {
356 assert(cur->Display == dpy);
357 break;
358 }
359 cur = cur->Next;
360 }
361 return (cur != NULL);
362 }
363
364
365 #endif /* !_EGL_SKIP_HANDLE_CHECK */