*
**************************************************************************/
+#ifdef HAVE_LIBDRM
+#include <xf86drm.h>
+#endif
#include "util/macros.h"
#include "eglcurrent.h"
#include "egldevice.h"
+#include "egllog.h"
#include "eglglobals.h"
#include "egltypedefs.h"
_EGLDevice *Next;
const char *extensions;
+
+ EGLBoolean MESA_device_software;
+ EGLBoolean EXT_device_drm;
+
+#ifdef HAVE_LIBDRM
+ drmDevicePtr device;
+#endif
};
void
/* atexit function is called with global mutex locked */
dev_list = _eglGlobal.DeviceList;
+
+ /* The first device is static allocated SW device */
+ assert(dev_list);
+ assert(_eglDeviceSupports(dev_list, _EGL_DEVICE_SOFTWARE));
+ dev_list = dev_list->Next;
+
while (dev_list) {
/* pop list head */
dev = dev_list;
dev_list = dev_list->Next;
+#ifdef HAVE_LIBDRM
+ assert(_eglDeviceSupports(dev, _EGL_DEVICE_DRM));
+ drmFreeDevice(&dev->device);
+#endif
free(dev);
}
return (cur != NULL);
}
+_EGLDevice _eglSoftwareDevice = {
+ .extensions = "EGL_MESA_device_software",
+ .MESA_device_software = EGL_TRUE,
+};
+
+#ifdef HAVE_LIBDRM
+/*
+ * Negative value on error, zero if newly added, one if already in list.
+ */
+static int
+_eglAddDRMDevice(drmDevicePtr device, _EGLDevice **out_dev)
+{
+ _EGLDevice *dev;
+
+ if ((device->available_nodes & (1 << DRM_NODE_PRIMARY |
+ 1 << DRM_NODE_RENDER)) == 0)
+ return -1;
+
+ dev = _eglGlobal.DeviceList;
+
+ /* The first device is always software */
+ assert(dev);
+ assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
+
+ while (dev->Next) {
+ dev = dev->Next;
+
+ assert(_eglDeviceSupports(dev, _EGL_DEVICE_DRM));
+ if (drmDevicesEqual(device, dev->device) != 0) {
+ if (out_dev)
+ *out_dev = dev;
+ return 1;
+ }
+ }
+
+ dev->Next = calloc(1, sizeof(_EGLDevice));
+ if (!dev->Next) {
+ if (out_dev)
+ *out_dev = NULL;
+ return -1;
+ }
+
+ dev = dev->Next;
+ dev->extensions = "EGL_EXT_device_drm";
+ dev->EXT_device_drm = EGL_TRUE;
+ dev->device = device;
+
+ if (out_dev)
+ *out_dev = dev;
+
+ return 0;
+}
+#endif
+
/* Adds a device in DeviceList, if needed for the given fd.
*
* If a software device, the fd is ignored.
_EGLDevice *dev;
mtx_lock(_eglGlobal.Mutex);
+ dev = _eglGlobal.DeviceList;
+
+ /* The first device is always software */
+ assert(dev);
+ assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
+ if (software)
+ goto out;
+#ifdef HAVE_LIBDRM
+ drmDevicePtr device;
+
+ if (drmGetDevice2(fd, 0, &device) != 0) {
+ dev = NULL;
+ goto out;
+ }
+
+ /* Device is not added - error or already present */
+ if (_eglAddDRMDevice(device, &dev) != 0)
+ drmFreeDevice(&device);
+#else
+ _eglLog(_EGL_FATAL, "Driver bug: Built without libdrm, yet looking for HW device");
dev = NULL;
+#endif
out:
mtx_unlock(_eglGlobal.Mutex);
_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext)
{
switch (ext) {
+ case _EGL_DEVICE_SOFTWARE:
+ return dev->MESA_device_software;
+ case _EGL_DEVICE_DRM:
+ return dev->EXT_device_drm;
default:
assert(0);
return EGL_FALSE;
};
}
+/* Ideally we'll have an extension which passes the render node,
+ * instead of the card one + magic.
+ *
+ * Then we can move this in _eglQueryDeviceStringEXT below. Until then
+ * keep it separate.
+ */
+const char *
+_eglGetDRMDeviceRenderNode(_EGLDevice *dev)
+{
+ return dev->device->nodes[DRM_NODE_RENDER];
+}
+
EGLBoolean
_eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute,
EGLAttrib *value)
switch (name) {
case EGL_EXTENSIONS:
return dev->extensions;
+#ifdef HAVE_LIBDRM
+ case EGL_DRM_DEVICE_FILE_EXT:
+ if (_eglDeviceSupports(dev, _EGL_DEVICE_DRM))
+ return dev->device->nodes[DRM_NODE_PRIMARY];
+ /* fall through */
+#endif
default:
_eglError(EGL_BAD_PARAMETER, "eglQueryDeviceStringEXT");
return NULL;
dev = _eglGlobal.DeviceList;
+ /* The first device is always software */
+ assert(dev);
+ assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
+ count++;
+
+#ifdef HAVE_LIBDRM
+ drmDevicePtr devices[64];
+ int num_devs, ret;
+
+ num_devs = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
+ for (int i = 0; i < num_devs; i++) {
+ ret = _eglAddDRMDevice(devices[i], NULL);
+
+ /* Device is not added - error or already present */
+ if (ret != 0)
+ drmFreeDevice(&devices[i]);
+
+ if (ret >= 0)
+ count++;
+ }
+#endif
+
return count;
}