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