From 27d7c395c7600e9bf6b13dd8b3d06ee19aab1aba Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Fri, 19 Oct 2018 12:14:11 +0300 Subject: [PATCH] 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 --- Makefile.am | 21 ++- configure.ac | 5 +- libweston/compositor-headless.c | 6 + libweston/compositor.c | 5 + libweston/compositor.h | 3 + libweston/linux-explicit-synchronization.c | 164 ++++++++++++++++++++ libweston/linux-explicit-synchronization.h | 34 ++++ libweston/meson.build | 3 + protocol/meson.build | 6 +- tests/linux-explicit-synchronization-test.c | 96 ++++++++++++ tests/meson.build | 7 + 11 files changed, 345 insertions(+), 5 deletions(-) create mode 100644 libweston/linux-explicit-synchronization.c create mode 100644 libweston/linux-explicit-synchronization.h create mode 100644 tests/linux-explicit-synchronization-test.c diff --git a/Makefile.am b/Makefile.am index 24561a58..358dd7bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -94,6 +94,8 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ libweston/timeline-object.h \ libweston/linux-dmabuf.c \ libweston/linux-dmabuf.h \ + libweston/linux-explicit-synchronization.c \ + libweston/linux-explicit-synchronization.h \ libweston/pixel-formats.c \ libweston/pixel-formats.h \ libweston/weston-debug.c \ @@ -177,7 +179,9 @@ nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ protocol/input-timestamps-unstable-v1-protocol.c \ protocol/input-timestamps-unstable-v1-server-protocol.h \ protocol/weston-touch-calibration-protocol.c \ - protocol/weston-touch-calibration-server-protocol.h + protocol/weston-touch-calibration-server-protocol.h \ + protocol/linux-explicit-synchronization-unstable-v1-protocol.c \ + protocol/linux-explicit-synchronization-unstable-v1-server-protocol.h BUILT_SOURCES += $(nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES) @@ -968,7 +972,9 @@ BUILT_SOURCES += \ protocol/input-timestamps-unstable-v1-protocol.c \ protocol/input-timestamps-unstable-v1-client-protocol.h \ protocol/xdg-output-unstable-v1-protocol.c \ - protocol/xdg-output-unstable-v1-client-protocol.h + protocol/xdg-output-unstable-v1-client-protocol.h \ + protocol/linux-explicit-synchronization-unstable-v1-protocol.c \ + protocol/linux-explicit-synchronization-unstable-v1-client-protocol.h westondatadir = $(datadir)/weston dist_westondata_DATA = \ @@ -1308,7 +1314,8 @@ weston_tests = \ subsurface.weston \ subsurface-shot.weston \ devices.weston \ - touch.weston + touch.weston \ + linux-explicit-synchronization.weston AM_TESTS_ENVIRONMENT = \ abs_builddir='$(abs_builddir)'; export abs_builddir; \ @@ -1502,6 +1509,14 @@ touch_weston_SOURCES = tests/touch-test.c touch_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS) touch_weston_LDADD = libtest-client.la +linux_explicit_synchronization_weston_SOURCES = \ + tests/linux-explicit-synchronization-test.c +nodist_linux_explicit_synchronization_weston_SOURCES = \ + protocol/linux-explicit-synchronization-unstable-v1-protocol.c \ + protocol/linux-explicit-synchronization-unstable-v1-client-protocol.h +linux_explicit_synchronization_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS) +linux_explicit_synchronization_weston_LDADD = libtest-client.la + if ENABLE_XWAYLAND_TEST weston_tests += xwayland-test.weston xwayland_test_weston_SOURCES = tests/xwayland-test.c diff --git a/configure.ac b/configure.ac index 00066eae..cb8b0a5b 100644 --- a/configure.ac +++ b/configure.ac @@ -239,7 +239,10 @@ PKG_CHECK_MODULES(LIBEVDEV, [libevdev]) PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0]) PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES]) -PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.14], +# XXX: For minor version 2 of zwp_linux_explicit_synchronization_v1, we +# actually need a development version after 1.17, but there is no way to +# express such a requirement at the moment. +PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.17], [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`]) AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir) diff --git a/libweston/compositor-headless.c b/libweston/compositor-headless.c index 61a5bd93..5a0e46c8 100644 --- a/libweston/compositor-headless.c +++ b/libweston/compositor-headless.c @@ -36,6 +36,7 @@ #include "compositor.h" #include "compositor-headless.h" #include "shared/helpers.h" +#include "linux-explicit-synchronization.h" #include "pixman-renderer.h" #include "presentation-time-server-protocol.h" #include "windowed-output-api.h" @@ -339,6 +340,11 @@ headless_backend_create(struct weston_compositor *compositor, if (!b->use_pixman && noop_renderer_init(compositor) < 0) goto err_input; + /* Support zwp_linux_explicit_synchronization_unstable_v1 to enable + * testing. */ + if (linux_explicit_synchronization_setup(compositor) < 0) + goto err_input; + ret = weston_plugin_api_register(compositor, WESTON_WINDOWED_OUTPUT_API_NAME, &api, sizeof(api)); diff --git a/libweston/compositor.c b/libweston/compositor.c index 3ef472e3..14033cbd 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -2035,6 +2035,11 @@ destroy_surface(struct wl_resource *resource) if (surface->viewport_resource) wl_resource_set_user_data(surface->viewport_resource, NULL); + if (surface->synchronization_resource) { + wl_resource_set_user_data(surface->synchronization_resource, + NULL); + } + weston_surface_destroy(surface); } diff --git a/libweston/compositor.h b/libweston/compositor.h index b4b75197..3f2ad01e 100644 --- a/libweston/compositor.h +++ b/libweston/compositor.h @@ -1486,6 +1486,9 @@ struct weston_surface { /* An list of per seat pointer constraints. */ struct wl_list pointer_constraints; + + /* zwp_surface_synchronization_v1 resource for this surface */ + struct wl_resource *synchronization_resource; }; struct weston_subsurface { diff --git a/libweston/linux-explicit-synchronization.c b/libweston/linux-explicit-synchronization.c new file mode 100644 index 00000000..c42b8aa3 --- /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 + +#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; +} diff --git a/libweston/linux-explicit-synchronization.h b/libweston/linux-explicit-synchronization.h new file mode 100644 index 00000000..96edbbb6 --- /dev/null +++ b/libweston/linux-explicit-synchronization.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef WESTON_LINUX_EXPLICIT_SYNCHRONIZATION_H +#define WESTON_LINUX_EXPLICIT_SYNCHRONIZATION_H + +struct weston_compositor; + +int +linux_explicit_synchronization_setup(struct weston_compositor *compositor); + +#endif /* WESTON_LINUX_EXPLICIT_SYNCHRONIZATION */ diff --git a/libweston/meson.build b/libweston/meson.build index 0e43a3fb..64efdd95 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -16,6 +16,7 @@ srcs_libweston = [ 'data-device.c', 'input.c', 'linux-dmabuf.c', + 'linux-explicit-synchronization.c', 'log.c', 'noop-renderer.c', 'pixel-formats.c', @@ -29,6 +30,8 @@ srcs_libweston = [ '../shared/matrix.c', linux_dmabuf_unstable_v1_protocol_c, linux_dmabuf_unstable_v1_server_protocol_h, + linux_explicit_synchronization_unstable_v1_protocol_c, + linux_explicit_synchronization_unstable_v1_server_protocol_h, input_method_unstable_v1_protocol_c, input_method_unstable_v1_server_protocol_h, input_timestamps_unstable_v1_protocol_c, diff --git a/protocol/meson.build b/protocol/meson.build index a947eeab..b3ea5b21 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -1,7 +1,10 @@ dep_scanner = dependency('wayland-scanner', native: true) prog_scanner = find_program(dep_scanner.get_pkgconfig_variable('wayland_scanner')) -dep_wp = dependency('wayland-protocols', version: '>= 1.14') +# XXX: For minor version 2 of zwp_linux_explicit_synchronization_v1, we +# actually need a development version after 1.17, but there is no way to +# express such a requirement at the moment. +dep_wp = dependency('wayland-protocols', version: '>= 1.17') dir_wp_base = dep_wp.get_pkgconfig_variable('pkgdatadir') install_data( @@ -18,6 +21,7 @@ generated_protocols = [ [ 'ivi-hmi-controller', 'internal' ], [ 'fullscreen-shell', 'v1' ], [ 'linux-dmabuf', 'v1' ], + [ 'linux-explicit-synchronization', 'v1' ], [ 'presentation-time', 'stable' ], [ 'pointer-constraints', 'v1' ], [ 'relative-pointer', 'v1' ], diff --git a/tests/linux-explicit-synchronization-test.c b/tests/linux-explicit-synchronization-test.c new file mode 100644 index 00000000..62a54e0d --- /dev/null +++ b/tests/linux-explicit-synchronization-test.c @@ -0,0 +1,96 @@ +/* + * 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 + +#include "linux-explicit-synchronization-unstable-v1-client-protocol.h" +#include "weston-test-client-helper.h" +#include "wayland-server-protocol.h" + +static struct zwp_linux_explicit_synchronization_v1 * +get_linux_explicit_synchronization(struct client *client) +{ + struct global *g; + struct global *global_sync = NULL; + struct zwp_linux_explicit_synchronization_v1 *sync = NULL; + + wl_list_for_each(g, &client->global_list, link) { + if (strcmp(g->interface, + zwp_linux_explicit_synchronization_v1_interface.name)) + continue; + + if (global_sync) + assert(!"Multiple linux explicit sync objects"); + + global_sync = g; + } + + assert(global_sync); + assert(global_sync->version == 1); + + sync = wl_registry_bind( + client->wl_registry, global_sync->name, + &zwp_linux_explicit_synchronization_v1_interface, 1); + assert(sync); + + return sync; +} + +static struct client * +create_test_client(void) +{ + struct client *cl = create_client_and_test_surface(0, 0, 100, 100); + assert(cl); + return cl; +} + +TEST(second_surface_synchronization_on_surface_raises_error) +{ + struct client *client = create_test_client(); + struct zwp_linux_explicit_synchronization_v1 *sync = + get_linux_explicit_synchronization(client); + struct zwp_linux_surface_synchronization_v1 *surface_sync1; + struct zwp_linux_surface_synchronization_v1 *surface_sync2; + + surface_sync1 = + zwp_linux_explicit_synchronization_v1_get_synchronization( + sync, client->surface->wl_surface); + client_roundtrip(client); + + /* Second surface_synchronization creation should fail */ + surface_sync2 = + zwp_linux_explicit_synchronization_v1_get_synchronization( + sync, client->surface->wl_surface); + expect_protocol_error( + client, + &zwp_linux_explicit_synchronization_v1_interface, + ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS); + + zwp_linux_surface_synchronization_v1_destroy(surface_sync2); + zwp_linux_surface_synchronization_v1_destroy(surface_sync1); + zwp_linux_explicit_synchronization_v1_destroy(sync); +} diff --git a/tests/meson.build b/tests/meson.build index ebd3872a..7baee512 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -127,6 +127,13 @@ tests_weston = [ input_timestamps_unstable_v1_protocol_c, ] ], + [ + 'linux-explicit-synchronization', + [ + linux_explicit_synchronization_unstable_v1_client_protocol_h, + linux_explicit_synchronization_unstable_v1_protocol_c, + ] + ], ['internal-screenshot'], [ 'presentation',