d7a8d142929476580695ba70c596435a02c71598
[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 "eglmutex.h"
14 #include "egllog.h"
15
16
17 /**
18 * Finish display management.
19 */
20 void
21 _eglFiniDisplay(void)
22 {
23 _EGLDisplay *dpyList, *dpy;
24
25 /* atexit function is called with global mutex locked */
26 dpyList = _eglGlobal.DisplayList;
27 while (dpyList) {
28 EGLint i;
29
30 /* pop list head */
31 dpy = dpyList;
32 dpyList = dpyList->Next;
33
34 for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
35 if (dpy->ResourceLists[i]) {
36 _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
37 break;
38 }
39 }
40
41 free(dpy);
42 }
43 _eglGlobal.DisplayList = NULL;
44 }
45
46
47 /**
48 * Allocate a new _EGLDisplay object for the given nativeDisplay handle.
49 * We'll also try to determine the device driver name at this time.
50 *
51 * Note that nativeDisplay may be an X Display ptr, or a string.
52 */
53 _EGLDisplay *
54 _eglNewDisplay(EGLNativeDisplayType nativeDisplay)
55 {
56 _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
57 if (dpy) {
58 dpy->NativeDisplay = nativeDisplay;
59 }
60 return dpy;
61 }
62
63
64 /**
65 * Link a display to itself and return the handle of the link.
66 * The handle can be passed to client directly.
67 */
68 EGLDisplay
69 _eglLinkDisplay(_EGLDisplay *dpy)
70 {
71 _eglLockMutex(_eglGlobal.Mutex);
72
73 dpy->Next = _eglGlobal.DisplayList;
74 _eglGlobal.DisplayList = dpy;
75
76 _eglUnlockMutex(_eglGlobal.Mutex);
77
78 return (EGLDisplay) dpy;
79 }
80
81
82 /**
83 * Unlink a linked display from itself.
84 * Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
85 */
86 void
87 _eglUnlinkDisplay(_EGLDisplay *dpy)
88 {
89 _EGLDisplay *prev;
90
91 _eglLockMutex(_eglGlobal.Mutex);
92
93 prev = _eglGlobal.DisplayList;
94 if (prev != dpy) {
95 while (prev) {
96 if (prev->Next == dpy)
97 break;
98 prev = prev->Next;
99 }
100 assert(prev);
101 prev->Next = dpy->Next;
102 }
103 else {
104 _eglGlobal.DisplayList = dpy->Next;
105 }
106
107 _eglUnlockMutex(_eglGlobal.Mutex);
108 }
109
110
111 /**
112 * Find the display corresponding to the specified native display id in all
113 * linked displays.
114 */
115 _EGLDisplay *
116 _eglFindDisplay(EGLNativeDisplayType nativeDisplay)
117 {
118 _EGLDisplay *dpy;
119
120 _eglLockMutex(_eglGlobal.Mutex);
121
122 dpy = _eglGlobal.DisplayList;
123 while (dpy) {
124 if (dpy->NativeDisplay == nativeDisplay) {
125 _eglUnlockMutex(_eglGlobal.Mutex);
126 return dpy;
127 }
128 dpy = dpy->Next;
129 }
130
131 _eglUnlockMutex(_eglGlobal.Mutex);
132
133 return NULL;
134 }
135
136
137 /**
138 * Destroy the contexts and surfaces that are linked to the display.
139 */
140 void
141 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
142 {
143 _EGLResource *list;
144
145 list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
146 while (list) {
147 _EGLContext *ctx = (_EGLContext *) list;
148 list = list->Next;
149
150 _eglUnlinkContext(ctx);
151 drv->API.DestroyContext(drv, display, ctx);
152 }
153 assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
154
155 list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
156 while (list) {
157 _EGLSurface *surf = (_EGLSurface *) list;
158 list = list->Next;
159
160 _eglUnlinkSurface(surf);
161 drv->API.DestroySurface(drv, display, surf);
162 }
163 assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
164 }
165
166
167 /**
168 * Free all the data hanging of an _EGLDisplay object, but not
169 * the object itself.
170 */
171 void
172 _eglCleanupDisplay(_EGLDisplay *disp)
173 {
174 EGLint i;
175
176 if (disp->Configs) {
177 for (i = 0; i < disp->NumConfigs; i++)
178 free(disp->Configs[i]);
179 free(disp->Configs);
180 disp->Configs = NULL;
181 disp->NumConfigs = 0;
182 disp->MaxConfigs = 0;
183 }
184
185 /* XXX incomplete */
186 }
187
188
189 #ifndef _EGL_SKIP_HANDLE_CHECK
190
191
192 /**
193 * Return EGL_TRUE if the given handle is a valid handle to a display.
194 */
195 EGLBoolean
196 _eglCheckDisplayHandle(EGLDisplay dpy)
197 {
198 _EGLDisplay *cur;
199
200 _eglLockMutex(_eglGlobal.Mutex);
201 cur = _eglGlobal.DisplayList;
202 while (cur) {
203 if (cur == (_EGLDisplay *) dpy)
204 break;
205 cur = cur->Next;
206 }
207 _eglUnlockMutex(_eglGlobal.Mutex);
208 return (cur != NULL);
209 }
210
211
212 /**
213 * Return EGL_TRUE if the given resource is valid. That is, the display does
214 * own the resource.
215 */
216 EGLBoolean
217 _eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
218 {
219 _EGLResource *list = dpy->ResourceLists[type];
220
221 if (!res)
222 return EGL_FALSE;
223
224 while (list) {
225 if (res == (void *) list) {
226 assert(list->Display == dpy);
227 break;
228 }
229 list = list->Next;
230 }
231
232 return (list != NULL);
233 }
234
235
236 #endif /* !_EGL_SKIP_HANDLE_CHECK */
237
238
239 /**
240 * Link a resource to a display.
241 */
242 void
243 _eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy)
244 {
245 assert(!res->Display || res->Display == dpy);
246
247 res->Display = dpy;
248 res->IsLinked = EGL_TRUE;
249 res->Next = dpy->ResourceLists[type];
250 dpy->ResourceLists[type] = res;
251 }
252
253
254 /**
255 * Unlink a linked resource from its display.
256 */
257 void
258 _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
259 {
260 _EGLResource *prev;
261
262 prev = res->Display->ResourceLists[type];
263 if (prev != res) {
264 while (prev) {
265 if (prev->Next == res)
266 break;
267 prev = prev->Next;
268 }
269 assert(prev);
270 prev->Next = res->Next;
271 }
272 else {
273 res->Display->ResourceLists[type] = res->Next;
274 }
275
276 res->Next = NULL;
277 /* do not reset res->Display */
278 res->IsLinked = EGL_FALSE;
279 }