egldisplay.c revision 4a49301e
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 */
21void
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 */
49char *
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 */
99EGLDisplay
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 */
117void
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 */
171void
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 */
204void
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 */
225EGLContext
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 */
239void
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 */
267EGLSurface
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 */
281void
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 */
312EGLBoolean
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 */
332EGLBoolean
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 */
353EGLBoolean
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 */
372