~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
 *
3
 
 * Copyright 2011 Intel Corporation
4
 
 * Copyright 2012 Francisco Jerez
5
 
 * All Rights Reserved.
6
 
 *
7
 
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 
 * copy of this software and associated documentation files (the
9
 
 * "Software"), to deal in the Software without restriction, including
10
 
 * without limitation the rights to use, copy, modify, merge, publish,
11
 
 * distribute, sub license, and/or sell copies of the Software, and to
12
 
 * permit persons to whom the Software is furnished to do so, subject to
13
 
 * the following conditions:
14
 
 *
15
 
 * The above copyright notice and this permission notice (including the
16
 
 * next paragraph) shall be included in all copies or substantial portions
17
 
 * of the Software.
18
 
 *
19
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
 
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23
 
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
 
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 
 *
27
 
 * Authors:
28
 
 *    Kristian Høgsberg <krh@bitplanet.net>
29
 
 *    Benjamin Franzke <benjaminfranzke@googlemail.com>
30
 
 *
31
 
 **************************************************************************/
32
 
 
33
 
#include <fcntl.h>
34
 
#include <stdio.h>
35
 
#include <string.h>
36
 
#include <xf86drm.h>
37
 
#include <unistd.h>
38
 
#include <fcntl.h>
39
 
 
40
 
#include "loader.h"
41
 
#include "target-helpers/drm_helper_public.h"
42
 
#include "frontend/drm_driver.h"
43
 
#include "pipe_loader_priv.h"
44
 
 
45
 
#include "util/os_file.h"
46
 
#include "util/u_memory.h"
47
 
#include "util/u_dl.h"
48
 
#include "util/u_debug.h"
49
 
#include "util/xmlconfig.h"
50
 
 
51
 
#define DRM_RENDER_NODE_DEV_NAME_FORMAT "%s/renderD%d"
52
 
#define DRM_RENDER_NODE_MAX_NODES 63
53
 
#define DRM_RENDER_NODE_MIN_MINOR 128
54
 
#define DRM_RENDER_NODE_MAX_MINOR (DRM_RENDER_NODE_MIN_MINOR + DRM_RENDER_NODE_MAX_NODES)
55
 
 
56
 
struct pipe_loader_drm_device {
57
 
   struct pipe_loader_device base;
58
 
   const struct drm_driver_descriptor *dd;
59
 
#ifndef GALLIUM_STATIC_TARGETS
60
 
   struct util_dl_library *lib;
61
 
#endif
62
 
   int fd;
63
 
};
64
 
 
65
 
#define pipe_loader_drm_device(dev) ((struct pipe_loader_drm_device *)dev)
66
 
 
67
 
static const struct pipe_loader_ops pipe_loader_drm_ops;
68
 
 
69
 
#ifdef GALLIUM_STATIC_TARGETS
70
 
static const struct drm_driver_descriptor *driver_descriptors[] = {
71
 
   &i915_driver_descriptor,
72
 
   &iris_driver_descriptor,
73
 
   &crocus_driver_descriptor,
74
 
   &nouveau_driver_descriptor,
75
 
   &r300_driver_descriptor,
76
 
   &r600_driver_descriptor,
77
 
   &radeonsi_driver_descriptor,
78
 
   &vmwgfx_driver_descriptor,
79
 
   &kgsl_driver_descriptor,
80
 
   &msm_driver_descriptor,
81
 
   &virtio_gpu_driver_descriptor,
82
 
   &v3d_driver_descriptor,
83
 
   &vc4_driver_descriptor,
84
 
   &panfrost_driver_descriptor,
85
 
   &etnaviv_driver_descriptor,
86
 
   &tegra_driver_descriptor,
87
 
   &lima_driver_descriptor,
88
 
   &zink_driver_descriptor,
89
 
};
90
 
#endif
91
 
 
92
 
static const struct drm_driver_descriptor *
93
 
get_driver_descriptor(const char *driver_name, struct util_dl_library **plib)
94
 
{
95
 
#ifdef GALLIUM_STATIC_TARGETS
96
 
   for (int i = 0; i < ARRAY_SIZE(driver_descriptors); i++) {
97
 
      if (strcmp(driver_descriptors[i]->driver_name, driver_name) == 0)
98
 
         return driver_descriptors[i];
99
 
   }
100
 
   return &kmsro_driver_descriptor;
101
 
#else
102
 
   const char *search_dir = getenv("GALLIUM_PIPE_SEARCH_DIR");
103
 
   if (search_dir == NULL)
104
 
      search_dir = PIPE_SEARCH_DIR;
105
 
 
106
 
   *plib = pipe_loader_find_module(driver_name, search_dir);
107
 
   if (!*plib)
108
 
      return NULL;
109
 
 
110
 
   const struct drm_driver_descriptor *dd =
111
 
         (const struct drm_driver_descriptor *)
112
 
         util_dl_get_proc_address(*plib, "driver_descriptor");
113
 
 
114
 
   /* sanity check on the driver name */
115
 
   if (dd && strcmp(dd->driver_name, driver_name) == 0)
116
 
      return dd;
117
 
#endif
118
 
 
119
 
   return NULL;
120
 
}
121
 
 
122
 
static bool
123
 
pipe_loader_drm_probe_fd_nodup(struct pipe_loader_device **dev, int fd)
124
 
{
125
 
   struct pipe_loader_drm_device *ddev = CALLOC_STRUCT(pipe_loader_drm_device);
126
 
   int vendor_id, chip_id;
127
 
 
128
 
   if (!ddev)
129
 
      return false;
130
 
 
131
 
   if (loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) {
132
 
      ddev->base.type = PIPE_LOADER_DEVICE_PCI;
133
 
      ddev->base.u.pci.vendor_id = vendor_id;
134
 
      ddev->base.u.pci.chip_id = chip_id;
135
 
   } else {
136
 
      ddev->base.type = PIPE_LOADER_DEVICE_PLATFORM;
137
 
   }
138
 
   ddev->base.ops = &pipe_loader_drm_ops;
139
 
   ddev->fd = fd;
140
 
 
141
 
   ddev->base.driver_name = loader_get_driver_for_fd(fd);
142
 
   if (!ddev->base.driver_name)
143
 
      goto fail;
144
 
 
145
 
   /* For the closed source AMD OpenGL driver, we want libgbm to load
146
 
    * "amdgpu_dri.so", but we want Gallium multimedia drivers to load
147
 
    * "radeonsi". So change amdgpu to radeonsi for Gallium.
148
 
    */
149
 
   if (strcmp(ddev->base.driver_name, "amdgpu") == 0) {
150
 
      FREE(ddev->base.driver_name);
151
 
      ddev->base.driver_name = strdup("radeonsi");
152
 
   }
153
 
 
154
 
   struct util_dl_library **plib = NULL;
155
 
#ifndef GALLIUM_STATIC_TARGETS
156
 
   plib = &ddev->lib;
157
 
#endif
158
 
   ddev->dd = get_driver_descriptor(ddev->base.driver_name, plib);
159
 
 
160
 
   /* vgem is a virtual device; don't try using it with kmsro */
161
 
   if (strcmp(ddev->base.driver_name, "vgem") == 0)
162
 
      goto fail;
163
 
 
164
 
   /* kmsro supports lots of drivers, try as a fallback */
165
 
   if (!ddev->dd)
166
 
      ddev->dd = get_driver_descriptor("kmsro", plib);
167
 
 
168
 
   if (!ddev->dd)
169
 
      goto fail;
170
 
 
171
 
   *dev = &ddev->base;
172
 
   return true;
173
 
 
174
 
  fail:
175
 
#ifndef GALLIUM_STATIC_TARGETS
176
 
   if (ddev->lib)
177
 
      util_dl_close(ddev->lib);
178
 
#endif
179
 
   FREE(ddev->base.driver_name);
180
 
   FREE(ddev);
181
 
   return false;
182
 
}
183
 
 
184
 
bool
185
 
pipe_loader_drm_probe_fd(struct pipe_loader_device **dev, int fd)
186
 
{
187
 
   bool ret;
188
 
   int new_fd;
189
 
 
190
 
   if (fd < 0 || (new_fd = os_dupfd_cloexec(fd)) < 0)
191
 
     return false;
192
 
 
193
 
   ret = pipe_loader_drm_probe_fd_nodup(dev, new_fd);
194
 
   if (!ret)
195
 
      close(new_fd);
196
 
 
197
 
   return ret;
198
 
}
199
 
 
200
 
static int
201
 
open_drm_render_node_minor(int minor)
202
 
{
203
 
   char path[PATH_MAX];
204
 
   snprintf(path, sizeof(path), DRM_RENDER_NODE_DEV_NAME_FORMAT, DRM_DIR_NAME,
205
 
            minor);
206
 
   return loader_open_device(path);
207
 
}
208
 
 
209
 
int
210
 
pipe_loader_drm_probe(struct pipe_loader_device **devs, int ndev)
211
 
{
212
 
   int i, j, fd;
213
 
 
214
 
   for (i = DRM_RENDER_NODE_MIN_MINOR, j = 0;
215
 
        i <= DRM_RENDER_NODE_MAX_MINOR; i++) {
216
 
      struct pipe_loader_device *dev;
217
 
 
218
 
      fd = open_drm_render_node_minor(i);
219
 
      if (fd < 0)
220
 
         continue;
221
 
 
222
 
      if (!pipe_loader_drm_probe_fd_nodup(&dev, fd)) {
223
 
         close(fd);
224
 
         continue;
225
 
      }
226
 
 
227
 
      if (j < ndev) {
228
 
         devs[j] = dev;
229
 
      } else {
230
 
         close(fd);
231
 
         dev->ops->release(&dev);
232
 
      }
233
 
      j++;
234
 
   }
235
 
 
236
 
   return j;
237
 
}
238
 
 
239
 
static void
240
 
pipe_loader_drm_release(struct pipe_loader_device **dev)
241
 
{
242
 
   struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(*dev);
243
 
 
244
 
#ifndef GALLIUM_STATIC_TARGETS
245
 
   if (ddev->lib)
246
 
      util_dl_close(ddev->lib);
247
 
#endif
248
 
 
249
 
   close(ddev->fd);
250
 
   FREE(ddev->base.driver_name);
251
 
   pipe_loader_base_release(dev);
252
 
}
253
 
 
254
 
static const struct driOptionDescription *
255
 
pipe_loader_drm_get_driconf(struct pipe_loader_device *dev, unsigned *count)
256
 
{
257
 
   struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(dev);
258
 
 
259
 
   *count = ddev->dd->driconf_count;
260
 
   return ddev->dd->driconf;
261
 
}
262
 
 
263
 
static struct pipe_screen *
264
 
pipe_loader_drm_create_screen(struct pipe_loader_device *dev,
265
 
                              const struct pipe_screen_config *config, bool sw_vk)
266
 
{
267
 
   struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(dev);
268
 
 
269
 
   return ddev->dd->create_screen(ddev->fd, config);
270
 
}
271
 
 
272
 
const struct driOptionDescription *
273
 
pipe_loader_drm_get_driconf_by_name(const char *driver_name, unsigned *count)
274
 
{
275
 
   driOptionDescription *driconf = NULL;
276
 
   struct util_dl_library *lib = NULL;
277
 
   const struct drm_driver_descriptor *dd =
278
 
      get_driver_descriptor(driver_name, &lib);
279
 
 
280
 
   if (!dd) {
281
 
      *count = 0;
282
 
   } else {
283
 
      *count = dd->driconf_count;
284
 
      size_t size = sizeof(*driconf) * *count;
285
 
      driconf = malloc(size);
286
 
      memcpy(driconf, dd->driconf, size);
287
 
   }
288
 
   if (lib)
289
 
      util_dl_close(lib);
290
 
 
291
 
   return driconf;
292
 
}
293
 
 
294
 
static const struct pipe_loader_ops pipe_loader_drm_ops = {
295
 
   .create_screen = pipe_loader_drm_create_screen,
296
 
   .get_driconf = pipe_loader_drm_get_driconf,
297
 
   .release = pipe_loader_drm_release
298
 
};