Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  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 for choosing and opening/loading device drivers.
  33.  */
  34.  
  35.  
  36. #include <assert.h>
  37. #include <string.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include "c11/threads.h"
  41.  
  42. #include "eglstring.h"
  43. #include "egldefines.h"
  44. #include "egldisplay.h"
  45. #include "egldriver.h"
  46. #include "egllog.h"
  47.  
  48. typedef struct _egl_module {
  49.    char *Name;
  50.    _EGLMain_t BuiltIn;
  51.    _EGLDriver *Driver;
  52. } _EGLModule;
  53.  
  54. static mtx_t _eglModuleMutex = _MTX_INITIALIZER_NP;
  55. static _EGLArray *_eglModules;
  56.  
  57. const struct {
  58.    const char *name;
  59.    _EGLMain_t main;
  60. } _eglBuiltInDrivers[] = {
  61. #ifdef _EGL_BUILT_IN_DRIVER_DRI2
  62.    { "egl_dri2", _eglBuiltInDriverDRI2 },
  63. #endif
  64. #ifdef _EGL_BUILT_IN_DRIVER_HAIKU
  65.    { "egl_haiku", _eglBuiltInDriverHaiku },
  66. #endif
  67.    { NULL, NULL }
  68. };
  69.  
  70. /**
  71.  * Load a module and create the driver object.
  72.  */
  73. static EGLBoolean
  74. _eglLoadModule(_EGLModule *mod)
  75. {
  76.    _EGLDriver *drv;
  77.  
  78.    if (mod->Driver)
  79.       return EGL_TRUE;
  80.  
  81.    if (!mod->BuiltIn)
  82.          return EGL_FALSE;
  83.  
  84.    drv = mod->BuiltIn(NULL);
  85.    if (!drv || !drv->Name)
  86.       return EGL_FALSE;
  87.  
  88.    mod->Driver = drv;
  89.  
  90.    return EGL_TRUE;
  91. }
  92.  
  93.  
  94. /**
  95.  * Unload a module.
  96.  */
  97. static void
  98. _eglUnloadModule(_EGLModule *mod)
  99. {
  100. #if defined(_EGL_OS_UNIX)
  101.    /* destroy the driver */
  102.    if (mod->Driver && mod->Driver->Unload)
  103.       mod->Driver->Unload(mod->Driver);
  104.  
  105. #elif defined(_EGL_OS_WINDOWS)
  106.    /* XXX Windows unloads DLLs before atexit */
  107. #endif
  108.  
  109.    mod->Driver = NULL;
  110. }
  111.  
  112.  
  113. /**
  114.  * Add a module to the module array.
  115.  */
  116. static _EGLModule *
  117. _eglAddModule(const char *name)
  118. {
  119.    _EGLModule *mod;
  120.    EGLint i;
  121.  
  122.    if (!_eglModules) {
  123.       _eglModules = _eglCreateArray("Module", 8);
  124.       if (!_eglModules)
  125.          return NULL;
  126.    }
  127.  
  128.    /* find duplicates */
  129.    for (i = 0; i < _eglModules->Size; i++) {
  130.       mod = _eglModules->Elements[i];
  131.       if (strcmp(mod->Name, name) == 0)
  132.          return mod;
  133.    }
  134.  
  135.    /* allocate a new one */
  136.    mod = calloc(1, sizeof(*mod));
  137.    if (mod) {
  138.       mod->Name = _eglstrdup(name);
  139.       if (!mod->Name) {
  140.          free(mod);
  141.          mod = NULL;
  142.       }
  143.    }
  144.    if (mod) {
  145.       _eglAppendArray(_eglModules, (void *) mod);
  146.       _eglLog(_EGL_DEBUG, "added %s to module array", mod->Name);
  147.    }
  148.  
  149.    return mod;
  150. }
  151.  
  152.  
  153. /**
  154.  * Free a module.
  155.  */
  156. static void
  157. _eglFreeModule(void *module)
  158. {
  159.    _EGLModule *mod = (_EGLModule *) module;
  160.  
  161.    _eglUnloadModule(mod);
  162.    free(mod->Name);
  163.    free(mod);
  164. }
  165.  
  166.  
  167. /**
  168.  * Add the user driver to the module array.
  169.  *
  170.  * The user driver is specified by EGL_DRIVER.
  171.  */
  172. static EGLBoolean
  173. _eglAddUserDriver(void)
  174. {
  175.    char *env;
  176.  
  177.    env = getenv("EGL_DRIVER");
  178.    if (env) {
  179.       EGLint i;
  180.  
  181.       for (i = 0; _eglBuiltInDrivers[i].name; i++) {
  182.          if (!strcmp(_eglBuiltInDrivers[i].name, env)) {
  183.             _EGLModule *mod = _eglAddModule(env);
  184.             if (mod)
  185.                mod->BuiltIn = _eglBuiltInDrivers[i].main;
  186.  
  187.             return EGL_TRUE;
  188.          }
  189.       }
  190.    }
  191.  
  192.    return EGL_FALSE;
  193. }
  194.  
  195.  
  196. /**
  197.  * Add built-in drivers to the module array.
  198.  */
  199. static void
  200. _eglAddBuiltInDrivers(void)
  201. {
  202.    _EGLModule *mod;
  203.    EGLint i;
  204.  
  205.    for (i = 0; _eglBuiltInDrivers[i].name; i++) {
  206.       mod = _eglAddModule(_eglBuiltInDrivers[i].name);
  207.       if (mod)
  208.          mod->BuiltIn = _eglBuiltInDrivers[i].main;
  209.    }
  210. }
  211.  
  212.  
  213. /**
  214.  * Add drivers to the module array.  Drivers will be loaded as they are matched
  215.  * to displays.
  216.  */
  217. static EGLBoolean
  218. _eglAddDrivers(void)
  219. {
  220.    if (_eglModules)
  221.       return EGL_TRUE;
  222.  
  223.    if (!_eglAddUserDriver()) {
  224.       /*
  225.        * Add other drivers only when EGL_DRIVER is not set.  The order here
  226.        * decides the priorities.
  227.        */
  228.       _eglAddBuiltInDrivers();
  229.    }
  230.  
  231.    return (_eglModules != NULL);
  232. }
  233.  
  234.  
  235. /**
  236.  * A helper function for _eglMatchDriver.  It finds the first driver that can
  237.  * initialize the display and return.
  238.  */
  239. static _EGLDriver *
  240. _eglMatchAndInitialize(_EGLDisplay *dpy)
  241. {
  242.    _EGLDriver *drv = NULL;
  243.    EGLint i = 0;
  244.  
  245.    if (!_eglAddDrivers()) {
  246.       _eglLog(_EGL_WARNING, "failed to find any driver");
  247.       return NULL;
  248.    }
  249.  
  250.    if (dpy->Driver) {
  251.       drv = dpy->Driver;
  252.       /* no re-matching? */
  253.       if (!drv->API.Initialize(drv, dpy))
  254.          drv = NULL;
  255.       return drv;
  256.    }
  257.  
  258.    while (i < _eglModules->Size) {
  259.       _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
  260.  
  261.       if (!_eglLoadModule(mod)) {
  262.          /* remove invalid modules */
  263.          _eglEraseArray(_eglModules, i, _eglFreeModule);
  264.          continue;
  265.       }
  266.  
  267.       if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
  268.          drv = mod->Driver;
  269.          break;
  270.       }
  271.       else {
  272.          i++;
  273.       }
  274.    }
  275.  
  276.    return drv;
  277. }
  278.  
  279.  
  280. /**
  281.  * Match a display to a driver.  The display is initialized unless test_only is
  282.  * true.  The matching is done by finding the first driver that can initialize
  283.  * the display.
  284.  */
  285. _EGLDriver *
  286. _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
  287. {
  288.    _EGLDriver *best_drv;
  289.  
  290.    assert(!dpy->Initialized);
  291.  
  292.    mtx_lock(&_eglModuleMutex);
  293.  
  294.    /* set options */
  295.    dpy->Options.TestOnly = test_only;
  296.    dpy->Options.UseFallback = EGL_FALSE;
  297.  
  298.    best_drv = _eglMatchAndInitialize(dpy);
  299.    if (!best_drv) {
  300.       dpy->Options.UseFallback = EGL_TRUE;
  301.       best_drv = _eglMatchAndInitialize(dpy);
  302.    }
  303.  
  304.    mtx_unlock(&_eglModuleMutex);
  305.  
  306.    if (best_drv) {
  307.       _eglLog(_EGL_DEBUG, "the best driver is %s%s",
  308.             best_drv->Name, (test_only) ? " (test only) " : "");
  309.       if (!test_only) {
  310.          dpy->Driver = best_drv;
  311.          dpy->Initialized = EGL_TRUE;
  312.       }
  313.    }
  314.  
  315.    return best_drv;
  316. }
  317.  
  318.  
  319. __eglMustCastToProperFunctionPointerType
  320. _eglGetDriverProc(const char *procname)
  321. {
  322.    EGLint i;
  323.    _EGLProc proc = NULL;
  324.  
  325.    if (!_eglModules) {
  326.       /* load the driver for the default display */
  327.       EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  328.       _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
  329.       if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
  330.          return NULL;
  331.    }
  332.  
  333.    for (i = 0; i < _eglModules->Size; i++) {
  334.       _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
  335.  
  336.       if (!mod->Driver)
  337.          break;
  338.       proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
  339.       if (proc)
  340.          break;
  341.    }
  342.  
  343.    return proc;
  344. }
  345.  
  346.  
  347. /**
  348.  * Unload all drivers.
  349.  */
  350. void
  351. _eglUnloadDrivers(void)
  352. {
  353.    /* this is called at atexit time */
  354.    if (_eglModules) {
  355.       _eglDestroyArray(_eglModules, _eglFreeModule);
  356.       _eglModules = NULL;
  357.    }
  358. }
  359.