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