000db6c69af495ff959d4bf5297c9efbc7017bb7
[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 * Return the handle of a linked display, or EGL_NO_DISPLAY.
118 */
119 EGLDisplay
120 _eglGetDisplayHandle(_EGLDisplay *dpy)
121 {
122 return (EGLDisplay) ((dpy) ? dpy : EGL_NO_DISPLAY);
123 }
124
125
126 /**
127 * Lookup a handle to find the linked display.
128 * Return NULL if the handle has no corresponding linked display.
129 */
130 _EGLDisplay *
131 _eglLookupDisplay(EGLDisplay display)
132 {
133 _EGLDisplay *dpy = (_EGLDisplay *) display;
134 return dpy;
135 }
136
137
138 /**
139 * Find the display corresponding to the specified native display id in all
140 * linked displays.
141 */
142 _EGLDisplay *
143 _eglFindDisplay(NativeDisplayType nativeDisplay)
144 {
145 _EGLDisplay *dpy;
146
147 _eglLockMutex(_eglGlobal.Mutex);
148
149 dpy = _eglGlobal.DisplayList;
150 while (dpy) {
151 if (dpy->NativeDisplay == nativeDisplay) {
152 _eglUnlockMutex(_eglGlobal.Mutex);
153 return dpy;
154 }
155 dpy = dpy->Next;
156 }
157
158 _eglUnlockMutex(_eglGlobal.Mutex);
159
160 return NULL;
161 }
162
163
164 /**
165 * Destroy the contexts and surfaces that are linked to the display.
166 */
167 void
168 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
169 {
170 _EGLContext *contexts;
171 _EGLSurface *surfaces;
172
173 contexts = display->ContextList;
174 surfaces = display->SurfaceList;
175
176 while (contexts) {
177 _EGLContext *ctx = contexts;
178 contexts = contexts->Next;
179
180 _eglUnlinkContext(ctx);
181 drv->API.DestroyContext(drv, display, ctx);
182 }
183 assert(!display->ContextList);
184
185 while (surfaces) {
186 _EGLSurface *surf = surfaces;
187 surfaces = surfaces->Next;
188
189 _eglUnlinkSurface(surf);
190 drv->API.DestroySurface(drv, display, surf);
191 }
192 assert(!display->SurfaceList);
193 }
194
195
196 /**
197 * Free all the data hanging of an _EGLDisplay object, but not
198 * the object itself.
199 */
200 void
201 _eglCleanupDisplay(_EGLDisplay *disp)
202 {
203 EGLint i;
204
205 if (disp->Configs) {
206 for (i = 0; i < disp->NumConfigs; i++)
207 free(disp->Configs[i]);
208 free(disp->Configs);
209 disp->Configs = NULL;
210 disp->NumConfigs = 0;
211 }
212
213 /* XXX incomplete */
214 }
215
216
217 /**
218 * Link a context to a display and return the handle of the link.
219 * The handle can be passed to client directly.
220 */
221 EGLContext
222 _eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
223 {
224 ctx->Display = dpy;
225 ctx->Next = dpy->ContextList;
226 dpy->ContextList = ctx;
227 return (EGLContext) ctx;
228 }
229
230
231 /**
232 * Unlink a linked context from its display.
233 * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
234 */
235 void
236 _eglUnlinkContext(_EGLContext *ctx)
237 {
238 _EGLContext *prev;
239
240 prev = ctx->Display->ContextList;
241 if (prev != ctx) {
242 while (prev) {
243 if (prev->Next == ctx)
244 break;
245 prev = prev->Next;
246 }
247 assert(prev);
248 prev->Next = ctx->Next;
249 }
250 else {
251 ctx->Display->ContextList = ctx->Next;
252 }
253
254 ctx->Next = NULL;
255 ctx->Display = NULL;
256 }
257
258
259 /**
260 * Return the handle of a linked context, or EGL_NO_CONTEXT.
261 */
262 EGLContext
263 _eglGetContextHandle(_EGLContext *ctx)
264 {
265 return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT);
266 }
267
268
269 /**
270 * Lookup a handle to find the linked context.
271 * Return NULL if the handle has no corresponding linked context.
272 */
273 _EGLContext *
274 _eglLookupContext(EGLContext ctx, _EGLDisplay *dpy)
275 {
276 _EGLContext *context = (_EGLContext *) ctx;
277 return (context && context->Display) ? context : NULL;
278 }
279
280
281 /**
282 * Link a surface to a display and return the handle of the link.
283 * The handle can be passed to client directly.
284 */
285 EGLSurface
286 _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
287 {
288 surf->Display = dpy;
289 surf->Next = dpy->SurfaceList;
290 dpy->SurfaceList = surf;
291 return (EGLSurface) surf;
292 }
293
294
295 /**
296 * Unlink a linked surface from its display.
297 * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
298 */
299 void
300 _eglUnlinkSurface(_EGLSurface *surf)
301 {
302 _EGLSurface *prev;
303
304 prev = surf->Display->SurfaceList;
305 if (prev != surf) {
306 while (prev) {
307 if (prev->Next == surf)
308 break;
309 prev = prev->Next;
310 }
311 assert(prev);
312 prev->Next = surf->Next;
313 }
314 else {
315 prev = NULL;
316 surf->Display->SurfaceList = surf->Next;
317 }
318
319 surf->Next = NULL;
320 surf->Display = NULL;
321 }
322
323
324 /**
325 * Return the handle of a linked surface, or EGL_NO_SURFACE.
326 */
327 EGLSurface
328 _eglGetSurfaceHandle(_EGLSurface *surf)
329 {
330 return (EGLSurface) ((surf && surf->Display) ? surf : EGL_NO_SURFACE);
331 }
332
333
334 /**
335 * Lookup a handle to find the linked surface.
336 * Return NULL if the handle has no corresponding linked surface.
337 */
338 _EGLSurface *
339 _eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy)
340 {
341 _EGLSurface *surf = (_EGLSurface *) surface;
342 return (surf && surf->Display) ? surf : NULL;
343 }