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