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