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
42e084fe54f93c9d51df99812b76d3299b0cff57a3Brian Paul#include "egldefines.h"
43adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include "egldisplay.h"
44adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul#include "egldriver.h"
45b711eb793b68bb0c4561e5e345b76453dfac286bBrian Paul#include "egllog.h"
46adbff7e977c7c768e752a24fb643d68bdf961bfeBrian Paul
47f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wutypedef struct _egl_module {
48209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   char *Name;
49c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLMain_t BuiltIn;
50f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLDriver *Driver;
51f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu} _EGLModule;
52f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
53efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikovstatic mtx_t _eglModuleMutex = _MTX_INITIALIZER_NP;
54f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGLArray *_eglModules;
55f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
56c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wuconst struct {
57c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   const char *name;
58c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLMain_t main;
59c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu} _eglBuiltInDrivers[] = {
60c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#ifdef _EGL_BUILT_IN_DRIVER_DRI2
61c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { "egl_dri2", _eglBuiltInDriverDRI2 },
62c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu#endif
63400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV#ifdef _EGL_BUILT_IN_DRIVER_HAIKU
64400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV   { "egl_haiku", _eglBuiltInDriverHaiku },
65400b833592d9aad7b2c4627a897380642d52189fAlexander von Gluck IV#endif
66c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   { NULL, NULL }
67c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu};
68f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
69a8533d54930f8fa989036c197ad20b0778ec0cacBrian Paul/**
70f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Load a module and create the driver object.
710eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu */
72f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic EGLBoolean
73f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglLoadModule(_EGLModule *mod)
740eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu{
75f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLDriver *drv;
760eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
77c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   if (mod->Driver)
78c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      return EGL_TRUE;
79c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu
80209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   if (!mod->BuiltIn)
81c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         return EGL_FALSE;
820eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
83209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   drv = mod->BuiltIn(NULL);
84209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   if (!drv || !drv->Name)
85f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      return EGL_FALSE;
860eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
87f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Driver = drv;
88f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
89f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return EGL_TRUE;
90f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
91b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
920eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
93f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
94f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Unload a module.
95f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
96f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
97f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglUnloadModule(_EGLModule *mod)
98f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
99f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* destroy the driver */
100f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod->Driver && mod->Driver->Unload)
101f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod->Driver->Unload(mod->Driver);
102d6b1478ff0499059661df145efe469e7b28ff7bfChia-I Wu
103f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod->Driver = NULL;
1040eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
1050eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1060eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1070eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
108f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add a module to the module array.
1090eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu */
110f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic _EGLModule *
111209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov_eglAddModule(const char *name)
1120eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu{
113f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLModule *mod;
114f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
1150eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
116f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglModules) {
117f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglModules = _eglCreateArray("Module", 8);
118f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!_eglModules)
119f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return NULL;
120f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
121cf22fd5e5b13ccdb02ba0368ea722ede3bbc6de0Chia-I Wu
122f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* find duplicates */
123f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   for (i = 0; i < _eglModules->Size; i++) {
124f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      mod = _eglModules->Elements[i];
125209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      if (strcmp(mod->Name, name) == 0)
126f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return mod;
127f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
128f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
129f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* allocate a new one */
130f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   mod = calloc(1, sizeof(*mod));
131f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod) {
1323593f37fd7b599e217bd1f894ac671a14a058b8dEmil Velikov      mod->Name = strdup(name);
133209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      if (!mod->Name) {
134f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         free(mod);
135f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         mod = NULL;
1360eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu      }
1370eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu   }
138f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (mod) {
139f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglAppendArray(_eglModules, (void *) mod);
140209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov      _eglLog(_EGL_DEBUG, "added %s to module array", mod->Name);
141f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
1420eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
143f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return mod;
144f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
145f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
146f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
147f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
148f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Free a module.
149f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
150f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
151f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglFreeModule(void *module)
152f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
153f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLModule *mod = (_EGLModule *) module;
154f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
155f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _eglUnloadModule(mod);
156209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   free(mod->Name);
157f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   free(mod);
1580eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu}
1590eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1600eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
1610eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu/**
162f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add the user driver to the module array.
163b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu *
164f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * The user driver is specified by EGL_DRIVER.
165b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu */
1661e4f412242391000eea3fd28452865c3d27f987dChia-I Wustatic EGLBoolean
167f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddUserDriver(void)
168b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
16921b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu   char *env;
170b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
171b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu   env = getenv("EGL_DRIVER");
172209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov   if (env) {
173c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      EGLint i;
174c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu
175c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      for (i = 0; _eglBuiltInDrivers[i].name; i++) {
176209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov         if (!strcmp(_eglBuiltInDrivers[i].name, env)) {
177209360bbb91bb10346ebc509db3d8173ea32f6b1Emil Velikov            _EGLModule *mod = _eglAddModule(env);
178c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu            if (mod)
179c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu               mod->BuiltIn = _eglBuiltInDrivers[i].main;
180f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
181f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu            return EGL_TRUE;
182c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         }
183c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      }
184f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu   }
185f36cba6cf3d51a3937d3bb429609d258399751a0Chia-I Wu
1861e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   return EGL_FALSE;
187f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
188b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
189f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
190f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
191c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu * Add built-in drivers to the module array.
192f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
193f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic void
194c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu_eglAddBuiltInDrivers(void)
195f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
196c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   _EGLModule *mod;
197f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
198f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
199c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu   for (i = 0; _eglBuiltInDrivers[i].name; i++) {
200c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      mod = _eglAddModule(_eglBuiltInDrivers[i].name);
201c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu      if (mod)
202c98ea26e16b6458b4385d6558936696e4d099455Chia-I Wu         mod->BuiltIn = _eglBuiltInDrivers[i].main;
20321b2c0a6e5ecb6d542bd7d3750c5a0b745104eddChia-I Wu   }
204f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
205b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
206f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
207f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
208f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Add drivers to the module array.  Drivers will be loaded as they are matched
209f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * to displays.
210f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
211f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wustatic EGLBoolean
212f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglAddDrivers(void)
213f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
214f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (_eglModules)
215f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      return EGL_TRUE;
216f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
2171e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   if (!_eglAddUserDriver()) {
2181e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      /*
2191e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       * Add other drivers only when EGL_DRIVER is not set.  The order here
2201e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       * decides the priorities.
2211e4f412242391000eea3fd28452865c3d27f987dChia-I Wu       */
2221e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglAddBuiltInDrivers();
2231e4f412242391000eea3fd28452865c3d27f987dChia-I Wu   }
224f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
225f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return (_eglModules != NULL);
226b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu}
227b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
228b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
229b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu/**
230655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * A helper function for _eglMatchDriver.  It finds the first driver that can
231655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * initialize the display and return.
232b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu */
233655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wustatic _EGLDriver *
234655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_eglMatchAndInitialize(_EGLDisplay *dpy)
235b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu{
236655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _EGLDriver *drv = NULL;
237655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   EGLint i = 0;
2384afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
239f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglAddDrivers()) {
2401e4f412242391000eea3fd28452865c3d27f987dChia-I Wu      _eglLog(_EGL_WARNING, "failed to find any driver");
241655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      return NULL;
2424afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu   }
243b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
244655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   if (dpy->Driver) {
245655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      drv = dpy->Driver;
246655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      /* no re-matching? */
247655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!drv->API.Initialize(drv, dpy))
248655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         drv = NULL;
249655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      return drv;
250655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   }
251b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
252655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   while (i < _eglModules->Size) {
253655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
254655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
255655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!_eglLoadModule(mod)) {
256655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         /* remove invalid modules */
257655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         _eglEraseArray(_eglModules, i, _eglFreeModule);
258655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         continue;
259655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      }
260655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
261655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
262655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         drv = mod->Driver;
263655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         break;
264f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
265f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      else {
266655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu         i++;
267f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
268f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
2694afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
270655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   return drv;
271655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu}
272b3bcd33f7a8b32ce4ea6e979e9cc764d0f903ae9Chia-I Wu
2734afe24808ee253c44c65b855f65bd0749c1e1524Chia-I Wu
274655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu/**
275655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * Match a display to a driver.  The display is initialized unless test_only is
276655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * true.  The matching is done by finding the first driver that can initialize
277655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu * the display.
278655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu */
279655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_EGLDriver *
280655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
281655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu{
282655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   _EGLDriver *best_drv;
283f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
284655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   assert(!dpy->Initialized);
285f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
286efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikov   mtx_lock(&_eglModuleMutex);
287655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
288655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   /* set options */
289655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   dpy->Options.TestOnly = test_only;
290a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   dpy->Options.UseFallback = EGL_FALSE;
291655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu
292655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu   best_drv = _eglMatchAndInitialize(dpy);
293a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   if (!best_drv) {
294a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu      dpy->Options.UseFallback = EGL_TRUE;
295a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu      best_drv = _eglMatchAndInitialize(dpy);
296a22a332fc7cc54d4d0973dcd21a90159cc51de1aChia-I Wu   }
2970eaa02c836821556c1e8d0141f49f57e23f2548dChia-I Wu
298efe87f1a801c61d087cd2b29a2c150453241c3d4Emil Velikov   mtx_unlock(&_eglModuleMutex);
299f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
300f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (best_drv) {
301655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      _eglLog(_EGL_DEBUG, "the best driver is %s%s",
302655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu            best_drv->Name, (test_only) ? " (test only) " : "");
303655e4598927728a663f4cfcd6babdf7e5ad83f77Chia-I Wu      if (!test_only) {
304f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         dpy->Driver = best_drv;
305f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         dpy->Initialized = EGL_TRUE;
306f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      }
307f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
308f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
309f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return best_drv;
310e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul}
311e3805cad0d15ed25ce8f6c5a1f1ea913e5d0986aBrian Paul
312f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
313f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu__eglMustCastToProperFunctionPointerType
314f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglGetDriverProc(const char *procname)
315681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg{
316f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   EGLint i;
317f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   _EGLProc proc = NULL;
318f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
319f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (!_eglModules) {
320f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      /* load the driver for the default display */
321f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
322f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
323f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
324f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         return NULL;
325f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
326681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
327f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   for (i = 0; i < _eglModules->Size; i++) {
328f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
329681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
330f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (!mod->Driver)
331f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu         break;
332f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
333f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      if (proc)
334afcea9b115cdfa0a6c948784f753d38b43240d25Chia-I Wu         break;
335afcea9b115cdfa0a6c948784f753d38b43240d25Chia-I Wu   }
336681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
337f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   return proc;
338f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu}
339f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu
340681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg
341f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu/**
342f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu * Unload all drivers.
343f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu */
344f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wuvoid
345f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu_eglUnloadDrivers(void)
346f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu{
347f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   /* this is called at atexit time */
348f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   if (_eglModules) {
349f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglDestroyArray(_eglModules, _eglFreeModule);
350f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu      _eglModules = NULL;
351f2aa361f3b58a91780c9358b3f8716f6434074c7Chia-I Wu   }
352681fd73f1e95d43425b946a250b241bfdb0ce1c8Kristian Høgsberg}
353