From 1d59530e4b72dbf89ac5f6485a4ca2a3b45e2120 Mon Sep 17 00:00:00 2001
From: Philipp Zabel
Date: Wed, 19 Jul 2023 10:18:43 +0200
Subject: [PATCH] libweston: Set the presentation clock in the compositor
Let backends declare the presentation clocks they can use with a
new bitfield weston_backend::supported_presentation_clocks and set
presentation clock after loading the backend in the compositor.
Make weston_compositor_set_presentation_clock() internal and replace
weston_compositor_set_presentation_clock_software() with an exported
weston_compositor_backends_loaded(), which is called by the compositor
after the backend is loaded.
In the future, this can be extended to determine the subset of clocks
supported by all backends.
Signed-off-by: Philipp Zabel
---
compositor/main.c | 3 +++
include/libweston/libweston.h | 3 +++
libweston/backend-drm/kms.c | 6 +----
libweston/backend-headless/headless.c | 4 +--
libweston/backend-pipewire/pipewire.c | 4 +--
libweston/backend-rdp/rdp.c | 4 +--
libweston/backend-vnc/vnc.c | 4 +--
libweston/backend-wayland/wayland.c | 4 +--
libweston/backend-x11/x11.c | 4 +--
libweston/backend.h | 11 ++++++++
libweston/compositor.c | 37 +++++++++++++++++++--------
libweston/libweston-internal.h | 7 -----
12 files changed, 57 insertions(+), 34 deletions(-)
diff --git a/compositor/main.c b/compositor/main.c
index b3cb6842..66927e97 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -4141,6 +4141,9 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
goto out;
}
+ if (weston_compositor_backends_loaded(wet.compositor) < 0)
+ goto out;
+
if (test_data && !check_compositor_capabilities(wet.compositor,
test_data->test_quirks.required_capabilities)) {
ret = WET_MAIN_RET_MISSING_CAPS;
diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h
index 626a5bee..4eff82ac 100644
--- a/include/libweston/libweston.h
+++ b/include/libweston/libweston.h
@@ -2665,6 +2665,9 @@ weston_compositor_add_screenshot_authority(struct weston_compositor *compositor,
void (*auth)(struct wl_listener *l,
struct weston_output_capture_attempt *att));
+int
+weston_compositor_backends_loaded(struct weston_compositor *compositor);
+
#ifdef __cplusplus
}
#endif
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
index e57b4ab9..ba1c1696 100644
--- a/libweston/backend-drm/kms.c
+++ b/libweston/backend-drm/kms.c
@@ -1787,7 +1787,6 @@ int
init_kms_caps(struct drm_device *device)
{
struct drm_backend *b = device->backend;
- struct weston_compositor *compositor = b->compositor;
uint64_t cap;
int ret;
@@ -1799,10 +1798,7 @@ init_kms_caps(struct drm_device *device)
return -1;
}
- if (weston_compositor_set_presentation_clock(compositor, CLOCK_MONOTONIC) < 0) {
- weston_log("Error: failed to set presentation clock to CLOCK_MONOTONIC.\n");
- return -1;
- }
+ b->base.supported_presentation_clocks = 1 << CLOCK_MONOTONIC;
ret = drmGetCap(device->drm.fd, DRM_CAP_CURSOR_WIDTH, &cap);
if (ret == 0)
diff --git a/libweston/backend-headless/headless.c b/libweston/backend-headless/headless.c
index 20644cc8..92fe26a5 100644
--- a/libweston/backend-headless/headless.c
+++ b/libweston/backend-headless/headless.c
@@ -539,8 +539,8 @@ headless_backend_create(struct weston_compositor *compositor,
b->compositor = compositor;
compositor->backend = &b->base;
- if (weston_compositor_set_presentation_clock_software(compositor) < 0)
- goto err_free;
+ b->base.supported_presentation_clocks =
+ WESTON_PRESENTATION_CLOCKS_SOFTWARE;
b->base.destroy = headless_destroy;
b->base.create_output = headless_output_create;
diff --git a/libweston/backend-pipewire/pipewire.c b/libweston/backend-pipewire/pipewire.c
index b5e95c42..dc2fe10c 100644
--- a/libweston/backend-pipewire/pipewire.c
+++ b/libweston/backend-pipewire/pipewire.c
@@ -1041,8 +1041,8 @@ pipewire_backend_create(struct weston_compositor *compositor,
backend->formats = pixel_format_get_array(pipewire_formats,
backend->formats_count);
- if (weston_compositor_set_presentation_clock_software(compositor) < 0)
- goto err_compositor;
+ backend->base.supported_presentation_clocks =
+ WESTON_PRESENTATION_CLOCKS_SOFTWARE;
switch (config->renderer) {
case WESTON_RENDERER_AUTO:
diff --git a/libweston/backend-rdp/rdp.c b/libweston/backend-rdp/rdp.c
index 14dc62ad..79eee839 100644
--- a/libweston/backend-rdp/rdp.c
+++ b/libweston/backend-rdp/rdp.c
@@ -1891,8 +1891,8 @@ rdp_backend_create(struct weston_compositor *compositor,
wl_list_init(&b->peers);
- if (weston_compositor_set_presentation_clock_software(compositor) < 0)
- goto err_compositor;
+ b->base.supported_presentation_clocks =
+ WESTON_PRESENTATION_CLOCKS_SOFTWARE;
b->formats_count = ARRAY_LENGTH(rdp_formats);
b->formats = pixel_format_get_array(rdp_formats, b->formats_count);
diff --git a/libweston/backend-vnc/vnc.c b/libweston/backend-vnc/vnc.c
index 96d2bc1e..f8b496f2 100644
--- a/libweston/backend-vnc/vnc.c
+++ b/libweston/backend-vnc/vnc.c
@@ -1188,8 +1188,8 @@ vnc_backend_create(struct weston_compositor *compositor,
compositor->backend = &backend->base;
- if (weston_compositor_set_presentation_clock_software(compositor) < 0)
- goto err_compositor;
+ backend->base.supported_presentation_clocks =
+ WESTON_PRESENTATION_CLOCKS_SOFTWARE;
backend->formats_count = ARRAY_LENGTH(vnc_formats);
backend->formats = pixel_format_get_array(vnc_formats,
diff --git a/libweston/backend-wayland/wayland.c b/libweston/backend-wayland/wayland.c
index affeee8d..89442d05 100644
--- a/libweston/backend-wayland/wayland.c
+++ b/libweston/backend-wayland/wayland.c
@@ -2882,8 +2882,8 @@ wayland_backend_create(struct weston_compositor *compositor,
b->compositor = compositor;
compositor->backend = &b->base;
- if (weston_compositor_set_presentation_clock_software(compositor) < 0)
- goto err_compositor;
+ b->base.supported_presentation_clocks =
+ WESTON_PRESENTATION_CLOCKS_SOFTWARE;
b->parent.wl_display = wl_display_connect(new_config->display_name);
if (b->parent.wl_display == NULL) {
diff --git a/libweston/backend-x11/x11.c b/libweston/backend-x11/x11.c
index d9df40f7..b345e310 100644
--- a/libweston/backend-x11/x11.c
+++ b/libweston/backend-x11/x11.c
@@ -1884,8 +1884,8 @@ x11_backend_create(struct weston_compositor *compositor,
compositor->backend = &b->base;
- if (weston_compositor_set_presentation_clock_software(compositor) < 0)
- goto err_free;
+ b->base.supported_presentation_clocks =
+ WESTON_PRESENTATION_CLOCKS_SOFTWARE;
b->dpy = XOpenDisplay(NULL);
if (b->dpy == NULL)
diff --git a/libweston/backend.h b/libweston/backend.h
index ad60786d..4bb430b6 100644
--- a/libweston/backend.h
+++ b/libweston/backend.h
@@ -32,9 +32,20 @@
#ifndef LIBWESTON_BACKEND_INTERNAL_H
#define LIBWESTON_BACKEND_INTERNAL_H
+#define WESTON_PRESENTATION_CLOCKS_SOFTWARE \
+ ((1 << CLOCK_MONOTONIC) | \
+ (1 << CLOCK_MONOTONIC_RAW) | \
+ (1 << CLOCK_MONOTONIC_COARSE))
+
struct weston_hdr_metadata_type1;
struct weston_backend {
+ /** Bitfield of supported presentation clocks
+ *
+ * Bit positions correspond to system clock IDs.
+ */
+ unsigned int supported_presentation_clocks;
+
/** Prepare for compositor shutdown (optional)
*
* This will be called before weston_compositor_shutdown()
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 68120939..239dd2b6 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -8841,6 +8841,9 @@ weston_compositor_create(struct wl_display *display,
if (test_data)
ec->test_data = *test_data;
+ /* No backend supports CLOCK_REALTIME, use it to mean 'uninitialized' */
+ ec->presentation_clock = CLOCK_REALTIME;
+
ec->weston_log_ctx = log_ctx;
ec->wl_display = display;
ec->user_data = user_data;
@@ -9046,10 +9049,7 @@ weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
}
}
-/** weston_compositor_set_presentation_clock
- * \ingroup compositor
- */
-WL_EXPORT int
+static int
weston_compositor_set_presentation_clock(struct weston_compositor *compositor,
clockid_t clk_id)
{
@@ -9063,15 +9063,19 @@ weston_compositor_set_presentation_clock(struct weston_compositor *compositor,
return 0;
}
-/** For choosing the software clock, when the display hardware or API
- * does not expose a compatible presentation timestamp.
+/** To be called by the compositor after the last backend is loaded.
+ *
+ * \param compositor A compositor that has all backends loaded.
+ *
+ * \return 0 on success, or -1 on error.
*
* \ingroup compositor
*/
WL_EXPORT int
-weston_compositor_set_presentation_clock_software(
- struct weston_compositor *compositor)
+weston_compositor_backends_loaded(struct weston_compositor *compositor)
{
+ struct weston_backend *backend = compositor->backend;
+ uint32_t supported_clocks = backend->supported_presentation_clocks;
/* In order of preference */
static const clockid_t clocks[] = {
CLOCK_MONOTONIC_RAW, /* no jumps, no crawling */
@@ -9080,10 +9084,17 @@ weston_compositor_set_presentation_clock_software(
};
unsigned i;
- for (i = 0; i < ARRAY_LENGTH(clocks); i++)
+ for (i = 0; i < ARRAY_LENGTH(clocks); i++) {
+ clockid_t clk_id = clocks[i];
+ bool supported = (supported_clocks >> clocks[i]) & 1;
+
+ if (!supported)
+ continue;
+
if (weston_compositor_set_presentation_clock(compositor,
- clocks[i]) == 0)
+ clk_id) == 0)
return 0;
+ }
weston_log("Error: no suitable presentation clock available.\n");
@@ -9111,6 +9122,12 @@ weston_compositor_read_presentation_clock(
{
int ret;
+ /*
+ * Make sure weston_compositor_backends_loaded() was called.
+ * We use CLOCK_REALTIME to mean 'uninitialized'.
+ */
+ assert(compositor->presentation_clock != CLOCK_REALTIME);
+
ret = clock_gettime(compositor->presentation_clock, ts);
if (ret < 0) {
ts->tv_sec = 0;
diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h
index c153a72e..0cb98dc5 100644
--- a/libweston/libweston-internal.h
+++ b/libweston/libweston-internal.h
@@ -238,13 +238,6 @@ weston_compositor_set_touch_mode_normal(struct weston_compositor *compositor);
void
weston_compositor_set_touch_mode_calib(struct weston_compositor *compositor);
-int
-weston_compositor_set_presentation_clock(struct weston_compositor *compositor,
- clockid_t clk_id);
-int
-weston_compositor_set_presentation_clock_software(
- struct weston_compositor *compositor);
-
void
weston_compositor_xkb_destroy(struct weston_compositor *ec);