egl: Make surfaces and contexts resources.
[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 EGLint i;
30
31 /* pop list head */
32 dpy = dpyList;
33 dpyList = dpyList->Next;
34
35 for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
36 if (dpy->ResourceLists[i]) {
37 _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
38 break;
39 }
40 }
41
42 free(dpy);
43 }
44 _eglGlobal.DisplayList = NULL;
45 }
46
47
48 /**
49 * Allocate a new _EGLDisplay object for the given nativeDisplay handle.
50 * We'll also try to determine the device driver name at this time.
51 *
52 * Note that nativeDisplay may be an X Display ptr, or a string.
53 */
54 _EGLDisplay *
55 _eglNewDisplay(NativeDisplayType nativeDisplay)
56 {
57 _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
58 if (dpy) {
59 dpy->NativeDisplay = nativeDisplay;
60 }
61 return dpy;
62 }
63
64
65 /**
66 * Link a display to itself and return the handle of the link.
67 * The handle can be passed to client directly.
68 */
69 EGLDisplay
70 _eglLinkDisplay(_EGLDisplay *dpy)
71 {
72 _eglLockMutex(_eglGlobal.Mutex);
73
74 dpy->Next = _eglGlobal.DisplayList;
75 _eglGlobal.DisplayList = dpy;
76
77 _eglUnlockMutex(_eglGlobal.Mutex);
78
79 return (EGLDisplay) dpy;
80 }
81
82
83 /**
84 * Unlink a linked display from itself.
85 * Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
86 */
87 void
88 _eglUnlinkDisplay(_EGLDisplay *dpy)
89 {
90 _EGLDisplay *prev;
91
92 _eglLockMutex(_eglGlobal.Mutex);
93
94 prev = _eglGlobal.DisplayList;
95 if (prev != dpy) {
96 while (prev) {
97 if (prev->Next == dpy)
98 break;
99 prev = prev->Next;
100 }
101 assert(prev);
102 prev->Next = dpy->Next;
103 }
104 else {
105 _eglGlobal.DisplayList = dpy->Next;
106 }
107
108 _eglUnlockMutex(_eglGlobal.Mutex);
109 }
110
111
112 /**
113 * Find the display corresponding to the specified native display id in all
114 * linked displays.
115 */
116 _EGLDisplay *
117 _eglFindDisplay(NativeDisplayType nativeDisplay)
118 {
119 _EGLDisplay *dpy;
120
121 _eglLockMutex(_eglGlobal.Mutex);
122
123 dpy = _eglGlobal.DisplayList;
124 while (dpy) {
125 if (dpy->NativeDisplay == nativeDisplay) {
126 _eglUnlockMutex(_eglGlobal.Mutex);
127 return dpy;
128 }
129 dpy = dpy->Next;
130 }
131
132 _eglUnlockMutex(_eglGlobal.Mutex);
133
134 return NULL;
135 }
136
137
138 /**
139 * Destroy the contexts and surfaces that are linked to the display.
140 */
141 void
142 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
143 {
144 _EGLResource *list;
145
146 list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
147 while (list) {
148 _EGLContext *ctx = (_EGLContext *) list;
149 list = list->Next;
150
151 _eglUnlinkContext(ctx);
152 drv->API.DestroyContext(drv, display, ctx);
153 }
154 assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
155
156 list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
157 while (list) {
158 _EGLSurface *surf = (_EGLSurface *) list;
159 list = list->Next;
160
161 _eglUnlinkSurface(surf);
162 drv->API.DestroySurface(drv, display, surf);
163 }
164 assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
165 }
166
167
168 /**
169 * Free all the data hanging of an _EGLDisplay object, but not
170 * the object itself.
171 */
172 void
173 _eglCleanupDisplay(_EGLDisplay *disp)
174 {
175 EGLint i;
176
177 if (disp->Configs) {
178 for (i = 0; i < disp->NumConfigs; i++)
179 free(disp->Configs[i]);
180 free(disp->Configs);
181 disp->Configs = NULL;
182 disp->NumConfigs = 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(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy)
218 {
219 _EGLResource *list = dpy->ResourceLists[type];
220
221 while (list) {
222 if (res == list) {
223 assert(list->Display == dpy);
224 break;
225 }
226 list = list->Next;
227 }
228
229 return (list != NULL);
230 }
231
232
233 #endif /* !_EGL_SKIP_HANDLE_CHECK */
234
235
236 /**
237 * Link a resource to a display.
238 */
239 void
240 _eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy)
241 {
242 res->Display = dpy;
243 res->Next = dpy->ResourceLists[type];
244 dpy->ResourceLists[type] = res;
245 }
246
247
248 /**
249 * Unlink a linked resource from its display.
250 */
251 void
252 _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
253 {
254 _EGLResource *prev;
255
256 prev = res->Display->ResourceLists[type];
257 if (prev != res) {
258 while (prev) {
259 if (prev->Next == res)
260 break;
261 prev = prev->Next;
262 }
263 assert(prev);
264 prev->Next = res->Next;
265 }
266 else {
267 res->Display->ResourceLists[type] = res->Next;
268 }
269
270 res->Next = NULL;
271 res->Display = NULL;
272 }