diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c index 5f8a68fd8..a211e0915 100644 --- a/hw/xwayland/xwayland-glamor-gbm.c +++ b/hw/xwayland/xwayland-glamor-gbm.c @@ -124,6 +124,22 @@ is_fd_render_node(int fd) return 0; } +static char +is_device_path_render_node (const char *device_path) +{ + char is_render_node; + int fd; + + fd = open(device_path, O_RDWR | O_CLOEXEC); + if (fd < 0) + return 0; + + is_render_node = is_fd_render_node(fd); + close(fd); + + return is_render_node; +} + static PixmapPtr xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth) @@ -611,14 +627,80 @@ static const dri3_screen_info_rec xwl_dri3_info = { .get_drawable_modifiers = glamor_get_drawable_modifiers, }; +static const char * +get_render_node_path_for_device(const drmDevicePtr drm_device, + const char *device_path) +{ + char *render_node_path = NULL; + char device_found = 0; + int i; + + for (i = 0; i < DRM_NODE_MAX; i++) { + if ((drm_device->available_nodes & (1 << i)) == 0) + continue; + + if (!strcmp (device_path, drm_device->nodes[i])) + device_found = 1; + + if (is_device_path_render_node(drm_device->nodes[i])) + render_node_path = drm_device->nodes[i]; + + if (device_found && render_node_path) + return render_node_path; + } + + return NULL; +} + +static char * +get_render_node_path(const char *device_path) +{ + drmDevicePtr *devices = NULL; + char *render_node_path = NULL; + int i, n_devices, max_devices; + + max_devices = drmGetDevices2(0, NULL, 0); + if (max_devices <= 0) + goto out; + + devices = calloc(max_devices, sizeof(drmDevicePtr)); + if (!devices) + goto out; + + n_devices = drmGetDevices2(0, devices, max_devices); + if (n_devices < 0) + goto out; + + for (i = 0; i < n_devices; i++) { + const char *node_path = get_render_node_path_for_device(devices[i], + device_path); + if (node_path) { + render_node_path = strdup(node_path); + break; + } + } + +out: + free(devices); + return render_node_path; +} + static void xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device) { struct xwl_screen *xwl_screen = data; struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); drm_magic_t magic; + char *render_node_path = NULL; + + if (!is_device_path_render_node(device)) + render_node_path = get_render_node_path(device); + + if (render_node_path) + xwl_gbm->device_name = render_node_path; + else + xwl_gbm->device_name = strdup(device); - xwl_gbm->device_name = strdup(device); if (!xwl_gbm->device_name) { xwl_glamor_gbm_cleanup(xwl_screen); return;