Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gbm/main/backend.c
4564 views
1
/*
2
* Copyright © 2011 Intel Corporation
3
* Copyright © 2021 NVIDIA Corporation
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the next
13
* paragraph) shall be included in all copies or substantial portions of the
14
* Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
* DEALINGS IN THE SOFTWARE.
24
*
25
* Authors:
26
* Benjamin Franzke <[email protected]>
27
* James Jones <[email protected]>
28
*/
29
30
#include <stdio.h>
31
#include <stddef.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <limits.h>
35
#include <assert.h>
36
#include <dlfcn.h>
37
#include <xf86drm.h>
38
39
#include "loader.h"
40
#include "backend.h"
41
42
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
43
#define VER_MIN(a, b) ((a) < (b) ? (a) : (b))
44
45
extern const struct gbm_backend gbm_dri_backend;
46
47
struct gbm_backend_desc {
48
const char *name;
49
const struct gbm_backend *backend;
50
void *lib;
51
};
52
53
static const struct gbm_backend_desc builtin_backends[] = {
54
{ "dri", &gbm_dri_backend },
55
};
56
57
#define BACKEND_LIB_SUFFIX "_gbm"
58
static const char *backend_search_path_vars[] = {
59
"GBM_BACKENDS_PATH",
60
NULL
61
};
62
63
static void
64
free_backend_desc(const struct gbm_backend_desc *backend_desc)
65
{
66
assert(backend_desc->lib);
67
68
dlclose(backend_desc->lib);
69
free((void *)backend_desc->name);
70
free((void *)backend_desc);
71
}
72
73
static struct gbm_backend_desc *
74
create_backend_desc(const char *name,
75
const struct gbm_backend *backend,
76
void *lib)
77
{
78
struct gbm_backend_desc *new_desc = calloc(1, sizeof(*new_desc));
79
80
if (!new_desc)
81
return NULL;
82
83
new_desc->name = strdup(name);
84
85
if (!new_desc->name) {
86
free(new_desc);
87
return NULL;
88
}
89
90
new_desc->backend = backend;
91
new_desc->lib = lib;
92
93
return new_desc;
94
}
95
96
static struct gbm_device *
97
backend_create_device(const struct gbm_backend_desc *bd, int fd)
98
{
99
const uint32_t abi_ver = VER_MIN(GBM_BACKEND_ABI_VERSION,
100
bd->backend->v0.backend_version);
101
struct gbm_device *dev = bd->backend->v0.create_device(fd, abi_ver);
102
103
if (dev) {
104
if (abi_ver != dev->v0.backend_version) {
105
_gbm_device_destroy(dev);
106
return NULL;
107
}
108
dev->v0.backend_desc = bd;
109
}
110
111
return dev;
112
}
113
114
static struct gbm_device *
115
load_backend(void *lib, int fd, const char *name)
116
{
117
struct gbm_device *dev = NULL;
118
struct gbm_backend_desc *backend_desc;
119
const struct gbm_backend *gbm_backend;
120
GBM_GET_BACKEND_PROC_PTR get_backend;
121
122
get_backend = dlsym(lib, GBM_GET_BACKEND_PROC_NAME);
123
124
if (!get_backend)
125
goto fail;
126
127
gbm_backend = get_backend(&gbm_core);
128
backend_desc = create_backend_desc(name, gbm_backend, lib);
129
130
if (!backend_desc)
131
goto fail;
132
133
dev = backend_create_device(backend_desc, fd);
134
135
if (!dev)
136
free_backend_desc(backend_desc);
137
138
return dev;
139
140
fail:
141
dlclose(lib);
142
return NULL;
143
}
144
145
static struct gbm_device *
146
find_backend(const char *name, int fd)
147
{
148
struct gbm_device *dev = NULL;
149
const struct gbm_backend_desc *bd;
150
void *lib;
151
unsigned i;
152
153
for (i = 0; i < ARRAY_SIZE(builtin_backends); ++i) {
154
bd = &builtin_backends[i];
155
156
if (name && strcmp(bd->name, name))
157
continue;
158
159
dev = backend_create_device(bd, fd);
160
161
if (dev)
162
break;
163
}
164
165
if (name && !dev) {
166
lib = loader_open_driver_lib(name, BACKEND_LIB_SUFFIX,
167
backend_search_path_vars,
168
DEFAULT_BACKENDS_PATH,
169
true);
170
171
if (lib)
172
dev = load_backend(lib, fd, name);
173
}
174
175
return dev;
176
}
177
178
static struct gbm_device *
179
override_backend(int fd)
180
{
181
struct gbm_device *dev = NULL;
182
const char *b;
183
184
b = getenv("GBM_BACKEND");
185
if (b)
186
dev = find_backend(b, fd);
187
188
return dev;
189
}
190
191
static struct gbm_device *
192
backend_from_driver_name(int fd)
193
{
194
struct gbm_device *dev = NULL;
195
drmVersionPtr v = drmGetVersion(fd);
196
void *lib;
197
198
if (!v)
199
return NULL;
200
201
lib = loader_open_driver_lib(v->name, BACKEND_LIB_SUFFIX,
202
backend_search_path_vars,
203
DEFAULT_BACKENDS_PATH,
204
false);
205
206
if (lib)
207
dev = load_backend(lib, fd, v->name);
208
209
drmFreeVersion(v);
210
211
return dev;
212
}
213
214
struct gbm_device *
215
_gbm_create_device(int fd)
216
{
217
struct gbm_device *dev;
218
219
dev = override_backend(fd);
220
221
if (!dev)
222
dev = backend_from_driver_name(fd);
223
224
if (!dev)
225
dev = find_backend(NULL, fd);
226
227
return dev;
228
}
229
230
void
231
_gbm_device_destroy(struct gbm_device *gbm)
232
{
233
const struct gbm_backend_desc *backend_desc = gbm->v0.backend_desc;
234
gbm->v0.destroy(gbm);
235
236
if (backend_desc && backend_desc->lib)
237
free_backend_desc(backend_desc);
238
}
239
240