diff options
Diffstat (limited to 'backend')
-rw-r--r-- | backend/backend.c | 7 | ||||
-rw-r--r-- | backend/drm/backend.c | 6 | ||||
-rw-r--r-- | backend/drm/drm.c | 33 | ||||
-rw-r--r-- | backend/headless/output.c | 4 | ||||
-rw-r--r-- | backend/multi/backend.c | 17 | ||||
-rw-r--r-- | backend/wayland/output.c | 10 | ||||
-rw-r--r-- | backend/x11/output.c | 7 |
7 files changed, 75 insertions, 9 deletions
diff --git a/backend/backend.c b/backend/backend.c index 2d6464b7..4b186767 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -64,6 +64,13 @@ struct wlr_session *wlr_backend_get_session(struct wlr_backend *backend) { return NULL; } +clockid_t wlr_backend_get_presentation_clock(struct wlr_backend *backend) { + if (backend->impl->get_presentation_clock) { + return backend->impl->get_presentation_clock(backend); + } + return CLOCK_MONOTONIC; +} + static size_t parse_outputs_env(const char *name) { const char *outputs_str = getenv(name); if (outputs_str == NULL) { diff --git a/backend/drm/backend.c b/backend/drm/backend.c index b298365e..a9082077 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -65,10 +65,16 @@ static struct wlr_renderer *backend_get_renderer( } } +static clockid_t backend_get_presentation_clock(struct wlr_backend *backend) { + struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); + return drm->clock; +} + static struct wlr_backend_impl backend_impl = { .start = backend_start, .destroy = backend_destroy, .get_renderer = backend_get_renderer, + .get_presentation_clock = backend_get_presentation_clock, }; bool wlr_backend_is_drm(struct wlr_backend *b) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index fa9a95ae..0187e5d0 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 199309L #include <assert.h> #include <drm_mode.h> #include <EGL/egl.h> @@ -27,8 +28,8 @@ #include "util/signal.h" bool check_drm_features(struct wlr_drm_backend *drm) { + uint64_t cap; if (drm->parent) { - uint64_t cap; if (drmGetCap(drm->fd, DRM_CAP_PRIME, &cap) || !(cap & DRM_PRIME_CAP_IMPORT)) { wlr_log(WLR_ERROR, @@ -51,16 +52,21 @@ bool check_drm_features(struct wlr_drm_backend *drm) { const char *no_atomic = getenv("WLR_DRM_NO_ATOMIC"); if (no_atomic && strcmp(no_atomic, "1") == 0) { - wlr_log(WLR_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); + wlr_log(WLR_DEBUG, + "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); drm->iface = &legacy_iface; } else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { - wlr_log(WLR_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); + wlr_log(WLR_DEBUG, + "Atomic modesetting unsupported, using legacy DRM interface"); drm->iface = &legacy_iface; } else { wlr_log(WLR_DEBUG, "Using atomic DRM interface"); drm->iface = &atomic_iface; } + int ret = drmGetCap(drm->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap); + drm->clock = (ret == 0 && cap == 1) ? CLOCK_MONOTONIC : CLOCK_REALTIME; + return true; } @@ -1148,9 +1154,13 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { attempt_enable_needs_modeset(drm); } +static int mhz_to_nsec(int mhz) { + return 1000000000000LL / mhz; +} + static void page_flip_handler(int fd, unsigned seq, - unsigned tv_sec, unsigned tv_usec, void *user) { - struct wlr_drm_connector *conn = user; + unsigned tv_sec, unsigned tv_usec, void *data) { + struct wlr_drm_connector *conn = data; struct wlr_drm_backend *drm = get_drm_backend_from_backend(conn->output.backend); @@ -1170,6 +1180,19 @@ static void page_flip_handler(int fd, unsigned seq, post_drm_surface(&conn->crtc->primary->mgpu_surf); } + struct timespec present_time = { + .tv_sec = tv_sec, + .tv_nsec = tv_usec * 1000, + }; + struct wlr_output_event_present present_event = { + .when = &present_time, + .seq = seq, + .refresh = mhz_to_nsec(conn->output.refresh), + .flags = WLR_OUTPUT_PRESENT_VSYNC | WLR_OUTPUT_PRESENT_HW_CLOCK | + WLR_OUTPUT_PRESENT_HW_COMPLETION, + }; + wlr_output_send_present(&conn->output, &present_event); + if (drm->session->active) { wlr_output_send_frame(&conn->output); } diff --git a/backend/headless/output.c b/backend/headless/output.c index 143900d4..3cb35dce 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -67,7 +67,9 @@ static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age) static bool output_swap_buffers(struct wlr_output *wlr_output, pixman_region32_t *damage) { - return true; // No-op + // Nothing needs to be done for pbuffers + wlr_output_send_present(wlr_output, NULL); + return true; } static void output_destroy(struct wlr_output *wlr_output) { diff --git a/backend/multi/backend.c b/backend/multi/backend.c index 2f4b929f..cefaa361 100644 --- a/backend/multi/backend.c +++ b/backend/multi/backend.c @@ -1,6 +1,8 @@ +#define _POSIX_C_SOURCE 199309L #include <assert.h> #include <stdbool.h> #include <stdlib.h> +#include <time.h> #include <wlr/backend/interface.h> #include <wlr/backend/session.h> #include <wlr/util/log.h> @@ -77,11 +79,26 @@ static struct wlr_session *multi_backend_get_session( return backend->session; } +static clockid_t multi_backend_get_presentation_clock( + struct wlr_backend *backend) { + struct wlr_multi_backend *multi = multi_backend_from_backend(backend); + + struct subbackend_state *sub; + wl_list_for_each(sub, &multi->backends, link) { + if (sub->backend->impl->get_presentation_clock) { + return wlr_backend_get_presentation_clock(sub->backend); + } + } + + return CLOCK_MONOTONIC; +} + struct wlr_backend_impl backend_impl = { .start = multi_backend_start, .destroy = multi_backend_destroy, .get_renderer = multi_backend_get_renderer, .get_session = multi_backend_get_session, + .get_presentation_clock = multi_backend_get_presentation_clock, }; static void handle_display_destroy(struct wl_listener *listener, void *data) { diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 4eb99a3b..bc7a9f05 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -66,8 +66,14 @@ static bool output_swap_buffers(struct wlr_output *wlr_output, output->frame_callback = wl_surface_frame(output->surface); wl_callback_add_listener(output->frame_callback, &frame_listener, output); - return wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface, - damage); + if (!wlr_egl_swap_buffers(&output->backend->egl, + output->egl_surface, damage)) { + return false; + } + + // TODO: if available, use the presentation-time protocol + wlr_output_send_present(wlr_output, NULL); + return true; } static void output_transform(struct wlr_output *wlr_output, diff --git a/backend/x11/output.c b/backend/x11/output.c index e0210b1a..1ac12a8d 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -102,7 +102,12 @@ static bool output_swap_buffers(struct wlr_output *wlr_output, struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; struct wlr_x11_backend *x11 = output->x11; - return wlr_egl_swap_buffers(&x11->egl, output->surf, damage); + if (!wlr_egl_swap_buffers(&x11->egl, output->surf, damage)) { + return false; + } + + wlr_output_send_present(wlr_output, NULL); + return true; } static const struct wlr_output_impl output_impl = { |