diff --git a/meson.build b/meson.build index 90d2f3644fa..c551bad452e 100644 --- a/meson.build +++ b/meson.build @@ -2014,6 +2014,12 @@ if with_platform_wayland dep_wayland_egl_headers = dep_wayland_egl.partial_dependency(compile_args : true) endif pre_args += '-DWL_HIDE_DEPRECATED' + if cc.has_function( + 'wl_display_dispatch_queue_timeout', + prefix : '#include ', + dependencies: dep_wayland_client) + pre_args += ['-DHAVE_WL_DISPATCH_QUEUE_TIMEOUT'] + endif endif dep_x11 = null_dep diff --git a/src/loader/loader_wayland_helper.c b/src/loader/loader_wayland_helper.c new file mode 100644 index 00000000000..4cb2da7d156 --- /dev/null +++ b/src/loader/loader_wayland_helper.c @@ -0,0 +1,129 @@ +/* + * Copyright © 2022 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * 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 "loader_wayland_helper.h" + +#ifndef HAVE_WL_DISPATCH_QUEUE_TIMEOUT +static int +wl_display_poll(struct wl_display *display, + short int events, + const struct timespec *timeout) +{ + int ret; + struct pollfd pfd[1]; + struct timespec now; + struct timespec deadline = {0}; + struct timespec result; + struct timespec *remaining_timeout = NULL; + + if (timeout) { + clock_gettime(CLOCK_MONOTONIC, &now); + timespec_add(&deadline, &now, timeout); + } + + pfd[0].fd = wl_display_get_fd(display); + pfd[0].events = events; + do { + if (timeout) { + clock_gettime(CLOCK_MONOTONIC, &now); + timespec_sub_saturate(&result, &deadline, &now); + remaining_timeout = &result; + } + ret = ppoll(pfd, 1, remaining_timeout, NULL); + } while (ret == -1 && errno == EINTR); + + return ret; +} + +int +wl_display_dispatch_queue_timeout(struct wl_display *display, + struct wl_event_queue *queue, + const struct timespec *timeout) +{ + int ret; + struct timespec now; + struct timespec deadline = {0}; + struct timespec result; + struct timespec *remaining_timeout = NULL; + + if (timeout) { + clock_gettime(CLOCK_MONOTONIC, &now); + timespec_add(&deadline, &now, timeout); + } + + if (wl_display_prepare_read_queue(display, queue) == -1) + return wl_display_dispatch_queue_pending(display, queue); + + while (true) { + ret = wl_display_flush(display); + + if (ret != -1 || errno != EAGAIN) + break; + + if (timeout) { + clock_gettime(CLOCK_MONOTONIC, &now); + timespec_sub_saturate(&result, &deadline, &now); + remaining_timeout = &result; + } + ret = wl_display_poll(display, POLLOUT, remaining_timeout); + + if (ret <= 0) { + wl_display_cancel_read(display); + return ret; + } + } + + /* Don't stop if flushing hits an EPIPE; continue so we can read any + * protocol error that may have triggered it. */ + if (ret < 0 && errno != EPIPE) { + wl_display_cancel_read(display); + return -1; + } + + while (true) { + if (timeout) { + clock_gettime(CLOCK_MONOTONIC, &now); + timespec_sub_saturate(&result, &deadline, &now); + remaining_timeout = &result; + } + + ret = wl_display_poll(display, POLLIN, remaining_timeout); + if (ret <= 0) { + wl_display_cancel_read(display); + break; + } + + ret = wl_display_read_events(display); + if (ret == -1) + break; + + ret = wl_display_dispatch_queue_pending(display, queue); + if (ret != 0) + break; + } + + return ret; +} +#endif diff --git a/src/loader/loader_wayland_helper.h b/src/loader/loader_wayland_helper.h new file mode 100644 index 00000000000..ecd01e6d45a --- /dev/null +++ b/src/loader/loader_wayland_helper.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2022 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * 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 LOADER_WAYLAND_HELPER_HEADER_H +#define LOADER_WAYLAND_HELPER_HEADER_H + +#ifndef HAVE_WL_DISPATCH_QUEUE_TIMEOUT + +#include +#include +int +wl_display_dispatch_queue_timeout(struct wl_display *display, + struct wl_event_queue *queue, + const struct timespec *deadline); +#endif + +#endif diff --git a/src/loader/meson.build b/src/loader/meson.build index 043cc852112..ffb970f26be 100644 --- a/src/loader/meson.build +++ b/src/loader/meson.build @@ -37,6 +37,21 @@ else libloader_dri3_helper = [] endif +if with_platform_wayland + libloader_wayland_helper = static_library( + 'loader_wayland_helper', + 'loader_wayland_helper.c', + gnu_symbol_visibility : 'hidden', + include_directories : [inc_include, inc_src], + dependencies : [ + dep_wayland_client, + ], + build_by_default : false, + ) +else + libloader_wayland_helper = [] +endif + loader_c_args = [ '-DUSE_DRICONF', '-DDEFAULT_DRIVER_DIR="@0@"'.format(dri_search_path), diff --git a/src/meson.build b/src/meson.build index fb516e122e6..62c65face77 100644 --- a/src/meson.build +++ b/src/meson.build @@ -63,6 +63,9 @@ if cc.get_argument_syntax() == 'msvc' else idep_getopt = null_dep endif +if with_gallium or with_gbm or with_platform_wayland + subdir('loader') +endif if with_gallium subdir('mapi') endif @@ -115,9 +118,6 @@ endif if with_gallium_asahi or with_tools.contains('asahi') subdir('asahi') endif -if with_gallium or with_gbm - subdir('loader') -endif if with_gbm subdir('gbm') else diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build index be4886a1a9e..12b037d7d69 100644 --- a/src/vulkan/wsi/meson.build +++ b/src/vulkan/wsi/meson.build @@ -68,6 +68,7 @@ libvulkan_wsi = static_library( idep_vulkan_runtime_headers, idep_xmlconfig, idep_mesautil, platform_deps, idep_blake3 ], + link_with: libloader_wayland_helper, gnu_symbol_visibility : 'hidden', build_by_default : false, ) diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index 15c4d2342aa..2d062b10579 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -54,6 +54,8 @@ #include #include +#include + #ifdef MAJOR_IN_MKDEV #include #endif