egldriver.c revision 209360bbb91bb10346ebc509db3d8173ea32f6b1
1f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu/**************************************************************************
2f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
3877128505431adaf817dc8069172ebe4a1cdf5d8José Fonseca * Copyright 2008 VMware, Inc.
4f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Copyright 2010-2011 LunarG, Inc.
6f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * All Rights Reserved.
7f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
8f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Permission is hereby granted, free of charge, to any person obtaining a
9f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * copy of this software and associated documentation files (the
10f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * "Software"), to deal in the Software without restriction, including
11f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * without limitation the rights to use, copy, modify, merge, publish,
12f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * distribute, sub license, and/or sell copies of the Software, and to
13f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * permit persons to whom the Software is furnished to do so, subject to
14f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * the following conditions:
15f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
16f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * The above copyright notice and this permission notice (including the
17f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * next paragraph) shall be included in all copies or substantial portions
18f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * of the Software.
19f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
20f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * DEALINGS IN THE SOFTWARE.
27f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
28f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu **************************************************************************/
29f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu
30f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu
316052af172f0241e6678cd16efac0a0f14f40146cBrian Paul/**
326052af172f0241e6678cd16efac0a0f14f40146cBrian Paul * Functions for choosing and opening/loading device drivers.
336052af172f0241e6678cd16efac0a0f14f40146cBrian Paul */
346052af172f0241e6678cd16efac0a0f14f40146cBrian Paul
356052af172f0241e6678cd16efac0a0f14f40146cBrian Paul
36adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include <assert.h>
3711a261ef4f1d4100c46f73ad51e7e4ed57cc1b5eBrian Paul#include <string.h>
38adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include <stdio.h>
390c8908c411c434eda318b41b4f2a370a1e794831Brian Paul#include <stdlib.h>
40efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikov#include "c11/threads.h"
411e6c10f4be9e36cc052a6b47fb2cb1eae60caa00Chia-I Wu
421e6c10f4be9e36cc052a6b47fb2cb1eae60caa00Chia-I Wu#include "eglstring.h"
43e084fe54f93c9d51df99812b76d3299b0cff57a3Brian Paul#include "egldefines.h"
44adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include "egldisplay.h"
45adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include "egldriver.h"
46b711eb793b68bb0c4561e5e345b76453dfac286bBrian Paul#include "egllog.h"
47adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul
48400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV#ifdef _EGL_BUILT_IN_DRIVER_HAIKU
49400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV_EGLDriver* _eglBuiltInDriverHaiku(const char* args);
50400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV#endif
515541988578054345ca70b7ed7972710396e61b44Chia-I Wu
52f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wutypedef struct _egl_module {
53209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   char *Name;
54c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLMain_t BuiltIn;
55f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLDriver *Driver;
56f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu} _EGLModule;
57f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
58efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikovstatic mtx_t _eglModuleMutex = _MTX_INITIALIZER_NP;
59f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGLArray *_eglModules;
60f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
61c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wuconst struct {
62c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   const char *name;
63c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLMain_t main;
64c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu} _eglBuiltInDrivers[] = {
65c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#ifdef _EGL_BUILT_IN_DRIVER_DRI2
66c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { "egl_dri2", _eglBuiltInDriverDRI2 },
67c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#endif
68400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV#ifdef _EGL_BUILT_IN_DRIVER_HAIKU
69400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV   { "egl_haiku", _eglBuiltInDriverHaiku },
70400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV#endif
71c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { NULL, NULL }
72c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu};
73f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
74a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul/**
75f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Load a module and create the driver object.
760eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu */
77f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic EGLBoolean
78f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglLoadModule(_EGLModule *mod)
790eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu{
80f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLDriver *drv;
810eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
82c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   if (mod->Driver)
83c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      return EGL_TRUE;
84c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu
85209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   if (!mod->BuiltIn)
86c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         return EGL_FALSE;
870eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
88209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   drv = mod->BuiltIn(NULL);
89209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   if (!drv || !drv->Name)
90f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      return EGL_FALSE;
910eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
92f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Driver = drv;
93f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
94f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return EGL_TRUE;
95f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
96b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
970eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
98f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
99f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Unload a module.
100f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
101f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
102f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglUnloadModule(_EGLModule *mod)
103f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
104d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#if defined(_EGL_OS_UNIX)
105f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* destroy the driver */
106f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod->Driver && mod->Driver->Unload)
107f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod->Driver->Unload(mod->Driver);
108d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu
109d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#elif defined(_EGL_OS_WINDOWS)
110d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu   /* XXX Windows unloads DLLs before atexit */
111d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu#endif
112f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
113f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Driver = NULL;
1140eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
1150eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1160eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1170eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
118f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add a module to the module array.
1190eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu */
120f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGLModule *
121209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov_eglAddModule(const char *name)
1220eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu{
123f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLModule *mod;
124f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
1250eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
126f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglModules) {
127f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglModules = _eglCreateArray("Module", 8);
128f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!_eglModules)
129f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return NULL;
130f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
131cf22fd5e5b13ccdb02ba0368ea722ede3bbc6de0Chia-I Wu
132f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* find duplicates */
133f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   for (i = 0; i < _eglModules->Size; i++) {
134f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod = _eglModules->Elements[i];
135209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      if (strcmp(mod->Name, name) == 0)
136f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return mod;
137f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
138f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
139f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* allocate a new one */
140f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod = calloc(1, sizeof(*mod));
141f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod) {
142209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      mod->Name = _eglstrdup(name);
143209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      if (!mod->Name) {
144f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         free(mod);
145f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         mod = NULL;
1460eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu      }
1470eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   }
148f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod) {
149f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglAppendArray(_eglModules, (void *) mod);
150209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      _eglLog(_EGL_DEBUG, "added %s to module array", mod->Name);
151f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
1520eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
153f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return mod;
154f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
155f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
156f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
157f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
158f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Free a module.
159f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
160f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
161f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglFreeModule(void *module)
162f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
163f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLModule *mod = (_EGLModule *) module;
164f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
165f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _eglUnloadModule(mod);
166209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   free(mod->Name);
167f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   free(mod);
1680eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
1690eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1700eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1710eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
172f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add the user driver to the module array.
173b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu *
174f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * The user driver is specified by EGL_DRIVER.
175b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu */
1761e4f412242391000eea3fd28452865c3d27f987dChia-I Wustatic EGLBoolean
177f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddUserDriver(void)
178b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
17921b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu   char *env;
180b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
181b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu   env = getenv("EGL_DRIVER");
182209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   if (env) {
183c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      EGLint i;
184c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu
185c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      for (i = 0; _eglBuiltInDrivers[i].name; i++) {
186209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov         if (!strcmp(_eglBuiltInDrivers[i].name, env)) {
187209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov            _EGLModule *mod = _eglAddModule(env);
188c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu            if (mod)
189c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu               mod->BuiltIn = _eglBuiltInDrivers[i].main;
190f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
191f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu            return EGL_TRUE;
192c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         }
193c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      }
194f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   }
195f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
1961e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   return EGL_FALSE;
197f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
198b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
199f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
200f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
201c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu * Add built-in drivers to the module array.
202f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
203f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
204c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu_eglAddBuiltInDrivers(void)
205f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
206c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLModule *mod;
207f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
208f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
209c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   for (i = 0; _eglBuiltInDrivers[i].name; i++) {
210c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      mod = _eglAddModule(_eglBuiltInDrivers[i].name);
211c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      if (mod)
212c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         mod->BuiltIn = _eglBuiltInDrivers[i].main;
21321b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu   }
214f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
215b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
216f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
217f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
218f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add drivers to the module array.  Drivers will be loaded as they are matched
219f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * to displays.
220f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
221f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic EGLBoolean
222f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddDrivers(void)
223f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
224f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (_eglModules)
225f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      return EGL_TRUE;
226f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
2271e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   if (!_eglAddUserDriver()) {
2281e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      /*
2291e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       * Add other drivers only when EGL_DRIVER is not set.  The order here
2301e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       * decides the priorities.
2311e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       */
2321e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglAddBuiltInDrivers();
2331e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   }
234f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
235f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return (_eglModules != NULL);
236b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu}
237b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
238b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
239b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu/**
240655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * A helper function for _eglMatchDriver.  It finds the first driver that can
241655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * initialize the display and return.
242b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu */
243655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wustatic _EGLDriver *
244655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_eglMatchAndInitialize(_EGLDisplay *dpy)
245b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
246655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _EGLDriver *drv = NULL;
247655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   EGLint i = 0;
2484afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
249f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglAddDrivers()) {
2501e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglLog(_EGL_WARNING, "failed to find any driver");
251655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      return NULL;
2524afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu   }
253b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
254655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   if (dpy->Driver) {
255655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      drv = dpy->Driver;
256655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      /* no re-matching? */
257655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!drv->API.Initialize(drv, dpy))
258655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         drv = NULL;
259655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      return drv;
260655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   }
261b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
262655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   while (i < _eglModules->Size) {
263655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
264655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
265655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!_eglLoadModule(mod)) {
266655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         /* remove invalid modules */
267655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         _eglEraseArray(_eglModules, i, _eglFreeModule);
268655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         continue;
269655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      }
270655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
271655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
272655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         drv = mod->Driver;
273655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         break;
274f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
275f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      else {
276655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         i++;
277f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
278f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
2794afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
280655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   return drv;
281655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu}
282b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
2834afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
284655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu/**
285655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * Match a display to a driver.  The display is initialized unless test_only is
286655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * true.  The matching is done by finding the first driver that can initialize
287655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * the display.
288655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu */
289655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_EGLDriver *
290655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
291655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu{
292655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _EGLDriver *best_drv;
293f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
294655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   assert(!dpy->Initialized);
295f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
296efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikov   mtx_lock(&_eglModuleMutex);
297655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
298655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   /* set options */
299655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   dpy->Options.TestOnly = test_only;
300a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   dpy->Options.UseFallback = EGL_FALSE;
301655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
302655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   best_drv = _eglMatchAndInitialize(dpy);
303a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   if (!best_drv) {
304a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu      dpy->Options.UseFallback = EGL_TRUE;
305a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu      best_drv = _eglMatchAndInitialize(dpy);
306a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   }
3070eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
308efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikov   mtx_unlock(&_eglModuleMutex);
309f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
310f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (best_drv) {
311655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      _eglLog(_EGL_DEBUG, "the best driver is %s%s",
312655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu            best_drv->Name, (test_only) ? " (test only) " : "");
313655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!test_only) {
314f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         dpy->Driver = best_drv;
315f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         dpy->Initialized = EGL_TRUE;
316f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
317f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
318f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
319f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return best_drv;
320e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul}
321e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul
322f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
323f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu__eglMustCastToProperFunctionPointerType
324f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglGetDriverProc(const char *procname)
325681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg{
326f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
327f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLProc proc = NULL;
328f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
329f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglModules) {
330f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      /* load the driver for the default display */
331f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
332f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
333f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
334f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return NULL;
335f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
336681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
337f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   for (i = 0; i < _eglModules->Size; i++) {
338f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
339681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
340f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!mod->Driver)
341f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         break;
342f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
343f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (proc)
344afcea9b115cdfa0a6c948784f753d38b43240d25Chia-I Wu         break;
345afcea9b115cdfa0a6c948784f753d38b43240d25Chia-I Wu   }
346681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
347f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return proc;
348f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
349f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
350681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
351f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
352f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Unload all drivers.
353f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
354f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wuvoid
355f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglUnloadDrivers(void)
356f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
357f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* this is called at atexit time */
358f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (_eglModules) {
359f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglDestroyArray(_eglModules, _eglFreeModule);
360f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglModules = NULL;
361f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
362681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg}
363