diff --git a/.clang-tidy b/.clang-tidy index c83ed8f..da14682 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -20,6 +20,7 @@ Checks: > -cppcoreguidelines-avoid-do-while, -cppcoreguidelines-pro-type-reinterpret-cast, -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-union-access, -cppcoreguidelines-use-enum-class, google-global-names-in-headers, google-readability-casting, diff --git a/BUILD.md b/BUILD.md index 04421c0..d624a06 100644 --- a/BUILD.md +++ b/BUILD.md @@ -33,6 +33,7 @@ Quickshell has a set of base dependencies you will always need, names vary by di - `cmake` - `qt6base` - `qt6declarative` +- `libdrm` - `qtshadertools` (build-time) - `spirv-tools` (build-time) - `pkg-config` (build-time) @@ -146,7 +147,6 @@ Enables streaming video from monitors and toplevel windows through various proto To disable: `-DSCREENCOPY=OFF` Dependencies: -- `libdrm` - `libgbm` - `vulkan-headers` (build-time) diff --git a/changelog/next.md b/changelog/next.md index 587e667..e9b297c 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -64,3 +64,4 @@ set shell id. - `vulkan-headers` has been added as a build-time dependency for screencopy (Vulkan backend support). - `breakpad` has been replaced by `cpptrace`, which is far easier to package, and the `CRASH_REPORTER` cmake variable has been replaced with `CRASH_HANDLER` to stop this from being easy to ignore. - `DISTRIBUTOR_DEBUGINFO_AVAILABLE` was removed as it is no longer important without breakpad. +- `libdrm` is now unconditionally required as a direct dependency. diff --git a/default.nix b/default.nix index 02b8659..749ef49 100644 --- a/default.nix +++ b/default.nix @@ -76,6 +76,7 @@ buildInputs = [ qt6.qtbase qt6.qtdeclarative + libdrm cli11 ] ++ lib.optional withQtSvg qt6.qtsvg @@ -88,7 +89,7 @@ ++ lib.optional withJemalloc jemalloc ++ lib.optional (withWayland && lib.strings.compareVersions qt6.qtbase.version "6.10.0" == -1) qt6.qtwayland ++ lib.optionals withWayland [ wayland wayland-protocols ] - ++ lib.optionals (withWayland && libgbm != null) [ libdrm libgbm vulkan-headers ] + ++ lib.optionals (withWayland && libgbm != null) [ libgbm vulkan-headers ] ++ lib.optional withX11 libxcb ++ lib.optional withPam pam ++ lib.optional withPipewire pipewire diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 076ab90..4824965 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,3 +1,4 @@ +pkg_check_modules(libdrm REQUIRED IMPORTED_TARGET libdrm) qt_add_library(quickshell-core STATIC plugin.cpp shell.cpp @@ -54,7 +55,7 @@ qt_add_qml_module(quickshell-core install_qml_module(quickshell-core) -target_link_libraries(quickshell-core PRIVATE Qt::Quick Qt::QuickPrivate Qt::Widgets quickshell-build) +target_link_libraries(quickshell-core PRIVATE Qt::Quick Qt::QuickPrivate Qt::Widgets quickshell-build PkgConfig::libdrm) qs_module_pch(quickshell-core SET large) diff --git a/src/core/debuginfo.cpp b/src/core/debuginfo.cpp index f948d42..f26c72e 100644 --- a/src/core/debuginfo.cpp +++ b/src/core/debuginfo.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include #include "build.hpp" @@ -20,10 +22,82 @@ QString qsVersion() { QString qtVersion() { return qVersion() % QStringLiteral(" (built against " QT_VERSION_STR ")"); } +QString gpuInfo() { + auto deviceCount = drmGetDevices2(0, nullptr, 0); + if (deviceCount < 0) return "Failed to get DRM device count: " % QString::number(deviceCount); + auto* devices = new drmDevicePtr[deviceCount]; + auto devicesArrayGuard = qScopeGuard([&] { delete[] devices; }); + auto r = drmGetDevices2(0, devices, deviceCount); + if (deviceCount < 0) return "Failed to get DRM devices: " % QString::number(r); + auto devicesGuard = qScopeGuard([&] { + for (auto i = 0; i != deviceCount; ++i) drmFreeDevice(&devices[i]); // NOLINT + }); + + QString info; + auto stream = QTextStream(&info); + + for (auto i = 0; i != deviceCount; ++i) { + auto* device = devices[i]; // NOLINT + + int deviceNodeType = -1; + if (device->available_nodes & (1 << DRM_NODE_RENDER)) deviceNodeType = DRM_NODE_RENDER; + else if (device->available_nodes & (1 << DRM_NODE_PRIMARY)) deviceNodeType = DRM_NODE_PRIMARY; + + if (deviceNodeType == -1) continue; + + auto* deviceNode = device->nodes[DRM_NODE_RENDER]; // NOLINT + + auto driver = [&]() -> QString { + auto fd = open(deviceNode, O_RDWR | O_CLOEXEC); + if (fd == -1) return ""; + auto fdGuard = qScopeGuard([&] { close(fd); }); + auto* ver = drmGetVersion(fd); + if (!ver) return ""; + auto verGuard = qScopeGuard([&] { drmFreeVersion(ver); }); + + // clang-format off + return QString(ver->name) + % ' ' % QString::number(ver->version_major) + % '.' % QString::number(ver->version_minor) + % '.' % QString::number(ver->version_patchlevel) + % " (" % ver->desc % ')'; + // clang-format on + }(); + + QString product = "unknown"; + QString address = "unknown"; + + auto hex = [](int num, int pad) { return QString::number(num, 16).rightJustified(pad, '0'); }; + + switch (device->bustype) { + case DRM_BUS_PCI: { + auto* b = device->businfo.pci; + auto* d = device->deviceinfo.pci; + address = "PCI " % hex(b->bus, 2) % ':' % hex(b->dev, 2) % '.' % hex(b->func, 1); + product = hex(d->vendor_id, 4) % ':' % hex(d->device_id, 4); + } break; + case DRM_BUS_USB: { + auto* b = device->businfo.usb; + auto* d = device->deviceinfo.usb; + address = "USB " % QString::number(b->bus) % ':' % QString::number(b->dev); + product = hex(d->vendor, 4) % ':' % hex(d->product, 4); + } break; + default: break; + } + + stream << "GPU " << deviceNode << "\n Driver: " << driver << "\n Model: " << product + << "\n Address: " << address << '\n'; + } + + return info; +} + QString systemInfo() { QString info; auto stream = QTextStream(&info); + stream << gpuInfo() << '\n'; + stream << "/etc/os-release:"; auto osReleaseFile = QFile("/etc/os-release"); if (osReleaseFile.open(QFile::ReadOnly)) { diff --git a/src/core/debuginfo.hpp b/src/core/debuginfo.hpp index 7759d53..cc13f97 100644 --- a/src/core/debuginfo.hpp +++ b/src/core/debuginfo.hpp @@ -6,6 +6,7 @@ namespace qs::debuginfo { QString qsVersion(); QString qtVersion(); +QString gpuInfo(); QString systemInfo(); QString combinedInfo();