This patch both adds support for probing & filtering DRM nodes and switches away from using the GRALLOC_MODULE_PERFORM_GET_DRM_FD gralloc call.
Currently the filtering is based just on the driver name, and the desired name is supplied using the "drm.gpu.vendor_name" Android property. The filtering itself is done using the newly introduced libdrm drmHandleMatch() call. Signed-off-by: Robert Foss <robert.f...@collabora.com> --- Changes since v1: - Do not rely on libdrm for probing - Distinguish between errors and when no drm devices are found Changes since RFC: - Rebased on newer libdrm drmHandleMatch patch - Added support for driver probing src/egl/drivers/dri2/platform_android.c | 202 +++++++++++++++++------- 1 file changed, 149 insertions(+), 53 deletions(-) diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 4ba96aad90..76e5474e48 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -27,6 +27,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <cutils/properties.h> #include <errno.h> #include <dlfcn.h> #include <fcntl.h> @@ -1130,31 +1131,6 @@ droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy) return (config_count != 0); } -enum { - /* perform(const struct gralloc_module_t *mod, - * int op, - * int *fd); - */ - GRALLOC_MODULE_PERFORM_GET_DRM_FD = 0x40000002, -}; - -static int -droid_open_device(struct dri2_egl_display *dri2_dpy) -{ - int fd = -1, err = -EINVAL; - - if (dri2_dpy->gralloc->perform) - err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc, - GRALLOC_MODULE_PERFORM_GET_DRM_FD, - &fd); - if (err || fd < 0) { - _eglLog(_EGL_WARNING, "fail to get drm fd"); - fd = -1; - } - - return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1; -} - static const struct dri2_egl_display_vtbl droid_display_vtbl = { .authenticate = NULL, .create_window_surface = droid_create_window_surface, @@ -1215,6 +1191,151 @@ static const __DRIextension *droid_image_loader_extensions[] = { NULL, }; +EGLBoolean +droid_load_driver(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = disp->DriverData; + const char *err; + + dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); + if (dri2_dpy->driver_name == NULL) { + err = "DRI2: failed to get driver name"; + goto error; + } + + dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; + + if (!dri2_dpy->is_render_node) { + #ifdef HAVE_DRM_GRALLOC + /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names + * for backwards compatibility with drm_gralloc. (Do not use on new + * systems.) */ + dri2_dpy->loader_extensions = droid_dri2_loader_extensions; + if (!dri2_load_driver(disp)) { + err = "DRI2: failed to load driver"; + goto error; + } + #else + err = "DRI2: handle is not for a render node"; + goto error; + #endif + } else { + dri2_dpy->loader_extensions = droid_image_loader_extensions; + if (!dri2_load_driver_dri3(disp)) { + err = "DRI3: failed to load driver"; + goto error; + } + } + + return EGL_TRUE; + +error: + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; + return _eglError(EGL_NOT_INITIALIZED, err); +} + +static int +droid_probe_driver(_EGLDisplay *disp, int fd) +{ + struct dri2_egl_display *dri2_dpy = disp->DriverData; + dri2_dpy->fd = fd; + + if (!droid_load_driver(disp)) + return false; + + /* Since this probe can succeed, but another filter may fail, + this string needs to be deallocated either way. + Once an FD has been found, this string will be set a second time. */ + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; + return true; +} + +static int +droid_probe_device(_EGLDisplay *disp, int fd, drmDevicePtr dev, char *vendor) +{ + drmVersionPtr ver = drmGetVersion(fd); + if (!ver) + goto fail; + + size_t vendor_len = strlen(vendor); + if (vendor_len != 0 && strncmp(vendor, ver->name, vendor_len)) + goto fail; + + if (!droid_probe_driver(disp, fd)) + goto fail; + + drmFreeVersion(ver); + return true; + +fail: + drmFreeVersion(ver); + return false; +} + +static int +droid_open_device(_EGLDisplay *disp) +{ + const int MAX_DRM_DEVICES = 32; + int prop_set, num_devices, ret; + int fd = -1, fallback_fd = -1; + + char vendor_name[PROPERTY_VALUE_MAX]; + property_get("drm.gpu.vendor_name", vendor_name, NULL); + + drmDevicePtr devices[MAX_DRM_DEVICES]; + num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES); + + if (num_devices < 0) { + _eglLog(_EGL_WARNING, "Unable to find DRM devices, error %d", num_devices); + return -1; + } + + if (num_devices == 0) { + _eglLog(_EGL_WARNING, "Failed to find any DRM devices"); + return -1; + } + + for (int i = 0; i < num_devices; i++) { + char *dev_path = devices[i]->nodes[DRM_NODE_RENDER]; + fd = loader_open_device(dev_path); + if (fd == -1) { + _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s", + __func__, dev_path); + continue; + } + + if (!droid_probe_device(disp, fd, devices[i], vendor_name)) + goto next; + + break; + +next: + if (fallback_fd == -1) { + fallback_fd = fd; + fd = -1; + } else { + close(fd); + fd = -1; + } + continue; + } + + if (fallback_fd < 0 && fd < 0) { + _eglLog(_EGL_WARNING, "Failed to open any DRM device"); + return -1; + } + + if (fd < 0) { + _eglLog(_EGL_WARNING, "Failed to open desired DRM device, using fallback"); + return fallback_fd; + } + + close(fallback_fd); + return fd; +} + EGLBoolean dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp) { @@ -1242,42 +1363,17 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp) disp->DriverData = (void *) dri2_dpy; - dri2_dpy->fd = droid_open_device(dri2_dpy); + dri2_dpy->fd = droid_open_device(disp); if (dri2_dpy->fd < 0) { err = "DRI2: failed to open device"; goto cleanup; } - dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); - if (dri2_dpy->driver_name == NULL) { - err = "DRI2: failed to get driver name"; + if (!droid_load_driver(disp)) { + err = "DRI2: failed to load driver"; goto cleanup; } - dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; - - if (!dri2_dpy->is_render_node) { - #ifdef HAVE_DRM_GRALLOC - /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names - * for backwards compatibility with drm_gralloc. (Do not use on new - * systems.) */ - dri2_dpy->loader_extensions = droid_dri2_loader_extensions; - if (!dri2_load_driver(disp)) { - err = "DRI2: failed to load driver"; - goto cleanup; - } - #else - err = "DRI2: handle is not for a render node"; - goto cleanup; - #endif - } else { - dri2_dpy->loader_extensions = droid_image_loader_extensions; - if (!dri2_load_driver_dri3(disp)) { - err = "DRI3: failed to load driver"; - goto cleanup; - } - } - if (!dri2_create_screen(disp)) { err = "DRI2: failed to create screen"; goto cleanup; -- 2.17.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev