Subversion Repositories Kolibri OS

Rev

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

  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. /* Includes for _eglNativePlatformDetectNativeDisplay */
  47. #ifdef HAVE_MINCORE
  48. #include <unistd.h>
  49. #include <sys/mman.h>
  50. #endif
  51. #ifdef HAVE_WAYLAND_PLATFORM
  52. #include <wayland-client.h>
  53. #endif
  54. #ifdef HAVE_DRM_PLATFORM
  55. #include <gbm.h>
  56. #endif
  57. #ifdef HAVE_FBDEV_PLATFORM
  58. #include <stdint.h>
  59. #include <sys/types.h>
  60. #include <sys/stat.h>
  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.    printf("%s Resource: %p\n", __FUNCTION__, res);
  359.  
  360.    res->IsLinked = EGL_TRUE;
  361.    res->Next = res->Display->ResourceLists[type];
  362.    res->Display->ResourceLists[type] = res;
  363.    _eglGetResource(res);
  364. }
  365.  
  366.  
  367. /**
  368.  * Unlink a linked resource from its display.
  369.  */
  370. void
  371. _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
  372. {
  373.    _EGLResource *prev;
  374.  
  375.    prev = res->Display->ResourceLists[type];
  376.    if (prev != res) {
  377.       while (prev) {
  378.          if (prev->Next == res)
  379.             break;
  380.          prev = prev->Next;
  381.       }
  382.       assert(prev);
  383.       prev->Next = res->Next;
  384.    }
  385.    else {
  386.       res->Display->ResourceLists[type] = res->Next;
  387.    }
  388.  
  389.    res->Next = NULL;
  390.    res->IsLinked = EGL_FALSE;
  391.    _eglPutResource(res);
  392.  
  393.    /* We always unlink before destroy.  The driver still owns a reference */
  394.    assert(res->RefCount);
  395. }
  396.