From 78ddc83ebfe7cf69c62610e1f7d14e7f49bf65c9 Mon Sep 17 00:00:00 2001 From: Pooja Prajod Date: Wed, 25 Jan 2017 17:09:35 +0530 Subject: [gst-bad-1.8] gstwaylandsink: Add DRM support on waylandsink Add wl_drm interface on waylandsink. The following features are supported: 1. Support for mouse drag and drop. 2. Support for video cropping The following bug fixes identified earlier have been picked: 1. Consolidate header files to avoid circular dependency 2. Fix bug reported on waylandsink incase of same process looping Signed-off-by: Pooja Prajod --- configure.ac | 4 +- ext/wayland/Makefile.am | 17 +- ext/wayland/gstwaylandsink.c | 82 ++++++- ext/wayland/gstwaylandsink.h | 4 +- ext/wayland/wayland-drm-client-protocol.h | 213 ++++++++++++++++++ ext/wayland/wayland-drm-protocol.c | 74 +++++++ ext/wayland/wlbuffer.c | 2 +- ext/wayland/wlbuffer.h | 67 ------ ext/wayland/wldisplay-wlwindow-wlbuffer.h | 216 ++++++++++++++++++ ext/wayland/wldisplay.c | 350 +++++++++++++++++++++++++++++- ext/wayland/wldisplay.h | 84 ------- ext/wayland/wldrm.c | 69 ++++++ ext/wayland/wldrm.h | 3 + ext/wayland/wlshmallocator.h | 2 +- ext/wayland/wlvideoformat.c | 8 +- ext/wayland/wlwindow.c | 47 +++- ext/wayland/wlwindow.h | 84 ------- 17 files changed, 1056 insertions(+), 270 deletions(-) create mode 100644 ext/wayland/wayland-drm-client-protocol.h create mode 100644 ext/wayland/wayland-drm-protocol.c delete mode 100644 ext/wayland/wlbuffer.h create mode 100644 ext/wayland/wldisplay-wlwindow-wlbuffer.h delete mode 100644 ext/wayland/wldisplay.h create mode 100644 ext/wayland/wldrm.c create mode 100644 ext/wayland/wldrm.h delete mode 100644 ext/wayland/wlwindow.h diff --git a/configure.ac b/configure.ac index 9fdfbc7..76166cb 100644 --- a/configure.ac +++ b/configure.ac @@ -2172,8 +2172,10 @@ AG_GST_CHECK_FEATURE(DIRECTFB, [directfb], dfbvideosink , [ dnl **** Wayland **** translit(dnm, m, l) AM_CONDITIONAL(USE_WAYLAND, true) AC_PATH_PROG([wayland_scanner], [wayland-scanner]) -AG_GST_CHECK_FEATURE(WAYLAND, [wayland sink], wayland , [ +AG_GST_CHECK_FEATURE(WAYLAND, [wayland sink], wayland libdrm libdrm_omap, [ PKG_CHECK_MODULES(WAYLAND, wayland-client >= 1.4.0, [ + AC_SUBST(DRM_CFLAGS) + AC_SUBST(DRM_LIBS) if test "x$wayland_scanner" != "x"; then HAVE_WAYLAND="yes" else diff --git a/ext/wayland/Makefile.am b/ext/wayland/Makefile.am index c742bfc..eb6e326 100644 --- a/ext/wayland/Makefile.am +++ b/ext/wayland/Makefile.am @@ -3,31 +3,34 @@ plugin_LTLIBRARIES = libgstwaylandsink.la libgstwaylandsink_la_SOURCES = \ gstwaylandsink.c \ wlshmallocator.c \ + wldrm.c \ wlbuffer.c \ wldisplay.c \ wlwindow.c \ wlvideoformat.c \ - scaler-protocol.c + scaler-protocol.c \ + wayland-drm-protocol.c libgstwaylandsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(WAYLAND_CFLAGS) $(GST_PLUGINS_BAD_CFLAGS) + $(WAYLAND_CFLAGS) $(GST_PLUGINS_BAD_CFLAGS) $(DRM_CFLAGS) libgstwaylandsink_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) \ -lgstvideo-$(GST_API_VERSION) \ -lgstallocators-$(GST_API_VERSION) \ $(WAYLAND_LIBS) \ - $(top_builddir)/gst-libs/gst/wayland/libgstwayland-$(GST_API_VERSION).la + $(top_builddir)/gst-libs/gst/wayland/libgstwayland-$(GST_API_VERSION).la \ + $(top_builddir)/gst-libs/gst/drm/libgstdrm-$(GST_API_VERSION).la libgstwaylandsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstwaylandsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) noinst_HEADERS = \ gstwaylandsink.h \ wlshmallocator.h \ - wlbuffer.h \ - wldisplay.h \ - wlwindow.h \ + wldisplay-wlwindow-wlbuffer.h \ + wldrm.h \ wlvideoformat.h \ - scaler-client-protocol.h + scaler-client-protocol.h \ + wayland-drm-client-protocol.h EXTRA_DIST = scaler.xml CLEANFILES = scaler-protocol.c scaler-client-protocol.h diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c index f4f34a8..3e8ff19 100644 --- a/ext/wayland/gstwaylandsink.c +++ b/ext/wayland/gstwaylandsink.c @@ -43,8 +43,14 @@ #include "gstwaylandsink.h" #include "wlvideoformat.h" -#include "wlbuffer.h" #include "wlshmallocator.h" +#include "wldrm.h" + +#include +#include "wayland-drm-client-protocol.h" +#include +#include +#include #include #include @@ -60,7 +66,8 @@ enum enum { PROP_0, - PROP_DISPLAY + PROP_DISPLAY, + PROP_ALLOCATION }; GST_DEBUG_CATEGORY (gstwayland_debug); @@ -75,6 +82,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", "YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }")) ); + static void gst_wayland_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_wayland_sink_set_property (GObject * object, @@ -158,6 +166,11 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass) g_param_spec_string ("display", "Wayland Display name", "Wayland " "display name to connect to, if not supplied via the GstContext", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_ALLOCATION, + g_param_spec_boolean ("use-drm", "Wayland Allocation name", "Wayland " + "Use DRM based memory for allocation", + FALSE, G_PARAM_WRITABLE)); } static void @@ -197,6 +210,11 @@ gst_wayland_sink_set_property (GObject * object, sink->display_name = g_value_dup_string (value); GST_OBJECT_UNLOCK (sink); break; + case PROP_ALLOCATION: + GST_OBJECT_LOCK (sink); + sink->use_drm = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (sink); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -281,6 +299,7 @@ gst_wayland_sink_find_display (GstWaylandSink * sink) /* if the application didn't set a display, let's create it ourselves */ GST_OBJECT_LOCK (sink); sink->display = gst_wl_display_new (sink->display_name, &error); + sink->display->use_drm = sink->use_drm; GST_OBJECT_UNLOCK (sink); if (error) { @@ -408,7 +427,6 @@ gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) caps = gst_caps_make_writable (caps); gst_structure_set_value (gst_caps_get_structure (caps, 0), "format", &list); - GST_DEBUG_OBJECT (sink, "display caps: %" GST_PTR_FORMAT, caps); } @@ -426,6 +444,18 @@ gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) return caps; } +static void +wait_authentication (GstWaylandSink * sink) +{ + GST_DEBUG_OBJECT (sink, "Before wait aunthenticated value is %d : \n", sink->display->authenticated ); + while (!sink->display->authenticated) { + GST_DEBUG_OBJECT (sink, "waiting for authentication"); + wl_display_roundtrip (sink->display->display); + } + GST_DEBUG_OBJECT (sink, "After wait aunthenticated value is %d : \n", sink->display->authenticated ); +} + + static gboolean gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { @@ -436,11 +466,20 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) GArray *formats; gint i; GstStructure *structure; + GstStructure *s; + gboolean use_drm = 0; + int num_buffers = 0; sink = GST_WAYLAND_SINK (bsink); GST_DEBUG_OBJECT (sink, "set caps %" GST_PTR_FORMAT, caps); + wait_authentication (sink); + + while (!sink->display->authenticated) { + GST_DEBUG_OBJECT (sink, "not authenticated yet"); + } + /* extract info from caps */ if (!gst_video_info_from_caps (&info, caps)) goto invalid_format; @@ -460,14 +499,27 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) goto unsupported_format; /* create a new pool for the new configuration */ - newpool = gst_video_buffer_pool_new (); + + s = gst_caps_get_structure (caps, 0); + gst_structure_get_boolean (s, "drm_mem", &use_drm); + gst_structure_get_int (s, "max-ref-frames", &num_buffers); + if (num_buffers ) + num_buffers = num_buffers + 2; + + newpool = gst_buffer_pool_new (); if (!newpool) goto pool_failed; structure = gst_buffer_pool_get_config (newpool); - gst_buffer_pool_config_set_params (structure, caps, info.size, 2, 0); - gst_buffer_pool_config_set_allocator (structure, gst_wl_shm_allocator_get (), - NULL); + gst_buffer_pool_config_set_params (structure, caps, info.size, 2, num_buffers); + if ( use_drm ) { + gst_buffer_pool_config_set_allocator (structure, gst_drm_allocator_get (), + NULL); + sink->display->use_drm = TRUE; + } else { + gst_buffer_pool_config_set_allocator (structure, gst_wl_shm_allocator_get (), + NULL); + } if (!gst_buffer_pool_set_config (newpool, structure)) goto config_failed; @@ -518,8 +570,11 @@ gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) /* we do have a pool for sure (created in set_caps), * so let's propose it anyway, but also propose the allocator on its own */ gst_query_add_allocation_pool (query, sink->pool, size, min_bufs, max_bufs); - gst_query_add_allocation_param (query, gst_wl_shm_allocator_get (), NULL); - + if (sink->display->use_drm) { + gst_query_add_allocation_param (query, gst_drm_allocator_get (), NULL); + } else { + gst_query_add_allocation_param (query, gst_wl_shm_allocator_get (), NULL); + } gst_structure_free (config); return TRUE; @@ -582,6 +637,10 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer) GST_LOG_OBJECT (sink, "render buffer %p", buffer); + if (sink->display) { + sink->display->crop = gst_buffer_get_video_crop_meta (buffer); + } + if (G_UNLIKELY (!sink->window)) { /* ask for window handle. Unlock render_lock while doing that because * set_window_handle & friends will lock it in this context */ @@ -623,6 +682,11 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer) wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display, &sink->video_info); } + + if (gst_is_drm_memory (mem)) { + wbuf = gst_wl_drm_memory_construct_wl_buffer (mem, sink->display, + &sink->video_info); + } if (wbuf) { gst_buffer_add_wl_buffer (buffer, wbuf, sink->display); diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h index afbed40..c1092ce 100644 --- a/ext/wayland/gstwaylandsink.h +++ b/ext/wayland/gstwaylandsink.h @@ -27,8 +27,7 @@ #include -#include "wldisplay.h" -#include "wlwindow.h" +#include "wldisplay-wlwindow-wlbuffer.h" G_BEGIN_DECLS @@ -61,6 +60,7 @@ struct _GstWaylandSink GstVideoInfo video_info; gchar *display_name; + gboolean use_drm; gboolean redraw_pending; GMutex render_lock; diff --git a/ext/wayland/wayland-drm-client-protocol.h b/ext/wayland/wayland-drm-client-protocol.h new file mode 100644 index 0000000..7ddb614 --- /dev/null +++ b/ext/wayland/wayland-drm-client-protocol.h @@ -0,0 +1,213 @@ +/* + * 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. + */ + +#ifndef DRM_CLIENT_PROTOCOL_H +#define DRM_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "wayland-util.h" + +struct wl_client; +struct wl_resource; + +struct wl_drm; + +extern const struct wl_interface wl_drm_interface; + +#ifndef WL_DRM_ERROR_ENUM +#define WL_DRM_ERROR_ENUM +enum wl_drm_error { + WL_DRM_ERROR_AUTHENTICATE_FAIL = 0, + WL_DRM_ERROR_INVALID_FORMAT = 1, + WL_DRM_ERROR_INVALID_NAME = 2, +}; +#endif /* WL_DRM_ERROR_ENUM */ + +#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_listener { + /** + * device - (none) + * @name: (none) + */ + void (*device)(void *data, + struct wl_drm *wl_drm, + const char *name); + /** + * format - (none) + * @format: (none) + */ + void (*format)(void *data, + struct wl_drm *wl_drm, + uint32_t format); + /** + * authenticated - (none) + */ + void (*authenticated)(void *data, + struct wl_drm *wl_drm); +}; + +static inline int +wl_drm_add_listener(struct wl_drm *wl_drm, + const struct wl_drm_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) wl_drm, + (void (**)(void)) listener, data); +} + +#define WL_DRM_AUTHENTICATE 0 +#define WL_DRM_CREATE_BUFFER 1 +#define WL_DRM_CREATE_PLANAR_BUFFER 2 + +static inline void +wl_drm_set_user_data(struct wl_drm *wl_drm, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wl_drm, user_data); +} + +static inline void * +wl_drm_get_user_data(struct wl_drm *wl_drm) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wl_drm); +} + +static inline void +wl_drm_destroy(struct wl_drm *wl_drm) +{ + wl_proxy_destroy((struct wl_proxy *) wl_drm); +} + +static inline void +wl_drm_authenticate(struct wl_drm *wl_drm, uint32_t id) +{ + wl_proxy_marshal((struct wl_proxy *) wl_drm, + WL_DRM_AUTHENTICATE, id); +} + +static inline struct wl_buffer * +wl_drm_create_buffer(struct wl_drm *wl_drm, uint32_t name, int32_t width, int32_t height, uint32_t stride, uint32_t format) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) wl_drm, + &wl_buffer_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) wl_drm, + WL_DRM_CREATE_BUFFER, id, name, width, height, stride, format); + + return (struct wl_buffer *) id; +} + +static inline struct wl_buffer * +wl_drm_create_planar_buffer(struct wl_drm *wl_drm, 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) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) wl_drm, + &wl_buffer_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) wl_drm, + WL_DRM_CREATE_PLANAR_BUFFER, id, name, width, height, format, offset0, stride0, offset1, stride1, offset2, stride2); + + return (struct wl_buffer *) id; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/wayland/wayland-drm-protocol.c b/ext/wayland/wayland-drm-protocol.c new file mode 100644 index 0000000..939af53 --- /dev/null +++ b/ext/wayland/wayland-drm-protocol.c @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#include +#include +#include "wayland-util.h" + +#define ARRAY_LENGTH(a) (sizeof (a) /sizeof (a)[0]) + +extern const struct wl_interface wl_buffer_interface; +extern const struct wl_interface wl_buffer_interface; + +static const struct wl_interface *types[] = { + NULL, + &wl_buffer_interface, + NULL, + NULL, + NULL, + NULL, + NULL, + &wl_buffer_interface, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static const struct wl_message wl_drm_requests[] = { + { "authenticate", "u", types + 0 }, + { "create_buffer", "nuiiuu", types + 1 }, + { "create_planar_buffer", "nuiiuiiiiii", types + 7 }, +}; + +static const struct wl_message wl_drm_events[] = { + { "device", "s", types + 0 }, + { "format", "u", types + 0 }, + { "authenticated", "", types + 0 }, +}; + +WL_EXPORT const struct wl_interface wl_drm_interface = { + "wl_drm", 1, + ARRAY_LENGTH(wl_drm_requests), wl_drm_requests, + ARRAY_LENGTH(wl_drm_events), wl_drm_events, +}; + diff --git a/ext/wayland/wlbuffer.c b/ext/wayland/wlbuffer.c index 4ac99ef..0e38d2e 100644 --- a/ext/wayland/wlbuffer.c +++ b/ext/wayland/wlbuffer.c @@ -76,7 +76,7 @@ * as soon as we remove the reference that GstWlDisplay holds. */ -#include "wlbuffer.h" +#include "wldisplay-wlwindow-wlbuffer.h" GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug); #define GST_CAT_DEFAULT gstwayland_debug diff --git a/ext/wayland/wlbuffer.h b/ext/wayland/wlbuffer.h deleted file mode 100644 index cbb50f7..0000000 --- a/ext/wayland/wlbuffer.h +++ /dev/null @@ -1,67 +0,0 @@ -/* GStreamer Wayland video sink - * - * Copyright (C) 2014 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ - -#ifndef __GST_WL_BUFFER_H__ -#define __GST_WL_BUFFER_H__ - -#include "wldisplay.h" - -G_BEGIN_DECLS - -#define GST_TYPE_WL_BUFFER (gst_wl_buffer_get_type ()) -#define GST_WL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_BUFFER, GstWlBuffer)) -#define GST_IS_WL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_BUFFER)) -#define GST_WL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_BUFFER, GstWlBufferClass)) -#define GST_IS_WL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_BUFFER)) -#define GST_WL_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_BUFFER, GstWlBufferClass)) - -typedef struct _GstWlBuffer GstWlBuffer; -typedef struct _GstWlBufferClass GstWlBufferClass; - -struct _GstWlBuffer -{ - GObject parent_instance; - - struct wl_buffer * wlbuffer; - GstBuffer *gstbuffer; - - GstWlDisplay *display; - - gboolean used_by_compositor; -}; - -struct _GstWlBufferClass -{ - GObjectClass parent_class; -}; - -GType gst_wl_buffer_get_type (void); - -GstWlBuffer * gst_buffer_add_wl_buffer (GstBuffer * gstbuffer, - struct wl_buffer * wlbuffer, GstWlDisplay * display); -GstWlBuffer * gst_buffer_get_wl_buffer (GstBuffer * gstbuffer); - -void gst_wl_buffer_force_release_and_unref (GstWlBuffer * self); - -void gst_wl_buffer_attach (GstWlBuffer * self, struct wl_surface *surface); - -G_END_DECLS - -#endif /* __GST_WL_BUFFER_H__ */ diff --git a/ext/wayland/wldisplay-wlwindow-wlbuffer.h b/ext/wayland/wldisplay-wlwindow-wlbuffer.h new file mode 100644 index 0000000..684d145 --- /dev/null +++ b/ext/wayland/wldisplay-wlwindow-wlbuffer.h @@ -0,0 +1,216 @@ +/* GStreamer Wayland video sink + * + * Copyright (C) 2014 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __GST_WL_DISPLAY_WL_WINDOW_H__ +#define __GST_WL_DISPLAY_WL_WINDOW_H__ + +#include +#include +#include +#include +#include "scaler-client-protocol.h" +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_WL_DISPLAY (gst_wl_display_get_type ()) +#define GST_WL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplay)) +#define GST_IS_WL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_DISPLAY)) +#define GST_WL_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_DISPLAY, GstWlDisplayClass)) +#define GST_IS_WL_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_DISPLAY)) +#define GST_WL_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplayClass)) + +#define GST_TYPE_WL_WINDOW (gst_wl_window_get_type ()) +#define GST_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_WINDOW, GstWlWindow)) +#define GST_IS_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_WINDOW)) +#define GST_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_WINDOW, GstWlWindowClass)) +#define GST_IS_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_WINDOW)) +#define GST_WL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_WINDOW, GstWlWindowClass)) + +#define GST_TYPE_WL_BUFFER (gst_wl_buffer_get_type ()) +#define GST_WL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_BUFFER, GstWlBuffer)) +#define GST_IS_WL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_BUFFER)) +#define GST_WL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_BUFFER, GstWlBufferClass)) +#define GST_IS_WL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_BUFFER)) +#define GST_WL_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_BUFFER, GstWlBufferClass)) + +typedef struct _GstWlBuffer GstWlBuffer; +typedef struct _GstWlBufferClass GstWlBufferClass; + +typedef struct _GstWlWindow GstWlWindow; +typedef struct _GstWlWindowClass GstWlWindowClass; + +typedef struct _GstWlDisplay GstWlDisplay; +typedef struct _GstWlDisplayClass GstWlDisplayClass; + +struct _GstWlBuffer +{ + GObject parent_instance; + + struct wl_buffer * wlbuffer; + GstBuffer *gstbuffer; + + GstWlDisplay *display; + + gboolean used_by_compositor; +}; + +struct _GstWlBufferClass +{ + GObjectClass parent_class; +}; + +GType gst_wl_buffer_get_type (void); + +GstWlBuffer * gst_buffer_add_wl_buffer (GstBuffer * gstbuffer, + struct wl_buffer * wlbuffer, GstWlDisplay * display); +GstWlBuffer * gst_buffer_get_wl_buffer (GstBuffer * gstbuffer); + +void gst_wl_buffer_force_release_and_unref (GstWlBuffer * self); + +void gst_wl_buffer_attach (GstWlBuffer * self, struct wl_surface *surface); + + +struct touch_point +{ + int32_t id; + struct wl_list link; +}; + +struct input +{ + GstWlDisplay *display; + struct wl_seat *seat; + struct wl_pointer *pointer; + struct wl_touch *touch; + struct wl_list touch_point_list; + GstWlWindow *pointer_focus; + GstWlWindow *touch_focus; + struct wl_list link; + GstWlWindow *grab; +}; + + +struct _GstWlWindow +{ + GObject parent_instance; + + GstWlDisplay *display; + struct wl_surface *area_surface; + struct wl_subsurface *area_subsurface; + struct wl_viewport *area_viewport; + struct wl_surface *video_surface; + struct wl_subsurface *video_subsurface; + struct wl_viewport *video_viewport; + struct wl_shell_surface *shell_surface; + + /* the size and position of the area_(sub)surface */ + GstVideoRectangle render_rectangle; + /* the size of the video in the buffers */ + gint video_width, video_height; + /* the size of the video_(sub)surface */ + gint surface_width, surface_height; +}; + +struct _GstWlWindowClass +{ + GObjectClass parent_class; +}; + +GType gst_wl_window_get_type (void); + +GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display, + const GstVideoInfo * info); +GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display, + struct wl_surface * parent); + +GstWlDisplay *gst_wl_window_get_display (GstWlWindow * window); +struct wl_surface *gst_wl_window_get_wl_surface (GstWlWindow * window); +gboolean gst_wl_window_is_toplevel (GstWlWindow *window); + +void gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer, + const GstVideoInfo * info); +void gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y, + gint w, gint h); + + +struct _GstWlDisplay +{ + GObject parent_instance; + + /* public objects */ + struct wl_display *display; + struct wl_event_queue *queue; + + /* globals */ + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; + struct wl_shell *shell; + struct wl_shm *shm; + struct wl_drm *drm; + struct wl_scaler *scaler; + GArray *shm_formats; + + /* private */ + gboolean own_display; + GThread *thread; + GstPoll *wl_fd_poll; + + GMutex buffers_mutex; + GHashTable *buffers; + gboolean shutting_down; + + /* the drm device.. needed for sharing direct-render buffers.. + * TODO nothing about this should really be omapdrm specific. But some + * of the code, like hashtable of imported buffers in libdrm_omap should + * be refactored out into some generic libdrm code.. + */ + struct omap_device *dev; + int fd; + int authenticated; + gboolean use_drm; + + struct wl_list input_list; + int seat_version; + uint32_t serial; + + GstVideoCropMeta *crop; +}; + +struct _GstWlDisplayClass +{ + GObjectClass parent_class; +}; + +GType gst_wl_display_get_type (void); + +GstWlDisplay *gst_wl_display_new (const gchar * name, GError ** error); +GstWlDisplay *gst_wl_display_new_existing (struct wl_display * display, + gboolean take_ownership, GError ** error); + +/* see wlbuffer.c for explanation */ +void gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf); +void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf); + +G_END_DECLS + +#endif /* __GST_WL_DISPLAY_WL_WINDOW_H__ */ diff --git a/ext/wayland/wldisplay.c b/ext/wayland/wldisplay.c index 3318095..2f58fd2 100644 --- a/ext/wayland/wldisplay.c +++ b/ext/wayland/wldisplay.c @@ -22,9 +22,15 @@ #include #endif -#include "wldisplay.h" -#include "wlbuffer.h" - +#include "wldisplay-wlwindow-wlbuffer.h" + +#include +#include "wayland-drm-client-protocol.h" +#include +#include +#include +#include +#include #include GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug); @@ -33,6 +39,8 @@ GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug); G_DEFINE_TYPE (GstWlDisplay, gst_wl_display, G_TYPE_OBJECT); static void gst_wl_display_finalize (GObject * gobject); +static void input_grab (struct input *input, GstWlWindow *window); +static void input_ungrab (struct input *input); static void gst_wl_display_class_init (GstWlDisplayClass * klass) @@ -45,12 +53,62 @@ static void gst_wl_display_init (GstWlDisplay * self) { self->shm_formats = g_array_new (FALSE, FALSE, sizeof (uint32_t)); + self->fd = -1; + self->use_drm = FALSE; self->wl_fd_poll = gst_poll_new (TRUE); self->buffers = g_hash_table_new (g_direct_hash, g_direct_equal); g_mutex_init (&self->buffers_mutex); } static void +input_grab (struct input *input, GstWlWindow *window) +{ + input->grab = window; +} + +static void +input_ungrab (struct input *input) +{ + input->grab = NULL; +} + +static void +input_remove_pointer_focus (struct input *input) +{ + GstWlWindow *window = input->pointer_focus; + + if (!window) + return; + + input->pointer_focus = NULL; +} + +static void +input_destroy (struct input *input) +{ + input_remove_pointer_focus (input); + + if (input->display->seat_version >= 3) { + if (input->pointer) + wl_pointer_release (input->pointer); + } + + wl_list_remove (&input->link); + wl_seat_destroy (input->seat); + free (input); +} + +static void +display_destroy_inputs (GstWlDisplay *display) +{ + struct input *tmp; + struct input *input; + + wl_list_for_each_safe (input, tmp, &display->input_list, link) + input_destroy (input); +} + +static void gst_wl_display_finalize (GObject * gobject) { GstWlDisplay *self = GST_WL_DISPLAY (gobject); @@ -71,13 +129,26 @@ gst_wl_display_finalize (GObject * gobject) g_hash_table_remove_all (self->buffers); g_array_unref (self->shm_formats); + + if (self->dev) { + omap_device_del (self->dev); + self->dev = NULL; + } + if (self->fd !=-1) + close (self->fd); + gst_poll_free (self->wl_fd_poll); g_hash_table_unref (self->buffers); g_mutex_clear (&self->buffers_mutex); + display_destroy_inputs (self); + if (self->shm) wl_shm_destroy (self->shm); + if (self->drm) + wl_drm_destroy (self->drm); + if (self->shell) wl_shell_destroy (self->shell); @@ -138,12 +209,277 @@ shm_format (void *data, struct wl_shm *wl_shm, uint32_t format) GstWlDisplay *self = data; g_array_append_val (self->shm_formats, format); + GST_DEBUG ("shm got format: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (format)); } static const struct wl_shm_listener shm_listener = { shm_format }; +/* For wl_drm_listener */ + +static void +drm_handle_device (void *data, struct wl_drm *drm, const char *device) +{ + GstWlDisplay *d = data; + drm_magic_t magic; + d->fd = open (device, O_RDWR | O_CLOEXEC); + if (d->fd == -1) { + GST_ERROR ("could not open %s: %m", device); + return; + } + drmGetMagic (d->fd, &magic); + wl_drm_authenticate (d->drm, magic); +} + +static void +drm_handle_format (void *data, struct wl_drm *drm, uint32_t format) +{ + GstWlDisplay *self = data; + g_array_append_val (self->shm_formats, format); + GST_DEBUG ("drm got format: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (format)); +} + +static void +drm_handle_authenticated (void *data, struct wl_drm *drm) +{ + GstWlDisplay *d = data; + GST_DEBUG ("authenticated"); + d->dev = omap_device_new (d->fd); + d->authenticated = 1; + GST_DEBUG ("drm_handle_authenticated: dev: %p, d->authenticated: %d\n", + d->dev, d->authenticated); +} + +static const struct wl_drm_listener drm_listener = { + drm_handle_device, + drm_handle_format, + drm_handle_authenticated +}; + + +static void +pointer_handle_enter (void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + struct input *input = data; + + if (!surface) { + /* enter event for a window we've just destroyed */ + return; + } + + input->display->serial = serial; + input->pointer_focus = wl_surface_get_user_data (surface); +} + +static void +pointer_handle_leave (void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + struct input *input = data; + + input_remove_pointer_focus (input); +} + +static void +pointer_handle_motion (void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + struct input *input = data; + GstWlWindow *window = input->pointer_focus; + + if (!window) + return; + + if (input->grab) + wl_shell_surface_move (input->grab->shell_surface, input->seat, + input->display->serial); + +} + +static void +pointer_handle_button (void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) +{ + struct input *input = data; + enum wl_pointer_button_state state = state_w; + input->display->serial = serial; + + if (button == BTN_LEFT) { + if (state == WL_POINTER_BUTTON_STATE_PRESSED) + input_grab (input, input->pointer_focus); + + if (input->grab && state == WL_POINTER_BUTTON_STATE_RELEASED) + input_ungrab (input); + } + + if (input->grab) + wl_shell_surface_move (input->grab->shell_surface, input->seat, + input->display->serial); +} + +static void +pointer_handle_axis (void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +static void +touch_handle_down (void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, struct wl_surface *surface, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + struct input *input = data; + struct touch_point *tp; + + input->display->serial = serial; + input->touch_focus = wl_surface_get_user_data (surface); + if (!input->touch_focus) { + return; + } + + tp = malloc (sizeof *tp); + if (tp) { + tp->id = id; + wl_list_insert (&input->touch_point_list, &tp->link); + wl_shell_surface_move (input->touch_focus->shell_surface, input->seat, + serial); + } +} + +static void +touch_handle_motion (void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + struct input *input = data; + struct touch_point *tp; + + + if (!input->touch_focus) { + return; + } + wl_list_for_each (tp, &input->touch_point_list, link) { + if (tp->id != id) + continue; + + wl_shell_surface_move (input->touch_focus->shell_surface, input->seat, + input->display->serial); + + return; + } +} + +static void +touch_handle_frame (void *data, struct wl_touch *wl_touch) +{ +} + +static void +touch_handle_cancel (void *data, struct wl_touch *wl_touch) +{ +} + +static void +touch_handle_up (void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) +{ + struct input *input = data; + struct touch_point *tp, *tmp; + + if (!input->touch_focus) { + return; + } + + wl_list_for_each_safe (tp, tmp, &input->touch_point_list, link) { + if (tp->id != id) + continue; + + wl_list_remove (&tp->link); + free (tp); + + return; + } +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel, +}; + + +static void +seat_handle_capabilities (void *data, struct wl_seat *seat, + enum wl_seat_capability caps) +{ + struct input *input = data; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) { + input->pointer = wl_seat_get_pointer (seat); + wl_pointer_set_user_data (input->pointer, input); + wl_pointer_add_listener (input->pointer, &pointer_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) { + wl_pointer_destroy (input->pointer); + input->pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { + input->touch = wl_seat_get_touch (seat); + wl_touch_set_user_data (input->touch, input); + wl_touch_add_listener (input->touch, &touch_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { + wl_touch_destroy (input->touch); + input->touch = NULL; + } +} + +static void +seat_handle_name (void *data, struct wl_seat *seat, const char *name) +{ + +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, + seat_handle_name +}; + +static void +display_add_input (GstWlDisplay *d, uint32_t id) +{ + struct input *input; + + input = calloc (1, sizeof (*input)); + if (input == NULL) { + fprintf (stderr, "%s: out of memory\n", "gst-wayland-sink"); + exit (EXIT_FAILURE); + } + input->display = d; + input->seat = wl_registry_bind (d->registry, id, &wl_seat_interface, + MAX (d->seat_version, 3)); + input->touch_focus = NULL; + input->pointer_focus = NULL; + wl_list_init (&input->touch_point_list); + wl_list_insert (d->input_list.prev, &input->link); + + wl_seat_add_listener (input->seat, &seat_listener, input); + wl_seat_set_user_data (input->seat, input); + +} + + static void registry_handle_global (void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) @@ -161,6 +497,12 @@ registry_handle_global (void *data, struct wl_registry *registry, } else if (g_strcmp0 (interface, "wl_shm") == 0) { self->shm = wl_registry_bind (registry, id, &wl_shm_interface, 1); wl_shm_add_listener (self->shm, &shm_listener, self); + } else if (g_strcmp0 (interface, "wl_drm") == 0) { + self->drm = wl_registry_bind (registry, id, &wl_drm_interface, 1); + wl_drm_add_listener (self->drm, &drm_listener, self); + } else if (g_strcmp0 (interface, "wl_seat") == 0) { + self->seat_version = version; + display_add_input (self, id); } else if (g_strcmp0 (interface, "wl_scaler") == 0) { self->scaler = wl_registry_bind (registry, id, &wl_scaler_interface, 2); } @@ -238,6 +580,7 @@ gst_wl_display_new_existing (struct wl_display * display, self->own_display = take_ownership; self->queue = wl_display_create_queue (self->display); + wl_list_init (&self->input_list); self->registry = wl_display_get_registry (self->display); wl_proxy_set_queue ((struct wl_proxy *) self->registry, self->queue); wl_registry_add_listener (self->registry, ®istry_listener, self); @@ -266,6 +609,7 @@ gst_wl_display_new_existing (struct wl_display * display, VERIFY_INTERFACE_EXISTS (subcompositor, "wl_subcompositor"); VERIFY_INTERFACE_EXISTS (shell, "wl_shell"); VERIFY_INTERFACE_EXISTS (shm, "wl_shm"); + VERIFY_INTERFACE_EXISTS (drm, "wl_drm"); VERIFY_INTERFACE_EXISTS (scaler, "wl_scaler"); #undef VERIFY_INTERFACE_EXISTS diff --git a/ext/wayland/wldisplay.h b/ext/wayland/wldisplay.h deleted file mode 100644 index e9df749..0000000 --- a/ext/wayland/wldisplay.h +++ /dev/null @@ -1,84 +0,0 @@ -/* GStreamer Wayland video sink - * - * Copyright (C) 2014 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ - -#ifndef __GST_WL_DISPLAY_H__ -#define __GST_WL_DISPLAY_H__ - -#include -#include -#include "scaler-client-protocol.h" - -G_BEGIN_DECLS - -#define GST_TYPE_WL_DISPLAY (gst_wl_display_get_type ()) -#define GST_WL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplay)) -#define GST_IS_WL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_DISPLAY)) -#define GST_WL_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_DISPLAY, GstWlDisplayClass)) -#define GST_IS_WL_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_DISPLAY)) -#define GST_WL_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplayClass)) - -typedef struct _GstWlDisplay GstWlDisplay; -typedef struct _GstWlDisplayClass GstWlDisplayClass; - -struct _GstWlDisplay -{ - GObject parent_instance; - - /* public objects */ - struct wl_display *display; - struct wl_event_queue *queue; - - /* globals */ - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_subcompositor *subcompositor; - struct wl_shell *shell; - struct wl_shm *shm; - struct wl_scaler *scaler; - GArray *shm_formats; - - /* private */ - gboolean own_display; - GThread *thread; - GstPoll *wl_fd_poll; - - GMutex buffers_mutex; - GHashTable *buffers; - gboolean shutting_down; -}; - -struct _GstWlDisplayClass -{ - GObjectClass parent_class; -}; - -GType gst_wl_display_get_type (void); - -GstWlDisplay *gst_wl_display_new (const gchar * name, GError ** error); -GstWlDisplay *gst_wl_display_new_existing (struct wl_display * display, - gboolean take_ownership, GError ** error); - -/* see wlbuffer.c for explanation */ -void gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf); -void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf); - -G_END_DECLS - -#endif /* __GST_WL_DISPLAY_H__ */ diff --git a/ext/wayland/wldrm.c b/ext/wayland/wldrm.c new file mode 100644 index 0000000..3dc9c21 --- /dev/null +++ b/ext/wayland/wldrm.c @@ -0,0 +1,69 @@ +#include "wldisplay-wlwindow-wlbuffer.h" +#include +#include "wayland-drm-client-protocol.h" +#include +#include +#include + +struct wl_buffer * +gst_wl_drm_memory_construct_wl_buffer (GstMemory * mem, GstWlDisplay * display, + const GstVideoInfo * info) +{ + gint video_width = GST_VIDEO_INFO_WIDTH (info); + gint video_height = GST_VIDEO_INFO_HEIGHT (info); + int fd = -1; + struct omap_bo *bo; + struct wl_buffer *buffer; + + /* TODO get format, etc from caps.. and query device for + * supported formats, and make this all more flexible to + * cope with various formats: + */ + uint32_t fourcc = GST_MAKE_FOURCC ('N', 'V', '1', '2'); + uint32_t name; + /* note: wayland and mesa use the terminology: + * stride - rowstride in bytes + * pitch - rowstride in pixels + */ + uint32_t strides[3] = { + GST_ROUND_UP_4 (video_width), GST_ROUND_UP_4 (video_width), 0, + }; + uint32_t offsets[3] = { + 0, strides[0] * video_height, 0 + }; + + fd = gst_fd_memory_get_fd (mem); + + if (fd < 0 ) { + GST_DEBUG ("Invalid fd"); + return NULL; + } + + bo = omap_bo_from_dmabuf (display->dev, fd); + + struct drm_gem_flink req = { + .handle = omap_bo_handle(bo), + }; + + int ret; + ret = drmIoctl(display->fd, DRM_IOCTL_GEM_FLINK, &req); + if (ret) { + GST_DEBUG ("could not get name, DRM_IOCTL_GEM_FLINK returned %d", ret); + return NULL; + } + + name = req.name; + + GST_LOG ("width = %d , height = %d , fourcc = %d ", video_width, video_height, fourcc ); + buffer = wl_drm_create_planar_buffer (display->drm, name, + video_width, video_height, fourcc, + offsets[0], strides[0], + offsets[1], strides[1], + offsets[2], strides[2]); + + GST_DEBUG ("create planar buffer: %p (name=%d)", + buffer, name); + + return buffer; +} + diff --git a/ext/wayland/wldrm.h b/ext/wayland/wldrm.h new file mode 100644 index 0000000..9751029 --- /dev/null +++ b/ext/wayland/wldrm.h @@ -0,0 +1,3 @@ +struct wl_buffer * +gst_wl_drm_memory_construct_wl_buffer (GstMemory * mem, GstWlDisplay * display, + const GstVideoInfo * info); diff --git a/ext/wayland/wlshmallocator.h b/ext/wayland/wlshmallocator.h index 07ae17f..2860fc3 100644 --- a/ext/wayland/wlshmallocator.h +++ b/ext/wayland/wlshmallocator.h @@ -26,7 +26,7 @@ #include #include #include -#include "wldisplay.h" +#include "wldisplay-wlwindow-wlbuffer.h" G_BEGIN_DECLS diff --git a/ext/wayland/wlvideoformat.c b/ext/wayland/wlvideoformat.c index 1302da6..aa336aa 100644 --- a/ext/wayland/wlvideoformat.c +++ b/ext/wayland/wlvideoformat.c @@ -106,6 +106,10 @@ gst_wl_shm_format_to_video_format (enum wl_shm_format wl_format) const gchar * gst_wl_shm_format_to_string (enum wl_shm_format wl_format) { - return gst_video_format_to_string - (gst_wl_shm_format_to_video_format (wl_format)); + GstVideoFormat fmt = gst_wl_shm_format_to_video_format (wl_format); + if (fmt != GST_VIDEO_FORMAT_UNKNOWN) { + return gst_video_format_to_string (fmt); + } else { + return NULL; + } } diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c index 79000ae..f7e3324 100644 --- a/ext/wayland/wlwindow.c +++ b/ext/wayland/wlwindow.c @@ -24,9 +24,10 @@ #include #endif -#include "wlwindow.h" +#include "wldisplay-wlwindow-wlbuffer.h" #include "wlshmallocator.h" -#include "wlbuffer.h" +#include "wldrm.h" +#include GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug); #define GST_CAT_DEFAULT gstwayland_debug @@ -111,6 +112,8 @@ gst_wl_window_new_internal (GstWlDisplay * display) window->area_surface = wl_compositor_create_surface (display->compositor); window->video_surface = wl_compositor_create_surface (display->compositor); + wl_surface_set_user_data (window->area_surface, window); + wl_surface_set_user_data (window->video_surface, window); wl_proxy_set_queue ((struct wl_proxy *) window->area_surface, display->queue); wl_proxy_set_queue ((struct wl_proxy *) window->video_surface, @@ -126,6 +129,21 @@ gst_wl_window_new_internal (GstWlDisplay * display) window->area_surface); window->video_viewport = wl_scaler_get_viewport (display->scaler, window->video_surface); + if (display->crop) { + GST_DEBUG ("Setting source crop : %d %d %d %d",display->crop->x, display->crop->y, + display->crop->width, display->crop->height); + wl_viewport_set_source (window->area_viewport, + wl_fixed_from_int(display->crop->x), + wl_fixed_from_int(display->crop->y), + wl_fixed_from_int(display->crop->width), + wl_fixed_from_int(display->crop->height)); + wl_viewport_set_source (window->video_viewport, + wl_fixed_from_int(display->crop->x), + wl_fixed_from_int(display->crop->y), + wl_fixed_from_int(display->crop->width), + wl_fixed_from_int(display->crop->height)); + + } /* draw the area_subsurface */ gst_video_info_set_format (&info, @@ -136,14 +154,25 @@ gst_wl_window_new_internal (GstWlDisplay * display) GST_VIDEO_FORMAT_BGRx, #endif 1, 1); - - buf = gst_buffer_new_allocate (gst_wl_shm_allocator_get (), info.size, NULL); + if (display->use_drm) { + buf = gst_buffer_new_allocate (gst_drm_allocator_get (), info.size, NULL); + } else { + buf = gst_buffer_new_allocate (gst_wl_shm_allocator_get (), info.size, NULL); + } gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE); - *((guint32 *) mapinfo.data) = 0; /* paint it black */ - gst_buffer_unmap (buf, &mapinfo); - wlbuf = - gst_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0), - display, &info); + *((guint32 *) mapinfo.data) = 0; /* paint it black */ + gst_buffer_unmap (buf, &mapinfo); + + if (display->use_drm) { + wlbuf = + gst_wl_drm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0), + display, &info); + } else { + wlbuf = + gst_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0), + display, &info); + } + gwlbuf = gst_buffer_add_wl_buffer (buf, wlbuf, display); gst_wl_buffer_attach (gwlbuf, window->area_surface); diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h deleted file mode 100644 index e22cb26..0000000 --- a/ext/wayland/wlwindow.h +++ /dev/null @@ -1,84 +0,0 @@ -/* GStreamer Wayland video sink - * - * Copyright (C) 2014 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ - -#ifndef __GST_WL_WINDOW_H__ -#define __GST_WL_WINDOW_H__ - -#include "wldisplay.h" -#include "wlbuffer.h" -#include - -G_BEGIN_DECLS - -#define GST_TYPE_WL_WINDOW (gst_wl_window_get_type ()) -#define GST_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_WINDOW, GstWlWindow)) -#define GST_IS_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_WINDOW)) -#define GST_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_WINDOW, GstWlWindowClass)) -#define GST_IS_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_WINDOW)) -#define GST_WL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_WINDOW, GstWlWindowClass)) - -typedef struct _GstWlWindow GstWlWindow; -typedef struct _GstWlWindowClass GstWlWindowClass; - -struct _GstWlWindow -{ - GObject parent_instance; - - GstWlDisplay *display; - struct wl_surface *area_surface; - struct wl_subsurface *area_subsurface; - struct wl_viewport *area_viewport; - struct wl_surface *video_surface; - struct wl_subsurface *video_subsurface; - struct wl_viewport *video_viewport; - struct wl_shell_surface *shell_surface; - - /* the size and position of the area_(sub)surface */ - GstVideoRectangle render_rectangle; - /* the size of the video in the buffers */ - gint video_width, video_height; - /* the size of the video_(sub)surface */ - gint surface_width, surface_height; -}; - -struct _GstWlWindowClass -{ - GObjectClass parent_class; -}; - -GType gst_wl_window_get_type (void); - -GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display, - const GstVideoInfo * info); -GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display, - struct wl_surface * parent); - -GstWlDisplay *gst_wl_window_get_display (GstWlWindow * window); -struct wl_surface *gst_wl_window_get_wl_surface (GstWlWindow * window); -gboolean gst_wl_window_is_toplevel (GstWlWindow *window); - -void gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer, - const GstVideoInfo * info); -void gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y, - gint w, gint h); - -G_END_DECLS - -#endif /* __GST_WL_WINDOW_H__ */ -- 2.7.4