vulkan/wsi: prefer the Wayland linux-dmabuf protocol

When the linux-dmabuf protocol is available, prefer it over the old
wl_drm protocol. Previously wl_drm was used when modifiers aren't
supported, however linux-dmabuf supports formats without modifiers too.
In this case, linux-dmabuf will send a DRM_FORMAT_MOD_INVALID modifier
for each supported format [1].

All of this allows compositors to better handle these buffers, getting a
DMA-BUF and implementing features like direct scan-out.

A similar logic has been implemented for EGL [2].

In this patch, we bind to linux-dmabuf even if the driver doesn't support
modifiers. In this case the formats advertised by the compositor will
still be added to the display->dmabuf.formats list.

In wsi_wl_image_init, drop the assertions that display->drm_wrapper and
display->dmabuf.wl_dmabuf can't be both present. If the driver doesn't
support modifiers, the modifier is already set to DRM_FORMAT_MOD_INVALID.
If the parent compositor doesn't support modifiers, the modifiers list
passed to wsi_create_native_image will be empty, and the common code
will ensure that the image's modifier is set to DRM_FORMAT_MOD_INVALID.

In wsi_wl_surface_create_swapchain, create the wl_proxy proxy if we've
bound to it earlier. Don't decide to create the proxy depending on the
number of supported modifiers.

[1]: fb9b2a8731
[2]: c376865f5e

Signed-off-by: Simon Ser <contact@emersion.fr>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4942>
This commit is contained in:
Simon Ser 2020-05-28 19:59:35 +02:00 committed by Marge Bot
parent 14f0c0d9db
commit fc667fdf3b

View file

@ -310,10 +310,6 @@ dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
if (display->dmabuf.formats.element_size == 0)
return;
if (modifier_hi == (DRM_FORMAT_MOD_INVALID >> 32) &&
modifier_lo == (DRM_FORMAT_MOD_INVALID & 0xffffffff))
return;
switch (format) {
case WL_DRM_FORMAT_ARGB8888:
modifiers = &display->dmabuf.modifiers.argb8888;
@ -327,6 +323,10 @@ dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
wsi_wl_display_add_wl_format(display, &display->dmabuf.formats, format);
if (modifier_hi == (DRM_FORMAT_MOD_INVALID >> 32) &&
modifier_lo == (DRM_FORMAT_MOD_INVALID & 0xffffffff))
return;
mod = u_vector_add(modifiers);
if (!mod)
return;
@ -353,8 +353,7 @@ registry_handle_global(void *data, struct wl_registry *registry,
display->drm.wl_drm =
wl_registry_bind(registry, name, &wl_drm_interface, 2);
wl_drm_add_listener(display->drm.wl_drm, &drm_listener, display);
} else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3 &&
display->wsi_wl->wsi->supports_modifiers) {
} else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) {
display->dmabuf.wl_dmabuf =
wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, 3);
zwp_linux_dmabuf_v1_add_listener(display->dmabuf.wl_dmabuf,
@ -461,12 +460,13 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
}
}
/* We need prime support for wl_drm */
if (display->drm.wl_drm &&
(display->drm.capabilities & WL_DRM_CAPABILITY_PRIME)) {
display->formats = &display->drm.formats;
} else if (display->dmabuf.wl_dmabuf) {
/* Prefer the linux-dmabuf protocol if available */
if (display->dmabuf.wl_dmabuf) {
display->formats = &display->dmabuf.formats;
} else if (display->drm.wl_drm &&
(display->drm.capabilities & WL_DRM_CAPABILITY_PRIME)) {
/* We need prime support for wl_drm */
display->formats = &display->drm.formats;
}
if (!display->formats) {
@ -760,9 +760,6 @@ struct wsi_wl_swapchain {
struct wl_surface * surface;
/* non-NULL when wl_drm should be used for wl_buffer creation; otherwise,
* zwp_linux_dmabuf_v1 should be used.
*/
struct wl_drm * drm_wrapper;
struct wl_callback * frame;
@ -956,11 +953,7 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
if (result != VK_SUCCESS)
return result;
if (!chain->drm_wrapper) {
/* Only request modifiers if we have dmabuf, else it must be implicit. */
assert(display->dmabuf.wl_dmabuf);
assert(image->base.drm_modifier != DRM_FORMAT_MOD_INVALID);
if (display->dmabuf.wl_dmabuf) {
struct zwp_linux_buffer_params_v1 *params =
zwp_linux_dmabuf_v1_create_params(display->dmabuf.wl_dmabuf);
wl_proxy_set_queue((struct wl_proxy *) params, chain->display->queue);
@ -1144,13 +1137,7 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
}
}
/* When there are explicit DRM format modifiers, we must use
* zwp_linux_dmabuf_v1 for wl_buffer creation. Otherwise, we must use
* wl_drm.
*/
if (!chain->num_drm_modifiers) {
assert(chain->display->drm.wl_drm);
if (chain->display->drm.wl_drm) {
chain->drm_wrapper =
wl_proxy_create_wrapper(chain->display->drm.wl_drm);
if (!chain->drm_wrapper) {