aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmil Velikov <emil.velikov@collabora.com>2021-06-20 13:01:00 +0100
committerEmil Velikov <emil.l.velikov@gmail.com>2021-07-13 14:47:42 +0000
commit6bf58d4bb9044a7c65818d5de5d4ca747766e77f (patch)
treebb902020f279ad5d1e3df7cc49a4375bfa350f31
parentc83212649b656bd66f57afe27d9ddf5a60a1405d (diff)
downloadwaffle-6bf58d4bb9044a7c65818d5de5d4ca747766e77f.tar.gz
gbm: use libdrm instead of libudev
Through Mesa we use libdrm's drmDevice2 API to gather DRM device details. Additionally the API is simpler and the code shorter. Execution time is nearly identical and with a pending libdrm MR - it will go down in half. While here, remove the link-time dependency - using dlopen/dlsym ftw. Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--Options.cmake2
-rw-r--r--README.md4
-rw-r--r--cmake/Modules/WaffleFindDependencies.cmake2
-rw-r--r--cmake/Modules/WaffleValidateOptions.cmake4
-rw-r--r--man/waffle_display.3.xml2
-rw-r--r--meson.build10
-rw-r--r--src/waffle/CMakeLists.txt4
-rw-r--r--src/waffle/gbm/wgbm_display.c63
-rw-r--r--src/waffle/gbm/wgbm_display.h3
-rw-r--r--src/waffle/gbm/wgbm_platform.c32
-rw-r--r--src/waffle/gbm/wgbm_platform.h10
-rw-r--r--src/waffle/meson.build2
13 files changed, 83 insertions, 57 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b03a24f..b692dc6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -40,10 +40,10 @@ container:
g++
gcc
libcmocka-dev
+ libdrm-dev
libegl1-mesa-dev
libgbm-dev
libgl1-mesa-dev
- libudev-dev
libwayland-dev
libx11-dev
libxcb1-dev
diff --git a/Options.cmake b/Options.cmake
index 699ec59..8f9439e 100644
--- a/Options.cmake
+++ b/Options.cmake
@@ -17,7 +17,7 @@ if(waffle_on_linux)
set(x11_egl_default OFF)
endif()
- if(gbm_FOUND AND libudev_FOUND AND egl_FOUND)
+ if(gbm_FOUND AND libdrm_FOUND AND egl_FOUND)
set(gbm_default ON)
else()
set(gbm_default OFF)
diff --git a/README.md b/README.md
index 6e04403..24e3f75 100644
--- a/README.md
+++ b/README.md
@@ -93,8 +93,8 @@ a comma-separated list of any combination of "x11", "wayland", and "drm".
- GBM:
- all: Install Mesa from source. Use -D platforms=drm
- Archlinux: pacman -S systemd
- - Fedora 17: yum install libudev-devel
- - Debian: apt-get install libgbm-dev libudev-dev
+ - Fedora 17: yum install libdrm-devel
+ - Debian: apt-get install libgbm-dev libdrm-dev
## Windows
diff --git a/cmake/Modules/WaffleFindDependencies.cmake b/cmake/Modules/WaffleFindDependencies.cmake
index d9005d2..fb7b322 100644
--- a/cmake/Modules/WaffleFindDependencies.cmake
+++ b/cmake/Modules/WaffleFindDependencies.cmake
@@ -87,7 +87,7 @@ if(waffle_on_linux)
# waffle_has_gbm
waffle_pkg_config(gbm gbm)
- waffle_pkg_config(libudev libudev)
+ waffle_pkg_config(libdrm libdrm)
endif()
diff --git a/cmake/Modules/WaffleValidateOptions.cmake b/cmake/Modules/WaffleValidateOptions.cmake
index 5e0029b..1409d96 100644
--- a/cmake/Modules/WaffleValidateOptions.cmake
+++ b/cmake/Modules/WaffleValidateOptions.cmake
@@ -87,9 +87,9 @@ if(waffle_on_linux)
"${gbm_missing_deps} gbm"
)
endif()
- if(NOT libudev_FOUND)
+ if(NOT libdrm_FOUND)
set(gbm_missing_deps
- "${gbm_missing_deps} libudev"
+ "${gbm_missing_deps} libdrm"
)
endif()
if(NOT egl_FOUND)
diff --git a/man/waffle_display.3.xml b/man/waffle_display.3.xml
index 9896247..87e76b2 100644
--- a/man/waffle_display.3.xml
+++ b/man/waffle_display.3.xml
@@ -111,7 +111,7 @@ struct waffle_display;
<envar>WAFFLE_GBM_DEVICE</envar>.
If <parameter>name</parameter> is null and <envar>WAFFLE_GBM_DEVICE</envar> is unset, then the function
- iterates using udev through the set of card devices in the drm subsystem, which are usually located in
+ iterates using libdrm through the set of card devices in the drm subsystem, which are usually located in
<filename>/dev/dri</filename>, and attempts to open each in turn with <code>open(O_RDWR | O_CLOEXEC)</code>
until successful.
</para>
diff --git a/meson.build b/meson.build
index 52ccc97..acf4e02 100644
--- a/meson.build
+++ b/meson.build
@@ -61,6 +61,7 @@ dep_threads = dependency('threads')
dep_dl = cc.find_library('dl', required : false)
dep_nacl = _dep_null
dep_gl = _dep_null
+dep_drm = _dep_null
dep_egl = _dep_null
dep_wayland_client = _dep_null
dep_wayland_egl = _dep_null
@@ -68,7 +69,6 @@ dep_wayland_scanner = _dep_null
dep_wayland_proto = _dep_null
dep_x11_xcb = _dep_null
dep_gbm = _dep_null
-dep_udev = _dep_null
dep_cocoa = _dep_null
dep_core_foundation = _dep_null
dep_gl_headers = _dep_null
@@ -93,10 +93,10 @@ else
dep_x11_xcb = dependency('x11-xcb', required : get_option('x11_egl'))
build_x11_egl = dep_egl.found() and dep_x11_xcb.found()
+ dep_drm = dependency('libdrm', required : get_option('gbm'))
dep_egl = dependency('egl', required : get_option('gbm'))
dep_gbm = dependency('gbm', required : get_option('gbm'))
- dep_udev = dependency('libudev', required : get_option('gbm'))
- build_gbm = dep_egl.found() and dep_gbm.found() and dep_udev.found()
+ build_gbm = dep_drm.found() and dep_egl.found() and dep_gbm.found()
dep_egl = dependency('egl', required : get_option('surfaceless_egl'))
build_surfaceless = dep_egl.found()
@@ -128,8 +128,8 @@ else
build_wayland = dep_egl.found() and dep_wayland_client.found() and dep_wayland_egl.found() and dep_wayland_scanner.found() and dep_wayland_proto.found()
# We're interested only in the headers provided
- # FINISHME: make x11_xcb and udev compile-only dependency
- _include_deps = [ dep_gl, dep_egl, dep_gbm, dep_wayland_client, dep_wayland_egl ]
+ # FINISHME: make x11_xcb compile-only dependency
+ _include_deps = [ dep_gl, dep_drm, dep_egl, dep_gbm, dep_wayland_client, dep_wayland_egl ]
foreach d : _include_deps
if d.found()
d = d.partial_dependency(compile_args : true)
diff --git a/src/waffle/CMakeLists.txt b/src/waffle/CMakeLists.txt
index e4f7fbf..6415ccf 100644
--- a/src/waffle/CMakeLists.txt
+++ b/src/waffle/CMakeLists.txt
@@ -26,7 +26,7 @@ include_directories(
${gbm_INCLUDE_DIRS}
${gl_INCLUDE_DIRS}
${GLEXT_INCLUDE_DIR}
- ${libudev_INCLUDE_DIRS}
+ ${libdrm_INCLUDE_DIRS}
${nacl_INCLUDE_DIRS}
${wayland-client_INCLUDE_DIRS}
${wayland-egl_INCLUDE_DIRS}
@@ -49,7 +49,7 @@ if(waffle_on_linux)
endif()
if(waffle_has_gbm)
list(APPEND waffle_libdeps
- ${libudev_LDFLAGS}
+ ${libdrm_LDFLAGS}
)
endif()
endif()
diff --git a/src/waffle/gbm/wgbm_display.c b/src/waffle/gbm/wgbm_display.c
index a106119..cc25f86 100644
--- a/src/waffle/gbm/wgbm_display.c
+++ b/src/waffle/gbm/wgbm_display.c
@@ -28,7 +28,7 @@
#include <stdlib.h>
#include <unistd.h>
-#include <libudev.h>
+#include <xf86drm.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -63,53 +63,40 @@ wgbm_display_destroy(struct wcore_display *wc_self)
return ok;
}
-int
-wgbm_get_default_fd_for_pattern(const char *pattern)
+static int
+wgbm_get_fd_for_node_type(drmDevicePtr *devs, int num_devs, int node_type)
{
- struct udev *ud;
- struct udev_enumerate *en;
- struct udev_list_entry *devices, *entry;
- const char *path, *filename;
- struct udev_device *device;
- int fd;
+ for (int i = 0; i < num_devs; i++) {
+ if (!(devs[i]->available_nodes & 1 << node_type))
+ continue;
- ud = udev_new();
- en = udev_enumerate_new(ud);
- udev_enumerate_add_match_subsystem(en, "drm");
- udev_enumerate_add_match_sysname(en, pattern);
- udev_enumerate_scan_devices(en);
- devices = udev_enumerate_get_list_entry(en);
-
- udev_list_entry_foreach(entry, devices) {
- path = udev_list_entry_get_name(entry);
- device = udev_device_new_from_syspath(ud, path);
- filename = udev_device_get_devnode(device);
- fd = open(filename, O_RDWR | O_CLOEXEC);
- udev_device_unref(device);
- if (fd >= 0) {
- udev_enumerate_unref(en);
- udev_unref(ud);
- return fd;
- }
+ int fd = open(devs[i]->nodes[node_type], O_RDWR | O_CLOEXEC);
+ if (fd < 0)
+ continue;
+
+ return fd;
}
- udev_enumerate_unref(en);
- udev_unref(ud);
return -1;
}
static int
-wgbm_get_default_fd(void)
+wgbm_get_default_fd(struct wgbm_platform *plat)
{
- int fd;
+ // Checking the first 64 devices is enough for now.
+ drmDevicePtr devs[64];
- // Try opening render node first
- fd = wgbm_get_default_fd_for_pattern("renderD[0-9]*");
- if (fd >= 0)
- return fd;
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+ int ret = plat->drm.GetDevices2(0, devs, ARRAY_SIZE(devs));
+ if (ret < 0)
+ return ret;
+
+ // Try opening render node first, then fall back to the primary
+ int fd = wgbm_get_fd_for_node_type(devs, ret, DRM_NODE_RENDER);
+ if (fd < 0)
+ fd = wgbm_get_fd_for_node_type(devs, ret, DRM_NODE_PRIMARY);
- // If render nodes are not supported, then fall back to the card
- fd = wgbm_get_default_fd_for_pattern("card[0-9]*");
+ plat->drm.FreeDevices(devs, ret);
return fd;
}
@@ -138,7 +125,7 @@ wgbm_display_connect(struct wcore_platform *wc_plat,
goto error;
}
} else {
- fd = wgbm_get_default_fd();
+ fd = wgbm_get_default_fd(plat);
if (fd < 0) {
wcore_errorf(WAFFLE_ERROR_UNKNOWN, "open drm file for gbm failed");
goto error;
diff --git a/src/waffle/gbm/wgbm_display.h b/src/waffle/gbm/wgbm_display.h
index e19664a..ba4bb89 100644
--- a/src/waffle/gbm/wgbm_display.h
+++ b/src/waffle/gbm/wgbm_display.h
@@ -65,6 +65,3 @@ wgbm_display_get_native(struct wcore_display *wc_self);
void
wgbm_display_fill_native(struct wgbm_display *self,
struct waffle_gbm_display *n_dpy);
-
-int
-wgbm_get_default_fd_for_pattern(const char *pattern);
diff --git a/src/waffle/gbm/wgbm_platform.c b/src/waffle/gbm/wgbm_platform.c
index 613b005..ada162d 100644
--- a/src/waffle/gbm/wgbm_platform.c
+++ b/src/waffle/gbm/wgbm_platform.c
@@ -41,6 +41,7 @@
#include "wgbm_window.h"
static const char *libgbm_filename = "libgbm.so.1";
+static const char *libdrm_filename = "libdrm.so.2";
static const struct wcore_platform_vtbl wgbm_platform_vtbl;
@@ -56,6 +57,16 @@ wgbm_platform_teardown(struct wgbm_platform *self)
if (self->linux)
ok &= linux_platform_destroy(self->linux);
+ if (self->drm.handle) {
+ error = dlclose(self->drm.handle);
+ if (error) {
+ ok = false;
+ wcore_errorf(WAFFLE_ERROR_UNKNOWN,
+ "dlclose(\"%s\") failed: %s",
+ libdrm_filename, dlerror());
+ }
+ }
+
if (self->gbmHandle) {
error = dlclose(self->gbmHandle);
if (error) {
@@ -112,6 +123,27 @@ wgbm_platform_init(struct wgbm_platform *self)
GBM_FUNCTIONS(RETRIEVE_GBM_SYMBOL);
#undef RETRIEVE_GBM_SYMBOL
+ self->drm.handle = dlopen(libdrm_filename, RTLD_LAZY | RTLD_LOCAL);
+ if (!self->drm.handle) {
+ wcore_errorf(WAFFLE_ERROR_FATAL,
+ "dlopen(\"%s\") failed: %s",
+ libdrm_filename, dlerror());
+ goto error;
+ }
+
+#define RETRIEVE_DRM_SYMBOL(function) \
+ self->drm.function = dlsym(self->drm.handle, "drm" #function); \
+ if (!self->drm.function) { \
+ wcore_errorf(WAFFLE_ERROR_FATAL, \
+ "dlsym(\"%s\", \"%s\") failed: %s", \
+ libdrm_filename, "drm" #function, dlerror()); \
+ goto error; \
+ }
+
+ RETRIEVE_DRM_SYMBOL(GetDevices2);
+ RETRIEVE_DRM_SYMBOL(FreeDevices);
+#undef RETRIEVE_DRM_SYMBOL
+
self->linux = linux_platform_create();
if (!self->linux)
goto error;
diff --git a/src/waffle/gbm/wgbm_platform.h b/src/waffle/gbm/wgbm_platform.h
index 1253e1d..c408060 100644
--- a/src/waffle/gbm/wgbm_platform.h
+++ b/src/waffle/gbm/wgbm_platform.h
@@ -28,6 +28,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <gbm.h>
+#include <xf86drm.h>
#undef linux
@@ -56,6 +57,15 @@ struct wgbm_platform {
#define DECLARE(type, function, required, args) type (*function) args;
GBM_FUNCTIONS(DECLARE)
#undef DECLARE
+
+ struct {
+ void *handle;
+
+ int (*GetDevices2)(uint32_t flags, drmDevicePtr devices[],
+ int max_devices);
+
+ void (*FreeDevices)(drmDevicePtr devices[], int count);
+ } drm;
};
DEFINE_CONTAINER_CAST_FUNC(wgbm_platform,
diff --git a/src/waffle/meson.build b/src/waffle/meson.build
index 02de934..7e0be27 100644
--- a/src/waffle/meson.build
+++ b/src/waffle/meson.build
@@ -30,9 +30,9 @@
# harm.
deps_for_waffle = [
dep_gl,
+ dep_drm,
dep_egl,
dep_gbm,
- dep_udev,
dep_nacl,
dep_wayland_client,
dep_wayland_egl,