egl: Make eglGetDisplay atomic.
[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 * Find the display corresponding to the specified native display, or create a
49 * new one.
50 */
51 _EGLDisplay *
52 _eglFindDisplay(EGLNativeDisplayType nativeDisplay)
53 {
54 _EGLDisplay *dpy;
55
56 _eglLockMutex(_eglGlobal.Mutex);
57
58 /* search the display list first */
59 dpy = _eglGlobal.DisplayList;
60 while (dpy) {
61 if (dpy->NativeDisplay == nativeDisplay)
62 break;
63 dpy = dpy->Next;
64 }
65
66 /* create a new display */
67 if (!dpy) {
68 dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
69 if (dpy) {
70 _eglInitMutex(&dpy->Mutex);
71 dpy->NativeDisplay = nativeDisplay;
72
73 /* add to the display list */
74 dpy->Next = _eglGlobal.DisplayList;
75 _eglGlobal.DisplayList = dpy;
76 }
77 }
78
79 _eglUnlockMutex(_eglGlobal.Mutex);
80
81 return dpy;
82 }
83
84
85 /**
86 * Destroy the contexts and surfaces that are linked to the display.
87 */
88 void
89 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
90 {
91 _EGLResource *list;
92
93 list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
94 while (list) {
95 _EGLContext *ctx = (_EGLContext *) list;
96 list = list->Next;
97
98 _eglUnlinkContext(ctx);
99 drv->API.DestroyContext(drv, display, ctx);
100 }
101 assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
102
103 list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
104 while (list) {
105 _EGLSurface *surf = (_EGLSurface *) list;
106 list = list->Next;
107
108 _eglUnlinkSurface(surf);
109 drv->API.DestroySurface(drv, display, surf);
110 }
111 assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
112 }
113
114
115 /**
116 * Free all the data hanging of an _EGLDisplay object, but not
117 * the object itself.
118 */
119 void
120 _eglCleanupDisplay(_EGLDisplay *disp)
121 {
122 EGLint i;
123
124 if (disp->Configs) {
125 for (i = 0; i < disp->NumConfigs; i++)
126 free(disp->Configs[i]);
127 free(disp->Configs);
128 disp->Configs = NULL;
129 disp->NumConfigs = 0;
130 disp->MaxConfigs = 0;
131 }
132
133 /* XXX incomplete */
134 }
135
136
137 #ifndef _EGL_SKIP_HANDLE_CHECK
138
139
140 /**
141 * Return EGL_TRUE if the given handle is a valid handle to a display.
142 */
143 EGLBoolean
144 _eglCheckDisplayHandle(EGLDisplay dpy)
145 {
146 _EGLDisplay *cur;
147
148 _eglLockMutex(_eglGlobal.Mutex);
149 cur = _eglGlobal.DisplayList;
150 while (cur) {
151 if (cur == (_EGLDisplay *) dpy)
152 break;
153 cur = cur->Next;
154 }
155 _eglUnlockMutex(_eglGlobal.Mutex);
156 return (cur != NULL);
157 }
158
159
160 /**
161 * Return EGL_TRUE if the given resource is valid. That is, the display does
162 * own the resource.
163 */
164 EGLBoolean
165 _eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
166 {
167 _EGLResource *list = dpy->ResourceLists[type];
168
169 if (!res)
170 return EGL_FALSE;
171
172 while (list) {
173 if (res == (void *) list) {
174 assert(list->Display == dpy);
175 break;
176 }
177 list = list->Next;
178 }
179
180 return (list != NULL);
181 }
182
183
184 #endif /* !_EGL_SKIP_HANDLE_CHECK */
185
186
187 /**
188 * Link a resource to a display.
189 */
190 void
191 _eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy)
192 {
193 assert(!res->Display || res->Display == dpy);
194
195 res->Display = dpy;
196 res->IsLinked = EGL_TRUE;
197 res->Next = dpy->ResourceLists[type];
198 dpy->ResourceLists[type] = res;
199 }
200
201
202 /**
203 * Unlink a linked resource from its display.
204 */
205 void
206 _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
207 {
208 _EGLResource *prev;
209
210 prev = res->Display->ResourceLists[type];
211 if (prev != res) {
212 while (prev) {
213 if (prev->Next == res)
214 break;
215 prev = prev->Next;
216 }
217 assert(prev);
218 prev->Next = res->Next;
219 }
220 else {
221 res->Display->ResourceLists[type] = res->Next;
222 }
223
224 res->Next = NULL;
225 /* do not reset res->Display */
226 res->IsLinked = EGL_FALSE;
227 }