egldriver.c revision b8e80941
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 "egldefines.h"
43#include "egldisplay.h"
44#include "egldriver.h"
45#include "egllog.h"
46
47#include "util/debug.h"
48
49static mtx_t _eglModuleMutex = _MTX_INITIALIZER_NP;
50static _EGLDriver *_eglDriver;
51
52static _EGLDriver *
53_eglGetDriver(void)
54{
55   mtx_lock(&_eglModuleMutex);
56
57   if (!_eglDriver) {
58      _eglDriver = calloc(1, sizeof(*_eglDriver));
59      if (!_eglDriver) {
60         mtx_unlock(&_eglModuleMutex);
61         return NULL;
62      }
63      _eglInitDriverFallbacks(_eglDriver);
64      _eglInitDriver(_eglDriver);
65   }
66
67   mtx_unlock(&_eglModuleMutex);
68
69   return _eglDriver;
70}
71
72static _EGLDriver *
73_eglMatchAndInitialize(_EGLDisplay *disp)
74{
75   if (_eglGetDriver())
76      if (_eglDriver->API.Initialize(_eglDriver, disp))
77         return _eglDriver;
78
79   return NULL;
80}
81
82/**
83 * Match a display to a driver.  The matching is done by finding the first
84 * driver that can initialize the display.
85 */
86_EGLDriver *
87_eglMatchDriver(_EGLDisplay *disp)
88{
89   _EGLDriver *best_drv;
90
91   assert(!disp->Initialized);
92
93   /* set options */
94   disp->Options.ForceSoftware =
95      env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
96
97   best_drv = _eglMatchAndInitialize(disp);
98   if (!best_drv && !disp->Options.ForceSoftware) {
99      disp->Options.ForceSoftware = EGL_TRUE;
100      best_drv = _eglMatchAndInitialize(disp);
101   }
102
103   if (best_drv) {
104      disp->Driver = best_drv;
105      disp->Initialized = EGL_TRUE;
106   }
107
108   return best_drv;
109}
110
111__eglMustCastToProperFunctionPointerType
112_eglGetDriverProc(const char *procname)
113{
114   if (_eglGetDriver())
115      return _eglDriver->API.GetProcAddress(_eglDriver, procname);
116
117   return NULL;
118}
119
120/**
121 * Unload all drivers.
122 */
123void
124_eglUnloadDrivers(void)
125{
126   /* this is called at atexit time */
127   free(_eglDriver);
128   _eglDriver = NULL;
129}
130