diff options
author | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2015-07-20 22:06:31 +0200 |
---|---|---|
committer | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2015-07-22 17:05:17 +0200 |
commit | c69b792962bba413875cec3a198ee54ad3c24e51 (patch) | |
tree | a64a7dbbb3c5d98721f819df79ad3af0e9720cc6 | |
parent | e3a20f380d646873fe818f3cb13b54931c2ad0fd (diff) |
egldevice: implement eglQueryDevicesEXT using udev
Enumerate udev devices by using:
SUBSYSTEM=="drm"
DEVTYPE=="drm_minor"
TAG=="master-of-seat"
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r-- | src/egl/main/eglapi.c | 7 | ||||
-rw-r--r-- | src/egl/main/egldevice.c | 153 | ||||
-rw-r--r-- | src/egl/main/egldevice.h | 7 |
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 */ |