[Mesa-dev] [PATCH v2 3/8] egl: add EGL_EXT_device_drm support
Mathias Fröhlich
Mathias.Froehlich at gmx.net
Thu Sep 20 14:12:31 UTC 2018
Hi Emil,
There are some comments inline below:
On Tuesday, 4 September 2018 20:33:00 CEST Emil Velikov wrote:
> From: Emil Velikov <emil.velikov at collabora.com>
>
> Add implementation based around the drmDevice API. As such it's only
> available only when building with libdrm. With the latter already a
> requirement when using !SW code paths in the platform code.
>
> Note: the current code will work if a device is hot-plugged. Yet
> hot-unplugged is not implemented, since I have no ways of testing it.
>
> v2:
> - ddd some _eglDeviceSupports checks
> - require DRM_NODE_RENDER
> - add _eglGetDRMDeviceRenderNode helper
>
> Signed-off-by: Emil Velikov <emil.velikov at collabora.com>
> ---
> src/egl/main/egldevice.c | 113 +++++++++++++++++++++++++++++++++++++++
> src/egl/main/egldevice.h | 4 ++
> 2 files changed, 117 insertions(+)
>
> diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c
> index 1d67fd71191..6bd584e025b 100644
> --- a/src/egl/main/egldevice.c
> +++ b/src/egl/main/egldevice.c
> @@ -25,10 +25,14 @@
> *
> **************************************************************************/
>
> +#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"
>
> @@ -39,6 +43,11 @@ struct _egl_device {
> const char *extensions;
>
> EGLBoolean MESA_device_software;
> + EGLBoolean EXT_device_drm;
> +
> +#ifdef HAVE_LIBDRM
> + drmDevicePtr device;
> +#endif
> };
>
> void
> @@ -60,6 +69,10 @@ _eglFiniDevice(void)
> dev = dev_list;
> dev_list = dev_list->Next;
>
> +#ifdef HAVE_LIBDRM
> + assert(!_eglDeviceSupports(dev_list, _EGL_DEVICE_DRM));
You probably mean dev instead of dev_list also the ! is probably wrong:
assert(_eglDeviceSupports(dev, _EGL_DEVICE_DRM));
> + drmFreeDevice(&dev->device);
> +#endif
> free(dev);
> }
>
> @@ -87,6 +100,55 @@ _EGLDevice _eglSoftwareDevice = {
> .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_list, _EGL_DEVICE_DRM));
That one does not compile with assertions enabled.
There is no dev_list.
Also the ! is probably wrong.
> + 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.
> @@ -105,7 +167,21 @@ _eglAddDevice(int fd, bool 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);
> @@ -118,12 +194,26 @@ _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)
> @@ -141,6 +231,12 @@ _eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
> 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];
... we probably want
return _eglGetDRMDeviceRenderNode(dev);
best
Mathias
> + /* fall through */
> +#endif
> default:
> _eglError(EGL_BAD_PARAMETER, "eglQueryDeviceStringEXT");
> return NULL;
> @@ -167,6 +263,23 @@ _eglRefreshDeviceList(void)
> 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;
> }
>
> diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h
> index 74b5ddeee5c..ddcdcd17f5a 100644
> --- a/src/egl/main/egldevice.h
> +++ b/src/egl/main/egldevice.h
> @@ -60,6 +60,7 @@ _eglAddDevice(int fd, bool software);
>
> enum _egl_device_extension {
> _EGL_DEVICE_SOFTWARE,
> + _EGL_DEVICE_DRM,
> };
>
> typedef enum _egl_device_extension _EGLDeviceExtension;
> @@ -67,6 +68,9 @@ typedef enum _egl_device_extension _EGLDeviceExtension;
> EGLBoolean
> _eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext);
>
> +const char *
> +_eglGetDRMDeviceRenderNode(_EGLDevice *dev);
> +
> EGLBoolean
> _eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute,
> EGLAttrib *value);
>
More information about the mesa-dev
mailing list