Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4
 * Copyright 2009-2010 Chia-I Wu 
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 
36
#include 
37
#include 
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
/* Includes for _eglNativePlatformDetectNativeDisplay */
47
#ifdef HAVE_MINCORE
48
#include 
49
#include 
50
#endif
51
#ifdef HAVE_WAYLAND_PLATFORM
52
#include 
53
#endif
54
#ifdef HAVE_DRM_PLATFORM
55
#include 
56
#endif
57
#ifdef HAVE_FBDEV_PLATFORM
58
#include 
59
#include 
60
#include 
61
#endif
62
 
63
 
64
/**
65
 * Map --with-egl-platforms names to platform types.
66
 */
67
static const struct {
68
   _EGLPlatformType platform;
69
   const char *name;
70
} egl_platforms[_EGL_NUM_PLATFORMS] = {
71
   { _EGL_PLATFORM_DRM, "drm" }
72
};
73
 
74
 
75
/**
76
 * Return the native platform by parsing EGL_PLATFORM.
77
 */
78
static _EGLPlatformType
79
_eglGetNativePlatformFromEnv(void)
80
{
81
   _EGLPlatformType plat = _EGL_INVALID_PLATFORM;
82
   const char *plat_name;
83
   EGLint i;
84
 
85
   plat_name = getenv("EGL_PLATFORM");
86
   /* try deprecated env variable */
87
   if (!plat_name || !plat_name[0])
88
      plat_name = getenv("EGL_DISPLAY");
89
   if (!plat_name || !plat_name[0])
90
      return _EGL_INVALID_PLATFORM;
91
 
92
   for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
93
      if (strcmp(egl_platforms[i].name, plat_name) == 0) {
94
         plat = egl_platforms[i].platform;
95
         break;
96
      }
97
   }
98
 
99
   return plat;
100
}
101
 
102
 
103
/**
104
 * Perform validity checks on a generic pointer.
105
 */
106
static EGLBoolean
107
_eglPointerIsDereferencable(void *p)
108
{
109
#ifdef HAVE_MINCORE
110
   uintptr_t addr = (uintptr_t) p;
111
   unsigned char valid = 0;
112
   const long page_size = getpagesize();
113
 
114
   if (p == NULL)
115
      return EGL_FALSE;
116
 
117
   /* align addr to page_size */
118
   addr &= ~(page_size - 1);
119
 
120
   if (mincore((void *) addr, page_size, &valid) < 0) {
121
      _eglLog(_EGL_DEBUG, "mincore failed: %m");
122
      return EGL_FALSE;
123
   }
124
 
125
   return (valid & 0x01) == 0x01;
126
#else
127
   return p != NULL;
128
#endif
129
}
130
 
131
 
132
/**
133
 * Try detecting native platform with the help of native display characteristcs.
134
 */
135
static _EGLPlatformType
136
_eglNativePlatformDetectNativeDisplay(EGLNativeDisplayType nativeDisplay)
137
{
138
   return _EGL_PLATFORM_DRM;
139
}
140
 
141
 
142
/**
143
 * Return the native platform.  It is the platform of the EGL native types.
144
 */
145
_EGLPlatformType
146
_eglGetNativePlatform(EGLNativeDisplayType nativeDisplay)
147
{
148
   return _EGL_PLATFORM_DRM;
149
}
150
 
151
 
152
/**
153
 * Finish display management.
154
 */
155
void
156
_eglFiniDisplay(void)
157
{
158
   _EGLDisplay *dpyList, *dpy;
159
 
160
   /* atexit function is called with global mutex locked */
161
   dpyList = _eglGlobal.DisplayList;
162
   while (dpyList) {
163
      EGLint i;
164
 
165
      /* pop list head */
166
      dpy = dpyList;
167
      dpyList = dpyList->Next;
168
 
169
      for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
170
         if (dpy->ResourceLists[i]) {
171
            _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
172
            break;
173
         }
174
      }
175
 
176
      free(dpy);
177
   }
178
   _eglGlobal.DisplayList = NULL;
179
}
180
 
181
 
182
/**
183
 * Find the display corresponding to the specified native display, or create a
184
 * new one.
185
 */
186
_EGLDisplay *
187
_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
188
{
189
   _EGLDisplay *dpy;
190
 
191
   if (plat == _EGL_INVALID_PLATFORM)
192
      return NULL;
193
 
194
   _eglLockMutex(_eglGlobal.Mutex);
195
 
196
   /* search the display list first */
197
   dpy = _eglGlobal.DisplayList;
198
   while (dpy) {
199
      if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy)
200
         break;
201
      dpy = dpy->Next;
202
   }
203
 
204
   /* create a new display */
205
   if (!dpy) {
206
      dpy = calloc(1, sizeof(_EGLDisplay));
207
      if (dpy) {
208
         _eglInitMutex(&dpy->Mutex);
209
         dpy->Platform = plat;
210
         dpy->PlatformDisplay = plat_dpy;
211
 
212
         /* add to the display list */
213
         dpy->Next = _eglGlobal.DisplayList;
214
         _eglGlobal.DisplayList = dpy;
215
      }
216
   }
217
 
218
   _eglUnlockMutex(_eglGlobal.Mutex);
219
 
220
   return dpy;
221
}
222
 
223
 
224
/**
225
 * Destroy the contexts and surfaces that are linked to the display.
226
 */
227
void
228
_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
229
{
230
   _EGLResource *list;
231
 
232
   list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
233
   while (list) {
234
      _EGLContext *ctx = (_EGLContext *) list;
235
      list = list->Next;
236
 
237
      _eglUnlinkContext(ctx);
238
      drv->API.DestroyContext(drv, display, ctx);
239
   }
240
   assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
241
 
242
   list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
243
   while (list) {
244
      _EGLSurface *surf = (_EGLSurface *) list;
245
      list = list->Next;
246
 
247
      _eglUnlinkSurface(surf);
248
      drv->API.DestroySurface(drv, display, surf);
249
   }
250
   assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
251
}
252
 
253
 
254
/**
255
 * Free all the data hanging of an _EGLDisplay object, but not
256
 * the object itself.
257
 */
258
void
259
_eglCleanupDisplay(_EGLDisplay *disp)
260
{
261
   if (disp->Configs) {
262
      _eglDestroyArray(disp->Configs, free);
263
      disp->Configs = NULL;
264
   }
265
 
266
   /* XXX incomplete */
267
}
268
 
269
 
270
/**
271
 * Return EGL_TRUE if the given handle is a valid handle to a display.
272
 */
273
EGLBoolean
274
_eglCheckDisplayHandle(EGLDisplay dpy)
275
{
276
   _EGLDisplay *cur;
277
 
278
   _eglLockMutex(_eglGlobal.Mutex);
279
   cur = _eglGlobal.DisplayList;
280
   while (cur) {
281
      if (cur == (_EGLDisplay *) dpy)
282
         break;
283
      cur = cur->Next;
284
   }
285
   _eglUnlockMutex(_eglGlobal.Mutex);
286
   return (cur != NULL);
287
}
288
 
289
 
290
/**
291
 * Return EGL_TRUE if the given resource is valid.  That is, the display does
292
 * own the resource.
293
 */
294
EGLBoolean
295
_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
296
{
297
   _EGLResource *list = dpy->ResourceLists[type];
298
 
299
   if (!res)
300
      return EGL_FALSE;
301
 
302
   while (list) {
303
      if (res == (void *) list) {
304
         assert(list->Display == dpy);
305
         break;
306
      }
307
      list = list->Next;
308
   }
309
 
310
   return (list != NULL);
311
}
312
 
313
 
314
/**
315
 * Initialize a display resource.
316
 */
317
void
318
_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy)
319
{
320
   memset(res, 0, size);
321
   res->Display = dpy;
322
   res->RefCount = 1;
323
}
324
 
325
 
326
/**
327
 * Increment reference count for the resource.
328
 */
329
void
330
_eglGetResource(_EGLResource *res)
331
{
332
   assert(res && res->RefCount > 0);
333
   /* hopefully a resource is always manipulated with its display locked */
334
   res->RefCount++;
335
}
336
 
337
 
338
/**
339
 * Decrement reference count for the resource.
340
 */
341
EGLBoolean
342
_eglPutResource(_EGLResource *res)
343
{
344
   assert(res && res->RefCount > 0);
345
   res->RefCount--;
346
   return (!res->RefCount);
347
}
348
 
349
 
350
/**
351
 * Link a resource to its display.
352
 */
353
void
354
_eglLinkResource(_EGLResource *res, _EGLResourceType type)
355
{
356
   assert(res->Display);
357
 
358
   res->IsLinked = EGL_TRUE;
359
   res->Next = res->Display->ResourceLists[type];
360
   res->Display->ResourceLists[type] = res;
361
   _eglGetResource(res);
362
}
363
 
364
 
365
/**
366
 * Unlink a linked resource from its display.
367
 */
368
void
369
_eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
370
{
371
   _EGLResource *prev;
372
 
373
   prev = res->Display->ResourceLists[type];
374
   if (prev != res) {
375
      while (prev) {
376
         if (prev->Next == res)
377
            break;
378
         prev = prev->Next;
379
      }
380
      assert(prev);
381
      prev->Next = res->Next;
382
   }
383
   else {
384
      res->Display->ResourceLists[type] = res->Next;
385
   }
386
 
387
   res->Next = NULL;
388
   res->IsLinked = EGL_FALSE;
389
   _eglPutResource(res);
390
 
391
   /* We always unlink before destroy.  The driver still owns a reference */
392
   assert(res->RefCount);
393
}