libweston: Introduce zwp_linux_explicit_synchronization_v1

Introduce support for the zwp_linux_explicit_synchronization_unstable_v1
protocol with an implementation of the zwp_linux_explicit_synchronization_v1
interface.

Explicit synchronization provides a more versatile notification
mechanism for buffer readiness and availability, and can be used to
improve efficiency by integrating with related functionality in display
and graphics APIs.

In addition, the per-commit nature of the release events provided by
this protocol potentially offers a solution to a deficiency of the
wl_buffer.release event (see
https://gitlab.freedesktop.org/wayland/wayland/issues/46).

Support for this protocol depends on the capabilities of the backend, so
we don't register it by default but provide a function which each
backend will need to call. In this commit only the headless backend when
using the noop renderer supports this to enable testing.

Note that the zwp_surface_synchronization_v1 interface, which contains
the core functionality of the protocol, is not implemented in this
commit. Support for it will be added in future commits.

Changes in v7:
  - Added some information in the commit message about the benefits of
    the explicit sync protocol.

Changes in v6:
  - Fall back to advertising minor version 1 of the explicit sync protocol,
    although we support minor version 2 features, until the new
    wayland-protocols version is released.

Changes in v5:
  - Meson support.
  - Advertise minor version 2 of the explicit sync protocol.

Changes in v4:
  - Enable explicit sync support in the headless backend for all
    renderers.

Changes in v3:
  - Use wl_resource_get_version() instead of hardcoding version 1.
  - Use updated protocol interface names.
  - Use correct format specifier for resource id.
  - Change test name to 'linux-explicit-synchronization.weston'
    (s/_/-/g).

Changes in v2:
  - Move implementation to separate file so protocol can be registered
    on demand by backends.
  - Register protocol in headless+noop backend for testing purposes.

Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com>
diff --git a/libweston/linux-explicit-synchronization.c b/libweston/linux-explicit-synchronization.c
new file mode 100644
index 0000000..c42b8aa
--- /dev/null
+++ b/libweston/linux-explicit-synchronization.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2018 Collabora, Ltd.
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include <inttypes.h>
+
+#include "compositor.h"
+#include "linux-explicit-synchronization.h"
+#include "linux-explicit-synchronization-unstable-v1-server-protocol.h"
+
+static void
+destroy_linux_surface_synchronization(struct wl_resource *resource)
+{
+	struct weston_surface *surface =
+		wl_resource_get_user_data(resource);
+
+	if (surface)
+		surface->synchronization_resource = NULL;
+}
+
+static void
+linux_surface_synchronization_destroy(struct wl_client *client,
+				      struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+static void
+linux_surface_synchronization_set_acquire_fence(struct wl_client *client,
+						struct wl_resource *resource,
+						int32_t fd)
+{
+	wl_client_post_no_memory(client);
+}
+
+static void
+linux_surface_synchronization_get_release(struct wl_client *client,
+					  struct wl_resource *resource,
+					  uint32_t id)
+{
+	wl_client_post_no_memory(client);
+}
+
+const struct zwp_linux_surface_synchronization_v1_interface
+linux_surface_synchronization_implementation = {
+	linux_surface_synchronization_destroy,
+	linux_surface_synchronization_set_acquire_fence,
+	linux_surface_synchronization_get_release,
+};
+
+static void
+linux_explicit_synchronization_destroy(struct wl_client *client,
+				       struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+static void
+linux_explicit_synchronization_get_synchronization(struct wl_client *client,
+						   struct wl_resource *resource,
+						   uint32_t id,
+						   struct wl_resource *surface_resource)
+{
+	struct weston_surface *surface =
+		wl_resource_get_user_data(surface_resource);
+
+	if (surface->synchronization_resource) {
+		wl_resource_post_error(
+			resource,
+			ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS,
+			"wl_surface@%"PRIu32" already has a synchronization object",
+			wl_resource_get_id(surface_resource));
+		return;
+	}
+
+	surface->synchronization_resource =
+		wl_resource_create(client,
+				   &zwp_linux_surface_synchronization_v1_interface,
+				   wl_resource_get_version(resource), id);
+	if (!surface->synchronization_resource) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	wl_resource_set_implementation(surface->synchronization_resource,
+				       &linux_surface_synchronization_implementation,
+				       surface,
+				       destroy_linux_surface_synchronization);
+}
+
+static const struct zwp_linux_explicit_synchronization_v1_interface
+linux_explicit_synchronization_implementation = {
+	linux_explicit_synchronization_destroy,
+	linux_explicit_synchronization_get_synchronization
+};
+
+static void
+bind_linux_explicit_synchronization(struct wl_client *client,
+				    void *data, uint32_t version,
+				    uint32_t id)
+{
+	struct weston_compositor *compositor = data;
+	struct wl_resource *resource;
+
+	resource = wl_resource_create(client,
+			&zwp_linux_explicit_synchronization_v1_interface,
+			version, id);
+	if (resource == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	wl_resource_set_implementation(resource,
+	       &linux_explicit_synchronization_implementation,
+	       compositor, NULL);
+}
+
+/** Advertise linux_explicit_synchronization support
+ *
+ * Calling this initializes the zwp_linux_explicit_synchronization_v1
+ * protocol support, so that the interface will be advertised to clients.
+ * Essentially it creates a global. Do not call this function multiple times
+ * in the compositor's lifetime. There is no way to deinit explicitly, globals
+ * will be reaped when the wl_display gets destroyed.
+ *
+ * \param compositor The compositor to init for.
+ * \return Zero on success, -1 on failure.
+ */
+WL_EXPORT int
+linux_explicit_synchronization_setup(struct weston_compositor *compositor)
+{
+	/* TODO: Update to minor version 2 when the next version of
+	 * wayland-protocols that contains it is released. */
+	if (!wl_global_create(compositor->wl_display,
+			      &zwp_linux_explicit_synchronization_v1_interface,
+			      1, compositor,
+			      bind_linux_explicit_synchronization))
+		return -1;
+
+	return 0;
+}