1 /**************************************************************************
3 * Copyright 2015, 2018 Collabora
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
31 #include "util/macros.h"
33 #include "eglcurrent.h"
34 #include "egldevice.h"
36 #include "eglglobals.h"
37 #include "egltypedefs.h"
43 const char *extensions
;
45 EGLBoolean MESA_device_software
;
46 EGLBoolean EXT_device_drm
;
56 _EGLDevice
*dev_list
, *dev
;
58 /* atexit function is called with global mutex locked */
60 dev_list
= _eglGlobal
.DeviceList
;
62 /* The first device is static allocated SW device */
64 assert(_eglDeviceSupports(dev_list
, _EGL_DEVICE_SOFTWARE
));
65 dev_list
= dev_list
->Next
;
70 dev_list
= dev_list
->Next
;
73 assert(_eglDeviceSupports(dev
, _EGL_DEVICE_DRM
));
74 drmFreeDevice(&dev
->device
);
79 _eglGlobal
.DeviceList
= NULL
;
83 _eglCheckDeviceHandle(EGLDeviceEXT device
)
87 mtx_lock(_eglGlobal
.Mutex
);
88 cur
= _eglGlobal
.DeviceList
;
90 if (cur
== (_EGLDevice
*) device
)
94 mtx_unlock(_eglGlobal
.Mutex
);
98 _EGLDevice _eglSoftwareDevice
= {
99 .extensions
= "EGL_MESA_device_software",
100 .MESA_device_software
= EGL_TRUE
,
105 * Negative value on error, zero if newly added, one if already in list.
108 _eglAddDRMDevice(drmDevicePtr device
, _EGLDevice
**out_dev
)
112 if ((device
->available_nodes
& (1 << DRM_NODE_PRIMARY
|
113 1 << DRM_NODE_RENDER
)) == 0)
116 dev
= _eglGlobal
.DeviceList
;
118 /* The first device is always software */
120 assert(_eglDeviceSupports(dev
, _EGL_DEVICE_SOFTWARE
));
125 assert(_eglDeviceSupports(dev
, _EGL_DEVICE_DRM
));
126 if (drmDevicesEqual(device
, dev
->device
) != 0) {
133 dev
->Next
= calloc(1, sizeof(_EGLDevice
));
141 dev
->extensions
= "EGL_EXT_device_drm";
142 dev
->EXT_device_drm
= EGL_TRUE
;
143 dev
->device
= device
;
152 /* Adds a device in DeviceList, if needed for the given fd.
154 * If a software device, the fd is ignored.
157 _eglAddDevice(int fd
, bool software
)
161 mtx_lock(_eglGlobal
.Mutex
);
162 dev
= _eglGlobal
.DeviceList
;
164 /* The first device is always software */
166 assert(_eglDeviceSupports(dev
, _EGL_DEVICE_SOFTWARE
));
173 if (drmGetDevice2(fd
, 0, &device
) != 0) {
178 /* Device is not added - error or already present */
179 if (_eglAddDRMDevice(device
, &dev
) != 0)
180 drmFreeDevice(&device
);
182 _eglLog(_EGL_FATAL
, "Driver bug: Built without libdrm, yet looking for HW device");
187 mtx_unlock(_eglGlobal
.Mutex
);
192 _eglDeviceSupports(_EGLDevice
*dev
, _EGLDeviceExtension ext
)
195 case _EGL_DEVICE_SOFTWARE
:
196 return dev
->MESA_device_software
;
197 case _EGL_DEVICE_DRM
:
198 return dev
->EXT_device_drm
;
205 /* Ideally we'll have an extension which passes the render node,
206 * instead of the card one + magic.
208 * Then we can move this in _eglQueryDeviceStringEXT below. Until then
212 _eglGetDRMDeviceRenderNode(_EGLDevice
*dev
)
214 return dev
->device
->nodes
[DRM_NODE_RENDER
];
218 _eglQueryDeviceAttribEXT(_EGLDevice
*dev
, EGLint attribute
,
223 _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryDeviceStringEXT");
229 _eglQueryDeviceStringEXT(_EGLDevice
*dev
, EGLint name
)
233 return dev
->extensions
;
235 case EGL_DRM_DEVICE_FILE_EXT
:
236 if (_eglDeviceSupports(dev
, _EGL_DEVICE_DRM
))
237 return dev
->device
->nodes
[DRM_NODE_PRIMARY
];
241 _eglError(EGL_BAD_PARAMETER
, "eglQueryDeviceStringEXT");
246 /* Do a fresh lookup for devices.
248 * Walks through the DeviceList, discarding no longer available ones
249 * and adding new ones as applicable.
251 * Must be called with the global lock held.
254 _eglRefreshDeviceList(void)
256 MAYBE_UNUSED _EGLDevice
*dev
;
259 dev
= _eglGlobal
.DeviceList
;
261 /* The first device is always software */
263 assert(_eglDeviceSupports(dev
, _EGL_DEVICE_SOFTWARE
));
267 drmDevicePtr devices
[64];
270 num_devs
= drmGetDevices2(0, devices
, ARRAY_SIZE(devices
));
271 for (int i
= 0; i
< num_devs
; i
++) {
272 ret
= _eglAddDRMDevice(devices
[i
], NULL
);
274 /* Device is not added - error or already present */
276 drmFreeDevice(&devices
[i
]);
287 _eglQueryDevicesEXT(EGLint max_devices
,
288 _EGLDevice
**devices
,
291 _EGLDevice
*dev
, *devs
;
294 if ((devices
&& max_devices
<= 0) || !num_devices
)
295 return _eglError(EGL_BAD_PARAMETER
, "eglQueryDevicesEXT");
297 mtx_lock(_eglGlobal
.Mutex
);
299 num_devs
= _eglRefreshDeviceList();
300 devs
= _eglGlobal
.DeviceList
;
302 /* bail early if we only care about the count */
304 *num_devices
= num_devs
;
308 *num_devices
= MIN2(num_devs
, max_devices
);
310 for (i
= 0, dev
= devs
; i
< *num_devices
; i
++) {
316 mtx_unlock(_eglGlobal
.Mutex
);