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

Reply via email to