From a7b866617a8f9810dc2d68310c57a3f4884832c1 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 23 Jul 2025 17:16:07 +0200 Subject: [PATCH] wsi/display: Fix vkGetRandROutputDisplayEXT when connector is not leased yet. Monado calls vkGetRandROutputDisplayEXT, which calls wsi_display_get_output, which then calls wsi_display_alloc_connector with fd = wsi->fd, which at this point is still -1 as the display is not leased yet. Signed-off-by: Torge Matthies Part-of: --- src/vulkan/wsi/wsi_common_display.c | 42 +++++++++++++++-------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c index d20cd19a0d9..d505cf785c1 100644 --- a/src/vulkan/wsi/wsi_common_display.c +++ b/src/vulkan/wsi/wsi_common_display.c @@ -414,6 +414,12 @@ find_object_properties(struct wsi_display_connector *connector, int fd, uint32_t return ret; } +static bool +find_connector_properties(struct wsi_display_connector *connector, drmModeConnectorPtr drm_connector, int fd) +{ + return find_properties(connector, drm_connector->count_props, drm_connector->props, drm_connector->prop_values, fd, DRM_MODE_OBJECT_CONNECTOR); +} + #define wsi_for_each_display_mode(_mode, _conn) \ list_for_each_entry_safe(struct wsi_display_mode, _mode, \ &(_conn)->display_modes, list) @@ -611,7 +617,6 @@ wsi_display_is_crtc_available(const struct wsi_display * const wsi, static struct wsi_display_connector * wsi_display_alloc_connector(struct wsi_display *wsi, - int fd, uint32_t connector_id) { struct wsi_display_connector *connector = @@ -620,14 +625,6 @@ wsi_display_alloc_connector(struct wsi_display *wsi, if (!connector) return NULL; - /* We set this flag because this is the common entrypoint before we start - * using atomic capabilities -- it's a simple bool setting in the kernel to - * make the properties we start querying be available, and re-setting it is - * harmless. Otherwise, we'd need to push it up to all the entrypoints that - * a drm FD comes thorugh. - */ - drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1); - connector->id = connector_id; connector->wsi = wsi; connector->active = false; @@ -635,15 +632,6 @@ wsi_display_alloc_connector(struct wsi_display *wsi, connector->name = "monitor"; list_inithead(&connector->display_modes); - /* note: drmModeConnector has props pointer, the extra - * drmModeObjectGetProperties here could be avoided - */ - if (!find_object_properties(connector, fd, DRM_MODE_OBJECT_CONNECTOR)) { - mesa_logd("Failed to find properties for connector"); - vk_free(wsi->alloc, connector); - return NULL; - } - return connector; } @@ -658,6 +646,14 @@ wsi_display_get_connector(struct wsi_device *wsi_device, if (drm_fd < 0) return NULL; + /* We set this flag because this is the common entrypoint before we start + * using atomic capabilities -- it's a simple bool setting in the kernel to + * make the properties we start querying be available, and re-setting it is + * harmless. Otherwise, we'd need to push it up to all the entrypoints that + * a drm FD comes thorugh. + */ + drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1); + drmModeConnectorPtr drm_connector = drmModeGetConnector(drm_fd, connector_id); @@ -668,7 +664,7 @@ wsi_display_get_connector(struct wsi_device *wsi_device, wsi_display_find_connector(wsi_device, connector_id); if (!connector) { - connector = wsi_display_alloc_connector(wsi, drm_fd, connector_id); + connector = wsi_display_alloc_connector(wsi, connector_id); if (!connector) { drmModeFreeConnector(drm_connector); return NULL; @@ -676,6 +672,12 @@ wsi_display_get_connector(struct wsi_device *wsi_device, list_addtail(&connector->list, &wsi->connectors); } + if (!find_connector_properties(connector, drm_connector, drm_fd)) { + mesa_logd("Failed to find properties for connector"); + drmModeFreeConnector(drm_connector); + return NULL; + } + connector->connected = drm_connector->connection != DRM_MODE_DISCONNECTED; /* Mark all connector modes as invalid */ @@ -3604,7 +3606,7 @@ wsi_display_get_output(struct wsi_device *wsi_device, connector = wsi_display_find_connector(wsi_device, connector_id); if (connector == NULL) { - connector = wsi_display_alloc_connector(wsi, wsi->fd, connector_id); + connector = wsi_display_alloc_connector(wsi, connector_id); if (!connector) { return NULL; }