Merge branch 'mesa_7_5_branch'
[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 #if defined(_EGL_PLATFORM_X)
85 dpy->Xdpy = (Display *) nativeDisplay;
86 #endif
87
88 dpy->DriverName = _eglPreloadDriver(dpy);
89 if (!dpy->DriverName) {
90 free(dpy);
91 return NULL;
92 }
93 }
94 return dpy;
95 }
96
97
98 /**
99 * Link a display to itself and return the handle of the link.
100 * The handle can be passed to client directly.
101 */
102 EGLDisplay
103 _eglLinkDisplay(_EGLDisplay *dpy)
104 {
105 _eglLockMutex(_eglGlobal.Mutex);
106
107 dpy->Next = _eglGlobal.DisplayList;
108 _eglGlobal.DisplayList = dpy;
109
110 _eglUnlockMutex(_eglGlobal.Mutex);
111
112 return (EGLDisplay) dpy;
113 }
114
115
116 /**
117 * Unlink a linked display from itself.
118 * Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
119 */
120 void
121 _eglUnlinkDisplay(_EGLDisplay *dpy)
122 {
123 _EGLDisplay *prev;
124
125 _eglLockMutex(_eglGlobal.Mutex);
126
127 prev = _eglGlobal.DisplayList;
128 if (prev != dpy) {
129 while (prev) {
130 if (prev->Next == dpy)
131 break;
132 prev = prev->Next;
133 }
134 assert(prev);
135 prev->Next = dpy->Next;
136 }
137 else {
138 _eglGlobal.DisplayList = dpy->Next;
139 }
140
141 _eglUnlockMutex(_eglGlobal.Mutex);
142 }
143
144
145 /**
146 * Find the display corresponding to the specified native display id in all
147 * linked displays.
148 */
149 _EGLDisplay *
150 _eglFindDisplay(NativeDisplayType nativeDisplay)
151 {
152 _EGLDisplay *dpy;
153
154 _eglLockMutex(_eglGlobal.Mutex);
155
156 dpy = _eglGlobal.DisplayList;
157 while (dpy) {
158 if (dpy->NativeDisplay == nativeDisplay) {
159 _eglUnlockMutex(_eglGlobal.Mutex);
160 return dpy;
161 }
162 dpy = dpy->Next;
163 }
164
165 _eglUnlockMutex(_eglGlobal.Mutex);
166
167 return NULL;
168 }
169
170
171 /**
172 * Destroy the contexts and surfaces that are linked to the display.
173 */
174 void
175 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
176 {
177 _EGLContext *contexts;
178 _EGLSurface *surfaces;
179
180 contexts = display->ContextList;
181 surfaces = display->SurfaceList;
182
183 while (contexts) {
184 _EGLContext *ctx = contexts;
185 contexts = contexts->Next;
186
187 _eglUnlinkContext(ctx);
188 drv->API.DestroyContext(drv, display, ctx);
189 }
190 assert(!display->ContextList);
191
192 while (surfaces) {
193 _EGLSurface *surf = surfaces;
194 surfaces = surfaces->Next;
195
196 _eglUnlinkSurface(surf);
197 drv->API.DestroySurface(drv, display, surf);
198 }
199 assert(!display->SurfaceList);
200 }
201
202
203 /**
204 * Free all the data hanging of an _EGLDisplay object, but not
205 * the object itself.
206 */
207 void
208 _eglCleanupDisplay(_EGLDisplay *disp)
209 {
210 EGLint i;
211
212 if (disp->Configs) {
213 for (i = 0; i < disp->NumConfigs; i++)
214 free(disp->Configs[i]);
215 free(disp->Configs);
216 disp->Configs = NULL;
217 disp->NumConfigs = 0;
218 }
219
220 /* XXX incomplete */
221 }
222
223
224 /**
225 * Link a context to a display and return the handle of the link.
226 * The handle can be passed to client directly.
227 */
228 EGLContext
229 _eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
230 {
231 ctx->Display = dpy;
232 ctx->Next = dpy->ContextList;
233 dpy->ContextList = ctx;
234 return (EGLContext) ctx;
235 }
236
237
238 /**
239 * Unlink a linked context from its display.
240 * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
241 */
242 void
243 _eglUnlinkContext(_EGLContext *ctx)
244 {
245 _EGLContext *prev;
246
247 prev = ctx->Display->ContextList;
248 if (prev != ctx) {
249 while (prev) {
250 if (prev->Next == ctx)
251 break;
252 prev = prev->Next;
253 }
254 assert(prev);
255 prev->Next = ctx->Next;
256 }
257 else {
258 ctx->Display->ContextList = ctx->Next;
259 }
260
261 ctx->Next = NULL;
262 ctx->Display = NULL;
263 }
264
265
266 /**
267 * Link a surface to a display and return the handle of the link.
268 * The handle can be passed to client directly.
269 */
270 EGLSurface
271 _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
272 {
273 surf->Display = dpy;
274 surf->Next = dpy->SurfaceList;
275 dpy->SurfaceList = surf;
276 return (EGLSurface) surf;
277 }
278
279
280 /**
281 * Unlink a linked surface from its display.
282 * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
283 */
284 void
285 _eglUnlinkSurface(_EGLSurface *surf)
286 {
287 _EGLSurface *prev;
288
289 prev = surf->Display->SurfaceList;
290 if (prev != surf) {
291 while (prev) {
292 if (prev->Next == surf)
293 break;
294 prev = prev->Next;
295 }
296 assert(prev);
297 prev->Next = surf->Next;
298 }
299 else {
300 prev = NULL;
301 surf->Display->SurfaceList = surf->Next;
302 }
303
304 surf->Next = NULL;
305 surf->Display = NULL;
306 }
307
308
309 #ifndef _EGL_SKIP_HANDLE_CHECK
310
311
312 /**
313 * Return EGL_TRUE if the given handle is a valid handle to a display.
314 */
315 EGLBoolean
316 _eglCheckDisplayHandle(EGLDisplay dpy)
317 {
318 _EGLDisplay *cur;
319
320 _eglLockMutex(_eglGlobal.Mutex);
321 cur = _eglGlobal.DisplayList;
322 while (cur) {
323 if (cur == (_EGLDisplay *) dpy)
324 break;
325 cur = cur->Next;
326 }
327 _eglUnlockMutex(_eglGlobal.Mutex);
328 return (cur != NULL);
329 }
330
331
332 /**
333 * Return EGL_TRUE if the given handle is a valid handle to a context.
334 */
335 EGLBoolean
336 _eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
337 {
338 _EGLContext *cur = NULL;
339
340 if (dpy)
341 cur = dpy->ContextList;
342 while (cur) {
343 if (cur == (_EGLContext *) ctx) {
344 assert(cur->Display == dpy);
345 break;
346 }
347 cur = cur->Next;
348 }
349 return (cur != NULL);
350 }
351
352
353 /**
354 * Return EGL_TRUE if the given handle is a valid handle to a surface.
355 */
356 EGLBoolean
357 _eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
358 {
359 _EGLSurface *cur = NULL;
360
361 if (dpy)
362 cur = dpy->SurfaceList;
363 while (cur) {
364 if (cur == (_EGLSurface *) surf) {
365 assert(cur->Display == dpy);
366 break;
367 }
368 cur = cur->Next;
369 }
370 return (cur != NULL);
371 }
372
373
374 #endif /* !_EGL_SKIP_HANDLE_CHECK */