diff options
author | Emil Velikov <emil.velikov@collabora.com> | 2021-06-20 13:01:00 +0100 |
---|---|---|
committer | Emil Velikov <emil.l.velikov@gmail.com> | 2021-07-13 14:47:42 +0000 |
commit | 6bf58d4bb9044a7c65818d5de5d4ca747766e77f (patch) | |
tree | bb902020f279ad5d1e3df7cc49a4375bfa350f31 | |
parent | c83212649b656bd66f57afe27d9ddf5a60a1405d (diff) | |
download | waffle-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.yml | 2 | ||||
-rw-r--r-- | Options.cmake | 2 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | cmake/Modules/WaffleFindDependencies.cmake | 2 | ||||
-rw-r--r-- | cmake/Modules/WaffleValidateOptions.cmake | 4 | ||||
-rw-r--r-- | man/waffle_display.3.xml | 2 | ||||
-rw-r--r-- | meson.build | 10 | ||||
-rw-r--r-- | src/waffle/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/waffle/gbm/wgbm_display.c | 63 | ||||
-rw-r--r-- | src/waffle/gbm/wgbm_display.h | 3 | ||||
-rw-r--r-- | src/waffle/gbm/wgbm_platform.c | 32 | ||||
-rw-r--r-- | src/waffle/gbm/wgbm_platform.h | 10 | ||||
-rw-r--r-- | src/waffle/meson.build | 2 |
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) @@ -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, |