summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/egl/main/eglapi.c7
-rw-r--r--src/egl/main/egldevice.c153
-rw-r--r--src/egl/main/egldevice.h7
3 files changed, 164 insertions, 3 deletions
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 66b2e3d32c..98589d9822 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -92,6 +92,7 @@
#include "eglglobals.h"
#include "eglcontext.h"
+#include "egldevice.h"
#include "egldisplay.h"
#include "egltypedefs.h"
#include "eglcurrent.h"
@@ -1849,7 +1850,11 @@ eglQueryDevicesEXT(EGLint max_devices,
EGLDeviceEXT *devices,
EGLint *num_devices)
{
- RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
+ EGLBoolean ret;
+
+ ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices, num_devices);
+
+ RETURN_EGL_EVAL(NULL, ret);
}
#endif
diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c
index c79daff7fc..9307b56e48 100644
--- a/src/egl/main/egldevice.c
+++ b/src/egl/main/egldevice.c
@@ -31,20 +31,31 @@
#include <libudev.h>
#endif
+#include "eglcurrent.h"
#include "egldevice.h"
#include "eglglobals.h"
#include "egllog.h"
#include "egltypedefs.h"
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+
typedef struct {
/* device list */
_EGLDevice *devices;
+ EGLBoolean got_devices;
+
+#ifdef HAVE_LIBUDEV
+ struct udev *udev;
+#endif
} _EGLDeviceInfo;
+static EGLBoolean _eglFillDeviceList(_EGLDeviceInfo *info);
+
static _EGLDeviceInfo *
-_eglEnsureDeviceInfo(void)
+_eglEnsureDeviceInfo(EGLBoolean get_devices)
{
_EGLDeviceInfo *info;
@@ -58,10 +69,20 @@ _eglEnsureDeviceInfo(void)
goto out;
info->devices = NULL;
+ info->got_devices = EGL_FALSE;
+
+#ifdef HAVE_LIBUDEV
+ info->udev = NULL;
+#endif
_eglGlobal.DeviceInfo = info;
}
+ if (get_devices && !info->got_devices) {
+ if (!_eglFillDeviceList(info))
+ info = NULL;
+ }
+
out:
mtx_unlock(_eglGlobal.Mutex);
@@ -124,6 +145,11 @@ _eglFiniDeviceInfo(void)
{
_EGLDeviceInfo *info;
_EGLDevice *device_list, *device;
+#ifdef HAVE_LIBUDEV
+ UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *));
+ UDEV_SYMBOL(struct udev_device *, udev_device_unref,
+ (struct udev_device *));
+#endif
/* atexit function is called with global mutex locked */
@@ -138,9 +164,134 @@ _eglFiniDeviceInfo(void)
device = device_list;
device_list = device_list->Next;
+#ifdef HAVE_LIBUDEV
+ if (!dlsym_failed)
+ udev_device_unref(device->Info);
+#endif
free(device);
}
+#ifdef HAVE_LIBUDEV
+ if (info->udev && !dlsym_failed)
+ udev_unref(info->udev);
+#endif
+
free(info);
_eglGlobal.DeviceInfo = NULL;
}
+
+static EGLBoolean
+_eglFillDeviceList(_EGLDeviceInfo *info)
+{
+#ifdef HAVE_LIBUDEV
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *entry;
+ UDEV_SYMBOL(struct udev *, udev_new, (void));
+ UDEV_SYMBOL(struct udev_enumerate *, udev_enumerate_new,
+ (struct udev *));
+ UDEV_SYMBOL(int, udev_enumerate_add_match_subsystem,
+ (struct udev_enumerate *, const char *));
+ UDEV_SYMBOL(int, udev_enumerate_add_match_property,
+ (struct udev_enumerate *, const char *, const char *));
+ UDEV_SYMBOL(int, udev_enumerate_add_match_tag,
+ (struct udev_enumerate *, const char *));
+ UDEV_SYMBOL(int, udev_enumerate_scan_devices,
+ (struct udev_enumerate *));
+ UDEV_SYMBOL(struct udev_list_entry *, udev_list_entry_get_next,
+ (struct udev_list_entry *));
+ UDEV_SYMBOL(struct udev_list_entry *, udev_enumerate_get_list_entry,
+ (struct udev_enumerate *));
+ UDEV_SYMBOL(const char *, udev_list_entry_get_name,
+ (struct udev_list_entry *));
+ UDEV_SYMBOL(struct udev_device *, udev_device_new_from_syspath,
+ (struct udev *, const char *));
+ UDEV_SYMBOL(void, udev_enumerate_unref,
+ (struct udev_enumerate *));
+
+ if (dlsym_failed)
+ return EGL_FALSE;
+
+ if (!info->udev)
+ info->udev = udev_new();
+ if (!info->udev)
+ return EGL_FALSE;
+
+ enumerate = udev_enumerate_new(info->udev);
+ udev_enumerate_add_match_subsystem(enumerate, "drm");
+ udev_enumerate_add_match_property(enumerate, "DEVTYPE", "drm_minor");
+ udev_enumerate_add_match_tag(enumerate, "master-of-seat");
+ udev_enumerate_scan_devices(enumerate);
+
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(enumerate)) {
+ struct udev_device *dev;
+ const char *path;
+ _EGLDevice *egl_device;
+
+ path = udev_list_entry_get_name(entry);
+ dev = udev_device_new_from_syspath(info->udev, path);
+
+ egl_device = calloc(1, sizeof(_EGLDevice));
+ egl_device->Info = dev;
+
+ egl_device->Next = info->devices;
+ info->devices = egl_device;
+ }
+
+ udev_enumerate_unref(enumerate);
+
+ info->got_devices = EGL_TRUE;
+
+ return EGL_TRUE;
+#else
+ return EGL_FALSE;
+#endif
+}
+
+/**
+ * Enumerate EGL devices.
+ */
+EGLBoolean
+_eglQueryDevicesEXT(EGLint max_devices,
+ _EGLDevice **devices,
+ EGLint *num_devices)
+{
+ _EGLDeviceInfo *info;
+ EGLBoolean ret = EGL_TRUE;
+ int i;
+ _EGLDevice *dev;
+
+ /* max_devices can only be bad if devices is non-NULL. num_devices must
+ * always be present. */
+ if ((devices && max_devices < 1) || !num_devices)
+ return _eglError(EGL_BAD_PARAMETER, "eglQueryDevicesEXT");
+
+ info = _eglEnsureDeviceInfo(EGL_TRUE);
+ if (!info)
+ return _eglError(EGL_BAD_ALLOC, "eglQueryDevicesEXT");
+
+ mtx_lock(_eglGlobal.Mutex);
+
+ /* work out total number of devices */
+ for (i = 0, dev = info->devices; dev; i++, dev = dev->Next)
+ ;
+
+ /* bail early if we devices is NULL */
+ if (!devices) {
+ *num_devices = i;
+ goto out;
+ }
+
+ /* create and fill devices array */
+ *num_devices = MIN(i, max_devices);
+
+ for (i = 0, dev = info->devices;
+ i < *num_devices;
+ i++, dev = dev->Next) {
+ devices[i] = dev;
+ }
+
+out:
+ mtx_unlock(_eglGlobal.Mutex);
+
+ return ret;
+}
diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h
index f8f3824623..682f4b1c3c 100644
--- a/src/egl/main/egldevice.h
+++ b/src/egl/main/egldevice.h
@@ -36,7 +36,7 @@
struct _egl_device {
_EGLDevice *Next;
- /* TODO */
+ void *Info;
};
@@ -44,4 +44,9 @@ extern void
_eglFiniDeviceInfo(void);
+EGLBoolean
+_eglQueryDevicesEXT(EGLint max_devices, _EGLDevice **devices,
+ EGLint *num_devices);
+
+
#endif /* EGLDEVICE_INCLUDED */