From: Pekka Paalanen <pekka.paala...@collabora.co.uk> Signed-off-by: Pekka Paalanen <pekka.paala...@collabora.co.uk> Signed-off-by: Louis-Francis Ratté-Boulianne <l...@collabora.com> --- Makefile.am | 2 + src/linux-dmabuf.c | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/linux-dmabuf.h | 45 ++++++++ 3 files changed, 369 insertions(+) create mode 100644 src/linux-dmabuf.c create mode 100644 src/linux-dmabuf.h
diff --git a/Makefile.am b/Makefile.am index 0462fdd..16f5d13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,6 +72,8 @@ weston_SOURCES = \ src/timeline.c \ src/timeline.h \ src/timeline-object.h \ + src/linux-dmabuf.c \ + src/linux-dmabuf.h \ shared/matrix.c \ shared/matrix.h \ shared/zalloc.h \ diff --git a/src/linux-dmabuf.c b/src/linux-dmabuf.c new file mode 100644 index 0000000..769bf60 --- /dev/null +++ b/src/linux-dmabuf.c @@ -0,0 +1,322 @@ +/* + * Copyright © 2014 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include <unistd.h> + +#include "compositor.h" +#include "linux-dmabuf.h" +#include "linux-dmabuf-server-protocol.h" + +struct dmabuf_item { + int fd; + int n_planes; + int32_t offset[3]; + int32_t stride[3]; +}; + +struct dmabuf_batch { + struct wl_resource *resource; + int n_bufs; + struct wl_array bufs; /* struct dmabuf_item */ +}; + +static void +destroy_dmabuf_batch(struct wl_resource *dmabuf_batch_resource) +{ + struct dmabuf_batch *batch; + struct dmabuf_item *buf; + + batch = wl_resource_get_user_data(dmabuf_batch_resource); + + wl_array_for_each(buf, &batch->bufs) + close(buf->fd); + wl_array_release(&batch->bufs); + + free(batch); +} + +static void +dmabuf_batch_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +dmabuf_batch_add(struct wl_client *client, + struct wl_resource *resource, + int32_t name, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride2) +{ + struct dmabuf_batch *batch = wl_resource_get_user_data(resource); + struct dmabuf_item *buf; + + buf = wl_array_add(&batch->bufs, sizeof *buf); + if (!buf) { + wl_client_post_no_memory(client); + return; + } + + buf->fd = name; + buf->n_planes = 1; + buf->offset[0] = offset0; + buf->stride[0] = stride0; + + if (offset1 && stride1) { + buf->offset[buf->n_planes] = offset1; + buf->stride[buf->n_planes] = stride1; + buf->n_planes++; + } + + if (offset2 && stride2) { + buf->offset[buf->n_planes] = offset2; + buf->stride[buf->n_planes] = stride2; + buf->n_planes++; + } +} + +static const struct dmabuf_batch_interface dmabuf_batch_implementation = { + dmabuf_batch_destroy, + dmabuf_batch_add +}; + +static void +linux_dmabuf_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +linux_dmabuf_create_batch(struct wl_client *client, + struct wl_resource *linux_dmabuf_resource, + uint32_t batch_id) +{ + struct dmabuf_batch *batch; + uint32_t version = wl_resource_get_version(linux_dmabuf_resource); + + batch = zalloc(sizeof *batch); + if (!batch) + goto err_out; + + batch->resource = wl_resource_create(client, &dmabuf_batch_interface, + version, batch_id); + if (!batch->resource) + goto err_dealloc; + + wl_resource_set_implementation(batch->resource, + &dmabuf_batch_implementation, + batch, destroy_dmabuf_batch); + + batch->n_bufs = 0; + wl_array_init(&batch->bufs); + + return; + +err_dealloc: + free(batch); + +err_out: + wl_resource_post_no_memory(linux_dmabuf_resource); +} + +static void +linux_dmabuf_buffer_close(struct linux_dmabuf_buffer *buffer) +{ + int i; + int last = -1; + + for (i = MAX_DMABUF_PLANES - 1; i >= 0; i--) { + if (last != buffer->dmabuf_fd[i]) { + last = buffer->dmabuf_fd[i]; + close(last); + } + buffer->dmabuf_fd[i] = -1; + } +} + +static void +destroy_linux_dmabuf_buffer(struct wl_resource *resource) +{ + struct linux_dmabuf_buffer *buffer; + + buffer = wl_resource_get_user_data(resource); + linux_dmabuf_buffer_close(buffer); + free(buffer); +} + +static void +linux_dmabuf_buffer_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct wl_buffer_interface linux_dmabuf_buffer_implementation = { + linux_dmabuf_buffer_destroy +}; + +static int +is_linux_dmabuf_supported(struct wl_resource *linux_dmabuf_resource, + struct linux_dmabuf_buffer *buffer) +{ + /* XXX: todo */ + /* XXX: verify from the renderer, that this is ok */ + return 1; +} + +static void +linux_dmabuf_create_buffer(struct wl_client *client, + struct wl_resource *linux_dmabuf_resource, + struct wl_resource *batch_resource, + int32_t width, + int32_t height, + uint32_t format, + uint32_t feedback_id) +{ + struct dmabuf_batch *batch = wl_resource_get_user_data(batch_resource); + struct linux_dmabuf_buffer *buffer; + struct wl_resource *feedback; + struct dmabuf_item *it; + int plane; + + buffer = zalloc(sizeof *buffer); + if (!buffer) { + wl_resource_post_no_memory(linux_dmabuf_resource); + return; + } + + buffer->width = width; + buffer->height = height; + buffer->format = format; + feedback = wl_resource_create(client, + &zlinux_dmabuf_create_feedback_interface, + 1, feedback_id); + + plane = 0; + wl_array_for_each(it, &batch->bufs) { + int i; + + for (i = 0; i < it->n_planes; i++) { + if (plane < MAX_DMABUF_PLANES) { + buffer->dmabuf_fd[plane] = it->fd; + buffer->offset[plane] = it->offset[i]; + buffer->stride[plane] = it->stride[i]; + } + plane++; + } + + it->fd = -1; + } + buffer->n_planes = plane; + + for (; plane < MAX_DMABUF_PLANES; plane++) + buffer->dmabuf_fd[plane] = -1; + + if (buffer->n_planes >= MAX_DMABUF_PLANES) { + wl_resource_post_error(linux_dmabuf_resource, + ZLINUX_DMABUF_ERROR_FORMAT_DMABUFS_MISMATCH, + "too many dmabuf planes in total"); + goto err_close; + } + + if (!is_linux_dmabuf_supported(linux_dmabuf_resource, buffer)) + goto err_close; + + buffer->resource = wl_resource_create(client, &wl_buffer_interface, + 1, 0); + if (!buffer->resource) { + wl_resource_post_no_memory(linux_dmabuf_resource); + goto err_close; + } + + wl_resource_set_implementation(buffer->resource, + &linux_dmabuf_buffer_implementation, + buffer, destroy_linux_dmabuf_buffer); + + zlinux_dmabuf_create_feedback_send_create_successful(feedback, + buffer->resource); + wl_resource_destroy(feedback); + return; + +err_close: + zlinux_dmabuf_create_feedback_send_create_failed(feedback); + wl_resource_destroy(feedback); + linux_dmabuf_buffer_close(buffer); + free(buffer); +} + +WL_EXPORT struct linux_dmabuf_buffer * +linux_dmabuf_buffer_get(struct wl_resource *resource) +{ + if (!resource) + return NULL; + + if (wl_resource_instance_of(resource, &wl_buffer_interface, + &linux_dmabuf_buffer_implementation)) + return wl_resource_get_user_data(resource); + return NULL; +} + +static const struct zlinux_dmabuf_interface linux_dmabuf_implementation = { + linux_dmabuf_destroy, + linux_dmabuf_create_batch, + linux_dmabuf_create_buffer +}; + +static void +bind_linux_dmabuf(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct weston_compositor *compositor = data; + struct wl_resource *resource; + + resource = wl_resource_create(client, &zlinux_dmabuf_interface, + MIN(version, 1), id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return; + } + + 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 */ +} + +WL_EXPORT int +linux_dmabuf_setup(struct weston_compositor *compositor) +{ + if (!wl_global_create(compositor->wl_display, + &zlinux_dmabuf_interface, 1, + compositor, bind_linux_dmabuf)) + return -1; + + return 0; +} diff --git a/src/linux-dmabuf.h b/src/linux-dmabuf.h new file mode 100644 index 0000000..bc9cf63 --- /dev/null +++ b/src/linux-dmabuf.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2014 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WESTON_LINUX_DMABUF_H +#define WESTON_LINUX_DMABUF_H + +#define MAX_DMABUF_PLANES 3 + +struct linux_dmabuf_buffer { + struct wl_resource *resource; + int32_t width; + int32_t height; + uint32_t format; + int n_planes; + int dmabuf_fd[MAX_DMABUF_PLANES]; + int offset[MAX_DMABUF_PLANES]; + int stride[MAX_DMABUF_PLANES]; +}; + +int +linux_dmabuf_setup(struct weston_compositor *compositor); + +struct linux_dmabuf_buffer * +linux_dmabuf_buffer_get(struct wl_resource *resource); + +#endif /* WESTON_LINUX_DMABUF_H */ -- 2.1.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel