Hi all,

I'm working for Linaro on enabling a zero copy path in GStreamer by
using dmabuf.
To make this possible I have patched gst wayland sink to use wayland
drm protocol: https://bugzilla.gnome.org/show_bug.cgi?id=711155

Today wayland drm protocol is limited to Mesa so I have decided to
move it into wayland-core.
My hardware doesn't have gpu support yet so I have patched weston
(pixman) to allow usage of wl_drm buffers.
With this I able to share/use a buffer allocated by DRM in gstreamer
pipeline even if I don't have gpu and EGL.

What do you think about make wayland drm protocol available like this ?

Please note those patches are for wayland/weston 1.1.0

Regards,
Benjamin

-- 
Benjamin Gaignard

Graphic Working Group

Linaro.org │ Open source software for ARM SoCs

Follow Linaro: Facebook | Twitter | Blog
From b185fe89a1ea8ddbe19d943cb19272f369b7b438 Mon Sep 17 00:00:00 2001
From: Benjamin Gaignard <benjamin.gaign...@linaro.org>
Date: Mon, 25 Nov 2013 11:38:12 +0100
Subject: [PATCH] make weston able to use wl_drm protocol

Make compositor-drm able to provide wl_drm buffer even if EGL isn't used.
Update pixman to allow it to compose wl_drm buffer like it does for wl_shm.

Signed-off-by: Benjamin Gaignard <benjamin.gaign...@linaro.org>
---
 src/compositor-drm.c  |  131 +++++++++++++++++++++++++++++++++++++++++++++++--
 src/pixman-renderer.c |   60 +++++++++++++++-------
 2 files changed, 169 insertions(+), 22 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index da1ba79..b336127 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -45,6 +45,8 @@
 #include "pixman-renderer.h"
 #include "udev-seat.h"
 #include "launcher-util.h"
+#include "wayland-drm.h"
+#include "wayland-drm-server-protocol.h"
 
 static int option_current_mode = 0;
 static char *output_name;
@@ -79,10 +81,12 @@ struct drm_compositor {
 
 	struct udev_monitor *udev_monitor;
 	struct wl_event_source *udev_drm_source;
+	struct wl_drm *wl_server_drm;
 
 	struct {
 		int id;
 		int fd;
+		char *device_name;
 	} drm;
 	struct gbm_device *gbm;
 	uint32_t *crtcs;
@@ -754,7 +758,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
 	if (es->alpha != 1.0f)
 		return NULL;
 
-	if (wl_buffer_is_shm(es->buffer_ref.buffer))
+	if (wl_buffer_is_shm(es->buffer_ref.buffer) || wayland_buffer_is_drm(es->buffer_ref.buffer))
 		return NULL;
 
 	if (!drm_surface_transform_supported(es))
@@ -876,7 +880,7 @@ drm_output_prepare_cursor_surface(struct weston_output *output_base,
 	if (c->cursors_are_broken)
 		return NULL;
 	if (es->buffer_ref.buffer == NULL ||
-	    !wl_buffer_is_shm(es->buffer_ref.buffer) ||
+	    (!wl_buffer_is_shm(es->buffer_ref.buffer) && !wayland_buffer_is_drm(es->buffer_ref.buffer)) ||
 	    es->geometry.width > 64 || es->geometry.height > 64)
 		return NULL;
 
@@ -966,10 +970,10 @@ drm_assign_planes(struct weston_output *output)
 	primary = &c->base.primary_plane;
 	wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
 		/* test whether this buffer can ever go into a plane:
-		 * non-shm, or small enough to be a cursor
+		 * non-shm, non-drm, or small enough to be a cursor
 		 */
 		if ((es->buffer_ref.buffer &&
-		     !wl_buffer_is_shm(es->buffer_ref.buffer)) ||
+		     (!wl_buffer_is_shm(es->buffer_ref.buffer) && !wayland_buffer_is_drm(es->buffer_ref.buffer))) ||
 		    (es->geometry.width <= 64 && es->geometry.height <= 64))
 			es->keep_buffer = 1;
 		else
@@ -1174,8 +1178,120 @@ init_drm(struct drm_compositor *ec, struct udev_device *device)
 	weston_log("using %s\n", filename);
 
 	ec->drm.fd = fd;
+	ec->drm.device_name = strdup(filename);
 
+	return 0;
+}
+
+static int
+drm_display_authenticate(void *user_data, uint32_t magic)
+{
+	struct drm_compositor *ec = user_data;
+	weston_log("authentification\n");
+	return drmAuthMagic(ec->drm.fd, magic);
+}
+
+struct drm_driver_buffer {
+	uint32_t size;
+	uint32_t handle;
+	char *data;
+};
+
+static void
+drm_reference_buffer(void *user_data, uint32_t name, int prime_fd,
+		struct wl_drm_buffer *buffer)
+{
+	struct drm_compositor *ec = user_data;
+	uint32_t handles[4], pitches[4], offsets[4];
+	int ret;
+	uint32_t fd;
+	struct drm_driver_buffer *driver_buffer;
 
+	weston_log("reference buffer fd %d\n", prime_fd);
+	if (prime_fd == -1)
+		return;
+
+	drmPrimeFDToHandle(ec->drm.fd, prime_fd, &handles[0]);
+	pitches[0] = buffer->stride[0];
+	pitches[1] = buffer->stride[1];
+	pitches[2] = buffer->stride[2];
+	offsets[0] = buffer->offset[0];
+	offsets[1] = buffer->offset[1];
+	offsets[2] = buffer->offset[2];
+
+	weston_log("drmModeAddFB2 fd %d\n", prime_fd);
+	ret = drmModeAddFB2 (ec->drm.fd, buffer->buffer.width, buffer->buffer.height,
+		  buffer->format, handles, pitches, offsets, &fd, 0);
+	if (ret) {
+		weston_log("addfb2 failed: %m\n");
+		return;
+	}
+
+	weston_log("addfb2 success\n");
+	driver_buffer = malloc(sizeof *driver_buffer);
+	if (driver_buffer == NULL)
+		return;
+
+	driver_buffer->size = buffer->buffer.width * buffer->buffer.height * 4;
+	driver_buffer->handle = handles[0];
+	driver_buffer->data = NULL;
+	buffer->driver_buffer = driver_buffer;
+	weston_log("drm_reference_buffer success\n");
+}
+
+static void
+drm_unreference_buffer(void *user_data, struct wl_drm_buffer *buffer)
+{
+	struct drm_driver_buffer *driver_buffer = buffer->driver_buffer;
+
+	weston_log("unreference buffer\n");
+
+	if(driver_buffer->data)
+		munmap(driver_buffer->data, driver_buffer->size);
+
+	free(buffer->driver_buffer);
+}
+
+static void*
+drm_get_data(void *user_data, struct wl_drm_buffer *buffer)
+{
+	struct drm_driver_buffer *driver_buffer = buffer->driver_buffer;
+	struct drm_compositor *ec = user_data;
+
+	if (!driver_buffer->data) {
+		int fd;
+		drmPrimeHandleToFD(ec->drm.fd, driver_buffer->handle, 0, &fd);
+		driver_buffer->data = mmap (0, driver_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+		close(fd);
+	}
+	return driver_buffer->data;
+}
+
+static void
+drm_put_data(void *user_data, struct wl_drm_buffer *buffer)
+{
+	struct drm_driver_buffer *driver_buffer = buffer->driver_buffer;
+	struct drm_compositor *ec = user_data;
+
+	if (!driver_buffer->data) {
+		munmap (driver_buffer->data, driver_buffer->size);
+		driver_buffer->data = NULL;
+	}
+}
+
+static struct wayland_drm_callbacks wl_drm_callbacks = {
+	drm_display_authenticate,
+	drm_reference_buffer,
+	drm_unreference_buffer,
+	drm_get_data,
+	drm_put_data
+};
+
+static int
+init_drm_protocol(struct drm_compositor *ec)
+{
+	wayland_drm_init(ec->base.wl_display, ec->drm.device_name,
+		&wl_drm_callbacks, ec, 0);
 	return 0;
 }
 
@@ -1982,6 +2098,9 @@ drm_destroy(struct weston_compositor *ec)
 		weston_log("failed to drop master: %m\n");
 	tty_destroy(d->tty);
 
+	if (d->drm.device_name)
+		free(d->drm.device_name);
+
 	free(d);
 }
 
@@ -2229,6 +2348,10 @@ drm_compositor_create(struct wl_display *display,
 			weston_log("failed to initialize pixman renderer\n");
 			goto err_udev_dev;
 		}
+		if (init_drm_protocol(ec) < 0) {
+			weston_log("failed to initialize wayand drm protocol\n");
+			goto err_udev_dev;
+		}
 	} else {
 		if (init_egl(ec) < 0) {
 			weston_log("failed to initialize egl\n");
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 9dbe9f0..ac671cb 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 
 #include "pixman-renderer.h"
+#include "wayland-drm.h"
 
 #include <linux/input.h>
 
@@ -375,30 +376,53 @@ pixman_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
 	if (!buffer)
 		return;
 
-	if (!wl_buffer_is_shm(buffer)) {
-		weston_log("Pixman renderer supports only SHM buffers\n");
+	if (!wl_buffer_is_shm(buffer) && !wayland_buffer_is_drm(buffer)) {
+		weston_log("Pixman renderer supports only SHM and DRM buffers\n");
 		weston_buffer_reference(&ps->buffer_ref, NULL);
 		return;
 	}
 
-	switch (wl_shm_buffer_get_format(buffer)) {
-	case WL_SHM_FORMAT_XRGB8888:
-		pixman_format = PIXMAN_x8r8g8b8;
-		break;
-	case WL_SHM_FORMAT_ARGB8888:
-		pixman_format = PIXMAN_a8r8g8b8;
-		break;
-	default:
+	if (wl_buffer_is_shm(buffer)) {
+		switch (wl_shm_buffer_get_format(buffer)) {
+		case WL_SHM_FORMAT_XRGB8888:
+			pixman_format = PIXMAN_x8r8g8b8;
+			break;
+		case WL_SHM_FORMAT_ARGB8888:
+			pixman_format = PIXMAN_a8r8g8b8;
+			break;
+		default:
 		weston_log("Unsupported SHM buffer format\n");
-		weston_buffer_reference(&ps->buffer_ref, NULL);
-		return;
-	break;
+			weston_buffer_reference(&ps->buffer_ref, NULL);
+			return;
+		}
+		ps->image = pixman_image_create_bits(pixman_format,
+			wl_shm_buffer_get_width(buffer),
+			wl_shm_buffer_get_height(buffer),
+			wl_shm_buffer_get_data(buffer),
+			wl_shm_buffer_get_stride(buffer));
+	}
+
+	if (wayland_buffer_is_drm(buffer)) {
+		switch (wayland_drm_buffer_get_format(buffer)) {
+		case WL_DRM_FORMAT_XRGB8888:
+			pixman_format = PIXMAN_x8r8g8b8;
+			break;
+		case WL_DRM_FORMAT_ARGB8888:
+			pixman_format = PIXMAN_a8r8g8b8;
+			break;
+		default:
+			weston_log("Unsupported DRM buffer format\n");
+			weston_buffer_reference(&ps->buffer_ref, NULL);
+			return;
+		}
+		ps->image = pixman_image_create_bits(pixman_format,
+			wayland_drm_buffer_get_width(buffer),
+			wayland_drm_buffer_get_height(buffer),
+			wayland_drm_buffer_get_data(buffer),
+			wayland_drm_buffer_get_stride(buffer, 0));
+
+		wayland_drm_buffer_put_data(buffer);
 	}
-	ps->image = pixman_image_create_bits(pixman_format,
-		wl_shm_buffer_get_width(buffer),
-		wl_shm_buffer_get_height(buffer),
-		wl_shm_buffer_get_data(buffer),
-		wl_shm_buffer_get_stride(buffer));
 }
 
 static int
-- 
1.7.9.5

From 6e4615fe2201fa58f2f902063d9dc97c267dbe50 Mon Sep 17 00:00:00 2001
From: Benjamin Gaignard <benjamin.gaign...@linaro.org>
Date: Wed, 27 Nov 2013 09:52:43 +0100
Subject: [PATCH] add wayland-drm protocol

Move wayland-drm protocol from mesa to wayland-core.
Fix some indentations.
Add WL_EXPORT to function declaration.
Add {get/put}_data callback to get access to memory.

Signed-off-by: Benjamin Gaignard <benjamin.gaign...@linaro.org>
---
 protocol/Makefile.am     |    2 +-
 protocol/wayland-drm.xml |  182 ++++++++++++++++++++++++
 src/Makefile.am          |   11 +-
 src/wayland-drm.c        |  348 ++++++++++++++++++++++++++++++++++++++++++++++
 src/wayland-drm.h        |  127 +++++++++++++++++
 5 files changed, 668 insertions(+), 2 deletions(-)
 create mode 100644 protocol/wayland-drm.xml
 create mode 100644 src/wayland-drm.c
 create mode 100644 src/wayland-drm.h

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 08690b3..6aabb1b 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -1 +1 @@
-EXTRA_DIST = wayland.xml
+EXTRA_DIST = wayland.xml wayland-drm.xml
diff --git a/protocol/wayland-drm.xml b/protocol/wayland-drm.xml
new file mode 100644
index 0000000..8a3ad69
--- /dev/null
+++ b/protocol/wayland-drm.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+
+  <copyright>
+    Copyright © 2008-2011 Kristian Høgsberg
+    Copyright © 2010-2011 Intel Corporation
+
+    Permission to use, copy, modify, distribute, and sell this
+    software and its documentation for any purpose is hereby granted
+    without fee, provided that\n 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.
+  </copyright>
+
+  <!-- drm support. This object is created by the server and published
+       using the display's global event. -->
+  <interface name="wl_drm" version="2">
+    <enum name="error">
+      <entry name="authenticate_fail" value="0"/>
+      <entry name="invalid_format" value="1"/>
+      <entry name="invalid_name" value="2"/>
+    </enum>
+
+    <enum name="format">
+      <!-- The drm format codes match the #defines in drm_fourcc.h.
+           The formats actually supported by the compositor will be
+           reported by the format event. -->
+      <entry name="c8" value="0x20203843"/>
+      <entry name="rgb332" value="0x38424752"/>
+      <entry name="bgr233" value="0x38524742"/>
+      <entry name="xrgb4444" value="0x32315258"/>
+      <entry name="xbgr4444" value="0x32314258"/>
+      <entry name="rgbx4444" value="0x32315852"/>
+      <entry name="bgrx4444" value="0x32315842"/>
+      <entry name="argb4444" value="0x32315241"/>
+      <entry name="abgr4444" value="0x32314241"/>
+      <entry name="rgba4444" value="0x32314152"/>
+      <entry name="bgra4444" value="0x32314142"/>
+      <entry name="xrgb1555" value="0x35315258"/>
+      <entry name="xbgr1555" value="0x35314258"/>
+      <entry name="rgbx5551" value="0x35315852"/>
+      <entry name="bgrx5551" value="0x35315842"/>
+      <entry name="argb1555" value="0x35315241"/>
+      <entry name="abgr1555" value="0x35314241"/>
+      <entry name="rgba5551" value="0x35314152"/>
+      <entry name="bgra5551" value="0x35314142"/>
+      <entry name="rgb565" value="0x36314752"/>
+      <entry name="bgr565" value="0x36314742"/>
+      <entry name="rgb888" value="0x34324752"/>
+      <entry name="bgr888" value="0x34324742"/>
+      <entry name="xrgb8888" value="0x34325258"/>
+      <entry name="xbgr8888" value="0x34324258"/>
+      <entry name="rgbx8888" value="0x34325852"/>
+      <entry name="bgrx8888" value="0x34325842"/>
+      <entry name="argb8888" value="0x34325241"/>
+      <entry name="abgr8888" value="0x34324241"/>
+      <entry name="rgba8888" value="0x34324152"/>
+      <entry name="bgra8888" value="0x34324142"/>
+      <entry name="xrgb2101010" value="0x30335258"/>
+      <entry name="xbgr2101010" value="0x30334258"/>
+      <entry name="rgbx1010102" value="0x30335852"/>
+      <entry name="bgrx1010102" value="0x30335842"/>
+      <entry name="argb2101010" value="0x30335241"/>
+      <entry name="abgr2101010" value="0x30334241"/>
+      <entry name="rgba1010102" value="0x30334152"/>
+      <entry name="bgra1010102" value="0x30334142"/>
+      <entry name="yuyv" value="0x56595559"/>
+      <entry name="yvyu" value="0x55595659"/>
+      <entry name="uyvy" value="0x59565955"/>
+      <entry name="vyuy" value="0x59555956"/>
+      <entry name="ayuv" value="0x56555941"/>
+      <entry name="nv12" value="0x3231564e"/>
+      <entry name="nv21" value="0x3132564e"/>
+      <entry name="nv16" value="0x3631564e"/>
+      <entry name="nv61" value="0x3136564e"/>
+      <entry name="yuv410" value="0x39565559"/>
+      <entry name="yvu410" value="0x39555659"/>
+      <entry name="yuv411" value="0x31315559"/>
+      <entry name="yvu411" value="0x31315659"/>
+      <entry name="yuv420" value="0x32315559"/>
+      <entry name="yvu420" value="0x32315659"/>
+      <entry name="yuv422" value="0x36315559"/>
+      <entry name="yvu422" value="0x36315659"/>
+      <entry name="yuv444" value="0x34325559"/>
+      <entry name="yvu444" value="0x34325659"/>
+    </enum>
+
+    <!-- Call this request with the magic received from drmGetMagic().
+         It will be passed on to the drmAuthMagic() or
+         DRIAuthConnection() call.  This authentication must be
+         completed before create_buffer could be used. -->
+    <request name="authenticate">
+      <arg name="id" type="uint"/>
+    </request>
+
+    <!-- Create a wayland buffer for the named DRM buffer.  The DRM
+         surface must have a name using the flink ioctl -->
+    <request name="create_buffer">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="stride" type="uint"/>
+      <arg name="format" type="uint"/>
+    </request>
+
+    <!-- Create a wayland buffer for the named DRM buffer.  The DRM
+         surface must have a name using the flink ioctl -->
+    <request name="create_planar_buffer">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="format" type="uint"/>
+      <arg name="offset0" type="int"/>
+      <arg name="stride0" type="int"/>
+      <arg name="offset1" type="int"/>
+      <arg name="stride1" type="int"/>
+      <arg name="offset2" type="int"/>
+      <arg name="stride2" type="int"/>
+    </request>
+
+    <!-- Create a wayland buffer for the prime fd.  Use for regular and planar
+         buffers.  Pass 0 for offset and stride for unused planes. -->
+    <request name="create_prime_buffer" since="2">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="fd"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="format" type="uint"/>
+      <arg name="offset0" type="int"/>
+      <arg name="stride0" type="int"/>
+      <arg name="offset1" type="int"/>
+      <arg name="stride1" type="int"/>
+      <arg name="offset2" type="int"/>
+      <arg name="stride2" type="int"/>
+    </request>
+
+    <!-- Notification of the path of the drm device which is used by
+         the server.  The client should use this device for creating
+         local buffers.  Only buffers created from this device should
+         be be passed to the server using this drm object's
+         create_buffer request. -->
+    <event name="device">
+      <arg name="name" type="string"/>
+    </event>
+
+    <event name="format">
+      <arg name="format" type="uint"/>
+    </event>
+
+    <!-- Raised if the authenticate request succeeded -->
+    <event name="authenticated"/>
+
+    <enum name="capability" since="2">
+      <description summary="wl_drm capability bitmask">
+        Bitmask of capabilities.
+      </description>
+      <entry name="prime" value="1" summary="wl_drm prime available"/>
+    </enum>
+
+    <event name="capabilities">
+      <arg name="value" type="uint"/>
+    </event>
+  </interface>
+
+</protocol>
diff --git a/src/Makefile.am b/src/Makefile.am
index e1d04ea..679467c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,8 +4,11 @@ noinst_LTLIBRARIES = libwayland-util.la
 include_HEADERS =				\
 	wayland-util.h				\
 	wayland-server-protocol.h		\
+	wayland-drm-server-protocol.h 	\
 	wayland-server.h			\
+	wayland-drm.h 				\
 	wayland-client-protocol.h		\
+	wayland-drm-client-protocol.h 	\
 	wayland-client.h			\
 	wayland-egl.h				\
 	wayland-version.h
@@ -21,8 +24,10 @@ libwayland_util_la_SOURCES =			\
 libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm
 libwayland_server_la_SOURCES =			\
 	wayland-protocol.c			\
+	wayland-drm-protocol.c 		\
 	wayland-server.c			\
 	wayland-shm.c				\
+	wayland-drm.c 				\
 	data-device.c				\
 	event-loop.c
 
@@ -30,6 +35,7 @@ libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm
 libwayland_client_la_LDFLAGS = -version-info 1:0:1
 libwayland_client_la_SOURCES =			\
 	wayland-protocol.c			\
+	wayland-drm-protocol.c  	\
 	wayland-client.c
 
 pkgconfigdir = $(libdir)/pkgconfig
@@ -62,7 +68,10 @@ endif
 BUILT_SOURCES =					\
 	wayland-server-protocol.h		\
 	wayland-client-protocol.h		\
-	wayland-protocol.c
+	wayland-protocol.c \
+	wayland-drm-server-protocol.h 	\
+	wayland-drm-client-protocol.h 	\
+	wayland-drm-protocol.c
 
 CLEANFILES = $(BUILT_SOURCES)
 DISTCLEANFILES = wayland-version.h
diff --git a/src/wayland-drm.c b/src/wayland-drm.c
new file mode 100644
index 0000000..4e70196
--- /dev/null
+++ b/src/wayland-drm.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ * Copyright © 2011 Benjamin Franzke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kristian Høgsberg <k...@bitplanet.net>
+ *    Benjamin Franzke <benjaminfran...@googlemail.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include "wayland-server.h"
+#include "wayland-drm.h"
+#include "wayland-drm-server-protocol.h"
+
+struct wl_drm {
+	struct wl_display *display;
+
+	void *user_data;
+	char *device_name;
+    uint32_t flags;
+
+	struct wayland_drm_callbacks *callbacks;
+};
+
+static void
+destroy_buffer(struct wl_resource *resource)
+{
+	struct wl_drm_buffer *buffer = resource->data;
+	struct wl_drm *drm = buffer->drm;
+
+	drm->callbacks->release_buffer(drm->user_data, buffer);
+	free(buffer);
+}
+
+static void
+buffer_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+const static struct wl_buffer_interface drm_buffer_interface = {
+	buffer_destroy
+};
+
+static void
+create_buffer(struct wl_client *client, struct wl_resource *resource,
+              uint32_t id, uint32_t name, int fd,
+              int32_t width, int32_t height,
+              uint32_t format,
+              int32_t offset0, int32_t stride0,
+              int32_t offset1, int32_t stride1,
+              int32_t offset2, int32_t stride2)
+{
+	struct wl_drm *drm = resource->data;
+	struct wl_drm_buffer *buffer;
+
+	buffer = calloc(1, sizeof *buffer);
+	if (buffer == NULL) {
+		wl_resource_post_no_memory(resource);
+		return;
+	}
+
+	buffer->drm = drm;
+	buffer->buffer.width = width;
+	buffer->buffer.height = height;
+	buffer->format = format;
+	buffer->offset[0] = offset0;
+	buffer->stride[0] = stride0;
+	buffer->offset[1] = offset1;
+	buffer->stride[1] = stride1;
+	buffer->offset[2] = offset2;
+	buffer->stride[2] = stride2;
+
+	drm->callbacks->reference_buffer(drm->user_data, name, fd, buffer);
+	if (buffer->driver_buffer == NULL) {
+		wl_resource_post_error(resource,
+				       WL_DRM_ERROR_INVALID_NAME,
+				       "invalid name");
+		return;
+	}
+
+	buffer->buffer.resource.object.id = id;
+	buffer->buffer.resource.object.interface = &wl_buffer_interface;
+	buffer->buffer.resource.object.implementation =
+		(void (**)(void)) &drm_buffer_interface;
+	buffer->buffer.resource.data = buffer;
+
+	buffer->buffer.resource.destroy = destroy_buffer;
+	buffer->buffer.resource.client = resource->client;
+
+	wl_client_add_resource(resource->client, &buffer->buffer.resource);
+}
+
+static void
+drm_create_buffer(struct wl_client *client, struct wl_resource *resource,
+		  uint32_t id, uint32_t name, int32_t width, int32_t height,
+		  uint32_t stride, uint32_t format)
+{
+	switch (format) {
+		case WL_DRM_FORMAT_ARGB8888:
+		case WL_DRM_FORMAT_XRGB8888:
+        case WL_DRM_FORMAT_YUYV:
+			break;
+        default:
+                wl_resource_post_error(resource,
+                                       WL_DRM_ERROR_INVALID_FORMAT,
+                                       "invalid format");
+			return;
+    }
+
+    create_buffer(client, resource, id,
+		name, -1, width, height, format, 0, stride, 0, 0, 0, 0);
+}
+
+static void
+drm_create_planar_buffer(struct wl_client *client,
+                         struct wl_resource *resource,
+                         uint32_t id, uint32_t name,
+                         int32_t width, int32_t height, uint32_t format,
+                         int32_t offset0, int32_t stride0,
+                         int32_t offset1, int32_t stride1,
+                         int32_t offset2, int32_t stride2)
+{
+    switch (format) {
+		case WL_DRM_FORMAT_YUV410:
+		case WL_DRM_FORMAT_YUV411:
+		case WL_DRM_FORMAT_YUV420:
+		case WL_DRM_FORMAT_YUV422:
+		case WL_DRM_FORMAT_YUV444:
+		case WL_DRM_FORMAT_NV12:
+        case WL_DRM_FORMAT_NV16:
+			break;
+        default:
+                wl_resource_post_error(resource,
+                                       WL_DRM_ERROR_INVALID_FORMAT,
+                                       "invalid format");
+			return;
+    }
+
+	create_buffer(client, resource, id, name, -1, width, height, format,
+		offset0, stride0, offset1, stride1, offset2, stride2);
+}
+
+static void
+drm_create_prime_buffer(struct wl_client *client,
+                        struct wl_resource *resource,
+                        uint32_t id, int fd,
+                        int32_t width, int32_t height, uint32_t format,
+                        int32_t offset0, int32_t stride0,
+                        int32_t offset1, int32_t stride1,
+                        int32_t offset2, int32_t stride2)
+{
+        create_buffer(client, resource, id, 0, fd, width, height, format,
+                      offset0, stride0, offset1, stride1, offset2, stride2);
+        close(fd);
+}
+
+static void
+drm_authenticate(struct wl_client *client,
+		 struct wl_resource *resource, uint32_t id)
+{
+	struct wl_drm *drm = resource->data;
+
+	if (drm->callbacks->authenticate(drm->user_data, id) < 0)
+		wl_resource_post_error(resource,
+				       WL_DRM_ERROR_AUTHENTICATE_FAIL,
+				       "authenicate failed");
+	else
+		wl_resource_post_event(resource, WL_DRM_AUTHENTICATED);
+}
+
+const static struct wl_drm_interface drm_interface = {
+	drm_authenticate,
+	drm_create_buffer,
+    drm_create_planar_buffer,
+    drm_create_prime_buffer
+};
+
+static void
+bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+	struct wl_drm *drm = data;
+	struct wl_resource *resource;
+    uint32_t capabilities;
+
+	resource = wl_client_add_object(client, &wl_drm_interface,
+					&drm_interface, id, data);
+	wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);
+	wl_resource_post_event(resource, WL_DRM_FORMAT,
+			       WL_DRM_FORMAT_ARGB8888);
+	wl_resource_post_event(resource, WL_DRM_FORMAT,
+			       WL_DRM_FORMAT_XRGB8888);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV410);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV411);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV420);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV422);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV444);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16);
+    wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV);
+
+    capabilities = 0;
+    if (drm->flags & WAYLAND_DRM_PRIME)
+		capabilities |= WL_DRM_CAPABILITY_PRIME;
+
+    if (version >= 2)
+        wl_resource_post_event(resource, WL_DRM_CAPABILITIES, capabilities);
+}
+
+WL_EXPORT struct wl_drm *
+wayland_drm_init(struct wl_display *display, char *device_name,
+                 struct wayland_drm_callbacks *callbacks, void *user_data,
+                 uint32_t flags)
+{
+	struct wl_drm *drm;
+
+	drm = malloc(sizeof *drm);
+
+	drm->display = display;
+	drm->device_name = strdup(device_name);
+	drm->callbacks = callbacks;
+	drm->user_data = user_data;
+    drm->flags = flags;
+
+	wl_display_add_global(display, &wl_drm_interface, drm, bind_drm);
+
+	return drm;
+}
+
+WL_EXPORT void
+wayland_drm_uninit(struct wl_drm *drm)
+{
+	free(drm->device_name);
+
+	/* FIXME: need wl_display_del_{object,global} */
+
+	free(drm);
+}
+
+WL_EXPORT int
+wayland_buffer_is_drm(struct wl_buffer *buffer)
+{
+	return buffer->resource.object.implementation ==
+		(void (**)(void)) &drm_buffer_interface;
+}
+
+WL_EXPORT uint32_t
+wayland_drm_buffer_get_format(struct wl_buffer *buffer_base)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+
+	return buffer->format;
+}
+
+WL_EXPORT void *
+wayland_drm_buffer_get_buffer(struct wl_buffer *buffer_base)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+
+	return buffer->driver_buffer;
+}
+
+WL_EXPORT int32_t
+wayland_drm_buffer_get_stride(struct wl_buffer *buffer_base, int idx)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+
+	if (!wayland_buffer_is_drm(buffer_base))
+		return 0;
+
+	return buffer->stride[idx];
+}
+
+WL_EXPORT void *
+wayland_drm_buffer_get_data(struct wl_buffer *buffer_base)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+	struct wl_drm *drm;
+
+	if (!wayland_buffer_is_drm(buffer_base))
+		return NULL;
+
+	drm = buffer->drm;
+
+	if (drm->callbacks->get_data)
+		return drm->callbacks->get_data(drm->user_data, buffer);
+
+	return NULL;
+}
+
+WL_EXPORT void
+wayland_drm_buffer_put_data(struct wl_buffer *buffer_base)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+	struct wl_drm *drm;
+
+	if (!wayland_buffer_is_drm(buffer_base))
+		return;
+
+	drm = buffer->drm;
+
+	if (drm->callbacks->put_data)
+		drm->callbacks->put_data(drm->user_data, buffer);
+
+	return;
+}
+
+
+WL_EXPORT int32_t
+wayland_drm_buffer_get_width(struct wl_buffer *buffer_base)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+
+	return buffer->buffer.width;
+}
+
+WL_EXPORT int32_t
+wayland_drm_buffer_get_height(struct wl_buffer *buffer_base)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
+
+	return buffer->buffer.height;
+}
diff --git a/src/wayland-drm.h b/src/wayland-drm.h
new file mode 100644
index 0000000..af3c2ad
--- /dev/null
+++ b/src/wayland-drm.h
@@ -0,0 +1,127 @@
+#ifndef WAYLAND_DRM_H
+#define WAYLAND_DRM_H
+
+#include <wayland-server.h>
+
+#ifndef WL_DRM_FORMAT_ENUM
+#define WL_DRM_FORMAT_ENUM
+enum wl_drm_format {
+	WL_DRM_FORMAT_C8 = 0x20203843,
+	WL_DRM_FORMAT_RGB332 = 0x38424752,
+	WL_DRM_FORMAT_BGR233 = 0x38524742,
+	WL_DRM_FORMAT_XRGB4444 = 0x32315258,
+	WL_DRM_FORMAT_XBGR4444 = 0x32314258,
+	WL_DRM_FORMAT_RGBX4444 = 0x32315852,
+	WL_DRM_FORMAT_BGRX4444 = 0x32315842,
+	WL_DRM_FORMAT_ARGB4444 = 0x32315241,
+	WL_DRM_FORMAT_ABGR4444 = 0x32314241,
+	WL_DRM_FORMAT_RGBA4444 = 0x32314152,
+	WL_DRM_FORMAT_BGRA4444 = 0x32314142,
+	WL_DRM_FORMAT_XRGB1555 = 0x35315258,
+	WL_DRM_FORMAT_XBGR1555 = 0x35314258,
+	WL_DRM_FORMAT_RGBX5551 = 0x35315852,
+	WL_DRM_FORMAT_BGRX5551 = 0x35315842,
+	WL_DRM_FORMAT_ARGB1555 = 0x35315241,
+	WL_DRM_FORMAT_ABGR1555 = 0x35314241,
+	WL_DRM_FORMAT_RGBA5551 = 0x35314152,
+	WL_DRM_FORMAT_BGRA5551 = 0x35314142,
+	WL_DRM_FORMAT_RGB565 = 0x36314752,
+	WL_DRM_FORMAT_BGR565 = 0x36314742,
+	WL_DRM_FORMAT_RGB888 = 0x34324752,
+	WL_DRM_FORMAT_BGR888 = 0x34324742,
+	WL_DRM_FORMAT_XRGB8888 = 0x34325258,
+	WL_DRM_FORMAT_XBGR8888 = 0x34324258,
+	WL_DRM_FORMAT_RGBX8888 = 0x34325852,
+	WL_DRM_FORMAT_BGRX8888 = 0x34325842,
+	WL_DRM_FORMAT_ARGB8888 = 0x34325241,
+	WL_DRM_FORMAT_ABGR8888 = 0x34324241,
+	WL_DRM_FORMAT_RGBA8888 = 0x34324152,
+	WL_DRM_FORMAT_BGRA8888 = 0x34324142,
+	WL_DRM_FORMAT_XRGB2101010 = 0x30335258,
+	WL_DRM_FORMAT_XBGR2101010 = 0x30334258,
+	WL_DRM_FORMAT_RGBX1010102 = 0x30335852,
+	WL_DRM_FORMAT_BGRX1010102 = 0x30335842,
+	WL_DRM_FORMAT_ARGB2101010 = 0x30335241,
+	WL_DRM_FORMAT_ABGR2101010 = 0x30334241,
+	WL_DRM_FORMAT_RGBA1010102 = 0x30334152,
+	WL_DRM_FORMAT_BGRA1010102 = 0x30334142,
+	WL_DRM_FORMAT_YUYV = 0x56595559,
+	WL_DRM_FORMAT_YVYU = 0x55595659,
+	WL_DRM_FORMAT_UYVY = 0x59565955,
+	WL_DRM_FORMAT_VYUY = 0x59555956,
+	WL_DRM_FORMAT_AYUV = 0x56555941,
+	WL_DRM_FORMAT_NV12 = 0x3231564e,
+	WL_DRM_FORMAT_NV21 = 0x3132564e,
+	WL_DRM_FORMAT_NV16 = 0x3631564e,
+	WL_DRM_FORMAT_NV61 = 0x3136564e,
+	WL_DRM_FORMAT_YUV410 = 0x39565559,
+	WL_DRM_FORMAT_YVU410 = 0x39555659,
+	WL_DRM_FORMAT_YUV411 = 0x31315559,
+	WL_DRM_FORMAT_YVU411 = 0x31315659,
+	WL_DRM_FORMAT_YUV420 = 0x32315559,
+	WL_DRM_FORMAT_YVU420 = 0x32315659,
+	WL_DRM_FORMAT_YUV422 = 0x36315559,
+	WL_DRM_FORMAT_YVU422 = 0x36315659,
+	WL_DRM_FORMAT_YUV444 = 0x34325559,
+	WL_DRM_FORMAT_YVU444 = 0x34325659,
+};
+#endif /* WL_DRM_FORMAT_ENUM */
+
+struct wl_drm;
+
+struct wl_drm_buffer {
+	struct wl_buffer buffer;
+	struct wl_drm *drm;
+	uint32_t format;
+    const void *driver_format;
+    int32_t offset[3];
+    int32_t stride[3];
+	void *driver_buffer;
+};
+
+struct wayland_drm_callbacks {
+	int (*authenticate)(void *user_data, uint32_t id);
+
+    void (*reference_buffer)(void *user_data, uint32_t name, int fd,
+                                 struct wl_drm_buffer *buffer);
+
+	void (*release_buffer)(void *user_data, struct wl_drm_buffer *buffer);
+	void* (*get_data)(void *user_data, struct wl_drm_buffer *buffer);
+	void (*put_data)(void *user_data, struct wl_drm_buffer *buffer);
+};
+
+enum { WAYLAND_DRM_PRIME = 0x01 };
+
+struct wl_drm *
+wayland_drm_init(struct wl_display *display, char *device_name,
+		 struct wayland_drm_callbacks *callbacks, void *user_data,
+                 uint32_t flags);
+
+void
+wayland_drm_uninit(struct wl_drm *drm);
+
+int
+wayland_buffer_is_drm(struct wl_buffer *buffer);
+
+uint32_t
+wayland_drm_buffer_get_format(struct wl_buffer *buffer_base);
+
+void *
+wayland_drm_buffer_get_buffer(struct wl_buffer *buffer);
+
+int32_t
+wayland_drm_buffer_get_stride(struct wl_buffer *buffer_base, int idx);
+
+void *
+wayland_drm_buffer_get_data(struct wl_buffer *buffer_base);
+
+void
+wayland_drm_buffer_put_data(struct wl_buffer *buffer_base);
+
+int32_t
+wayland_drm_buffer_get_width(struct wl_buffer *buffer_base);
+
+int32_t
+wayland_drm_buffer_get_height(struct wl_buffer *buffer_base);
+
+#endif
-- 
1.7.9.5

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to