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