From 1cdbcb0d943a38c0b2115bf3054ea85ea5595817 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Thu, 10 Aug 2017 11:29:20 -0500 Subject: [PATCH] Resynch with weston's dmabuf implementation Weston's dmabuf implementation continues to be modular enough that we can pull it in with minimal change. This updates us to version 3 of the protocol - required by recent mesa to use dmabuf buffers instead of wl_drm ones. Currently only contains stubs for format query. --- src/bin/e_comp_wl_dmabuf.c | 112 ++++++++++++++++++++++++++++++------- src/bin/e_comp_wl_dmabuf.h | 5 +- src/bin/e_pixmap.c | 17 ++++++ src/bin/e_pixmap.h | 3 + 4 files changed, 117 insertions(+), 20 deletions(-) diff --git a/src/bin/e_comp_wl_dmabuf.c b/src/bin/e_comp_wl_dmabuf.c index 6efba605d..61cb0fe1b 100644 --- a/src/bin/e_comp_wl_dmabuf.c +++ b/src/bin/e_comp_wl_dmabuf.c @@ -51,7 +51,6 @@ linux_dmabuf_buffer_destroy(struct linux_dmabuf_buffer *buffer) } buffer->attributes.n_planes = 0; - free(buffer); } @@ -119,7 +118,7 @@ params_add(struct wl_client *client, buffer->attributes.offset[plane_idx] = offset; buffer->attributes.stride[plane_idx] = stride; buffer->attributes.modifier[plane_idx] = ((uint64_t)modifier_hi << 32) | - modifier_lo; + modifier_lo; buffer->attributes.n_planes++; } @@ -150,12 +149,13 @@ destroy_linux_dmabuf_wl_buffer(struct wl_resource *resource) } static void -params_create(struct wl_client *client, - struct wl_resource *params_resource, - int32_t width, - int32_t height, - uint32_t format, - uint32_t flags) +params_create_common(struct wl_client *client, + struct wl_resource *params_resource, + uint32_t buffer_id, + int32_t width, + int32_t height, + uint32_t format, + uint32_t flags) { struct linux_dmabuf_buffer *buffer; int i; @@ -271,7 +271,7 @@ params_create(struct wl_client *client, buffer->buffer_resource = wl_resource_create(client, &wl_buffer_interface, - 1, 0); + 1, buffer_id); if (!buffer->buffer_resource) { wl_resource_post_no_memory(params_resource); goto err_buffer; @@ -281,7 +281,10 @@ params_create(struct wl_client *client, &linux_dmabuf_buffer_implementation, buffer, destroy_linux_dmabuf_wl_buffer); - zwp_linux_buffer_params_v1_send_created(params_resource, + /* send 'created' event when the request is not for an immediate + * import, ie buffer_id is zero */ + if (buffer_id == 0) + zwp_linux_buffer_params_v1_send_created(params_resource, buffer->buffer_resource); return; @@ -291,17 +294,54 @@ err_buffer: buffer->user_data_destroy_func(buffer); err_failed: - zwp_linux_buffer_params_v1_send_failed(params_resource); + if (buffer_id == 0) + zwp_linux_buffer_params_v1_send_failed(params_resource); + else + /* since the behavior is left implementation defined by the + * protocol in case of create_immed failure due to an unknown cause, + * we choose to treat it as a fatal error and immediately kill the + * client instead of creating an invalid handle and waiting for it + * to be used. + */ + wl_resource_post_error(params_resource, + ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, + "importing the supplied dmabufs failed"); err_out: linux_dmabuf_buffer_destroy(buffer); } +static void +params_create(struct wl_client *client, + struct wl_resource *params_resource, + int32_t width, + int32_t height, + uint32_t format, + uint32_t flags) +{ + params_create_common(client, params_resource, 0, width, height, format, + flags); +} + +static void +params_create_immed(struct wl_client *client, + struct wl_resource *params_resource, + uint32_t buffer_id, + int32_t width, + int32_t height, + uint32_t format, + uint32_t flags) +{ + params_create_common(client, params_resource, buffer_id, width, height, + format, flags); +} + static const struct zwp_linux_buffer_params_v1_interface zwp_linux_buffer_params_implementation = { params_destroy, params_add, - params_create + params_create, + params_create_immed }; static void @@ -315,7 +355,7 @@ linux_dmabuf_create_params(struct wl_client *client, struct wl_resource *linux_dmabuf_resource, uint32_t params_id) { - struct weston_compositor *compositor; + void *compositor; struct linux_dmabuf_buffer *buffer; uint32_t version; int i; @@ -432,8 +472,13 @@ static void bind_linux_dmabuf(struct wl_client *client, void *data, uint32_t version, uint32_t id) { - struct weston_compositor *compositor = data; + void *compositor = data; struct wl_resource *resource; + int *formats = NULL; + uint64_t *modifiers = NULL; + int num_formats, num_modifiers; + uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID; + int i, j; resource = wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id); @@ -445,9 +490,38 @@ bind_linux_dmabuf(struct wl_client *client, wl_resource_set_implementation(resource, &linux_dmabuf_implementation, compositor, NULL); - /* EGL_EXT_image_dma_buf_import does not provide a way to query the - * supported pixel formats. */ - /* XXX: send formats */ + if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) + return; + /* + * Use EGL_EXT_image_dma_buf_import_modifiers to query and advertise + * format/modifier codes. + */ + e_pixmap_dmabuf_formats_query(&formats, + &num_formats); + + for (i = 0; i < num_formats; i++) { + e_pixmap_dmabuf_modifiers_query( + formats[i], + &modifiers, + &num_modifiers); + + /* send DRM_FORMAT_MOD_INVALID token when no modifiers are supported + * for this format */ + if (num_modifiers == 0) { + num_modifiers = 1; + modifiers = &modifier_invalid; + } + for (j = 0; j < num_modifiers; j++) { + uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF; + uint32_t modifier_hi = modifiers[j] >> 32; + zwp_linux_dmabuf_v1_send_modifier(resource, formats[i], + modifier_hi, + modifier_lo); + } + if (modifiers != &modifier_invalid) + free(modifiers); + } + free(formats); } /** Advertise linux_dmabuf support @@ -465,7 +539,7 @@ EINTERN int linux_dmabuf_setup(struct wl_display *display) { if (!wl_global_create(display, - &zwp_linux_dmabuf_v1_interface, 1, + &zwp_linux_dmabuf_v1_interface, 3, NULL, bind_linux_dmabuf)) return -1; @@ -483,7 +557,7 @@ linux_dmabuf_setup(struct wl_display *display) * In any case, the options are to either composite garbage or nothing, * or disconnect the client. This is a helper function for the latter. * - * The error is sent as a INVALID_OBJECT error on the client's wl_display. + * The error is sent as an INVALID_OBJECT error on the client's wl_display. * * \param buffer The linux_dmabuf_buffer that is unusable. * \param msg A custom error message attached to the protocol error. diff --git a/src/bin/e_comp_wl_dmabuf.h b/src/bin/e_comp_wl_dmabuf.h index 1299724e4..945490f38 100644 --- a/src/bin/e_comp_wl_dmabuf.h +++ b/src/bin/e_comp_wl_dmabuf.h @@ -29,6 +29,9 @@ #include #define MAX_DMABUF_PLANES 4 +#ifndef DRM_FORMAT_MOD_INVALID +#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1) +#endif struct linux_dmabuf_buffer; typedef void (*dmabuf_user_data_destroy_func)( @@ -50,7 +53,7 @@ struct dmabuf_attributes { struct linux_dmabuf_buffer { struct wl_resource *buffer_resource; struct wl_resource *params_resource; - struct weston_compositor *compositor; + void *compositor; struct dmabuf_attributes attributes; void *user_data; diff --git a/src/bin/e_pixmap.c b/src/bin/e_pixmap.c index dcb4b0c08..7a43dc27f 100644 --- a/src/bin/e_pixmap.c +++ b/src/bin/e_pixmap.c @@ -1133,4 +1133,21 @@ e_pixmap_dmabuf_test(struct linux_dmabuf_buffer *dmabuf) return EINA_TRUE; } + +E_API Eina_Bool +e_pixmap_dmabuf_formats_query(int **formats EINA_UNUSED, int *num_formats) +{ + *num_formats = 0; + + return EINA_TRUE; +} + +E_API Eina_Bool +e_pixmap_dmabuf_modifiers_query(int format EINA_UNUSED, uint64_t **modifiers EINA_UNUSED, int *num_modifiers) +{ + *num_modifiers = 0; + + return EINA_TRUE; +} + #endif diff --git a/src/bin/e_pixmap.h b/src/bin/e_pixmap.h index ed04078f7..293a6786c 100644 --- a/src/bin/e_pixmap.h +++ b/src/bin/e_pixmap.h @@ -55,6 +55,9 @@ E_API void e_pixmap_alias(E_Pixmap *cp, E_Pixmap_Type type, ...); #ifdef HAVE_WAYLAND E_API Eina_Bool e_pixmap_dmabuf_test(struct linux_dmabuf_buffer *); +E_API Eina_Bool e_pixmap_dmabuf_formats_query(int **formats, int *num_formats); +E_API Eina_Bool e_pixmap_dmabuf_modifiers_query(int format, uint64_t **modifiers, int *num_modifiers); + #endif static inline Eina_Bool