linux-dmabuf: Add support for protocol version 5

It adds the followig paragraph:
```
Starting from version 5, the invalid_format protocol error is sent if
all planes don't use the same modifier.
```

We already assumed this in some places and, most importantly, it's
required by the kernel. Thus alter `dmabuf_attributes.modifier` to make
it clear that different modifiers for multi-planar dmabufs were never
supported.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
This commit is contained in:
Robert Mader 2023-12-11 14:27:12 +01:00
parent be201fc204
commit e37454a262
6 changed files with 37 additions and 35 deletions

View File

@ -384,7 +384,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
.height = dmabuf->attributes.height,
.format = dmabuf->attributes.format,
.num_fds = dmabuf->attributes.n_planes,
.modifier = dmabuf->attributes.modifier[0],
.modifier = dmabuf->attributes.modifier,
};
/* We should not import to KMS a buffer that has been allocated using no
@ -394,7 +394,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
* KMS driver can't know. So giving the buffer to KMS is not safe, as
* not knowing its layout can result in garbage being displayed. In
* short, importing a buffer to KMS requires explicit modifiers. */
if (dmabuf->attributes.modifier[0] == DRM_FORMAT_MOD_INVALID) {
if (dmabuf->attributes.modifier == DRM_FORMAT_MOD_INVALID) {
if (try_view_on_plane_failure_reasons)
*try_view_on_plane_failure_reasons |=
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
@ -436,7 +436,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
fb->width = dmabuf->attributes.width;
fb->height = dmabuf->attributes.height;
fb->modifier = dmabuf->attributes.modifier[0];
fb->modifier = dmabuf->attributes.modifier;
fb->size = 0;
fb->fd = device->drm.fd;

View File

@ -2634,7 +2634,7 @@ weston_buffer_from_resource(struct weston_compositor *ec,
/* dmabuf import should assure we don't create a buffer with an
* unknown format */
assert(buffer->pixel_format && !buffer->pixel_format->hide_from_clients);
buffer->format_modifier = dmabuf->attributes.modifier[0];
buffer->format_modifier = dmabuf->attributes.modifier;
if (dmabuf->attributes.flags & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
buffer->buffer_origin = ORIGIN_BOTTOM_LEFT;
else

View File

@ -85,6 +85,7 @@ params_add(struct wl_client *client,
uint32_t modifier_lo)
{
struct linux_dmabuf_buffer *buffer;
uint64_t modifier;
buffer = wl_resource_get_user_data(params_resource);
if (!buffer) {
@ -115,15 +116,24 @@ params_add(struct wl_client *client,
return;
}
if (wl_resource_get_version(params_resource) < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
modifier = DRM_FORMAT_MOD_INVALID;
else
modifier = u64_from_u32s(modifier_hi, modifier_lo);
if (plane_idx > 0 && buffer->attributes.modifier != modifier) {
wl_resource_post_error(params_resource,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT,
"modifier mismatch between planes");
close(name_fd);
return;
}
buffer->attributes.modifier = modifier;
buffer->attributes.fd[plane_idx] = name_fd;
buffer->attributes.offset[plane_idx] = offset;
buffer->attributes.stride[plane_idx] = stride;
if (wl_resource_get_version(params_resource) < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
buffer->attributes.modifier[plane_idx] = DRM_FORMAT_MOD_INVALID;
else
buffer->attributes.modifier[plane_idx] = u64_from_u32s(modifier_hi, modifier_lo);
buffer->attributes.n_planes++;
}
@ -1088,8 +1098,8 @@ linux_dmabuf_setup(struct weston_compositor *compositor)
/* If we were able to create the default dma-buf feedback for the
* compositor, that means that we are able to advertise dma-buf feedback
* events. In such case we support the version 4 of the protocol. */
max_version = compositor->default_dmabuf_feedback ? 4 : 3;
* events. In such case we support the version >=4 of the protocol. */
max_version = compositor->default_dmabuf_feedback ? 5 : 3;
if (!wl_global_create(compositor->wl_display,
&zwp_linux_dmabuf_v1_interface,

View File

@ -43,7 +43,7 @@ struct dmabuf_attributes {
int fd[MAX_DMABUF_PLANES];
uint32_t offset[MAX_DMABUF_PLANES];
uint32_t stride[MAX_DMABUF_PLANES];
uint64_t modifier[MAX_DMABUF_PLANES];
uint64_t modifier;
};
struct linux_dmabuf_buffer {

View File

@ -2594,7 +2594,7 @@ import_simple_dmabuf(struct gl_renderer *gr,
attribs[atti++] = EGL_IMAGE_PRESERVED_KHR;
attribs[atti++] = EGL_TRUE;
if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) {
if (attributes->modifier != DRM_FORMAT_MOD_INVALID) {
if (!gr->has_dmabuf_import_modifiers)
return NULL;
has_modifier = true;
@ -2611,9 +2611,9 @@ import_simple_dmabuf(struct gl_renderer *gr,
attribs[atti++] = attributes->stride[0];
if (has_modifier) {
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attribs[atti++] = attributes->modifier[0] & 0xFFFFFFFF;
attribs[atti++] = attributes->modifier & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attribs[atti++] = attributes->modifier[0] >> 32;
attribs[atti++] = attributes->modifier >> 32;
}
}
@ -2626,9 +2626,9 @@ import_simple_dmabuf(struct gl_renderer *gr,
attribs[atti++] = attributes->stride[1];
if (has_modifier) {
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
attribs[atti++] = attributes->modifier[1] & 0xFFFFFFFF;
attribs[atti++] = attributes->modifier & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
attribs[atti++] = attributes->modifier[1] >> 32;
attribs[atti++] = attributes->modifier >> 32;
}
}
@ -2641,9 +2641,9 @@ import_simple_dmabuf(struct gl_renderer *gr,
attribs[atti++] = attributes->stride[2];
if (has_modifier) {
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
attribs[atti++] = attributes->modifier[2] & 0xFFFFFFFF;
attribs[atti++] = attributes->modifier & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
attribs[atti++] = attributes->modifier[2] >> 32;
attribs[atti++] = attributes->modifier >> 32;
}
}
@ -2656,9 +2656,9 @@ import_simple_dmabuf(struct gl_renderer *gr,
attribs[atti++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
attribs[atti++] = attributes->stride[3];
attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
attribs[atti++] = attributes->modifier[3] & 0xFFFFFFFF;
attribs[atti++] = attributes->modifier & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
attribs[atti++] = attributes->modifier[3] >> 32;
attribs[atti++] = attributes->modifier >> 32;
}
}
@ -2688,7 +2688,7 @@ import_dmabuf_single_plane(struct gl_renderer *gr,
plane.fd[0] = attributes->fd[descriptor->plane_index];
plane.offset[0] = attributes->offset[descriptor->plane_index];
plane.stride[0] = attributes->stride[descriptor->plane_index];
plane.modifier[0] = attributes->modifier[descriptor->plane_index];
plane.modifier = attributes->modifier;
image = import_simple_dmabuf(gr, &plane);
if (image == EGL_NO_IMAGE_KHR) {
@ -2822,7 +2822,7 @@ choose_texture_target(struct gl_renderer *gr,
int i;
for (i = 0; i < format->num_modifiers; ++i) {
if (format->modifiers[i] == attributes->modifier[0]) {
if (format->modifiers[i] == attributes->modifier) {
if (format->external_only[i])
return GL_TEXTURE_EXTERNAL_OES;
else
@ -2997,22 +2997,14 @@ gl_renderer_import_dmabuf(struct weston_compositor *ec,
{
struct gl_renderer *gr = get_renderer(ec);
struct gl_buffer_state *gb;
int i;
assert(gr->has_dmabuf_import);
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
/* return if EGL doesn't support import modifiers */
if (dmabuf->attributes.modifier[i] != DRM_FORMAT_MOD_INVALID)
if (dmabuf->attributes.modifier != DRM_FORMAT_MOD_INVALID)
if (!gr->has_dmabuf_import_modifiers)
return false;
/* return if modifiers passed are unequal */
if (dmabuf->attributes.modifier[i] !=
dmabuf->attributes.modifier[0])
return false;
}
/* reject all flags we do not recognize or handle */
if (dmabuf->attributes.flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
return false;

View File

@ -1,7 +1,7 @@
dep_scanner = dependency('wayland-scanner', native: true)
prog_scanner = find_program(dep_scanner.get_variable(pkgconfig: 'wayland_scanner'))
dep_wp = dependency('wayland-protocols', version: '>= 1.31',
dep_wp = dependency('wayland-protocols', version: '>= 1.33',
fallback: ['wayland-protocols', 'wayland_protocols'])
dir_wp_base = dep_wp.get_variable(pkgconfig: 'pkgdatadir', internal: 'pkgdatadir')