[Mesa-dev] [PATCH v1 2/2] egl/android: Add DRM node probing and filtering
Robert Foss
robert.foss at collabora.com
Fri Apr 27 11:57:31 UTC 2018
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.foss at collabora.com>
---
Changes since RFC:
- Instead of removing code, #ifdef it out.
src/egl/drivers/dri2/platform_android.c | 193 ++++++++++++++++++++++----------
1 file changed, 135 insertions(+), 58 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index ab1337f750..c1690f996e 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>
@@ -1128,31 +1129,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,
@@ -1213,6 +1189,137 @@ 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
+ dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
+ if (!dri2_load_driver(disp)) {
+ err = "DRI2: failed to load driver";
+ goto error;
+ }
+ } else {
+ /* render nodes cannot use Gem names, and thus do not support
+ * the __DRI_DRI2_LOADER extension */
+ dri2_dpy->loader_extensions = droid_image_loader_extensions;
+ if (!dri2_load_driver_dri3(disp)) {
+ err = "DRI3: failed to load driver";
+ goto error;
+ }
+#else
+ err = "DRI2: handle is not for a render node";
+ goto error;
+ }
+
+ dri2_dpy->loader_extensions = droid_image_loader_extensions;
+ if (!dri2_load_driver_dri3(disp)) {
+ err = "DRI3: failed to load driver";
+ goto error;
+#endif
+ }
+
+ 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(int fd, void *data)
+{
+ _EGLDisplay *disp = data;
+ 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 failed
+ 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_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);
+
+ drm_match_t filters[] = {
+ {DRM_MATCH_DRIVER_NAME, .str = vendor_name },
+ {DRM_MATCH_FUNCTION, .func = { .fp = droid_probe_driver,
+ .data = disp }},
+ };
+ const int nbr_filters = sizeof(filters)/sizeof(drm_match_t);
+
+ drmDevicePtr devices[MAX_DRM_DEVICES];
+ num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES);
+
+ 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 (drmHandleMatch(fd, filters, nbr_filters))
+ 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)
{
@@ -1240,47 +1347,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
- dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
- if (!dri2_load_driver(disp)) {
- err = "DRI2: failed to load driver";
- goto cleanup;
- }
- } else {
- /* render nodes cannot use Gem names, and thus do not support
- * the __DRI_DRI2_LOADER extension */
- dri2_dpy->loader_extensions = droid_image_loader_extensions;
- if (!dri2_load_driver_dri3(disp)) {
- err = "DRI3: failed to load driver";
- goto cleanup;
- }
-#else
- err = "DRI2: handle is not for a render node";
- goto cleanup;
- }
-
- dri2_dpy->loader_extensions = droid_image_loader_extensions;
- if (!dri2_load_driver_dri3(disp)) {
- err = "DRI3: failed to load driver";
- goto cleanup;
-#endif
- }
-
if (!dri2_create_screen(disp)) {
err = "DRI2: failed to create screen";
goto cleanup;
--
2.14.1
More information about the mesa-dev
mailing list