[PATCH 2/7] dmabuf: implement linux_dmabuf extension
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Fri Dec 12 13:51:03 PST 2014
From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at 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
More information about the wayland-devel
mailing list