diff options
author | Daniel Stone <daniels@collabora.com> | 2023-04-05 12:11:48 +0100 |
---|---|---|
committer | Daniel Stone <daniels@collabora.com> | 2024-04-16 15:18:05 +0100 |
commit | fd4a6c521c6c16ee9edac78e5f22a2551d62df9b (patch) | |
tree | 63349c68f25e7941406bc6535445b4544a74394d | |
parent | df0d0ae79ae077bf9cdc4015d06f4616aa94b13c (diff) |
wayland: Add Wayland dmabuf driver-name test
This test checks to see whether the Wayland compositor advertises the
expected device as its primary device through the dmabuf interface, so
can be used as a basic smoke test for checking that clients are able to
use the right renderer.
Signed-off-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/piglit/-/merge_requests/796>
-rw-r--r-- | .gitlab-ci.yml | 2 | ||||
-rwxr-xr-x | .gitlab-ci/build-wayland.sh | 17 | ||||
-rwxr-xr-x | .gitlab-ci/debian-install.sh | 1 | ||||
-rw-r--r-- | CMakeLists.txt | 22 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tests/wayland/CMakeLists.no_api.txt | 28 | ||||
-rw-r--r-- | tests/wayland/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/wayland/wayland-dmabuf-target.c | 243 |
8 files changed, 317 insertions, 1 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 58672fa68..c46d8cf70 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ # with older commits using the same tag. variables: FDO_UPSTREAM_REPO: mesa/piglit - FDO_DISTRIBUTION_TAG: "2024-03-25-codespell-ignorelist" + FDO_DISTRIBUTION_TAG: "2024-04-16-wayland-protocols" FDO_DISTRIBUTION_VERSION: bullseye-slim WINDOWS_TAG: "2022-07-27-win2022" WINDOWS_IMAGE: "$CI_REGISTRY_IMAGE/windows/x64_build:$WINDOWS_TAG" diff --git a/.gitlab-ci/build-wayland.sh b/.gitlab-ci/build-wayland.sh new file mode 100755 index 000000000..c74e845a4 --- /dev/null +++ b/.gitlab-ci/build-wayland.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2086 # we want word splitting + +set -ex + +# When changing this file, you need to bump the following .gitlab-ci.yml tag: +# FDO_DISTRIBUTION_TAG + +export WAYLAND_PROTOCOLS_VERSION="1.24" + +git clone https://gitlab.freedesktop.org/wayland/wayland-protocols +cd wayland-protocols +git checkout "$WAYLAND_PROTOCOLS_VERSION" +meson setup _build $EXTRA_MESON_ARGS +meson install -C _build +cd .. +rm -rf wayland-protocols diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh index 957df2bc9..9a3c02308 100755 --- a/.gitlab-ci/debian-install.sh +++ b/.gitlab-ci/debian-install.sh @@ -88,6 +88,7 @@ do rm /tmp/waffle-$target.zip done +.gitlab-ci/build-wayland.sh apt-get purge -y $EPHEMERAL apt-get autoremove -y --purge diff --git a/CMakeLists.txt b/CMakeLists.txt index 107456bba..6dc89a1dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,20 @@ if(PIGLIT_USE_WAYLAND) "Failed to find xkbcommon library.") endif() pkg_check_modules(XKBCOMMON QUIET xkbcommon) + + pkg_check_modules(WaylandProtocols REQUIRED wayland-protocols>=1.24) + pkg_get_variable(WaylandProtocols_DATADIR wayland-protocols pkgdatadir) + if (NOT WaylandProtocols_DATADIR) + message(FATAL_ERROR "Failed to find wayland-protocols XML path") + endif() + + pkg_check_modules(WaylandScanner REQUIRED wayland-scanner) + pkg_get_variable(WaylandScannerPath wayland-scanner wayland_scanner) + if (NOT WaylandScannerPath) + message(FATAL_ERROR "Failed to find wayland-scanner path from pkg-config") + endif() + add_executable(WaylandScannerExe IMPORTED) + set_property(TARGET WaylandScannerExe PROPERTY IMPORTED_LOCATION ${WaylandScannerPath}) endif() if(PIGLIT_USE_X11 AND OPENGL_gl_LIBRARY AND PIGLIT_BUILD_GLX_TESTS) @@ -222,6 +236,14 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") pkg_check_modules(LIBVULKAN QUIET vulkan) ENDIF() +if(LIBDRM_FOUND) + if(LIBDRM_VERSION VERSION_GREATER "2.4.109") + set(PIGLIT_HAS_DRM_GET_DEVICE_BY_DEVID true) + else() + set(PIGLIT_HAS_DRM_GET_DEVICE_BY_DEVID false) + endif() +endif() + if(PIGLIT_BUILD_VK_TESTS) if (NOT LIBVULKAN_FOUND) message(FATAL_ERROR "libvulkan required by vulkan tests not found") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 704129474..e3c964a67 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -43,4 +43,8 @@ IF(PIGLIT_BUILD_CL_TESTS) add_subdirectory (cl) ENDIF(PIGLIT_BUILD_CL_TESTS) +if(PIGLIT_USE_WAYLAND) + add_subdirectory (wayland) +ENDIF(PIGLIT_USE_WAYLAND) + piglit_include_target_api() diff --git a/tests/wayland/CMakeLists.no_api.txt b/tests/wayland/CMakeLists.no_api.txt new file mode 100644 index 000000000..538924c4a --- /dev/null +++ b/tests/wayland/CMakeLists.no_api.txt @@ -0,0 +1,28 @@ +link_libraries ( + ${WAYLAND_LDFLAGS} + ${WAYLAND_LIBRARIES} + ${LIBDRM_LDFLAGS} + piglitutil +) + +include_directories( + ${WAYLAND_INCLUDE_DIRS} + ${LIBDRM_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} +) + +set(WaylandDmaBuf_PATH "${WaylandProtocols_DATADIR}/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml") + +add_custom_command(PRE_BUILD + OUTPUT linux-dmabuf-unstable-v1-protocol.c + COMMAND WaylandScannerExe private-code ${WaylandDmaBuf_PATH} linux-dmabuf-unstable-v1-protocol.c) +add_custom_command(PRE_BUILD + OUTPUT linux-dmabuf-unstable-v1-client-protocol.h + COMMAND WaylandScannerExe client-header ${WaylandDmaBuf_PATH} linux-dmabuf-unstable-v1-client-protocol.h) + +if(PIGLIT_HAS_DRM_GET_DEVICE_BY_DEVID) + piglit_add_executable(wayland-dmabuf-target + wayland-dmabuf-target.c + linux-dmabuf-unstable-v1-protocol.c + linux-dmabuf-unstable-v1-client-protocol.h) +endif(PIGLIT_HAS_DRM_GET_DEVICE_BY_DEVID) diff --git a/tests/wayland/CMakeLists.txt b/tests/wayland/CMakeLists.txt new file mode 100644 index 000000000..144a306f4 --- /dev/null +++ b/tests/wayland/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/wayland/wayland-dmabuf-target.c b/tests/wayland/wayland-dmabuf-target.c new file mode 100644 index 000000000..fb5f5e403 --- /dev/null +++ b/tests/wayland/wayland-dmabuf-target.c @@ -0,0 +1,243 @@ +/* + * Copyright 2021 Eric Engestrom + * Copyright 2023 Collabora, Ltd. + * SPDX-License-Identifier: MIT + */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <xf86drm.h> +#include <wayland-client.h> +#include "linux-dmabuf-unstable-v1-client-protocol.h" + +#include "piglit-util.h" + + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +struct wayland_display_target { + unsigned int roundtrips_needed; + struct wl_display *dpy; + struct wl_registry *registry; + struct zwp_linux_dmabuf_v1 *dmabuf; + struct zwp_linux_dmabuf_feedback_v1 *feedback; + bool feedback_done; + char *primary_driver_name; +}; + + +static int +open_drm_by_devid(dev_t devid) +{ + drmDevice *device; + int ret = -1; + int err; + + err = drmGetDeviceFromDevId(devid, 0, &device); + if (err != 0) { + printf("libdrm reports no devices for our devid\n"); + piglit_report_result(PIGLIT_FAIL); + } + + if (device->available_nodes & (1 << DRM_NODE_RENDER)) + ret = open(device->nodes[DRM_NODE_RENDER], O_RDWR); + if (ret == -1 && device->available_nodes & (1 << DRM_NODE_PRIMARY)) + ret = open(device->nodes[DRM_NODE_PRIMARY], O_RDWR); + if (ret == -1) { + printf("Couldn't open any libdrm devices for our devid\n"); + piglit_report_result(PIGLIT_FAIL); + } + + drmFreeDevice(&device); + + return ret; +} + + +static void +feedback_handle_done(void *_data, struct zwp_linux_dmabuf_feedback_v1 *feedback) +{ + struct wayland_display_target *data = _data; + + /* We've got all our feedback events now, so we can remove the roundtrip we + * added when binding the interface */ + data->feedback_done = true; +} + +static void +feedback_handle_format_table(void *_data, + struct zwp_linux_dmabuf_feedback_v1 *feedback, + int fd, uint32_t size) +{ + /* We don't need the format table for anything */ + close(fd); +} + +static void +feedback_handle_main_device(void *_data, + struct zwp_linux_dmabuf_feedback_v1 *feedback, + struct wl_array *dev_array) +{ + struct wayland_display_target *data = _data; + drmVersionPtr version; + dev_t dev; + int fd; + + /* This is basically a malformed compositor */ + if (dev_array->size != sizeof(dev)) { + printf("Expected main_device size to be %zu (dev_t), but it was %zu\n", + sizeof(dev), dev_array->size); + piglit_report_result(PIGLIT_FAIL); + } + + memcpy(&dev, dev_array->data, sizeof(dev)); + fd = open_drm_by_devid(dev); + if (fd < 0) { + printf("Couldn't open DRM device for main_device\n"); + piglit_report_result(PIGLIT_FAIL); + } + + version = drmGetVersion(fd); + if (!version || !version->name_len || !version->name) { + printf("drmGetVersion failed\n"); + piglit_report_result(PIGLIT_FAIL); + } + + data->primary_driver_name = malloc(version->name_len + 1); + assert(data->primary_driver_name); + memcpy(data->primary_driver_name, version->name, version->name_len); + data->primary_driver_name[version->name_len] = '\0'; + + drmFreeVersion(version); + close(fd); +} + +static void +feedback_handle_tranche_done(void *_data, + struct zwp_linux_dmabuf_feedback_v1 *feedback) +{ + /* We don't care about the content of the format/modifier tranches */ +} + +static void +feedback_handle_tranche_target_device(void *_data, + struct zwp_linux_dmabuf_feedback_v1 *feedback, + struct wl_array *dev_arr) +{ + /* We don't care about per-tranche target devices (e.g. scanout) */ +} + +static void +feedback_handle_tranche_formats(void *_data, + struct zwp_linux_dmabuf_feedback_v1 *feedback, + struct wl_array *indices) +{ + /* We don't care about per-tranche formats */ +} + +static void +feedback_handle_tranche_flags(void *_data, + struct zwp_linux_dmabuf_feedback_v1 *feedback, + uint32_t flags) +{ + /* We don't care about per-tranche flags */ +} + +static const struct zwp_linux_dmabuf_feedback_v1_listener feedback_listener = { + feedback_handle_done, + feedback_handle_format_table, + feedback_handle_main_device, + feedback_handle_tranche_done, + feedback_handle_tranche_target_device, + feedback_handle_tranche_formats, + feedback_handle_tranche_flags, +}; + +static void +registry_handle_global(void *_data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + struct wayland_display_target *data = _data; + + if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4) { + data->dmabuf = wl_registry_bind(data->registry, name, + &zwp_linux_dmabuf_v1_interface, + MIN(version, 4)); + data->feedback = zwp_linux_dmabuf_v1_get_default_feedback(data->dmabuf); + zwp_linux_dmabuf_feedback_v1_add_listener(data->feedback, + &feedback_listener, + data); + /* Need another roundtrip to collect the feedback events */ + data->roundtrips_needed++; + } +} + +static void +registry_handle_remove(void *_data, struct wl_registry *registry, uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_remove +}; + + +int +main(void) +{ + const char *expected_driver_name = NULL; + struct wayland_display_target data; + + memset(&data, 0, sizeof(data)); + + expected_driver_name = getenv("PIGLIT_WAYLAND_EXPECTED_DRIVER"); + if (!expected_driver_name) { + printf("$PIGLIT_WAYLAND_EXPECTED_DRIVER must be set to run this test\n"); + piglit_report_result(PIGLIT_SKIP); + } + + /* Connect to $WAYLAND_DISPLAY or $WAYLAND_SOCKET */ + data.dpy = wl_display_connect(NULL); + if (!data.dpy) { + printf("Could not connect to Wayland display\n"); + piglit_report_result(PIGLIT_SKIP); + } + + /* The registry advertises the available interfaces */ + data.registry = wl_display_get_registry(data.dpy); + assert(data.registry); + wl_registry_add_listener(data.registry, ®istry_listener, &data); + + /* Listen for the wl_registry advertisements to get supported interfaces */ + wl_display_roundtrip(data.dpy); + + if (!data.dmabuf) { + printf("zwp_linux_dmabuf_v1 is not available\n"); + piglit_report_result(PIGLIT_SKIP); + } + + /* Wait until we receive the zwp_linux_dmabuf_feedback_v1.done event */ + while (!data.feedback_done) + wl_display_roundtrip(data.dpy); + + if (!data.primary_driver_name || + strcmp(data.primary_driver_name, expected_driver_name) != 0) { + printf("Got driver name %s, wanted %s\n", data.primary_driver_name, + expected_driver_name); + piglit_report_result(PIGLIT_FAIL); + } + + free(data.primary_driver_name); + zwp_linux_dmabuf_feedback_v1_destroy(data.feedback); + zwp_linux_dmabuf_v1_destroy(data.dmabuf); + wl_registry_destroy(data.registry); + wl_display_disconnect(data.dpy); + + piglit_report_result(PIGLIT_PASS); +} |