summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2023-04-05 12:11:48 +0100
committerDaniel Stone <daniels@collabora.com>2024-04-16 15:18:05 +0100
commitfd4a6c521c6c16ee9edac78e5f22a2551d62df9b (patch)
tree63349c68f25e7941406bc6535445b4544a74394d
parentdf0d0ae79ae077bf9cdc4015d06f4616aa94b13c (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.yml2
-rwxr-xr-x.gitlab-ci/build-wayland.sh17
-rwxr-xr-x.gitlab-ci/debian-install.sh1
-rw-r--r--CMakeLists.txt22
-rw-r--r--tests/CMakeLists.txt4
-rw-r--r--tests/wayland/CMakeLists.no_api.txt28
-rw-r--r--tests/wayland/CMakeLists.txt1
-rw-r--r--tests/wayland/wayland-dmabuf-target.c243
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, &registry_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);
+}