egldisplay.c revision 3464ebd5
1/**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31/**
32 * Functions related to EGLDisplay.
33 */
34
35#include <assert.h>
36#include <stdlib.h>
37#include <string.h>
38#include "eglcontext.h"
39#include "eglsurface.h"
40#include "egldisplay.h"
41#include "egldriver.h"
42#include "eglglobals.h"
43#include "eglmutex.h"
44#include "egllog.h"
45
46
47/**
48 * Return the native platform by parsing EGL_PLATFORM.
49 */
50static _EGLPlatformType
51_eglGetNativePlatformFromEnv(void)
52{
53   /* map --with-egl-platforms names to platform types */
54   static const struct {
55      _EGLPlatformType platform;
56      const char *name;
57   } egl_platforms[_EGL_NUM_PLATFORMS] = {
58      { _EGL_PLATFORM_WINDOWS, "gdi" },
59      { _EGL_PLATFORM_X11, "x11" },
60      { _EGL_PLATFORM_WAYLAND, "wayland" },
61      { _EGL_PLATFORM_DRM, "drm" },
62      { _EGL_PLATFORM_FBDEV, "fbdev" }
63   };
64   _EGLPlatformType plat = _EGL_INVALID_PLATFORM;
65   const char *plat_name;
66   EGLint i;
67
68   plat_name = getenv("EGL_PLATFORM");
69   /* try deprecated env variable */
70   if (!plat_name || !plat_name[0])
71      plat_name = getenv("EGL_DISPLAY");
72   if (!plat_name || !plat_name[0])
73      return _EGL_INVALID_PLATFORM;
74
75   for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
76      if (strcmp(egl_platforms[i].name, plat_name) == 0) {
77         plat = egl_platforms[i].platform;
78         break;
79      }
80   }
81
82   return plat;
83}
84
85
86/**
87 * Return the native platform.  It is the platform of the EGL native types.
88 */
89_EGLPlatformType
90_eglGetNativePlatform(void)
91{
92   static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
93
94   if (native_platform == _EGL_INVALID_PLATFORM) {
95      native_platform = _eglGetNativePlatformFromEnv();
96      if (native_platform == _EGL_INVALID_PLATFORM)
97         native_platform = _EGL_NATIVE_PLATFORM;
98   }
99
100   return native_platform;
101}
102
103
104/**
105 * Finish display management.
106 */
107void
108_eglFiniDisplay(void)
109{
110   _EGLDisplay *dpyList, *dpy;
111
112   /* atexit function is called with global mutex locked */
113   dpyList = _eglGlobal.DisplayList;
114   while (dpyList) {
115      EGLint i;
116
117      /* pop list head */
118      dpy = dpyList;
119      dpyList = dpyList->Next;
120
121      for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
122         if (dpy->ResourceLists[i]) {
123            _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
124            break;
125         }
126      }
127
128      free(dpy);
129   }
130   _eglGlobal.DisplayList = NULL;
131}
132
133
134/**
135 * Find the display corresponding to the specified native display, or create a
136 * new one.
137 */
138_EGLDisplay *
139_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
140{
141   _EGLDisplay *dpy;
142
143   if (plat == _EGL_INVALID_PLATFORM)
144      return NULL;
145
146   _eglLockMutex(_eglGlobal.Mutex);
147
148   /* search the display list first */
149   dpy = _eglGlobal.DisplayList;
150   while (dpy) {
151      if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy)
152         break;
153      dpy = dpy->Next;
154   }
155
156   /* create a new display */
157   if (!dpy) {
158      dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
159      if (dpy) {
160         _eglInitMutex(&dpy->Mutex);
161         dpy->Platform = plat;
162         dpy->PlatformDisplay = plat_dpy;
163
164         /* add to the display list */
165         dpy->Next = _eglGlobal.DisplayList;
166         _eglGlobal.DisplayList = dpy;
167      }
168   }
169
170   _eglUnlockMutex(_eglGlobal.Mutex);
171
172   return dpy;
173}
174
175
176/**
177 * Destroy the contexts and surfaces that are linked to the display.
178 */
179void
180_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
181{
182   _EGLResource *list;
183
184   list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
185   while (list) {
186      _EGLContext *ctx = (_EGLContext *) list;
187      list = list->Next;
188
189      _eglUnlinkContext(ctx);
190      drv->API.DestroyContext(drv, display, ctx);
191   }
192   assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
193
194   list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
195   while (list) {
196      _EGLSurface *surf = (_EGLSurface *) list;
197      list = list->Next;
198
199      _eglUnlinkSurface(surf);
200      drv->API.DestroySurface(drv, display, surf);
201   }
202   assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
203}
204
205
206/**
207 * Free all the data hanging of an _EGLDisplay object, but not
208 * the object itself.
209 */
210void
211_eglCleanupDisplay(_EGLDisplay *disp)
212{
213   if (disp->Configs) {
214      _eglDestroyArray(disp->Configs, free);
215      disp->Configs = NULL;
216   }
217
218   /* XXX incomplete */
219}
220
221
222/**
223 * Return EGL_TRUE if the given handle is a valid handle to a display.
224 */
225EGLBoolean
226_eglCheckDisplayHandle(EGLDisplay dpy)
227{
228   _EGLDisplay *cur;
229
230   _eglLockMutex(_eglGlobal.Mutex);
231   cur = _eglGlobal.DisplayList;
232   while (cur) {
233      if (cur == (_EGLDisplay *) dpy)
234         break;
235      cur = cur->Next;
236   }
237   _eglUnlockMutex(_eglGlobal.Mutex);
238   return (cur != NULL);
239}
240
241
242/**
243 * Return EGL_TRUE if the given resource is valid.  That is, the display does
244 * own the resource.
245 */
246EGLBoolean
247_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
248{
249   _EGLResource *list = dpy->ResourceLists[type];
250
251   if (!res)
252      return EGL_FALSE;
253
254   while (list) {
255      if (res == (void *) list) {
256         assert(list->Display == dpy);
257         break;
258      }
259      list = list->Next;
260   }
261
262   return (list != NULL);
263}
264
265
266/**
267 * Initialize a display resource.
268 */
269void
270_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy)
271{
272   memset(res, 0, size);
273   res->Display = dpy;
274   res->RefCount = 1;
275}
276
277
278/**
279 * Increment reference count for the resource.
280 */
281void
282_eglGetResource(_EGLResource *res)
283{
284   assert(res && res->RefCount > 0);
285   /* hopefully a resource is always manipulated with its display locked */
286   res->RefCount++;
287}
288
289
290/**
291 * Decrement reference count for the resource.
292 */
293EGLBoolean
294_eglPutResource(_EGLResource *res)
295{
296   assert(res && res->RefCount > 0);
297   res->RefCount--;
298   return (!res->RefCount);
299}
300
301
302/**
303 * Link a resource to its display.
304 */
305void
306_eglLinkResource(_EGLResource *res, _EGLResourceType type)
307{
308   assert(res->Display);
309
310   res->IsLinked = EGL_TRUE;
311   res->Next = res->Display->ResourceLists[type];
312   res->Display->ResourceLists[type] = res;
313   _eglGetResource(res);
314}
315
316
317/**
318 * Unlink a linked resource from its display.
319 */
320void
321_eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
322{
323   _EGLResource *prev;
324
325   prev = res->Display->ResourceLists[type];
326   if (prev != res) {
327      while (prev) {
328         if (prev->Next == res)
329            break;
330         prev = prev->Next;
331      }
332      assert(prev);
333      prev->Next = res->Next;
334   }
335   else {
336      res->Display->ResourceLists[type] = res->Next;
337   }
338
339   res->Next = NULL;
340   res->IsLinked = EGL_FALSE;
341   _eglPutResource(res);
342
343   /* We always unlink before destroy.  The driver still owns a reference */
344   assert(res->RefCount);
345}
346