Compare commits

...

166 Commits

Author SHA1 Message Date
Carter Li 0869809857 Merge pull request #2446 from fastfetch-cli/dev
Release: v2.66.0
2026-07-10 02:04:09 -05:00
Carter Li c31779e99d CI: ensures CMAKE_BUILD_TYPE is correctly set 2026-07-10 14:44:39 +08:00
Carter Li 89ad35d8a1 GPU (BSD): fixes building when DRM is not enabled 2026-07-10 13:41:13 +08:00
Carter Li d651f3de43 Common (Tracer): updates comments [ci skip] 2026-07-10 13:11:17 +08:00
Carter Li c34c3e5aae Release: v2.66.0 2026-07-10 10:21:45 +08:00
Carter Li c5c61584d9 CPU / GPU (macOS): fixes operator priority bug 2026-07-10 10:12:00 +08:00
Carter Li 48c3b4f980 CPU (Linux): removes ARM core count in CPU name 2026-07-10 08:32:42 +08:00
Carter Li 93bca8d480 CPU (Linux): disables printing package count by default
The detection code is problematic. Let's hide the package count before we can find the root cause.
2026-07-10 08:32:42 +08:00
Carter Li c690fe5aa9 BluetoothRadio: fixes memleaks 2026-07-10 08:32:42 +08:00
Carter Li 55e674e1cb GPU: code cleanups and bug fixes 2026-07-09 20:40:49 +08:00
Carter Li 0495c47909 GPU (Linux): fixes GPU core counting on Asahi Linux 2026-07-09 20:04:11 +08:00
Marvin Hinz 2f79c39f62 OS (Linux): adds support for proxmox backup server detection (#2443)
* add support for proxmox backup server detection

* Update Proxmox identifiers and pretty names

* Simplify Proxmox logo names in p.inc

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-07-09 19:05:22 +08:00
Carter Li 44056f1c85 GPU (Linux): fixes accurate AMD GPU names are not queried in driverSpecific mode 2026-07-08 18:14:06 +08:00
李通洲 6358bd7844 FFstrbuf: optimises ffStrbufEnsureFreeNoCheck 2026-07-07 19:15:36 +08:00
Carter Li 11d77e0d09 Logo (Builtin): updates linuxmint_small 2026-07-06 17:27:33 +08:00
李通洲 ec25659503 Presets: uses the builtin icons in examples/10 to avoid inconsistency [ci skip]
Fixes #2438
2026-07-05 08:16:55 +08:00
Carter Li 35dbcb2588 CI: updates scripts 2026-07-04 18:49:00 +08:00
Carter Li 8b6a74f2ec Doc: update changelog 2026-07-03 16:18:01 +08:00
Carter Li 2ea6c3767e Logo (Builtin): cleanup a lot of distro names 2026-07-03 16:15:58 +08:00
Carter Li 827bc26b0a Trace: removes useless empty lines 2026-07-03 15:40:32 +08:00
Carter Li e12f3631d4 OS (Linux): fixes potencial issue 2026-07-03 15:37:38 +08:00
Carter Li 52c9730542 Tracer: query tid only when threading is enabled 2026-07-03 15:36:41 +08:00
Carter Li 225d9e7771 Release: v2.65.3 2026-07-03 14:50:59 +08:00
Carter Li d031d6c20f FFPlatform (Windows): hard codes i686 CPU arch 2026-07-03 14:36:18 +08:00
李通洲 35af768d92 Shell (Windows): improves performance of Windows PowerShell version detection 2026-07-03 11:07:15 +08:00
Carter Li 22c4620345 Logo (Builtin): adds Azure Linux
Fixes #2435
2026-07-03 09:45:34 +08:00
Carter Li 81738aa303 WM (Linux): fixes compatibility with WSL 2.9.3+ 2026-07-02 17:34:43 +08:00
Carter Li 113f7d34d8 OS (Linux): Add Astra Linux version detection
Fixes #2427
2026-07-01 10:57:01 +08:00
Carter Li 62513004c8 Logo (Builtin): adds Flatcar 2026-07-01 10:29:47 +08:00
Carter Li 1b36c3cd5f Logo (Builtin): updates c.inc 2026-07-01 10:29:47 +08:00
eepy 78874ae583 Logo: add chimera2, parabola2_small, postmarketos2, qubes_small (#2430)
* Logo: add chimera2, parabola2_small, postmarketos2, qubes_small

* Logo: add types to chimera2, parabola2_small, postmarketos2, qubes_small, remove "parabola-gnulinux"

* Change logo names to use capital letters

---------

Co-authored-by: v_v <circlepuller@inbox.lv>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-06-30 21:29:39 -05:00
李通洲 a447928853 FFstrbuf: don't try to inline functions with varargs 2026-06-30 19:35:34 +08:00
李通洲 9f446bdad7 Common (Library): adds fast path for loading only one lib 2026-06-30 19:35:34 +08:00
李通洲 4cf060eb27 Logo (Image): improves performance of DLL searching on WIndows 2026-06-30 19:35:34 +08:00
Carter Li 08d419d75c Global: adds a simple tracer 2026-06-30 16:19:57 +08:00
Carter Li 3ae1bfdc24 Media (macOS): uses perl for faster startup 2026-06-30 15:22:19 +08:00
李通洲 0e257f25c2 Platform (Windows): one less syscall 2026-06-30 09:03:00 +08:00
Carter Li 195e148cc1 Common: inlines more functions 2026-06-30 09:03:00 +08:00
Carter Li 5ab192ee05 Common (Thread): adds ffThreadGetCurrentId 2026-06-30 00:39:36 +08:00
weedygmd 4897152af6 Logo: adds chimera linux small logo (#2426)
* added small chimera linux logo

* Add logo type for Chimera_small

---------

Co-authored-by: Weed <weedygmd>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-06-29 00:36:10 -05:00
Carter Li 69418cb527 Packaging: updates debian stuff [ci skip] 2026-06-29 10:12:54 +08:00
李通洲 0e90f3a7d4 GPU (Windows): fixes typo 2026-06-28 17:07:48 +08:00
Carter Li 1a663e72da Release: v2.65.2 (#2425) 2026-06-28 03:55:56 -05:00
李通洲 e0ae1ac1a2 GPU (Intel): adds comments 2026-06-28 16:26:00 +08:00
李通洲 e0d141ecf6 Memory (BSD): adds underflow protection (should not happen) 2026-06-28 16:25:08 +08:00
李通洲 29eb8bb57d Chore: fixes typos 2026-06-28 16:25:07 +08:00
李通洲 bc1f240558 Memory (Linux): uses strtoull to avoid overflow in 32-bit systems 2026-06-28 16:25:07 +08:00
李通洲 3e15a2591a Release: v2.65.2 2026-06-28 16:25:07 +08:00
李通洲 0ec9443de5 Logo (Builtin): adds Turkish
Fixes #2421
2026-06-28 16:25:07 +08:00
李通洲 4a4ca9a4a8 Memory (NetBSD): takes ZFS arc bytes into account
Used logic from FreeBSD
2026-06-28 16:25:07 +08:00
李通洲 acf76e565a Memory (FreeBSD): don't query c_min if querying size fails 2026-06-28 16:25:07 +08:00
李通洲 778aa21192 Memory (SunOS): takes ZFS arc bytes into account 2026-06-28 16:25:07 +08:00
Carter Li dfdc7284a2 Memory (Linux): takes ZFS arc bytes into account
Fixes #1995
2026-06-28 16:25:07 +08:00
Carter Li 231d7fcd4d Memory (FreeBSD): takes ZFS arc bytes into account
Fixes #2418
2026-06-28 16:25:07 +08:00
Carter Li a3184601dc GPU: detects PCIe speed only in driverSpecific mode
Fixes #2419
2026-06-28 16:25:07 +08:00
李通洲 e3dfeeb8db GPU (MT): adds PCIe speed detection support 2026-06-27 09:46:30 +08:00
Carter Li ccdcd6ab6f Codec (Linux): fixes crashing on AMD GPUs
Ref: https://github.com/fastfetch-cli/fastfetch/issues/2419#issuecomment-4812121503
2026-06-27 08:12:22 +08:00
Carter Li 64d205628e Common (Settings): adds SQLITE_OPEN_NOMUTEX fiag when opening sqlite db 2026-06-26 22:52:59 +08:00
Carter Li ff13adf1b4 Logo (Builtin): updates CachyOS 2026-06-26 00:18:08 +08:00
iinsert c38fd9ec10 Chore: adds Catnap repo link to attribution comments in examples 13-16 (#2417) 2026-06-25 23:07:49 +08:00
Carter Li 96793ec604 Packaging: updates debian stuff [ci skip] 2026-06-24 14:28:35 +08:00
Carter Li b79a336576 Release: 2.65.1
Revision to make github happy
2026-06-24 10:21:03 +08:00
Carter Li d36e3a793b Merge pull request #2410 from fastfetch-cli/dev
Release v2.65.0
2026-06-23 20:39:21 -05:00
Carter Li d48bb48e4f Codec (Linux): fixes potential memleaks 2026-06-24 08:45:45 +08:00
李通洲 835001eb2f Doc: updates changelog 2026-06-23 15:51:42 +08:00
李通洲 5647703e4d WM (Linux): adds weston detection support 2026-06-23 15:51:42 +08:00
李通洲 eff0108bb5 Codec (Linux): adds va-x11 method 2026-06-23 15:33:58 +08:00
Carter Li 31c1431ac6 Release: v2.65.0 2026-06-23 13:16:49 +08:00
Carter Li fa2c56cb9f Global: fixes bugs found by CI
The code quality is to be improved...
2026-06-23 13:16:49 +08:00
Carter Li 104b33c1f7 Display: defaults disableLinewrap to false 2026-06-23 11:05:11 +08:00
Gretagen ZETA cb4502dacc Logo (Builtin): adds Zerene OS mainline (#2404)
* Create zerene.txt

* Update z.inc

* Fixed z.inc

Changed the problematic line mismatch

* Update z.inc

* Update z.inc

more fixes to z.inc

* Remove duplicate name entry for Zerene logo

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-06-22 20:24:55 +08:00
Carter Li 3dc86391ab Doc: update changelog [ci skip] 2026-06-22 16:11:44 +08:00
Carter Li f5a67b25f4 Packages (Linux): cleanups install-release package count code 2026-06-22 13:28:18 +08:00
Jess d8be61411e Packages (Linux): add install-release package count support (#2342)
* feat: add install-release package count support

* Apply suggestion from @codacy-production[bot]

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>

* Fix formatting of ffParsePropFileValues call

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>
2026-06-22 00:23:21 -05:00
Carter Li 61968ca95c Chore: tidy 2026-06-22 13:18:27 +08:00
Carter Li 9f190b46c9 DisplayServer (macOS): detects string serial number for Apple Silicon 2026-06-22 13:18:27 +08:00
Kerem Gökcek a6aac70a5e Packages (Linux): Improve emerge detection speed (#2406)
* Packages (Linux): Improve emerge detection speed

* Fix code styling
2026-06-21 21:56:01 -05:00
yabobay 3aa43212ff Packages (Linux): support porg 2026-06-22 10:45:08 +08:00
李通洲 7c39b64fb4 CMake: extracts package managers from source code 2026-06-20 19:24:19 +08:00
Carter Li e1963e41be Networking (Linux): don't use MSG_DONTWAIT to send HTTP request
Ref #2401
2026-06-20 10:17:04 +08:00
Carter Li a1d4cbf67f DisplayServer (Wayland): correctly reports platform api 2026-06-20 08:59:31 +08:00
Carter Li f5b9e09d91 DisplayServer (macOS): detects string serial number 2026-06-20 01:21:39 +08:00
Carter Li 9742dda795 Wifi (FreeBSD): adds WPA version detection support 2026-06-19 23:30:01 +08:00
Carter Li 677c213397 Codec (Linux): fixes bug in ffDetectCodecByVdpau 2026-06-19 23:02:13 +08:00
李通洲 8f0a12323b Doc: updates changelog 2026-06-19 20:30:32 +08:00
李通洲 b49f0b3d9c Fastfetch: improves error message for config errors 2026-06-19 20:19:50 +08:00
李通洲 bc686b2c84 Logo: improves error message for chafa options 2026-06-19 20:14:58 +08:00
Carter Li 7c2f7fa4f2 DisplayServer (Linux): detects preferred resolution from EDID 2026-06-19 19:21:00 +08:00
Carter Li 5fd059827d Display: fetch text serial if available instead of the 4-byte integer 2026-06-19 18:56:08 +08:00
Carter Li 240928138e GPU: adds egl-ext detection method 2026-06-18 21:03:28 +08:00
Carter Li 508a50f803 OpenGL (EGL): optimises code 2026-06-18 21:03:28 +08:00
Carter Li bd40d8756e GPU (FreeBSD): adds a missing var-init 2026-06-18 19:33:40 +08:00
Carter Li b732e0c6d7 Codec (Linux): fixes a crash 2026-06-18 18:11:48 +08:00
Carter Li 96685b7ebe Global: cleanups FF_HAVE_DRM macro 2026-06-18 17:45:19 +08:00
Carter Li 49a1e42efd CI: updates spellcheck 2026-06-18 13:39:56 +08:00
Carter Li b0fd11fcbd Global: simplifies code 2026-06-18 10:59:36 +08:00
Carter Li b6127ff2c9 Codec (Linux): removes usage of libdrm 2026-06-18 10:56:28 +08:00
Carter Li f3babe3187 Codec (Linux): fixes memleaks 2026-06-18 10:44:11 +08:00
Carter Li e9c0d886d1 DisplayServer (Linux): be compatible with KDE 6.7
This PR also removes usage of `kde-output-order-v1-protocol`, which disables detection of primary monitor for old KDE versions
2026-06-18 10:31:37 +08:00
Carter Li d6a4946511 DisplayServer (Linux): fixes memleaks 2026-06-18 10:06:52 +08:00
Carter Li 43e0cc22ff GPU: initializes pcieSpeed everywhere 2026-06-18 08:44:01 +08:00
Carter Li c42ea6eeea DisplayServer (Linux): adds HDR detection support
Fixes #2356
2026-06-17 20:07:37 +08:00
Carter Li fe7962d5d2 DisplayServer (Linux): embeds definitions of wl-output-* 2026-06-17 15:32:27 +08:00
Carter Li e84195bca0 Linux (Wayland): drops zwlr-output.c
It doesn't expose much more functions than `wl-output`
2026-06-17 15:10:24 +08:00
Carter Li bf0133fe60 Packaging: updates debian stuff [ci skip] 2026-06-17 15:06:15 +08:00
李通洲 942c15b7b0 CPU (X86): fixes detection for AMD Carrizo
Ref: https://github.com/anrieff/libcpuid/commit/b0c4959cf4a8b8351ab33add3f83ee0dcf37faf1
2026-06-15 18:41:48 +08:00
Carter Li 61a0bbcc8d GPU (Linux): fixes building for old kernel headers 2026-06-14 19:51:30 +08:00
Carter Li 8b3673eb38 GPU (Nvidia): replaces deprecated API nvmlDeviceGetTemperature with suggested one 2026-06-14 19:51:30 +08:00
Carter Li 22f9948497 GPU: detect current pcie link speed 2026-06-14 19:51:30 +08:00
李通洲 107f39eb15 JsonSchema: update moduleFormat 2026-06-14 19:51:30 +08:00
Carter Li 4e44c0520b GPU: detects max PCI gen & link width 2026-06-14 19:51:29 +08:00
Carter Li 55eb3c59d4 GPU (Linux): replaces amdgpu library with raw ioctl calls 2026-06-14 19:51:29 +08:00
Carter Li 878ccf1375 DisplayServer (Linux): use kernel headers if libdrm is not available 2026-06-13 12:29:51 +08:00
Carter Li ebb0cf77bd CMake: checks linux kernel headers 2026-06-13 12:29:51 +08:00
Carter Li 17914dc29e Global: unifies FF_STR macro 2026-06-13 12:29:51 +08:00
李通洲 14dfe171fb GPU (OpenBSD): adds DRM method 2026-06-13 12:29:51 +08:00
Carter Li 265c334399 GPU (FreeBSD): moves DRM detection to global space for OpenBSD use 2026-06-13 12:29:51 +08:00
Carter Li fc303c58db GPU: adds unified ffGPUFillVendorByDeviceName 2026-06-13 12:29:51 +08:00
Carter Li 01e7503263 GPU (BSD): uses direct ioctl calls (WIP) 2026-06-13 12:29:50 +08:00
Carter Li ffd0455fe3 DisplayServer (Linux): rewrites libdrm calls with plain ioctls 2026-06-12 14:34:36 +08:00
Carter Li 7df2ed2251 Packages: reorders package variables in custom format 2026-06-12 14:34:36 +08:00
Carter Li 2edc41dd9a CI (OpenBSD): updates packages 2026-06-11 15:14:39 +08:00
Carter Li cada77163e Chore: update .gitignore 2026-06-11 15:07:47 +08:00
Carter Li 7cecdb0e6d DisplayServer (Linux): don't return success if no devices are successfully connected 2026-06-11 10:49:07 +08:00
Carter Li 420a9e9d7b TerminalFont (Linux): adds kmscon support
Fixes #2393
2026-06-11 10:49:00 +08:00
Carter Li b96d8ad00b Terminal (Linux): adds kmscon version detection support 2026-06-11 10:15:50 +08:00
Carter Li 52970e2d13 Processing (Linux): don't use /proc/pid/exe as exePath when the file is not executable (no permission) 2026-06-11 10:15:50 +08:00
Carter Li 4594734b66 CI (OpenBSD): updates OS version 2026-06-09 16:07:56 +08:00
Carter Li eb54c89b4a OS (macOS): adds the code name of macOS 27 2026-06-09 14:05:23 +08:00
Carter Li 43301afc47 CPU: enables showPeCoreCount by default 2026-06-09 14:04:54 +08:00
Carter Li 09e28451ec CPU (Linux): simplifies code of frequency detection 2026-06-09 13:38:49 +08:00
Carter Li 35c2f8c924 CPU (Linux): fixes physical core detection on non-x86 2026-06-09 13:09:58 +08:00
李通洲 3ec7e94b47 CPU (Windows): uses a better way to fetch core types 2026-06-08 19:03:23 +08:00
Carter Li a720e1f945 Fastfetch (Windows): moves SetConsoleMode and SetConsoleOutputCP to the start of process
Fixes #2383
2026-06-08 10:58:14 +08:00
Carter Li 70061625f7 Chore: adds FF_A_COLD 2026-06-08 10:38:28 +08:00
李通洲 5cd4316f98 CPU (X86): uses normalized cpu brand name for pattern matching 2026-06-08 00:41:08 +08:00
李通洲 e946861eb0 Codec (Windows): fixes compatibility of Win 8.1 2026-06-08 00:41:01 +08:00
李通洲 f09aebecd5 CPU (X86): updates comments 2026-06-07 16:48:15 +08:00
李通洲 8f266eb2a7 Chore: don't check spelling in cpu_x86.c 2026-06-07 16:41:59 +08:00
李通洲 8ee08d0067 CI: don't run heavy tests if the light one failed 2026-06-07 16:40:40 +08:00
李通洲 e936ddef6b CPU (X86): adds code name and tech detection
Fixes #1501
2026-06-07 10:46:37 +08:00
李通洲 c706201282 Global: adds some always_inline 2026-06-06 23:01:18 +08:00
李通洲 e24e3b6b29 Global: returns false when an error is printed 2026-06-05 22:34:53 +08:00
李通洲 135547fd50 Logo: don't accept chafa options when chafa is disabled 2026-06-05 22:19:35 +08:00
李通洲 da05bed32f CMake: exposes pre-defined macros to fastfetch.c to avoid imcompatiblity with libfastfetch 2026-06-05 22:19:35 +08:00
Carter Li 636471c366 Merge pull request #2375 from fastfetch-cli/dev
Release v2.64.2
2026-06-05 18:36:58 +08:00
李通洲 cbc84fda6c Common (Lua): addresses AI's feedback 2026-06-05 18:21:28 +08:00
李通洲 fc7a0a8484 Codec (Linux): supports BINARY_LINK_TYPE=dynamic 2026-06-05 18:05:54 +08:00
李通洲 4d3b6c3b1b Common (QJS): supports BINARY_LINK_TYPE=dynamic 2026-06-05 17:49:49 +08:00
李通洲 70e67177fe Common (Lua): supports BINARY_LINK_TYPE=dynamic 2026-06-05 17:22:16 +08:00
李通洲 9fe7d6dbfa Logo: addresses review comments of AI 2026-06-05 16:34:02 +08:00
Carter Li a139a8c4a5 Doc: updates changelog [ci skip] 2026-06-05 16:22:04 +08:00
Valeriy Kosikhin da568c986e Logo (Builtin): update OpenWrt logo
Update the large logo for OpenWrt based on the official branding.
Add a small logo version.
Keep the old logo as openwrt_old.txt

Signed-off-by: Valeriy Kosikhin <vkosikhin@gmail.com>
2026-06-05 16:15:46 +08:00
Carter Li 727fbc0276 Doc: updates changelog 2026-06-05 15:29:00 +08:00
Carter Li 20aabdfd78 Global: resets keysHeight after every refresh 2026-06-05 15:27:25 +08:00
Carter Li e79aaf5ce1 Global: don't clear line in --logo-position right 2026-06-05 15:27:15 +08:00
Carter Li 53c2d07161 Release: v2.64.2 2026-06-05 14:51:50 +08:00
Carter Li 6b9f594620 Global: prevents ascii logo from being overwritten in --dynamic-interval mode 2026-06-05 14:47:01 +08:00
Carter Li ba3968784f Logo (Image): fixes image renders but quickly gets wiped
Regression from v2.64.0

Fixes: #2374
2026-06-05 13:12:07 +08:00
Carter Li 021ece1681 Merge pull request #2370 from fastfetch-cli/dev
Release: v2.64.1
2026-06-04 23:45:19 +08:00
李通洲 9787b56460 Release: v2.64.1 2026-06-04 20:15:54 +08:00
李通洲 54792e61ff Common (Lua): detects circular reference in encode_json 2026-06-04 20:15:54 +08:00
Carter Li b34e2a4055 Common (Base64): adds static to internal functions 2026-06-04 17:22:24 +08:00
Carter Li 3b56200ee4 Packages: adds option PACKAGES_REMOVE_DISABLED to remove disabled package managers from the build entirely 2026-06-04 17:22:24 +08:00
Carter Li de95a62e2f Codec (macOS): removes usage of JPEG XL; replaces enums with raw constants 2026-06-04 10:48:01 +08:00
Carter Li 72cb64a500 Common (Lua): optimises code; fixes incompatibility against lua 5.3 2026-06-04 10:48:01 +08:00
194 changed files with 8919 additions and 3778 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
[codespell]
check-filenames =
builtin = clear,rare,usage,informal
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda
+44 -21
View File
@@ -3,35 +3,58 @@ name: Reusable DragonFly amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: cpa.sh {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
uses: vmactions/dragonflybsd-vm@v1
- name: Start VM
uses: cross-platform-actions/action@master
with:
usesh: yes
envs: 'CMAKE_BUILD_TYPE'
prepare: |
uname -a
pkg update
pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf lua54 libva libvdpau
operating_system: dragonflybsd
version: '6.4.2'
shell: bash
cpu_count: 4
run: |
env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: Show system info
run: |
uname -a
pkg --version
- name: Update and install dependencies
run: |
sudo pkg update
sudo pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf lua54 libva libvdpau
- name: CMake configuration
run: env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
- name: CMake build
run: cmake --build . --target package --verbose -j4
- name: List features
run: ./fastfetch --list-features
- name: Run normal
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: Run json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: Run flashfetch
run: time ./flashfetch
- name: Run ldd
run: ldd fastfetch
- name: Run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
+43 -21
View File
@@ -3,37 +3,59 @@ name: Reusable FreeBSD amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: cpa.sh {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
- name: Start VM
uses: cross-platform-actions/action@master
with:
operating_system: freebsd
architecture: x86-64
cpu_count: 4
version: '15.1'
shell: bash
version: '15.0'
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa lua54 libva libvdpau
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
cpu_count: 4
- name: Show system info
run: |
uname -a
freebsd-version
pkg -v
- name: Update and install dependencies
run: |
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa lua54 libva libvdpau
- name: CMake configuration
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
- name: CMake build
run: cmake --build . --target package --verbose -j4
- name: List features
run: ./fastfetch --list-features
- name: Run normal
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: Run json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: Run flashfetch
run: time ./flashfetch
- name: Run ldd
run: ldd fastfetch
- name: Run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
+35 -18
View File
@@ -3,35 +3,52 @@ name: Reusable Haiku amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: cpa.sh {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
- name: Start VM
uses: cross-platform-actions/action@master
with:
operating_system: haiku
version: 'r1beta5'
architecture: x86-64
cpu_count: 4
shell: bash
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 lua
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ctest --output-on-failure
cpu_count: 4
- name: Show system info
run: uname -a
- name: Install dependencies
shell: cpa.sh {0} --reboot
run: pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake llvm22_clang ninja pkgconfig python3.10 lua || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake llvm22_clang ninja pkgconfig python3.10 lua
- name: CMake configuration
run: CC=clang CXX=clang++ cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
- name: CMake build
run: cmake --build . --target package --verbose -j4
- name: List features
run: ./fastfetch --list-features
- name: Run normal
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: Run json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: Run flashfetch
run: time ./flashfetch
- name: Run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
uses: uraimo/run-on-arch-action@v3
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
uses: uraimo/run-on-arch-action@v3
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
ffversion: ${{ steps.ffversion.outputs.ffversion }}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: uname -a
run: uname -a
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: uname -a
run: uname -a
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
uses: uraimo/run-on-arch-action@v3
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
runs-on: ${{ inputs.runs-on }}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: uname -a
run: uname -a
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: setup alpine linux
uses: jirutka/setup-alpine@master
+41 -20
View File
@@ -3,36 +3,57 @@ name: Reusable NetBSD amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: cpa.sh {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
- name: Start VM
uses: cross-platform-actions/action@master
with:
operating_system: netbsd
architecture: x86-64
cpu_count: 4
shell: bash
version: '10.1'
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick libva libvdpau
CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
shell: bash
cpu_count: 4
- name: Show system info
run: |
uname -a
pkgin -v
- name: Update and install dependencies
run: |
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick libva libvdpau
- name: CMake configuration
run: CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
- name: CMake build
run: cmake --build . --target package --verbose -j4
- name: List features
run: ./fastfetch --list-features
- name: Run normal
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: Run json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: Run flashfetch
run: time ./flashfetch
- name: Run ldd
run: ldd fastfetch
- name: Run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: uname -a
run: uname -a
+48 -23
View File
@@ -3,37 +3,62 @@ name: Reusable OmniOS amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: cpa.sh {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
uses: vmactions/omnios-vm@v1
- name: Start VM
uses: cross-platform-actions/action@master
with:
usesh: true
envs: 'CMAKE_BUILD_TYPE'
prepare: |
uname -a
pkg update --accept || true
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
operating_system: omnios
version: 'r151058'
shell: bash
cpu_count: 4
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
cmake --build . --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
cpack -V
- name: Show system info
run: |
uname -a
- name: Update and install dependencies
run: |
sudo pkg update --accept || true
sudo pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
- name: CMake configuration
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
- name: CMake build
run: cmake --build . --verbose -j4
- name: List features
run: ./fastfetch --list-features
- name: Run normal
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: Run json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: Run flashfetch
run: time ./flashfetch
- name: Run ldd
run: ldd fastfetch
- name: Run tests
run: ctest --output-on-failure
- name: Package
run: |
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
cpack -V
- name: upload artifacts
uses: actions/upload-artifact@v7
+41 -21
View File
@@ -3,37 +3,57 @@ name: Reusable OpenBSD amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: cpa.sh {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
- name: Start VM
uses: cross-platform-actions/action@master
with:
operating_system: openbsd
architecture: x86-64
cpu_count: 4
version: '7.9'
shell: bash
version: '7.8'
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
sudo pkg_add -u
sudo pkg_add -r llvm-21.1.2p0 cmake git wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa lua-5.4.7 # pkg-config is preinstalled
CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
cpu_count: 4
- name: Show system info
run: |
uname -a
- name: Update and install dependencies
run: |
sudo pkg_add -u
sudo pkg_add -r llvm-21.1.8p4 cmake git wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa lua-5.4.8p0 # pkg-config is preinstalled
- name: CMake configuration
run: CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
- name: CMake build
run: cmake --build . --target package --verbose -j4
- name: List features
run: ./fastfetch --list-features
- name: Run normal
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: Run json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: Run flashfetch
run: time ./flashfetch
- name: Run ldd
run: ldd fastfetch
- name: Run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: run VM
uses: vmactions/solaris-vm@v1
+3 -6
View File
@@ -3,22 +3,19 @@ name: Reusable Spellcheck
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install codespell
shell: bash
run: |
sudo apt-get update || true
sudo apt-get install -y codespell
pip3 install codespell
codespell --version
- name: Run Spellchecker
run: codespell
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: setup-msys2
uses: msys2/setup-msys2@v2
+16
View File
@@ -9,6 +9,7 @@ jobs:
uses: ./.github/workflows/build-spellcheck.yml
no-features-test:
needs: spellcheck
name: No-features-test
permissions:
security-events: write
@@ -17,6 +18,7 @@ jobs:
secrets: inherit
linux-hosts:
needs: no-features-test
name: Linux-${{ matrix.arch }}
permissions:
security-events: write
@@ -35,6 +37,7 @@ jobs:
secrets: inherit
linux-i686:
needs: no-features-test
name: Linux-i686
permissions:
security-events: write
@@ -43,6 +46,7 @@ jobs:
secrets: inherit
linux-armv7l:
needs: no-features-test
name: Linux-armv7l
permissions:
security-events: write
@@ -51,6 +55,7 @@ jobs:
secrets: inherit
linux-armv6l:
needs: no-features-test
name: Linux-armv6l
permissions:
security-events: write
@@ -59,6 +64,7 @@ jobs:
secrets: inherit
linux-vms:
needs: no-features-test
name: Linux-${{ matrix.arch }}
permissions:
security-events: write
@@ -75,11 +81,13 @@ jobs:
secrets: inherit
musl-amd64:
needs: no-features-test
name: Musl-amd64
uses: ./.github/workflows/build-musl-amd64.yml
secrets: inherit
macos-hosts:
needs: no-features-test
name: macOS-${{ matrix.arch }}
permissions:
security-events: write
@@ -98,16 +106,19 @@ jobs:
secrets: inherit
omnios-amd64:
needs: no-features-test
name: OmniOS-amd64
uses: ./.github/workflows/build-omnios-amd64.yml
secrets: inherit
solaris-amd64:
needs: no-features-test
name: Solaris-amd64
uses: ./.github/workflows/build-solaris-amd64.yml
secrets: inherit
freebsd-amd64:
needs: no-features-test
name: FreeBSD-amd64
permissions:
security-events: write
@@ -116,6 +127,7 @@ jobs:
secrets: inherit
openbsd-amd64:
needs: no-features-test
name: OpenBSD-amd64
permissions:
security-events: write
@@ -124,6 +136,7 @@ jobs:
secrets: inherit
netbsd-amd64:
needs: no-features-test
name: NetBSD-amd64
permissions:
security-events: write
@@ -132,6 +145,7 @@ jobs:
secrets: inherit
dragonfly-amd64:
needs: no-features-test
name: DragonFly-amd64
permissions:
security-events: write
@@ -140,6 +154,7 @@ jobs:
secrets: inherit
haiku-amd64:
needs: no-features-test
name: Haiku-amd64
permissions:
security-events: write
@@ -148,6 +163,7 @@ jobs:
secrets: inherit
windows-hosts:
needs: no-features-test
name: Windows-${{ matrix.arch }}
permissions:
security-events: write
+7 -5
View File
@@ -1,8 +1,10 @@
build/
.vs/
.vscode/
.cache/
.kdev4/
/build/
/build_*/
/build-*/
/.vs/
/.vscode/
/.cache/
/.kdev4/
.DS_Store
cscope.*
tags
+109
View File
@@ -1,3 +1,112 @@
# 2.66.0
Changes:
* CPU package count is no longer reported in the default output.
* Users can still print it in custom formats via `{packages}`
Bugfixes:
* Fixed compatibility with WSL 2.9.3 (#2433, WM, Linux)
* Fixed accurate AMD GPU names are not queried in `driverSpecific` mode (GPU, Linux)
* Fixed GPU core counting for Apple Silicon GPU on Asahi Linux (GPU, Linux)
* Some internal cleanups and optimizations
Features:
* Added Astra Linux version detection (OS, Linux)
* Improved performance of Windows PowerShell version detection (Shell, Windows)
* Improved performance of Media module on macOS (Media, macOS)
* Added proxmox backup server detection (#2443, OS, Linux)
Logos:
* Added Flatcar, Azure Linux
* Added Chimera_small, Chimera2, Parabola2_small, PostmarketOS2, Qubes_small
* Updated linuxmint_small
* Cleaned up distro names
# 2.65.2
Changes:
* Memory usage calculations now exclude the ZFS ARC cache on Linux, FreeBSD, NetBSD, and SunOS. (#1995 / #2418, Memory)
* This prevents the Memory module from reporting artificially high memory usage on systems with the ZFS kmod enabled.
Bugfixes:
* The GPU module no longer pings sleeping dedicated GPUs on dual-GPU laptops. (#2419, GPU)
* As a result, PCIe link speed detection (introduced in v2.65.0) is now only enabled in `driverSpecific` mode.
* Fixed a crash when detecting hardware codec support with the `amdgpu` driver on Linux. (#2419, Codec, Linux)
Logos:
* Updated CachyOS_small; fixed CachyOS logo colors to match the official logo better
* Added Turkish
# 2.65.1
No changes
# 2.65.0
Changes:
* `display.disableLinewrap` now defaults to `false`.
* This allows long lines to wrap instead of being truncated, preventing confusion for new users.
* Wrapped lines may overlap with the image logo. Users who prefer the old behavior can set `display.disableLinewrap: true` in their config file or use `--disable-linewrap true` on the command line.
* Reorders package manager variables in custom format strings, moving aggregate variables (e.g., `all`, `brew-all`, `flatpak-all`) to the end. (Packages)
* This is a breaking change for users relying on numeric placeholders (e.g., `{1}`). Numeric placeholders are a long-deprecated feature; named placeholders (e.g., `{pacman}`) are always preferred and future-proof.
* Enables `showPeCoreCount` by default to better display hybrid-architecture core counts. (CPU)
* No longer accepts `chafa` options in config files if `chafa` support was disabled at compile time. (Logo)
* This may affect users who generated their config files using `fastfetch --gen-full-config`. To resolve this, simply remove the `chafa` section from the config file.
Features:
* Adds detection for CPU code names (e.g., "Alder Lake", "Zen 4") and manufacturing technologies (e.g., "Intel 7", "TSMC N4") on x86 processors. (#1501, CPU, X86)
* These can be used in custom formats via `{code-name}` and `{technology}`.
* Adds PCIe link speed detection (current and max generation & lanes) for GPUs on Linux and Windows.
* These can be used in custom formats via `{pcie-max-speed}` and `{pcie-curr-speed}`.
* Adds HDR display detection via the `wp-color-management-v1` Wayland protocol. (#2356, Display, Linux)
* Previously, HDR detection was only supported on KDE Plasma.
* Adds the `egl-ext` detection method, which uses `EGL_EXT_device_enumeration` for GPU enumeration. (GPU)
* Adds terminal version and font detection for `kmscon`. (#2393, Terminal / TerminalFont, Linux)
* Adds the currently-in-beta code name "Golden Gate" for macOS 27. (OS, macOS)
* Adds WPA version detection on FreeBSD. (Wifi, FreeBSD)
* Adds package manager support for `porg` (#2405) and `install-release` (#2342). (Packages, Linux)
* Adds Weston version detection. (WM, Linux)
* Improves the core type (P-Core/E-Core) fetching mechanism on Windows by using `EfficiencyClass` instead of legacy frequency inference. (CPU, Windows)
* Improves display detection compatibility with KDE 6.7. (Display, Linux)
* Improves display serial number detection, now preferring alphanumeric serial numbers when available. (Display)
* This can be used in custom formats via `{serial}`.
* Improves the performance of `emerge` package manager detection. (#2406, Packages, Linux)
* Improves error messages for config file parsing errors.
* Improves reliability of the `Codec` module on Linux (Codec, Linux)
* Adds `va-x11` backend for VA-API and VDPAU, which is used if `va-drm` backend fails to initialize.
* Fixes an issue where the Codec module incorrectly reports no results when the `codec.showType` option is set.
Bugfixes:
* Fixes physical core detection on non-x86 architectures and simplifies the frequency detection code. (CPU, Linux)
* Fixes console mode and output code page initialization issues when running `fastfetch` in `Conhost`. (#2383, Windows)
* Fixes public IP detection randomly failing on Linux. (#2401, PublicIP, Linux)
* Fixes several memory leaks.
Logos:
* Adds Zerene OS. (#2404)
# 2.64.2
Bugfixes:
* Fixes image rendering being wiped quickly (#2374)
* Regression from v2.64.0
* Fixes ASCII logo being overwritten in `--dynamic-interval` mode
* Regression from v2.64.0
Logos:
* Updates OpenWrt and adds a small variant (#2376)
* The old one is renamed to `openwrt_old`
# 2.64.1
Features:
* Adds a CMake option `-DPACKAGES_REMOVE_DISABLED` to remove detection code of disabled packages (`-DPACKAGES_DISABLE_<PACKAGE_NAME>`) for slightly smaller binary size (Packages)
Bugfixes:
* Fixes compatibility issues with Lua 5.3
* Avoid possible infinite recursion in `encode_json` when encoding deeply nested tables or circular references
* Fixes compilation issues when building with old macOS SDKs
# 2.64.0
New **optional build** dependencies:
+91 -54
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.64.0
VERSION 2.66.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -63,6 +63,13 @@ endif()
include(CheckIncludeFile)
if(LINUX)
CHECK_INCLUDE_FILE("linux/version.h" HAVE_LINUX_VERSION_H)
if(NOT HAVE_LINUX_VERSION_H)
message(FATAL_ERROR "Linux headers (linux/version.h) not found! Please install linux-headers package.")
endif()
endif()
#####################
# Configure options #
#####################
@@ -70,13 +77,13 @@ include(CheckIncludeFile)
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR GNU" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VA "Enable libva" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VADRM "Enable libva-drm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VAX11 "Enable libva-x11" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VDPAU "Enable vdpau" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD OR GNU" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_EET "Enable eet" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
@@ -98,6 +105,7 @@ cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND"
option(ENABLE_ZLIB "Enable zlib" ON)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_TRACER "Build fastfetch with function tracing" OFF)
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
option(BUILD_FLASHFETCH "Build flashfetch" ON) # Also build the flashfetch binary
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
@@ -134,7 +142,10 @@ if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
endif()
set(PACKAGE_MANAGERS AM APPIMAGE APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SOAR SORCERY WINGET XBPS)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/packages/option.h" PACKAGE_MANAGERS)
string(REGEX MATCHALL "FF_PACKAGES_FLAG_[A-Z]+_BIT" PACKAGE_MANAGERS "${PACKAGE_MANAGERS}")
string(REGEX REPLACE "FF_PACKAGES_FLAG_([A-Z]+)_BIT" "\\1" PACKAGE_MANAGERS "${PACKAGE_MANAGERS}")
list(SORT PACKAGE_MANAGERS)
foreach(package_manager ${PACKAGE_MANAGERS})
if(package_manager STREQUAL "WINGET")
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
@@ -142,6 +153,7 @@ foreach(package_manager ${PACKAGE_MANAGERS})
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" OFF)
endif()
endforeach()
option(PACKAGES_REMOVE_DISABLED "Remove disabled package managers from the build entirely, instead of just skipping them at runtime" OFF)
if (LINUX)
set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
@@ -308,7 +320,7 @@ if(Python_FOUND)
endif()
else()
message(WARNING "Python3 is not found, 'help.json' will not be minified")
file(READ "doc/help.json" DATATEXT_JSON_HELP)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/doc/help.json" DATATEXT_JSON_HELP)
endif()
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
@@ -428,6 +440,7 @@ set(LIBFASTFETCH_SRC
src/detection/codec/codec.c
src/detection/codec/codec_vulkan.c
src/detection/cpu/cpu.c
src/detection/cpu/cpu_x86.c
src/detection/cpuusage/cpuusage.c
src/detection/command/command.c
src/detection/disk/disk.c
@@ -572,11 +585,10 @@ if(LINUX)
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
src/detection/displayserver/linux/wayland/zwlr-output.c
src/detection/displayserver/linux/wayland/wl-output-protocol.c
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
src/detection/displayserver/linux/wayland/kde-output.c
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
@@ -733,11 +745,10 @@ elseif(FreeBSD)
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
src/detection/displayserver/linux/wayland/zwlr-output.c
src/detection/displayserver/linux/wayland/kde-output.c
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
src/detection/displayserver/linux/wayland/wl-output-protocol.c
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
@@ -746,6 +757,7 @@ elseif(FreeBSD)
src/detection/gpu/gpu_bsd.c
src/detection/gpu/gpu_drm.c
src/detection/gpu/gpu_pci.c
src/detection/gpu/gpu_bsddrm.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_bsd.c
src/detection/lm/lm_linux.c
@@ -828,11 +840,10 @@ elseif(NetBSD)
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
src/detection/displayserver/linux/wayland/zwlr-output.c
src/detection/displayserver/linux/wayland/kde-output.c
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
src/detection/displayserver/linux/wayland/wl-output-protocol.c
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
@@ -913,11 +924,10 @@ elseif(OpenBSD)
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
src/detection/displayserver/linux/wayland/zwlr-output.c
src/detection/displayserver/linux/wayland/kde-output.c
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
src/detection/displayserver/linux/wayland/wl-output-protocol.c
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
@@ -925,6 +935,8 @@ elseif(OpenBSD)
src/detection/font/font_linux.c
src/detection/gpu/gpu_pci.c
src/detection/gpu/gpu_obsd.c
src/detection/gpu/gpu_drm.c
src/detection/gpu/gpu_bsddrm.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_obsd.c
src/detection/lm/lm_nosupport.c
@@ -1156,11 +1168,10 @@ elseif(SunOS)
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
src/detection/displayserver/linux/wayland/zwlr-output.c
src/detection/displayserver/linux/wayland/kde-output.c
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
src/detection/displayserver/linux/wayland/wl-output-protocol.c
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
@@ -1306,12 +1317,9 @@ elseif(GNU)
src/detection/physicalmemory/physicalmemory_nosupport.c
src/detection/diskio/diskio_nosupport.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
src/detection/displayserver/linux/wayland/zwlr-output.c
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
@@ -1358,6 +1366,22 @@ elseif(GNU)
)
endif()
if(ENABLE_TRACER)
message(STATUS "Tracer is enabled")
list(APPEND LIBFASTFETCH_SRC src/common/impl/tracer.c)
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions-after-inlining")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions -Dinline=\"__attribute__((no_instrument_function)) inline\"")
endif()
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gcodeview -fuse-ld=lld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--pdb=${CMAKE_BINARY_DIR}/fastfetch.pdb")
endif()
endif()
# Proprietary GPU driver APIs
if(LINUX OR FreeBSD OR WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
@@ -1557,24 +1581,24 @@ endif()
if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
endif()
if(NOT "${CUSTOM_AMDGPU_IDS_PATH}" STREQUAL "")
message(STATUS "Custom file path of amdgpu.ids: ${CUSTOM_AMDGPU_IDS_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
endif()
if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "")
message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
endif()
if(NOT "${CUSTOM_LSB_RELEASE_PATH}" STREQUAL "")
message(STATUS "Custom file path of lsb_release: ${CUSTOM_LSB_RELEASE_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_LSB_RELEASE_PATH=${CUSTOM_LSB_RELEASE_PATH})
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_LSB_RELEASE_PATH=${CUSTOM_LSB_RELEASE_PATH})
endif()
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
message(STATUS "Enabling custom link type: ${BINARY_LINK_TYPE}")
target_compile_definitions(libfastfetch PRIVATE FF_DISABLE_DLOPEN=1)
target_compile_definitions(libfastfetch PUBLIC FF_DISABLE_DLOPEN=1)
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--copy-dt-needed-entries")
endif()
@@ -1619,6 +1643,11 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME) # [CMAKE_TARGET_NAME]
set(${VARNAME}_LIBRARIES ${_FF_CMAKE_TARGET})
endif()
endif()
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
# INTERFACE_LINK_LIBRARIES doesn't expose libvarname.a
target_link_libraries(libfastfetch PRIVATE ${_FF_CMAKE_TARGET})
endif()
endif()
else()
set(${VARNAME}_INCLUDE_DIRS ${${CMAKE_NAME}_INCLUDE_DIRS})
@@ -1635,18 +1664,18 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME) # [CMAKE_TARGET_NAME]
message(STATUS "Library: found ${VARNAME} by ${${VARNAME}_FOUND}")
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_${VARNAME}=1)
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
target_link_directories(libfastfetch PUBLIC ${${VARNAME}_LIBRARY_DIRS})
target_link_directories(libfastfetch PRIVATE ${${VARNAME}_LIBRARY_DIRS})
target_link_libraries(libfastfetch PRIVATE ${${VARNAME}_LIBRARIES})
endif()
foreach(FLAG ${${VARNAME}_CFLAGS_OTHER})
if(FLAG MATCHES "-D.*")
string(SUBSTRING ${FLAG} 2 -1 FLAG)
target_compile_definitions(libfastfetch PRIVATE ${FLAG})
target_compile_definitions(libfastfetch PUBLIC ${FLAG})
endif()
endforeach()
endfunction()
@@ -1671,18 +1700,18 @@ ff_lib_enable(DRM
"libdrm"
"Libdrm"
)
ff_lib_enable(VA
"libva"
"Libva"
ff_lib_enable(VADRM
"libva-drm"
"Libva-drm"
)
ff_lib_enable(VAX11
"libva-x11"
"Libva-x11"
)
ff_lib_enable(VDPAU
"vdpau"
"vdpau"
)
ff_lib_enable(DRM_AMDGPU
"libdrm_amdgpu"
"Libdrm_Amdgpu"
)
ff_lib_enable(GIO
"gio-2.0"
"GIO"
@@ -1776,8 +1805,8 @@ if(ENABLE_LUA)
message(STATUS "Library: Lua version ${Lua_VERSION} is not supported, requires 5.3-5.5")
unset(Lua_FOUND)
else()
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LUA=1)
target_include_directories(libfastfetch PRIVATE ${LUA_INCLUDE_DIR})
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LUA=1)
target_include_directories(libfastfetch PUBLIC ${LUA_INCLUDE_DIR})
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
target_link_libraries(libfastfetch PRIVATE ${LUA_LIBRARIES})
@@ -1790,20 +1819,20 @@ if(ENABLE_LUA)
endif()
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_THREADS=1)
if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
target_link_libraries(libfastfetch PRIVATE Threads::Threads)
endif()
endif()
if(ENABLE_EMBEDDED_PCIIDS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_EMBEDDED_PCIIDS=1)
endif()
if(ENABLE_EMBEDDED_AMDGPUIDS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_EMBEDDED_AMDGPUIDS=1)
endif()
if(ENABLE_LIBZFS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LIBZFS=1)
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
target_link_libraries(libfastfetch
@@ -1877,6 +1906,11 @@ elseif(WIN32)
PRIVATE "runtimeobject"
)
endif()
if(ENABLE_TRACER)
target_link_libraries(libfastfetch
PRIVATE "dbghelp"
)
endif()
elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
@@ -1960,7 +1994,7 @@ target_link_libraries(libfastfetch
PRIVATE ${CMAKE_DL_LIBS}
)
target_compile_options(libfastfetch PRIVATE
target_compile_options(libfastfetch PUBLIC
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti>)
if(FreeBSD)
@@ -1969,18 +2003,18 @@ endif()
if(LINUX OR FreeBSD OR OpenBSD OR NetBSD)
CHECK_INCLUDE_FILE("linux/videodev2.h" HAVE_LINUX_VIDEODEV2)
if(HAVE_LINUX_VIDEODEV2)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LINUX_VIDEODEV2=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LINUX_VIDEODEV2=1)
endif()
endif()
if(NOT WIN32)
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX)
if(HAVE_UTMPX)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_UTMPX=1)
endif()
if(ENABLE_WORDEXP)
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
if(HAVE_WORDEXP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WORDEXP=1)
message(STATUS "wordexp.h found, wordexp support enabled")
else()
set(ENABLE_WORDEXP OFF)
@@ -1992,19 +2026,19 @@ if(NOT WIN32)
if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
if(HAVE_PTHREAD_NP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_PTHREAD_NP=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PTHREAD_NP=1)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} pthread_np.h)
endif()
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} Threads::Threads)
check_function_exists("pthread_timedjoin_np" HAVE_TIMEDJOIN_NP)
if(HAVE_TIMEDJOIN_NP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_TIMEDJOIN_NP=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_TIMEDJOIN_NP=1)
else()
message(WARNING "pthread_timedjoin_np was not found; networking timeout will not work")
endif()
endif()
elseif(HAVE_WINRT)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WINRT=1)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WINRT=1)
endif()
set(PACKAGES_DISABLE_LIST "")
@@ -2021,7 +2055,10 @@ else()
list(TRANSFORM PACKAGES_DISABLE_LIST APPEND "_BIT")
list(JOIN PACKAGES_DISABLE_LIST " | " PACKAGES_DISABLE_LIST)
endif()
target_compile_definitions(libfastfetch PRIVATE FF_PACKAGES_DISABLE_LIST=${PACKAGES_DISABLE_LIST})
target_compile_definitions(libfastfetch PUBLIC "FF_PACKAGES_DISABLE_LIST=${PACKAGES_DISABLE_LIST}")
if(PACKAGES_REMOVE_DISABLED)
target_compile_definitions(libfastfetch PUBLIC FF_PACKAGES_REMOVE_DISABLED=1)
endif()
######################
# Executable targets #
+18
View File
@@ -1,3 +1,21 @@
fastfetch (2.65.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.65.2
-- Carter Li <zhangsongcui@live.cn> Mon, 29 Jun 2026 10:05:47 +0800
fastfetch (2.65.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.65.1
-- Carter Li <zhangsongcui@live.cn> Wed, 24 Jun 2026 14:21:06 +0800
fastfetch (2.64.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.64.2
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Jun 2026 15:45:11 +0800
fastfetch (2.63.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.63.1
+1 -1
View File
@@ -10,7 +10,7 @@ SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
OUT_DIR="$(dirname "$ROOT_DIR")"
PPA="ppa:zhangsongcui3371/fastfetch"
CODENAMES=( jammy noble plucky questing resolute )
CODENAMES=( jammy noble plucky questing resolute stonking )
DRY_RUN=0
if [[ -d "$OUT_DIR/build" ]]; then
+7 -3
View File
@@ -322,7 +322,7 @@
"type": "string"
},
"cpuFormat": {
"description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count",
"description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count\n 13. {code-name}: CPU code name\n 14. {technology}: CPU technology",
"type": "string"
},
"cpucacheFormat": {
@@ -374,7 +374,7 @@
"type": "string"
},
"gpuFormat": {
"description": "Output format for the `GPU` module. See Wiki for formatting syntax\n 1. {vendor}: GPU vendor\n 2. {name}: GPU name\n 3. {driver}: GPU driver\n 4. {temperature}: GPU temperature\n 5. {core-count}: GPU core count\n 6. {type}: GPU type\n 7. {dedicated-total}: GPU total dedicated memory\n 8. {dedicated-used}: GPU used dedicated memory\n 9. {shared-total}: GPU total shared memory\n 10. {shared-used}: GPU used shared memory\n 11. {platform-api}: The platform API used when detecting the GPU\n 12. {frequency}: Current frequency in GHz\n 13. {index}: GPU vendor specific index\n 14. {dedicated-percentage-num}: Dedicated memory usage percentage num\n 15. {dedicated-percentage-bar}: Dedicated memory usage percentage bar\n 16. {shared-percentage-num}: Shared memory usage percentage num\n 17. {shared-percentage-bar}: Shared memory usage percentage bar\n 18. {core-usage-num}: Core usage percentage num\n 19. {core-usage-bar}: Core usage percentage bar\n 20. {memory-type}: Memory type (Windows only)",
"description": "Output format for the `GPU` module. See Wiki for formatting syntax\n 1. {vendor}: GPU vendor\n 2. {name}: GPU name\n 3. {driver}: GPU driver\n 4. {temperature}: GPU temperature\n 5. {core-count}: GPU core count\n 6. {type}: GPU type\n 7. {dedicated-total}: GPU total dedicated memory\n 8. {dedicated-used}: GPU used dedicated memory\n 9. {shared-total}: GPU total shared memory\n 10. {shared-used}: GPU used shared memory\n 11. {platform-api}: The platform API used when detecting the GPU\n 12. {frequency}: Current frequency in GHz\n 13. {index}: GPU vendor specific index\n 14. {dedicated-percentage-num}: Dedicated memory usage percentage num\n 15. {dedicated-percentage-bar}: Dedicated memory usage percentage bar\n 16. {shared-percentage-num}: Shared memory usage percentage num\n 17. {shared-percentage-bar}: Shared memory usage percentage bar\n 18. {core-usage-num}: Core usage percentage num\n 19. {core-usage-bar}: Core usage percentage bar\n 20. {memory-type}: Memory type (Windows only)\n 21. {pcie-max-speed}: PCIe maximum speed in gen and lanes\n 22. {pcie-curr-speed}: PCIe current speed in gen and lanes",
"type": "string"
},
"hostFormat": {
@@ -446,7 +446,7 @@
"type": "string"
},
"packagesFormat": {
"description": "Output format for the `Packages` module. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {am-system}: Number of am-system packages\n 3. {am-user}: Number of am-user (aka appman) packages\n 4. {appimage}: Number of appimage packages\n 5. {apk}: Number of apk packages\n 6. {brew}: Number of brew packages\n 7. {brew-all}: Total number of all brew packages\n 8. {brew-cask}: Number of brew-cask packages\n 9. {cards}: Number of cards packages\n 10. {choco}: Number of choco packages\n 11. {dpkg}: Number of dpkg packages\n 12. {emerge}: Number of emerge packages\n 13. {eopkg}: Number of eopkg packages\n 14. {flatpak-all}: Total number of all flatpak app packages\n 15. {flatpak-system}: Number of flatpak-system app packages\n 16. {flatpak-user}: Number of flatpak-user app packages\n 17. {guix-all}: Total number of all guix packages\n 18. {guix-home}: Number of guix-home packages\n 19. {guix-system}: Number of guix-system packages\n 20. {guix-user}: Number of guix-user packages\n 21. {hpkg-all}: Total number of all hpkg packages\n 22. {hpkg-system}: Number of hpkg-system packages\n 23. {hpkg-user}: Number of hpkg-user packages\n 24. {kiss}: Number of kiss packages\n 25. {linglong}: Number of linglong packages\n 26. {lpkg}: Number of lpkg packages\n 27. {lpkgbuild}: Number of lpkgbuild packages\n 28. {macports}: Number of macports packages\n 29. {mport}: Number of mport packages\n 30. {moss}: Number of moss packages\n 31. {nix-all}: Total number of all nix packages\n 32. {nix-default}: Number of nix-default packages\n 33. {nix-system}: Number of nix-system packages\n 34. {nix-user}: Number of nix-user packages\n 35. {opkg}: Number of opkg packages\n 36. {pacman}: Number of pacman packages\n 37. {pacman-branch}: Pacman branch on manjaro\n 38. {pacstall}: Number of pacstall packages\n 39. {paludis}: Number of paludis packages\n 40. {pisi}: Number of pisi packages\n 41. {pkg}: Number of pkg packages\n 42. {pkgsrc}: Number of pkgsrc packages\n 43. {pkgtool}: Number of pkgtool packages\n 44. {rpm}: Number of rpm packages\n 45. {scoop-global}: Number of scoop-global packages\n 46. {scoop-user}: Number of scoop-user packages\n 47. {snap}: Number of snap packages\n 48. {soar}: Number of soar packages\n 49. {sorcery}: Number of sorcery packages\n 50. {winget}: Number of winget packages\n 51. {xbps}: Number of xbps packages",
"description": "Output format for the `Packages` module. See Wiki for formatting syntax\n 1. {am-system}: Number of am-system packages\n 2. {am-user}: Number of am-user (aka appman) packages\n 3. {appimage}: Number of appimage packages\n 4. {apk}: Number of apk packages\n 5. {brew}: Number of brew packages\n 6. {brew-cask}: Number of brew-cask packages\n 7. {cards}: Number of cards packages\n 8. {choco}: Number of choco packages\n 9. {dpkg}: Number of dpkg packages\n 10. {emerge}: Number of emerge packages\n 11. {eopkg}: Number of eopkg packages\n 12. {flatpak-system}: Number of flatpak-system app packages\n 13. {flatpak-user}: Number of flatpak-user app packages\n 14. {guix-home}: Number of guix-home packages\n 15. {guix-system}: Number of guix-system packages\n 16. {guix-user}: Number of guix-user packages\n 17. {hpkg-system}: Number of hpkg-system packages\n 18. {hpkg-user}: Number of hpkg-user packages\n 19. {install-release}: Number of install-release packages\n 20. {kiss}: Number of kiss packages\n 21. {linglong}: Number of linglong packages\n 22. {lpkg}: Number of lpkg packages\n 23. {lpkgbuild}: Number of lpkgbuild packages\n 24. {macports}: Number of macports packages\n 25. {mport}: Number of mport packages\n 26. {moss}: Number of moss packages\n 27. {nix-default}: Number of nix-default packages\n 28. {nix-system}: Number of nix-system packages\n 29. {nix-user}: Number of nix-user packages\n 30. {opkg}: Number of opkg packages\n 31. {pacman}: Number of pacman packages\n 32. {pacman-branch}: Pacman branch on manjaro\n 33. {pacstall}: Number of pacstall packages\n 34. {paludis}: Number of paludis packages\n 35. {pisi}: Number of pisi packages\n 36. {pkg}: Number of pkg packages\n 37. {pkgsrc}: Number of pkgsrc packages\n 38. {pkgtool}: Number of pkgtool packages\n 39. {porg}: Number of porg packages\n 40. {rpm}: Number of rpm packages\n 41. {scoop-global}: Number of scoop-global packages\n 42. {scoop-user}: Number of scoop-user packages\n 43. {snap}: Number of snap packages\n 44. {soar}: Number of soar packages\n 45. {sorcery}: Number of sorcery packages\n 46. {winget}: Number of winget packages\n 47. {xbps}: Number of xbps packages\n 48. {brew-all}: Total number of all brew packages\n 49. {flatpak-all}: Total number of all flatpak app packages\n 50. {guix-all}: Total number of all guix packages\n 51. {hpkg-all}: Total number of all hpkg packages\n 52. {nix-all}: Total number of all nix packages\n 53. {all}: Number of all packages",
"type": "string"
},
"physicaldiskFormat": {
@@ -2850,6 +2850,10 @@
"const": "opencl",
"description": "Use OpenCL API.\nSlow and requires proper OpenCL drivers to be installed"
},
{
"const": "egl-ext",
"description": "Use EGL_EXT_device_enumeration and EGL_EXT_device_query APIs.\nSlow and only detects GPUs that support these extensions"
},
{
"const": "opengl",
"description": "Use OpenGL API.\nSlow and only detects one GPU.\nUsed for OpenBSD"
+13 -13
View File
@@ -42,12 +42,12 @@
},
{
"type": "kernel",
"key": "│ ├",
"key": "│ ├{icon}",
"keyColor": "yellow"
},
{
"type": "packages",
"key": "│ ├󰏖",
"key": "│ ├{icon}",
"keyColor": "yellow"
},
{
@@ -62,22 +62,22 @@
},
{
"type": "lm",
"key": "│ ├󰧨",
"key": "│ ├{icon}",
"keyColor": "blue"
},
{
"type": "wmtheme",
"key": "│ ├󰉼",
"key": "│ ├{icon}",
"keyColor": "blue"
},
{
"type": "icons",
"key": "│ ├󰀻",
"key": "│ ├{icon}",
"keyColor": "blue"
},
{
"type": "terminal",
"key": "│ ├",
"key": "│ ├{icon}",
"keyColor": "blue"
},
{
@@ -92,32 +92,32 @@
},
{
"type": "cpu",
"key": "│ ├󰻠",
"key": "│ ├{icon}",
"keyColor": "green"
},
{
"type": "gpu",
"key": "│ ├󰍛",
"key": "│ ├{icon}",
"keyColor": "green"
},
{
"type": "disk",
"key": "│ ├",
"key": "│ ├{icon}",
"keyColor": "green"
},
{
"type": "memory",
"key": "│ ├󰑭",
"key": "│ ├{icon}",
"keyColor": "green"
},
{
"type": "swap",
"key": "│ ├󰓡",
"key": "│ ├{icon}",
"keyColor": "green"
},
{
"type": "uptime",
"key": "│ ├󰅐",
"key": "│ ├{icon}",
"keyColor": "green"
},
{
@@ -132,7 +132,7 @@
},
{
"type": "player",
"key": "│ ├󰥠",
"key": "│ ├{icon}",
"keyColor": "cyan"
},
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Inspired by Catnap
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
+1 -1
View File
@@ -1,4 +1,4 @@
// Inspired by Catnap
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
+1 -1
View File
@@ -1,4 +1,4 @@
// Inspired by Catnap
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
+1 -1
View File
@@ -1,4 +1,4 @@
// Inspired by Catnap
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
+9 -2
View File
@@ -15,8 +15,6 @@ typedef struct FFlist {
uint32_t capacity;
} FFlist;
void* ffListAdd(FFlist* list, uint32_t elementSize);
// Removes the first element, and copy its value to `*result`
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result);
// Removes the last element, and copy its value to `*result`
@@ -105,6 +103,15 @@ static inline void ffListReserve(FFlist* list, uint32_t elementSize, uint32_t ne
list->capacity = newCapacity;
}
static inline void* ffListAdd(FFlist* list, uint32_t elementSize) {
if (__builtin_expect(list->length == list->capacity, false)) {
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
}
++list->length;
return ffListGet(list, elementSize, list->length - 1);
}
#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
for (itemType* itemVarName = (itemType*) (listVar).data; \
itemVarName - (itemType*) (listVar).data < (intptr_t) (listVar).length; \
+100 -46
View File
@@ -37,16 +37,13 @@ static inline void ffStrbufInit(FFstrbuf* strbuf);
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments);
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr);
FF_A_PRINTF(2, 3) void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...);
FF_A_PRINTF(1, 2) FF_A_NODISCARD FFstrbuf ffStrbufCreateF(const char* format, ...);
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free);
void ffStrbufClear(FFstrbuf* strbuf);
void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free);
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value);
void ffStrbufAppendC(FFstrbuf* strbuf, char c);
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c);
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int));
FF_A_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
@@ -88,13 +85,6 @@ bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end);
bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c);
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file);
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file);
FF_A_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue);
FF_A_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue);
FF_A_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue);
void ffStrbufUpperCase(FFstrbuf* strbuf);
void ffStrbufLowerCase(FFstrbuf* strbuf);
@@ -182,31 +172,6 @@ FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateMove(FFstrbuf* src) {
return strbuf;
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateVF(const char* format, va_list arguments) {
FFstrbuf strbuf;
ffStrbufInitVF(&strbuf, format, arguments);
return strbuf;
}
FF_A_PRINTF(2, 3) static inline void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(strbuf, format, arguments);
va_end(arguments);
}
FF_A_PRINTF(1, 2) FF_A_NODISCARD static inline FFstrbuf
ffStrbufCreateF(const char* format, ...) {
FFstrbuf strbuf;
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(&strbuf, format, arguments);
va_end(arguments);
return strbuf;
}
static inline void ffStrbufInitMoveS(FFstrbuf* strbuf, char* heapStr) {
ffStrbufInitMoveNS(strbuf, (uint32_t) strlen(heapStr), heapStr);
}
@@ -229,6 +194,76 @@ FF_A_NODISCARD static inline uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) {
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
}
static inline void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
if (__builtin_expect(free == 0, false)) {
if (__builtin_expect(!(strbuf->allocated == 0 && strbuf->length > 0), true)) {
return;
}
} else {
if (__builtin_expect(ffStrbufGetFree(strbuf) >= free, true)) {
return;
}
}
ffStrbufEnsureFreeNoCheck(strbuf, free);
}
static inline void ffStrbufClear(FFstrbuf* strbuf) {
assert(strbuf != NULL);
extern char* CHAR_NULL_PTR;
if (strbuf->allocated == 0) {
strbuf->chars = CHAR_NULL_PTR;
} else {
strbuf->chars[0] = '\0';
}
strbuf->length = 0;
}
static inline void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
if (__builtin_expect(ffStrbufGetFree(strbuf) == 0, false)) {
ffStrbufEnsureFreeNoCheck(strbuf, 1);
}
strbuf->chars[strbuf->length++] = c;
strbuf->chars[strbuf->length] = '\0';
}
static inline void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
if (__builtin_expect(num == 0, false)) {
return;
}
if (__builtin_expect(ffStrbufGetFree(strbuf) < num, false)) {
ffStrbufEnsureFreeNoCheck(strbuf, num);
}
memset(&strbuf->chars[strbuf->length], c, num);
strbuf->length += num;
strbuf->chars[strbuf->length] = '\0';
}
static inline void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
if (__builtin_expect(value == NULL || length == 0, false)) {
return;
}
if (__builtin_expect(ffStrbufGetFree(strbuf) < length, false)) {
ffStrbufEnsureFreeNoCheck(strbuf, length);
}
memcpy(&strbuf->chars[strbuf->length], value, length);
strbuf->length += length;
strbuf->chars[strbuf->length] = '\0';
}
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
assert(value != strbuf);
if (value == NULL) {
return;
}
ffStrbufAppendNS(strbuf, value->length, value->chars);
}
static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) {
strbuf->length = (uint32_t) strlen(strbuf->chars);
}
@@ -338,14 +373,6 @@ FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateS(const char* str) {
return strbuf;
}
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
assert(value != strbuf);
if (value == NULL) {
return;
}
ffStrbufAppendNS(strbuf, value->length, value->chars);
}
static inline void ffStrbufPrepend(FFstrbuf* strbuf, FFstrbuf* value) {
if (value == NULL) {
return;
@@ -578,6 +605,33 @@ static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const
return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator);
}
static inline void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
}
static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
ffStrbufWriteTo(strbuf, file);
fputc('\n', file);
}
FF_A_NODISCARD static inline double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
char* str_end;
double result = strtod(strbuf->chars, &str_end);
return str_end == strbuf->chars ? defaultValue : result;
}
FF_A_NODISCARD static inline uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
char* str_end;
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
}
FF_A_NODISCARD static inline int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
char* str_end;
long long result = strtoll(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
}
// Returns true if the strbuf is modified
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf);
+1
View File
@@ -17,3 +17,4 @@
#define FF_A_PACKED __attribute__((__packed__))
#define FF_A_WEAK_IMPORT __attribute__((__weak_import__))
#define FF_A_ALWAYS_INLINE __attribute__((__always_inline__))
#define FF_A_COLD __attribute__((__cold__))
+1
View File
@@ -33,5 +33,6 @@ static inline const char* ffFindFileName(const char* file) {
#if _WIN32
const char* ffDebugWin32Error(DWORD errorCode);
const char* ffDebugNtStatus(NTSTATUS status);
const char* ffDebugConfigRet(unsigned long /*CONFIGRET*/ ret);
const char* ffDebugHResult(HRESULT hr);
#endif
+2 -1
View File
@@ -8,6 +8,7 @@ bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name);
void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate);
void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint32_t* height);
void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* height); // in mm
void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week);
void ffEdidGetManufactureDate(const uint8_t edid[128], uint16_t* year, uint16_t* week);
bool ffEdidGetSerial(const uint8_t edid[128], FFstrbuf* result);
bool ffEdidGetHdrCompatible(const uint8_t* edid, uint32_t length);
bool ffEdidIsValid(const uint8_t edid[128], uint32_t length);
+2 -2
View File
@@ -30,7 +30,7 @@ static void getExePath(FFPlatform* platform) {
char exePath[PATH_MAX];
#if defined(__linux__) || defined(__GNU__)
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
if (exePathLen >= 0) {
if (exePathLen > 0) {
exePath[exePathLen] = '\0';
}
#elif defined(__APPLE__)
@@ -128,7 +128,7 @@ static void getExePath(FFPlatform* platform) {
}
#elif defined(__sun)
ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1);
if (exePathLen >= 0) {
if (exePathLen > 0) {
exePath[exePathLen] = '\0';
}
#elif defined(__HAIKU__)
+32 -48
View File
@@ -236,54 +236,38 @@ static void getSystemPageSize(FFPlatformSysinfo* info) {
}
static void getSystemArchitecture(FFPlatformSysinfo* info) {
SYSTEM_PROCESSOR_INFORMATION spi;
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorInformation, &spi, sizeof(spi), NULL))) {
switch (spi.ProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
ffStrbufSetStatic(&info->architecture, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA64:
ffStrbufSetStatic(&info->architecture, "ia64");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
switch (spi.ProcessorLevel) {
case 4:
ffStrbufSetStatic(&info->architecture, "i486");
break;
case 5:
ffStrbufSetStatic(&info->architecture, "i586");
break;
case 6:
ffStrbufSetStatic(&info->architecture, "i686");
break;
default:
ffStrbufSetStatic(&info->architecture, "i386");
break;
}
break;
case PROCESSOR_ARCHITECTURE_ARM64:
ffStrbufSetStatic(&info->architecture, "aarch64");
break;
case PROCESSOR_ARCHITECTURE_ARM:
ffStrbufSetStatic(&info->architecture, "arm");
break;
case PROCESSOR_ARCHITECTURE_PPC:
ffStrbufSetStatic(&info->architecture, "ppc");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
ffStrbufSetStatic(&info->architecture, "mips");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
ffStrbufSetStatic(&info->architecture, "alpha");
break;
case PROCESSOR_ARCHITECTURE_ALPHA64:
ffStrbufSetStatic(&info->architecture, "alpha64");
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
ffStrbufSetStatic(&info->architecture, "unknown");
break;
}
switch (SharedUserData->NativeProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
ffStrbufSetStatic(&info->architecture, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA64:
ffStrbufSetStatic(&info->architecture, "ia64");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
ffStrbufSetStatic(&info->architecture, "i686");
break;
case PROCESSOR_ARCHITECTURE_ARM64:
ffStrbufSetStatic(&info->architecture, "aarch64");
break;
case PROCESSOR_ARCHITECTURE_ARM:
ffStrbufSetStatic(&info->architecture, "arm");
break;
case PROCESSOR_ARCHITECTURE_PPC:
ffStrbufSetStatic(&info->architecture, "ppc");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
ffStrbufSetStatic(&info->architecture, "mips");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
ffStrbufSetStatic(&info->architecture, "alpha");
break;
case PROCESSOR_ARCHITECTURE_ALPHA64:
ffStrbufSetStatic(&info->architecture, "alpha64");
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
ffStrbufSetStatic(&info->architecture, "unknown");
break;
}
}
-9
View File
@@ -3,15 +3,6 @@
#include <stdlib.h>
#include <string.h>
void* ffListAdd(FFlist* list, uint32_t elementSize) {
if (list->length == list->capacity) {
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
}
++list->length;
return ffListGet(list, elementSize, list->length - 1);
}
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result) {
if (list->length == 0) {
return false;
+26 -78
View File
@@ -45,18 +45,33 @@ void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr) {
strbuf->chars = heapStr;
}
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
if (ffStrbufGetFree(strbuf) >= free && !(strbuf->allocated == 0 && strbuf->length > 0)) {
return;
}
void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(strbuf, format, arguments);
va_end(arguments);
}
uint32_t allocate = strbuf->allocated;
if (allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) {
FFstrbuf ffStrbufCreateF(const char* format, ...) {
FFstrbuf strbuf;
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(&strbuf, format, arguments);
va_end(arguments);
return strbuf;
}
void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free) {
uint32_t allocate = strbuf->length + free;
if (allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) { // `<` for null terminator
allocate = FASTFETCH_STRBUF_DEFAULT_ALLOC;
}
while ((strbuf->length + free + 1) > allocate) { // + 1 for the null byte
allocate *= 2;
} else {
// Round up to the next power of 2.
// If the value is already a power of 2, it will be rounded up to the next power of 2.
assert(allocate < (UINT32_MAX >> 1));
allocate = 1U << (32 - __builtin_clz(allocate));
}
if (strbuf->allocated == 0) {
@@ -100,46 +115,6 @@ void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) {
strbuf->allocated = newCap;
}
void ffStrbufClear(FFstrbuf* strbuf) {
assert(strbuf != NULL);
if (strbuf->allocated == 0) {
strbuf->chars = CHAR_NULL_PTR;
} else {
strbuf->chars[0] = '\0';
}
strbuf->length = 0;
}
void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
ffStrbufEnsureFree(strbuf, 1);
strbuf->chars[strbuf->length++] = c;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
if (num == 0) {
return;
}
ffStrbufEnsureFree(strbuf, num);
memset(&strbuf->chars[strbuf->length], c, num);
strbuf->length += num;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
if (value == NULL || length == 0) {
return;
}
ffStrbufEnsureFree(strbuf, length);
memcpy(&strbuf->chars[strbuf->length], value, length);
strbuf->length += length;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int)) {
if (value == NULL) {
return;
@@ -168,7 +143,7 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) {
int written = vsnprintf(strbuf->chars + strbuf->length, strbuf->allocated > 0 ? free + 1 : 0, format, arguments);
if (written > 0 && (uint32_t) written > free) {
ffStrbufEnsureFree(strbuf, (uint32_t) written);
ffStrbufEnsureFreeNoCheck(strbuf, (uint32_t) written);
written = vsnprintf(strbuf->chars + strbuf->length, (uint32_t) written + 1, format, copy);
}
@@ -550,33 +525,6 @@ bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c) {
return true;
}
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
}
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
ffStrbufWriteTo(strbuf, file);
fputc('\n', file);
}
double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
char* str_end;
double result = strtod(strbuf->chars, &str_end);
return str_end == strbuf->chars ? defaultValue : result;
}
uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
char* str_end;
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
}
int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
char* str_end;
long long result = strtoll(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
}
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value) {
ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
+1 -1
View File
@@ -34,7 +34,7 @@ void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char*
static uint8_t decode_table[256];
void init_decode_table() {
static void init_decode_table() {
uint8_t ch = 0;
do {
int32_t code = -1;
+5
View File
@@ -2,6 +2,7 @@
#include "common/windows/nt.h"
#include <windows.h>
#include <cfgmgr32.h>
const char* ffDebugWin32Error(DWORD errorCode) {
static char buffer[512];
@@ -34,6 +35,10 @@ const char* ffDebugWin32Error(DWORD errorCode) {
return buffer;
}
const char* ffDebugConfigRet(CONFIGRET ret) {
return ffDebugWin32Error(CM_MapCrToWin32Err(ret, ERROR_INTERNAL_ERROR));
}
const char* ffDebugNtStatus(NTSTATUS status) {
return ffDebugWin32Error(RtlNtStatusToDosError(status));
}
+43 -2
View File
@@ -66,7 +66,7 @@ void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* h
}
}
void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week) {
void ffEdidGetManufactureDate(const uint8_t edid[128], uint16_t* year, uint16_t* week) {
if (edid[17] > 0 && edid[17] < 0xFF) {
*year = (uint16_t) (edid[17] + 1990);
*week = (uint16_t) edid[16];
@@ -76,8 +76,49 @@ void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial
} else {
*year = *week = 0;
}
}
*serial = *(uint32_t*) &edid[12];
bool ffEdidGetSerial(const uint8_t edid[128], FFstrbuf* result) {
int descriptor_offsets[4] = {54, 72, 90, 108};
for (int i = 0; i < 4; i++) {
int offset = descriptor_offsets[i];
const uint8_t* desc = edid + offset;
if (desc[0] == 0x00 && desc[1] == 0x00) { // Monitor Descriptor
uint8_t tag = desc[3]; // Descriptor Type Tag
if (tag == 0xFF) { // Display Product Serial Number
ffStrbufClear(result);
for (int j = 0; j < 13; j++) {
uint8_t ch = desc[5 + j];
if (ch == 0x0A || ch == 0x00) {
break;
}
ffStrbufAppendC(result, (char) ch);
}
ffStrbufTrim(result, ' ');
if (result->length > 0) {
return true;
}
}
}
}
uint32_t int_serial = 0;
int_serial |= (uint32_t)edid[12];
int_serial |= (uint32_t)edid[13] << 8;
int_serial |= (uint32_t)edid[14] << 16;
int_serial |= (uint32_t)edid[15] << 24;
if (int_serial != 0 && int_serial != 0xFFFFFFFF) {
ffStrbufSetF(result, "0x%08X", int_serial);
return true;
}
return false;
}
bool ffEdidGetHdrCompatible(const uint8_t* edid, uint32_t length) {
+1 -2
View File
@@ -191,7 +191,7 @@ static bool parseLuaString(FFstrbuf* buffer, const char* script, uint32_t script
lua_pushboolean(L, *(bool*) arg->value);
break;
case FF_ARG_TYPE_STRING:
lua_pushstring(L, (const char*) arg->value);
lua_pushlstring(L, (const char*) arg->value, strlen((const char*) arg->value));
break;
case FF_ARG_TYPE_STRBUF: {
const FFstrbuf* sb = (const FFstrbuf*) arg->value;
@@ -232,7 +232,6 @@ static bool parseLuaString(FFstrbuf* buffer, const char* script, uint32_t script
if (res) {
ffStrbufAppendS(buffer, res);
} else {
// Fallback: use luaL_tolstring to get a reasonable representation
luaL_tolstring(L, 1, NULL);
const char* sval = lua_tolstring(L, -1, NULL);
if (sval) {
+32 -23
View File
@@ -3,6 +3,7 @@
#include "common/parsing.h"
#include "common/thread.h"
#include "common/textModifier.h"
#include "common/strutil.h"
#include "detection/displayserver/displayserver.h"
#include "detection/terminaltheme/terminaltheme.h"
#include "logo/logo.h"
@@ -16,6 +17,9 @@
#else
#include <signal.h>
#endif
#if __linux__
#include <linux/version.h>
#endif
FFinstance instance; // Global singleton
@@ -46,10 +50,30 @@ static void defaultConfig(void) {
ffOptionsInitDisplay(&instance.config.display);
}
#ifdef _WIN32
static volatile UINT oldCp = CP_UTF8;
void resetConsoleCP(void) {
if (oldCp != CP_UTF8) {
SetConsoleOutputCP(oldCp);
}
}
#endif
void ffInitInstance(void) {
#ifdef _WIN32
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendat>
setlocale(LC_ALL, ".UTF8");
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
if (GetConsoleMode(hStdout, &mode)) {
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
oldCp = GetConsoleOutputCP();
if (oldCp != CP_UTF8) {
SetConsoleOutputCP(CP_UTF8);
atexit(resetConsoleCP);
}
}
#else
// Never use `setlocale(LC_ALL, "")`
setlocale(LC_TIME, "");
@@ -61,9 +85,6 @@ void ffInitInstance(void) {
static volatile bool ffDisableLinewrap = false;
static volatile bool ffHideCursor = false;
#ifdef _WIN32
static volatile UINT oldCp = CP_UTF8;
#endif
static void resetConsole(void) {
if (ffDisableLinewrap) {
@@ -80,10 +101,6 @@ static void resetConsole(void) {
#if defined(_WIN32)
fflush(stdout);
if (oldCp != CP_UTF8) {
SetConsoleOutputCP(oldCp);
}
#endif
}
@@ -111,15 +128,6 @@ void ffStart(void) {
setvbuf(stdout, NULL, _IOFBF, 4096);
}
SetConsoleCtrlHandler(consoleHandler, TRUE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
if (GetConsoleMode(hStdout, &mode)) {
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
oldCp = GetConsoleOutputCP();
if (oldCp != CP_UTF8) {
SetConsoleOutputCP(CP_UTF8);
}
}
#else
if (instance.config.display.noBuffer) {
setvbuf(stdout, NULL, _IONBF, 0);
@@ -180,13 +188,14 @@ void ffDestroyInstance(void) {
#endif
#if FF_HAVE_QUICKJS
#include <quickjs.h>
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#endif
// Must be in a file compiled with the libfastfetch target, because the FF_HAVE* macros are not defined for the executable targets
void ffListFeatures(void) {
fputs(
#if __linux__
"linux-headers " FF_STR(LINUX_VERSION_MAJOR) "." FF_STR(LINUX_VERSION_PATCHLEVEL) "." FF_STR(LINUX_VERSION_SUBLEVEL) "\n"
#endif
#if FF_HAVE_THREADS
"threads\n"
#endif
@@ -205,9 +214,6 @@ void ffListFeatures(void) {
#if FF_HAVE_DRM
"drm\n"
#endif
#if FF_HAVE_DRM_AMDGPU
"drm_amdgpu\n"
#endif
#if FF_HAVE_GIO
"gio\n"
#endif
@@ -262,8 +268,11 @@ void ffListFeatures(void) {
#if FF_HAVE_LIBZFS
"libzfs\n"
#endif
#if FF_HAVE_VA
"va\n"
#if FF_HAVE_VADRM
"va-drm\n"
#endif
#if FF_HAVE_VAX11
"va-x11\n"
#endif
#if FF_HAVE_VDPAU
"vdpau\n"
+1 -1
View File
@@ -177,7 +177,7 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) {
}
static inline void readWithLength(HANDLE handle, FFstrbuf* buffer, uint32_t length) {
ffStrbufEnsureFree(buffer, length);
ffStrbufEnsureFixedLengthFree(buffer, length);
DWORD bytesRead = 0;
while (
length > 0 &&
+4 -4
View File
@@ -27,7 +27,7 @@
#endif
#endif
static void* libraryLoad(const char* path, int maxVersion) {
void* ffLibraryLoadSingle(const char* path, int maxVersion) {
void* result = dlopen(path, FF_DLOPEN_FLAGS);
#if _WIN32
@@ -81,8 +81,8 @@ static void* libraryLoad(const char* path, int maxVersion) {
return result;
}
void* ffLibraryLoad(const char* path, int maxVersion, ...) {
void* result = libraryLoad(path, maxVersion);
void* ffLibraryLoadMulti(const char* path, int maxVersion, ...) {
void* result = ffLibraryLoadSingle(path, maxVersion);
if (!result) {
va_list defaultNames;
@@ -95,7 +95,7 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...) {
}
int maxVersionRest = va_arg(defaultNames, int);
result = libraryLoad(pathRest, maxVersionRest);
result = ffLibraryLoadSingle(pathRest, maxVersionRest);
} while (!result);
va_end(defaultNames);
+44 -27
View File
@@ -5,7 +5,15 @@
struct FFLuaData luaData;
static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc) {
static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc, int depth) {
if (__builtin_expect(depth > 15, false)) {
yyjson_mut_doc_free(doc);
lua_pushlstring(
L, "yyjson: recursion depth exceeded; possible circular reference", strlen("yyjson: recursion depth exceeded; possible circular reference"));
lua_error(L); // noreturn
__builtin_unreachable();
}
if (idx < 0) {
idx = lua_gettop(L) + idx + 1;
}
@@ -66,7 +74,7 @@ static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc) {
yyjson_mut_val* arr = yyjson_mut_arr(doc);
for (lua_Unsigned i = 1; i <= len; i++) {
lua_rawgeti(L, idx, (lua_Integer) i);
yyjson_mut_val* val = lua2yyjson(L, -1, doc);
yyjson_mut_val* val = lua2yyjson(L, -1, doc, depth + 1);
yyjson_mut_arr_append(arr, val);
lua_pop(L, 1);
}
@@ -80,7 +88,7 @@ static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc) {
yyjson_mut_val* key = yyjson_mut_strncpy(doc, key_str, klen);
lua_pop(L, 1);
yyjson_mut_val* val = lua2yyjson(L, -1, doc);
yyjson_mut_val* val = lua2yyjson(L, -1, doc, depth + 1);
yyjson_mut_obj_add(obj, key, val);
lua_pop(L, 1);
}
@@ -102,28 +110,35 @@ static int yyjsonEncode(lua_State* L) {
}
yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL);
if (!doc) {
return luaL_error(L, "failed to create yyjson document");
if (__builtin_expect(!doc, false)) {
lua_pushlstring(L, "yyjson: yyjson_mut_doc_new() failed", strlen("yyjson: yyjson_mut_doc_new() failed"));
return lua_error(L);
}
yyjson_mut_val* root = lua2yyjson(L, 1, doc);
yyjson_mut_val* root = lua2yyjson(L, 1, doc, 0);
yyjson_mut_doc_set_root(doc, root);
size_t jsonLen;
yyjson_write_err err = {};
FF_AUTO_FREE const char* jsonStr = yyjson_mut_write_opts(doc, YYJSON_WRITE_ALLOW_INF_AND_NAN | (pretty ? YYJSON_WRITE_PRETTY_TWO_SPACES : 0), NULL, &jsonLen, &err);
if (jsonStr) {
if (__builtin_expect(jsonStr != NULL, true)) {
lua_pushlstring(L, jsonStr, jsonLen);
yyjson_mut_doc_free(doc);
return 1;
} else {
yyjson_mut_doc_free(doc);
return luaL_error(L, "failed to encode JSON: %s", err.msg);
{
FF_STRBUF_AUTO_DESTROY errBuf = ffStrbufCreateStatic("yyjson: yyjson_mut_write_opts() failed: ");
ffStrbufAppendS(&errBuf, err.msg);
lua_pushlstring(L, errBuf.chars, errBuf.length);
}
return lua_error(L); // longjmp
}
}
const char* ffLuaLoadState() {
const char* ffLuaLoadState(void) {
if (luaData.inited) {
if (luaData.L == NULL) {
return "Lua library is not available";
@@ -163,35 +178,37 @@ const char* ffLuaLoadState() {
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(liblua, luaopen_string)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(liblua, luaopen_table)
#endif
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_settop)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_loadbufferx)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tolstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_createtable)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushinteger)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnumber)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushboolean)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushlstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushvalue)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_seti)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnil)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_setfield)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pcallk)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_gettop)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_tolstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_error)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushcclosure)
#if !FF_DISABLE_DLOPEN
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_checkany)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_loadbufferx)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_tolstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_callk)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_createtable)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_error)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_gettop)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_isinteger)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_next)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pcallk)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushboolean)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushcclosure)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushinteger)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushlstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnil)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnumber)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushvalue)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_rawgeti)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_rawlen)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_setfield)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_setglobal)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_seti)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_settop)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_toboolean)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tointegerx)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tolstring)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tonumberx)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_type)
#endif
lua_State* L = ffluaL_newstate();
if (L == NULL) {
+1 -3
View File
@@ -1,12 +1,10 @@
#include "common/netif.h"
#include "common/io.h"
#include "common/strutil.h"
#include <net/if.h>
#include <stdio.h>
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) {
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/route", "r");
+9 -2
View File
@@ -56,7 +56,14 @@ static const char* tryNonThreadingFastPath(FFNetworkingState* state) {
}
#ifndef __APPLE__
FF_DEBUG("Using sendto() + MSG_DONTWAIT to send %u bytes of data", state->command.length);
FF_DEBUG("Using sendto() "
#ifdef MSG_FASTOPEN
"+ MSG_FASTOPEN "
#endif
#ifdef MSG_NOSIGNAL
"+ MSG_NOSIGNAL "
#endif
"to send %u bytes of data", state->command.length);
ssize_t sent = sendto(state->sockfd,
state->command.chars,
state->command.length,
@@ -66,7 +73,7 @@ static const char* tryNonThreadingFastPath(FFNetworkingState* state) {
#ifdef MSG_NOSIGNAL
MSG_NOSIGNAL |
#endif
MSG_DONTWAIT,
0,
state->addr->ai_addr,
state->addr->ai_addrlen);
#else
+2 -2
View File
@@ -269,7 +269,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
}
}
if (exePath->length == 0) {
if (exePath->length == 0 && access(filePath, X_OK) == 0) {
ffStrbufSetS(exePath, filePath);
}
}
@@ -546,7 +546,7 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
return "sysctl(KERN_PROC_PID) failed";
}
ffStrbufSetS(name, proc.kp_proc.p_comm); // trancated to 16 chars
ffStrbufSetS(name, proc.kp_proc.p_comm); // truncated to 16 chars
if (ppid) {
*ppid = (pid_t) proc.kp_eproc.e_ppid;
}
+1 -1
View File
@@ -391,7 +391,7 @@ int ffSettingsGetSQLite3Int(const char* dbPath, const char* query) {
}
sqlite3* db;
if (data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) {
if (data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) {
return 0;
}
+148
View File
@@ -0,0 +1,148 @@
// DON'T CALL ANY FASTFETCH FUNCTION IN THIS FILE (to avoid recursion when -finstrument-functions is enabled)
#include <stdio.h>
#include <time.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#if !_WIN32
#include <dlfcn.h>
#include <pthread.h>
#include <unistd.h>
#else
#include <windows.h>
#include <dbghelp.h>
#endif
#if _WIN32
static LARGE_INTEGER freq;
#define NtCurrentProcess() ((HANDLE) (-1))
#endif
static struct trace_event {
uint64_t ts;
uint64_t tid;
void* func;
} events[4 * 1024 * 1024]; // 4M events, 96 MiB memory usage
static _Atomic uint32_t event_count;
__attribute__((no_instrument_function, always_inline)) static inline uint64_t get_time_us() {
#if !_WIN32
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
#else
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (uint64_t) (now.QuadPart * 1000000 / freq.QuadPart);
#endif
}
#if _WIN32
__attribute__((constructor, no_instrument_function)) void trace_init() {
QueryPerformanceFrequency(&freq);
}
#endif
__attribute__((destructor, no_instrument_function)) void trace_fini() {
#if _WIN32
uint32_t pid = (uint32_t) GetCurrentProcessId();
#else
uint32_t pid = (uint32_t) getpid();
#endif
char fileName[64];
snprintf(fileName, sizeof(fileName), "trace_%d.json", pid);
FILE* trace_file = fopen(fileName, "wb");
if (!trace_file) {
fprintf(stderr, "Failed to open trace file %s for writing\n", fileName);
abort();
}
fputs("[\n", trace_file);
#if _WIN32
SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
SymInitialize(NtCurrentProcess(), NULL, TRUE);
#endif
const char* fnName = NULL;
uint32_t count = atomic_load_explicit(&event_count, memory_order_acquire);
for (uint32_t i = 0; i < count; ++i) {
void* fn = events[i].func;
uint64_t ts = events[i].ts;
bool is_exit = (ts >> 63) != 0;
ts &= ~(1ULL << 63); // clear the highest bit
uint64_t tid = events[i].tid;
#if _WIN32
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
DWORD64 displacement = 0;
if (SymFromAddr(NtCurrentProcess(), (DWORD64) fn, &displacement, pSymbol)) {
fnName = pSymbol->Name;
}
#else
char buffer[32];
Dl_info info;
if (dladdr(fn, &info) && info.dli_sname) {
fnName = info.dli_sname;
}
#endif
else {
snprintf(buffer, sizeof(buffer), "%p", fn);
fnName = buffer;
}
fprintf(trace_file, "{\"name\":\"%s\",\"ph\":\"%c\",\"pid\":%" PRIu32 ",\"tid\":%" PRIu64 ",\"ts\":%" PRIu64 "}%c\n", fnName, is_exit ? 'E' : 'B', pid, tid, ts, i < count - 1 ? ',' : ' ');
}
fputc(']', trace_file);
fclose(trace_file);
fprintf(stderr, "Trace written to trace_%d.json with %u events. Use https://ui.perfetto.dev/ to view it.\n", pid, count);
#if _WIN32
SymCleanup(NtCurrentProcess());
#endif
}
__attribute__((no_instrument_function)) static void write_event(void* this_fn, bool is_exit) {
uint32_t idx = atomic_fetch_add_explicit(&event_count, 1, memory_order_relaxed);
if (__builtin_expect(idx >= sizeof(events) / sizeof(events[0]), false)) {
abort();
}
events[idx].ts = get_time_us();
#if ENABLE_THREADS
#if _WIN32
events[idx].tid = (uint64_t) GetCurrentThreadId();
#else
events[idx].tid = (uint64_t) (uintptr_t) pthread_self();
#endif
#else
events[idx].tid = 0;
#endif
events[idx].func = this_fn;
if (is_exit) {
events[idx].ts |= (1ULL << 63); // set the highest bit to indicate function exit
}
}
__attribute__((no_instrument_function)) void __cyg_profile_func_enter(void* this_fn, void* call_site) {
(void) call_site;
write_event(this_fn, false);
}
__attribute__((no_instrument_function)) void __cyg_profile_func_exit(void* this_fn, void* call_site) {
(void) call_site;
write_event(this_fn, true);
}
+17 -25
View File
@@ -40,6 +40,7 @@ HANDLE openat(HANDLE dfd, const char* fileName, int oflag);
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory);
#endif
FF_A_ALWAYS_INLINE
static inline bool ffIsValidNativeFD(FFNativeFD fd) {
#ifndef _WIN32
return fd >= 0;
@@ -49,20 +50,17 @@ static inline bool ffIsValidNativeFD(FFNativeFD fd) {
#endif
}
FF_A_NONNULL(1) static inline bool wrapClose(FFNativeFD* pfd) {
FF_A_ALWAYS_INLINE FF_A_NONNULL(1)
static inline void wrapClose(FFNativeFD* pfd) {
assert(pfd);
if (!ffIsValidNativeFD(*pfd)) {
return false;
}
if (ffIsValidNativeFD(*pfd)) {
#ifndef _WIN32
close(*pfd);
close(*pfd);
#else
NtClose(*pfd);
NtClose(*pfd);
#endif
return true;
}
}
#define FF_AUTO_CLOSE_FD FF_A_CLEANUP(wrapClose)
@@ -250,34 +248,28 @@ static inline void ffUnsuppressIO(bool* suppressed) {
void ffListFilesRecursively(const char* path, bool pretty);
FF_A_NONNULL(1) static inline bool wrapFclose(FILE** pfile) {
FF_A_NONNULL(1) FF_A_ALWAYS_INLINE static inline void wrapFclose(FILE** pfile) {
assert(pfile);
if (!*pfile) {
return false;
if (*pfile) {
fclose(*pfile);
}
fclose(*pfile);
return true;
}
#define FF_AUTO_CLOSE_FILE FF_A_CLEANUP(wrapFclose)
FF_A_NONNULL(1)
FF_A_NONNULL(1) FF_A_ALWAYS_INLINE
#ifndef _WIN32
static inline bool wrapClosedir(DIR** pdir) {
static inline void wrapClosedir(DIR** pdir) {
assert(pdir);
if (!*pdir) {
return false;
if (*pdir) {
closedir(*pdir);
}
closedir(*pdir);
return true;
}
#else
static inline bool wrapClosedir(HANDLE* pdir) {
static inline void wrapClosedir(HANDLE* pdir) {
assert(pdir);
if (!*pdir) {
return false;
if (*pdir) {
FindClose(*pdir);
}
FindClose(*pdir);
return true;
}
#endif
#define FF_AUTO_CLOSE_DIR FF_A_CLEANUP(wrapClosedir)
+7 -5
View File
@@ -35,9 +35,10 @@ static inline void ffLibraryUnload(void** handle) {
#define FF_LIBRARY_SYMBOL(symbolName) \
__typeof__(&symbolName) ff##symbolName;
#define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...) \
void* FF_A_CLEANUP(ffLibraryUnload) libraryObjectName = ffLibraryLoad(__VA_ARGS__, NULL); \
if (libraryObjectName == NULL) \
#define FF_LIBRARY_LOAD(libraryObjectName, returnValue, libraryFileName, maxVersion, ...) \
void* FF_A_CLEANUP(ffLibraryUnload) libraryObjectName = ffLibraryLoadSingle(libraryFileName, maxVersion); \
__VA_OPT__(if (__builtin_expect(libraryObjectName == NULL, false)) libraryObjectName = ffLibraryLoadMulti(__VA_ARGS__, NULL);) \
if (__builtin_expect(libraryObjectName == NULL, false)) \
return returnValue;
#define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
@@ -45,7 +46,7 @@ static inline void ffLibraryUnload(void** handle) {
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
symbolMapping = (__typeof__(&symbolName)) dlsym(library, #symbolName); \
if (symbolMapping == NULL) \
if (__builtin_expect(symbolMapping == NULL, false)) \
return returnValue;
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
@@ -66,7 +67,8 @@ static inline void ffLibraryUnload(void** handle) {
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff##symbolName, symbolName, returnValue);
void* ffLibraryLoad(const char* path, int maxVersion, ...);
void* ffLibraryLoadSingle(const char* path, int maxVersion);
void* ffLibraryLoadMulti(const char* path, int maxVersion, ...);
#else
+45 -41
View File
@@ -3,16 +3,19 @@
#include "fastfetch.h"
#if FF_HAVE_LUA
// Hack. LUA_API is defined as extern which prevents us from implementing the functions ourselves.
#include <luaconf.h>
#undef LUA_API
#undef LUALIB_API
#undef LUAMOD_API
#define LUA_API static inline
#define LUALIB_API LUA_API
#define LUAMOD_API LUA_API
#if !FF_DISABLE_DLOPEN
// Hack. LUA_API is defined as extern which prevents us from implementing the functions ourselves.
#include <luaconf.h>
#undef LUA_API
#undef LUALIB_API
#undef LUAMOD_API
#define LUA_API static inline
#define LUALIB_API LUA_API
#define LUAMOD_API LUA_API
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#pragma GCC diagnostic ignored "-Wunused-function"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
@@ -24,48 +27,42 @@
#include "common/library.h"
extern struct FFLuaData {
FF_LIBRARY_SYMBOL(luaL_newstate)
#if LUA_VERSION_NUM >= 505
FF_LIBRARY_SYMBOL(luaL_openselectedlibs)
#else
FF_LIBRARY_SYMBOL(luaL_openlibs)
#endif
FF_LIBRARY_SYMBOL(lua_settop)
FF_LIBRARY_SYMBOL(luaL_loadbufferx)
FF_LIBRARY_SYMBOL(lua_tolstring)
FF_LIBRARY_SYMBOL(lua_createtable)
FF_LIBRARY_SYMBOL(lua_pushinteger)
FF_LIBRARY_SYMBOL(lua_pushnumber)
FF_LIBRARY_SYMBOL(lua_pushboolean)
FF_LIBRARY_SYMBOL(lua_pushstring)
FF_LIBRARY_SYMBOL(lua_pushlstring)
FF_LIBRARY_SYMBOL(lua_pushvalue)
FF_LIBRARY_SYMBOL(lua_seti)
FF_LIBRARY_SYMBOL(lua_pushnil)
FF_LIBRARY_SYMBOL(lua_setfield)
FF_LIBRARY_SYMBOL(lua_pcallk)
FF_LIBRARY_SYMBOL(lua_gettop)
FF_LIBRARY_SYMBOL(luaL_tolstring)
FF_LIBRARY_SYMBOL(luaL_error)
FF_LIBRARY_SYMBOL(lua_pushcclosure)
#if !FF_DISABLE_DLOPEN
FF_LIBRARY_SYMBOL(luaL_checkany)
FF_LIBRARY_SYMBOL(luaL_loadbufferx)
FF_LIBRARY_SYMBOL(luaL_tolstring)
FF_LIBRARY_SYMBOL(lua_callk)
FF_LIBRARY_SYMBOL(lua_createtable)
FF_LIBRARY_SYMBOL(lua_error)
FF_LIBRARY_SYMBOL(lua_gettop)
FF_LIBRARY_SYMBOL(lua_isinteger)
FF_LIBRARY_SYMBOL(lua_next)
FF_LIBRARY_SYMBOL(lua_pcallk)
FF_LIBRARY_SYMBOL(lua_pushboolean)
FF_LIBRARY_SYMBOL(lua_pushcclosure)
FF_LIBRARY_SYMBOL(lua_pushinteger)
FF_LIBRARY_SYMBOL(lua_pushlstring)
FF_LIBRARY_SYMBOL(lua_pushnil)
FF_LIBRARY_SYMBOL(lua_pushnumber)
FF_LIBRARY_SYMBOL(lua_pushvalue)
FF_LIBRARY_SYMBOL(lua_rawgeti)
FF_LIBRARY_SYMBOL(lua_rawlen)
FF_LIBRARY_SYMBOL(lua_setfield)
FF_LIBRARY_SYMBOL(lua_setglobal)
FF_LIBRARY_SYMBOL(lua_seti)
FF_LIBRARY_SYMBOL(lua_settop)
FF_LIBRARY_SYMBOL(lua_toboolean)
FF_LIBRARY_SYMBOL(lua_tointegerx)
FF_LIBRARY_SYMBOL(lua_tolstring)
FF_LIBRARY_SYMBOL(lua_tonumberx)
FF_LIBRARY_SYMBOL(lua_type)
#endif
lua_State* L;
bool inited;
} luaData;
const char* ffLuaLoadState();
#if !FF_DISABLE_DLOPEN
FF_A_ALWAYS_INLINE void(lua_settop)(lua_State* L, int idx) {
return luaData.fflua_settop(L, idx);
}
@@ -94,10 +91,6 @@ FF_A_ALWAYS_INLINE void(lua_pushboolean)(lua_State* L, int b) {
return luaData.fflua_pushboolean(L, b);
}
FF_A_ALWAYS_INLINE const char*(lua_pushstring) (lua_State * L, const char* s) {
return luaData.fflua_pushstring(L, s);
}
FF_A_ALWAYS_INLINE const char*(lua_pushlstring) (lua_State * L, const char* s, size_t len) {
return luaData.fflua_pushlstring(L, s, len);
}
@@ -130,7 +123,9 @@ FF_A_ALWAYS_INLINE const char*(luaL_tolstring) (lua_State * L, int idx, size_t*
return luaData.ffluaL_tolstring(L, idx, len);
}
#define luaL_error(L, fmt, ...) luaData.ffluaL_error(L, fmt, ##__VA_ARGS__)
FF_A_ALWAYS_INLINE int(lua_error)(lua_State* L) {
return luaData.fflua_error(L);
}
FF_A_ALWAYS_INLINE void(lua_pushcclosure)(lua_State* L, lua_CFunction fn, int n) {
return luaData.fflua_pushcclosure(L, fn, n);
@@ -156,7 +151,13 @@ FF_A_ALWAYS_INLINE int(lua_rawgeti)(lua_State* L, int idx, lua_Integer n) {
return luaData.fflua_rawgeti(L, idx, n);
}
FF_A_ALWAYS_INLINE lua_Unsigned(lua_rawlen)(lua_State* L, int idx) {
FF_A_ALWAYS_INLINE
#if LUA_VERSION_NUM > 503
lua_Unsigned
#else
size_t
#endif
(lua_rawlen)(lua_State* L, int idx) {
return luaData.fflua_rawlen(L, idx);
}
@@ -179,5 +180,8 @@ FF_A_ALWAYS_INLINE lua_Number(lua_tonumberx)(lua_State* L, int idx, int* isnum)
FF_A_ALWAYS_INLINE int(lua_type)(lua_State* L, int idx) {
return luaData.fflua_type(L, idx);
}
#endif
const char* ffLuaLoadState(void);
#endif
+2
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <assert.h>
#include "common/attributes.h"
#if FF_HAVE_MALLOC_USABLE_SIZE || FF_HAVE_MSVC_MSIZE
#if __has_include(<malloc.h>)
@@ -13,6 +14,7 @@
#include <malloc/malloc.h>
#endif
FF_A_ALWAYS_INLINE FF_A_NONNULL(1)
static inline void ffWrapFree(const void* pPtr) {
assert(pPtr);
if (*(void**) pPtr) {
+14
View File
@@ -5,6 +5,7 @@
#include <string.h>
#include <ctype.h>
#include "common/attributes.h"
#include "common/wcwidth.h"
#ifdef _WIN32
@@ -13,6 +14,9 @@ __stdcall char* StrStrIA(const char* lpFirst, const char* lpSrch);
#define strcasestr StrStrIA
#endif
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
static inline bool ffStrSet(const char* str) {
if (str == NULL) {
return false;
@@ -25,14 +29,17 @@ static inline bool ffStrSet(const char* str) {
return *str != '\0';
}
FF_A_ALWAYS_INLINE
static inline bool ffStrStartsWithIgnCase(const char* str, const char* compareTo) {
return strncasecmp(str, compareTo, strlen(compareTo)) == 0;
}
FF_A_ALWAYS_INLINE
static inline bool ffStrEqualsIgnCase(const char* str, const char* compareTo) {
return strcasecmp(str, compareTo) == 0;
}
FF_A_ALWAYS_INLINE
static inline bool ffStrStartsWith(const char* str, const char* compareTo) {
return strncmp(str, compareTo, strlen(compareTo)) == 0;
}
@@ -55,26 +62,32 @@ static inline bool ffStrEndsWithIgnCase(const char* str, const char* compareTo)
return strncasecmp(str + strLength - compareToLength, compareTo, compareToLength) == 0;
}
FF_A_ALWAYS_INLINE
static inline bool ffStrEquals(const char* str, const char* compareTo) {
return strcmp(str, compareTo) == 0;
}
FF_A_ALWAYS_INLINE
static inline bool ffStrContains(const char* str, const char* compareTo) {
return strstr(str, compareTo) != NULL;
}
FF_A_ALWAYS_INLINE
static inline bool ffStrContainsIgnCase(const char* str, const char* compareTo) {
return strcasestr(str, compareTo) != NULL;
}
FF_A_ALWAYS_INLINE
static inline bool ffStrContainsC(const char* str, char compareTo) {
return strchr(str, compareTo) != NULL;
}
FF_A_ALWAYS_INLINE
static inline bool ffCharIsEnglishAlphabet(char c) {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
}
FF_A_ALWAYS_INLINE
static inline bool ffCharIsDigit(char c) {
return '0' <= c && c <= '9';
}
@@ -86,6 +99,7 @@ uint8_t ffUtf8CharLenWidth(const char* str, uint32_t length, uint8_t* width);
uint32_t ffUtf8StrWidth(const char* str, uint32_t length);
FF_A_ALWAYS_INLINE
static inline bool ffCharIsHexDigit(char c) {
return ffCharIsDigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
}
+7 -1
View File
@@ -4,7 +4,7 @@
#ifdef FF_HAVE_THREADS
#if defined(_WIN32)
#include <winternl.h>
#include "common/windows/nt.h"
#include <synchapi.h>
#include <process.h>
#include <processthreadsapi.h>
@@ -41,6 +41,9 @@ static inline bool ffThreadJoin(FFThreadType thread, uint32_t timeout) {
}
NtClose(thread);
return true;
}
static inline uintptr_t ffThreadGetCurrentId() {
return (uintptr_t) ffGetTeb()->ClientId.UniqueThread;
}
#else
#include <pthread.h>
@@ -104,6 +107,9 @@ static inline bool ffThreadJoin(FFThreadType thread, FF_A_UNUSED uint32_t timeou
#endif
pthread_join(thread, NULL);
return true;
}
static inline uintptr_t ffThreadGetCurrentId() {
return (uintptr_t) pthread_self();
}
#endif
#else // FF_HAVE_THREADS
+1 -3
View File
@@ -10,7 +10,7 @@ static const char* detectWithBacklight(FFlist* result) {
// https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight
const char* backlightDirPath = "/sys/class/backlight/";
DIR* dirp = opendir(backlightDirPath);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(backlightDirPath);
if (dirp == NULL) {
return "Failed to open `/sys/class/backlight/`";
}
@@ -72,8 +72,6 @@ static const char* detectWithBacklight(FFlist* result) {
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
}
closedir(dirp);
return NULL;
}
+1 -2
View File
@@ -24,8 +24,7 @@ typedef enum FF_A_PACKED FFCodecType {
FF_CODEC_TYPE_DOLBY_VISION_HEVC = UINT32_C(1) << 16,
FF_CODEC_TYPE_PRORES = UINT32_C(1) << 17,
FF_CODEC_TYPE_PRORES_RAW = UINT32_C(1) << 18,
FF_CODEC_TYPE_JPEG_XL = UINT32_C(1) << 19,
FF_CODEC_TYPE_MAX = FF_CODEC_TYPE_JPEG_XL,
FF_CODEC_TYPE_MAX = FF_CODEC_TYPE_PRORES_RAW,
FF_CODEC_TYPE_FORCE_UNSIGNED = UINT32_MAX,
} FFCodecType;
+22 -22
View File
@@ -7,28 +7,28 @@ static const struct {
CMVideoCodecType codec;
FFCodecType type;
} FF_CODEC_CODECS[] = {
{ kCMVideoCodecType_H263, FF_CODEC_TYPE_H263 },
{ kCMVideoCodecType_JPEG, FF_CODEC_TYPE_MJPEG },
{ kCMVideoCodecType_JPEG_XL, FF_CODEC_TYPE_JPEG_XL },
{ kCMVideoCodecType_MPEG1Video, FF_CODEC_TYPE_MPEG1 },
{ kCMVideoCodecType_MPEG2Video, FF_CODEC_TYPE_MPEG2 },
{ kCMVideoCodecType_MPEG4Video, FF_CODEC_TYPE_DIVX_XVID },
{ kCMVideoCodecType_H264, FF_CODEC_TYPE_H264 },
{ kCMVideoCodecType_HEVC, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_HEVCWithAlpha, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_DolbyVisionHEVC, FF_CODEC_TYPE_DOLBY_VISION_HEVC },
{ kCMVideoCodecType_DisparityHEVC, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_DepthHEVC, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_VP9, FF_CODEC_TYPE_VP9 },
{ kCMVideoCodecType_AV1, FF_CODEC_TYPE_AV1 },
{ kCMVideoCodecType_AppleProRes4444XQ, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes4444, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422HQ, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422LT, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422Proxy, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProResRAW, FF_CODEC_TYPE_PRORES_RAW },
{ kCMVideoCodecType_AppleProResRAWHQ, FF_CODEC_TYPE_PRORES_RAW },
{ 'h263', FF_CODEC_TYPE_H263 }, // kCMVideoCodecType_H263
{ 'jpeg', FF_CODEC_TYPE_MJPEG }, // kCMVideoCodecType_JPEG
{ 'dmb1', FF_CODEC_TYPE_MJPEG }, // kCMVideoCodecType_JPEG_OpenDML
{ 'mp1v', FF_CODEC_TYPE_MPEG1 }, // kCMVideoCodecType_MPEG1Video
{ 'mp2v', FF_CODEC_TYPE_MPEG2 }, // kCMVideoCodecType_MPEG2Video
{ 'mp4v', FF_CODEC_TYPE_DIVX_XVID }, // kCMVideoCodecType_MPEG4Video
{ 'avc1', FF_CODEC_TYPE_H264 }, // kCMVideoCodecType_H264
{ 'hvc1', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_HEVC
{ 'muxa', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_HEVCWithAlpha
{ 'dvh1', FF_CODEC_TYPE_DOLBY_VISION_HEVC }, // kCMVideoCodecType_DolbyVisionHEVC
{ 'dish', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_DisparityHEVC
{ 'deph', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_DepthHEVC
{ 'vp09', FF_CODEC_TYPE_VP9 }, // kCMVideoCodecType_VP9
{ 'av01', FF_CODEC_TYPE_AV1 }, // kCMVideoCodecType_AV1
{ 'ap4x', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes4444XQ
{ 'ap4h', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes4444
{ 'apch', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422HQ
{ 'apcn', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422
{ 'apcs', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422LT
{ 'apco', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422Proxy
{ 'aprn', FF_CODEC_TYPE_PRORES_RAW }, // kCMVideoCodecType_AppleProResRAW
{ 'aprh', FF_CODEC_TYPE_PRORES_RAW }, // kCMVideoCodecType_AppleProResRAWHQ
};
static FFCodecType ffCodecCodecToType(CMVideoCodecType codec) {
+188 -186
View File
@@ -1,35 +1,33 @@
#include "codec.h"
#if (FF_HAVE_DRM && FF_HAVE_VA) || FF_HAVE_VDPAU
#if FF_HAVE_VADRM || FF_HAVE_VAX11
#define FF_HAVE_VA 1
#endif
#if FF_HAVE_VA || FF_HAVE_VDPAU
#include "common/library.h"
#include "common/mallocHelper.h"
#include "common/strutil.h"
#include "common/io.h"
#if FF_HAVE_DRM && FF_HAVE_VA
#include "detection/gpu/gpu.h"
#if FF_HAVE_VA
#include <fcntl.h>
#include <va/va.h>
#include <va/va_drm.h>
#include <xf86drm.h>
#endif
#include <string.h>
typedef struct FFVAData {
FF_LIBRARY_SYMBOL(vaInitialize)
FF_LIBRARY_SYMBOL(vaTerminate)
FF_LIBRARY_SYMBOL(vaMaxNumProfiles)
FF_LIBRARY_SYMBOL(vaMaxNumEntrypoints)
FF_LIBRARY_SYMBOL(vaQueryConfigProfiles)
FF_LIBRARY_SYMBOL(vaQueryConfigEntrypoints)
FF_LIBRARY_SYMBOL(vaQueryVendorString)
FF_LIBRARY_SYMBOL(vaGetConfigAttributes)
} FFVAData;
#if FF_HAVE_VDPAU
#include <stdlib.h>
#include <vdpau/vdpau.h>
VdpStatus vdp_device_create_x11(void* display, int screen, VdpDevice* device, VdpGetProcAddress** get_proc_address);
void* XOpenDisplay(const char* display_name);
int XCloseDisplay(void* display);
int XDefaultScreen(void* display);
#endif
#if FF_HAVE_DRM && FF_HAVE_VA
static FFCodecType ffCodecProfileToType(VAProfile profile) {
static FFCodecType vaProfileToType(VAProfile profile) {
switch (profile) {
case 11: // VAProfileH263Baseline
return FF_CODEC_TYPE_H263;
@@ -98,7 +96,7 @@ static FFCodecType ffCodecProfileToType(VAProfile profile) {
}
}
static FFCodecShowType ffCodecGetEntrypointType(VAEntrypoint entrypoint) {
static FFCodecShowType vaGetEntrypointType(VAEntrypoint entrypoint) {
switch (entrypoint) {
case VAEntrypointVLD:
case VAEntrypointIDCT:
@@ -113,21 +111,20 @@ static FFCodecShowType ffCodecGetEntrypointType(VAEntrypoint entrypoint) {
}
}
static bool ffCodecProfileHasOutput(
static bool vaProfileHasOutput(
FFVAData* vaData,
VADisplay display,
__typeof__(vaQueryConfigEntrypoints)* ffvaQueryConfigEntrypoints,
__typeof__(vaGetConfigAttributes)* ffvaGetConfigAttributes,
int maxEntrypoints,
VAEntrypoint* entrypoints,
VAProfile profile,
FFCodecShowType entrypointType) {
int numEntrypoints = maxEntrypoints;
if (ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
if (vaData->ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
return false;
}
for (int i = 0; i < numEntrypoints; ++i) {
if (ffCodecGetEntrypointType(entrypoints[i]) != entrypointType) {
if (vaGetEntrypointType(entrypoints[i]) != entrypointType) {
continue;
}
@@ -136,7 +133,7 @@ static bool ffCodecProfileHasOutput(
.value = 0,
};
if (ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
if (vaData->ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
attrib.value != VA_ATTRIB_NOT_SUPPORTED &&
attrib.value != 0) {
return true;
@@ -146,91 +143,101 @@ static bool ffCodecProfileHasOutput(
return false;
}
static void ffCodecFillGpuName(const drmDevice* dev, const char* path, FFstrbuf* name) {
ffStrbufInit(name);
switch (dev->bustype) {
case DRM_BUS_PCI: {
FFGPUResult gpu = {
.vendor = ffStrbufCreateStatic(ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id)),
.name = ffStrbufCreate(),
};
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, &gpu);
ffStrbufSetF(name, "%s %s", gpu.vendor.chars, gpu.name.chars);
ffStrbufDestroy(&gpu.vendor);
ffStrbufDestroy(&gpu.name);
break;
}
case DRM_BUS_PLATFORM:
ffStrbufSetS(name, dev->deviceinfo.platform->compatible[0]);
return;
case DRM_BUS_HOST1X:
ffStrbufSetS(name, dev->deviceinfo.host1x->compatible[0]);
return;
case DRM_BUS_USB:
ffStrbufSetF(name, "0x%04X 0x%04X", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
return;
default:
ffStrbufSetStatic(name, "Unknown GPU");
return;
static bool vaDetectDisplay(VADisplay display, FFVAData* vaData, FFCodecOptions* options, FFlist* result, const char* api) {
int major = 0, minor = 0;
if (vaData->ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
vaData->ffvaTerminate(display);
return false;
}
if (!name->length && path && *path) {
const char* base = strrchr(path, '/');
ffStrbufSetS(name, base ? base + 1 : path);
int maxProfiles = vaData->ffvaMaxNumProfiles(display);
int maxEntrypoints = vaData->ffvaMaxNumEntrypoints(display);
if (maxProfiles <= 0 || maxEntrypoints <= 0) {
vaData->ffvaTerminate(display);
return false;
}
if (!name->length) {
ffStrbufSetStatic(name, "Unknown GPU");
}
}
FF_AUTO_FREE VAProfile* profiles = (VAProfile*) malloc(sizeof(VAProfile) * (size_t) maxProfiles);
FF_AUTO_FREE VAEntrypoint* entrypoints = (VAEntrypoint*) malloc(sizeof(VAEntrypoint) * (size_t) maxEntrypoints);
static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
FF_LIBRARY_LOAD_MESSAGE(libva, "libva" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaInitialize)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaTerminate)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaMaxNumProfiles)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaMaxNumEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryConfigProfiles)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryConfigEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaGetConfigAttributes)
FF_LIBRARY_LOAD_MESSAGE(libvaDrm, "libva-drm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaDrm, vaGetDisplayDRM)
drmDevicePtr devices[64];
int numDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
if (numDevices < 0) {
return "drmGetDevices() failed";
}
if (numDevices == 0) {
return "No DRM devices found";
int numProfiles = maxProfiles;
if (vaData->ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
vaData->ffvaTerminate(display);
return false;
}
const char* error = "No DRM device could initialize VA-API";
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
for (int j = 0; j < numProfiles; ++j) {
FFCodecType type = vaProfileToType(profiles[j]);
for (int i = 0; i < numDevices; ++i) {
drmDevice* dev = devices[i];
bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) &&
!(decoderTypes & type) &&
vaProfileHasOutput(
vaData,
display,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_DECODER);
const char* path = NULL;
if (dev->available_nodes & (1 << DRM_NODE_RENDER)) {
path = dev->nodes[DRM_NODE_RENDER];
} else if (dev->available_nodes & (1 << DRM_NODE_PRIMARY)) {
path = dev->nodes[DRM_NODE_PRIMARY];
} else {
bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) &&
!(encoderTypes & type) &&
vaProfileHasOutput(
vaData,
display,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_ENCODER);
if (!hasDecoder && !hasEncoder) {
continue;
}
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0) {
fd = open(path, O_RDONLY | O_CLOEXEC);
if (hasDecoder) {
decoderTypes |= type;
}
if (hasEncoder) {
encoderTypes |= type;
}
}
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffStrbufInitS(&item->gpu, vaData->ffvaQueryVendorString(display));
item->decoders = decoderTypes;
item->encoders = encoderTypes;
item->platformApi = api;
}
vaData->ffvaTerminate(display);
return true;
}
#if FF_HAVE_VADRM
#include <va/va_drm.h>
static const char* detectCodecByVaDrm(FFVAData* vaData, FFCodecOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libvaDrm, "libva-drm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaDrm, vaGetDisplayDRM)
const char* error = "No DRM device could initialize VA-API";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/dri/");
if (dirp == NULL) {
return "opendir(/dev/dri/) failed";
}
int drifd = dirfd(dirp);
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.' || !ffStrStartsWith(entry->d_name, "renderD")) {
continue;
}
FF_AUTO_CLOSE_FD int fd = openat(drifd, entry->d_name, O_RDWR | O_CLOEXEC);
if (fd < 0) {
continue;
}
@@ -240,84 +247,77 @@ static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result) {
continue;
}
int major = 0, minor = 0;
if (ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
continue;
if (vaDetectDisplay(display, vaData, options, result, "VA-API (DRM)")) {
error = NULL;
}
error = NULL;
int maxProfiles = ffvaMaxNumProfiles(display);
int maxEntrypoints = ffvaMaxNumEntrypoints(display);
if (maxProfiles <= 0 || maxEntrypoints <= 0) {
ffvaTerminate(display);
continue;
}
FF_AUTO_FREE VAProfile* profiles = (VAProfile*) malloc(sizeof(VAProfile) * (size_t) maxProfiles);
FF_AUTO_FREE VAEntrypoint* entrypoints = (VAEntrypoint*) malloc(sizeof(VAEntrypoint) * (size_t) maxEntrypoints);
int numProfiles = maxProfiles;
if (ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
ffvaTerminate(display);
continue;
}
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
for (int j = 0; j < numProfiles; ++j) {
FFCodecType type = ffCodecProfileToType(profiles[j]);
bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) &&
!(decoderTypes & type) &&
ffCodecProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_DECODER);
bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) &&
!(encoderTypes & type) &&
ffCodecProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_ENCODER);
if (!hasDecoder && !hasEncoder) {
continue;
}
if (hasDecoder) {
decoderTypes |= type;
}
if (hasEncoder) {
encoderTypes |= type;
}
}
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffCodecFillGpuName(dev, path, &item->gpu);
item->decoders = decoderTypes;
item->encoders = encoderTypes;
item->platformApi = "VA-API";
}
ffvaTerminate(display);
}
ffdrmFreeDevices(devices, numDevices);
return error;
}
#endif
#if FF_HAVE_VAX11
#include <va/va_x11.h>
static const char* detectCodecByVaX11(FFVAData* vaData, FFCodecOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libX11, "libX11" FF_LIBRARY_EXTENSION, 6)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XOpenDisplay)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XCloseDisplay)
FF_LIBRARY_LOAD_MESSAGE(libvaX11, "libva-x11" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaX11, vaGetDisplay)
Display* x11Display = ffXOpenDisplay(NULL);
if (!x11Display) {
return "XOpenDisplay() failed";
}
VADisplay display = ffvaGetDisplay(x11Display);
if (!display) {
ffXCloseDisplay(x11Display);
return "vaGetDisplay() failed";
}
if (!vaDetectDisplay(display, vaData, options, result, "VA-API (X11)")) {
ffXCloseDisplay(x11Display);
return "VA-API could not detect any supported codec via X11";
}
ffXCloseDisplay(x11Display);
return NULL;
}
#endif
static const char* detectCodecByVa(FFCodecOptions* options, FFlist* result) {
FFVAData vaData = {};
FF_LIBRARY_LOAD_MESSAGE(libva, "libva" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaInitialize)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaTerminate)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaMaxNumProfiles)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaMaxNumEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryConfigProfiles)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryConfigEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryVendorString)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaGetConfigAttributes)
#if FF_HAVE_VADRM
if (detectCodecByVaDrm(&vaData, options, result) == NULL) {
return NULL;
}
#endif
#if FF_HAVE_VAX11
if (detectCodecByVaX11(&vaData, options, result) == NULL) {
return NULL;
}
#endif
return "VA-API could not detect any supported codec via DRM or X11";
}
#endif
#if FF_HAVE_VDPAU
#include <vdpau/vdpau_x11.h>
static const struct FFCodecVdpauCodec {
VdpDecoderProfile profile;
@@ -326,6 +326,13 @@ static const struct FFCodecVdpauCodec {
{ 0, FF_CODEC_TYPE_MPEG1 }, // VDP_DECODER_PROFILE_MPEG1
{ 1, FF_CODEC_TYPE_MPEG2 }, // VDP_DECODER_PROFILE_MPEG2_SIMPLE
{ 2, FF_CODEC_TYPE_MPEG2 }, // VDP_DECODER_PROFILE_MPEG2_MAIN
{ 6, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_BASELINE
{ 7, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_MAIN
{ 8, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH
{ 9, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_SIMPLE
{ 10, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_MAIN
{ 11, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_ADVANCED
{ 12, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_MPEG4_PART2_SP
{ 13, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_MPEG4_PART2_ASP
{ 14, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX4_QMOBILE
@@ -336,17 +343,16 @@ static const struct FFCodecVdpauCodec {
{ 19, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_MOBILE
{ 20, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_HOME_THEATER
{ 21, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_HD_1080P
{ 6, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_BASELINE
{ 7, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_MAIN
{ 8, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH
{ 22, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
{ 23, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_EXTENDED
{ 24, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_PROGRESSIVE_HIGH
{ 25, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH
{ 26, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
{ 9, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_SIMPLE
{ 10, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_MAIN
{ 11, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_ADVANCED
{ 27, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_0
{ 28, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_1
{ 29, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_2
{ 30, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_3
{ 100, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN
{ 101, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_10
{ 102, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_STILL
@@ -354,17 +360,13 @@ static const struct FFCodecVdpauCodec {
{ 104, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444
{ 105, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444_10
{ 106, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444_12
{ 27, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_0
{ 28, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_1
{ 29, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_2
{ 30, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_3
{ 107, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_MAIN
{ 108, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_HIGH
{ 109, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_PROFESSIONAL
};
static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result) {
if (options->showType == FF_CODEC_SHOW_TYPE_DECODER) {
static const char* detectCodecByVdpau(FFCodecOptions* options, FFlist* result) {
if (!(options->showType & FF_CODEC_SHOW_TYPE_DECODER)) {
return "VDPAU only supports decoding";
}
@@ -376,7 +378,7 @@ static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result)
FF_LIBRARY_LOAD_MESSAGE(libvdpau, "libvdpau" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvdpau, vdp_device_create_x11)
void* x11Display = ffXOpenDisplay(NULL);
Display* x11Display = ffXOpenDisplay(NULL);
if (!x11Display) {
return "XOpenDisplay() failed";
}
@@ -446,13 +448,13 @@ static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result)
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
FF_SUPPRESS_IO();
#if FF_HAVE_DRM && FF_HAVE_VA
if (ffDetectCodecByVa(options, result) == NULL) {
#if FF_HAVE_VA
if (detectCodecByVa(options, result) == NULL) {
return NULL;
}
#endif
#if FF_HAVE_VDPAU
if (ffDetectCodecByVdpau(options, result) == NULL) {
if (detectCodecByVdpau(options, result) == NULL) {
return NULL;
}
#endif
@@ -464,7 +466,7 @@ const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
FF_UNUSED(options, result);
return "Fastfetch was built without DRM / VA-API / VDPAU headers";
return "Fastfetch was built without VA-API / VDPAU headers";
}
#endif
+3 -3
View File
@@ -408,13 +408,13 @@ const char* detectD3d11va(FFCodecOptions* options, FFlist* result /*list of FFCo
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(d3d11, D3D11CreateDevice)
FF_LIBRARY_LOAD_MESSAGE(mfplat, "mfplat" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFTEnum2)
FF_LIBRARY_LOAD_SYMBOL_LAZY(mfplat, MFTEnum2) // Not available on Windows 8.1
ffEnumHardwareAdapters(factory, [&](IDXGIAdapter1* adapter, const DXGI_ADAPTER_DESC1& desc) {
FFCodecType decoders = (options->showType & FF_CODEC_SHOW_TYPE_DECODER)
? ffDetectD3d11vaDecoders(adapter, ffD3D11CreateDevice)
: FF_CODEC_TYPE_NONE;
FFCodecType encoders = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER)
FFCodecType encoders = ffMFTEnum2 && (options->showType & FF_CODEC_SHOW_TYPE_ENCODER)
? ffDetectD3d11MftEncoders(desc.AdapterLuid, ffMFCreateAttributes, ffMFTEnum2)
: FF_CODEC_TYPE_NONE;
@@ -426,7 +426,7 @@ const char* detectD3d11va(FFCodecOptions* options, FFlist* result /*list of FFCo
ffStrbufInitWS(&gpuResult->gpu, desc.Description);
gpuResult->decoders = decoders;
gpuResult->encoders = encoders;
gpuResult->platformApi = "D3D11VA+MFT";
gpuResult->platformApi = ffMFTEnum2 ? "D3D11VA+MFT" : "D3D11VA";
});
return nullptr;
+5
View File
@@ -22,6 +22,11 @@ const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu) {
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); // Cut the speed output in the name as we append our own
ffStrbufTrimRight(&cpu->name, ' '); // If we removed the @ in previous step there was most likely a space before it
ffStrbufRemoveDupWhitespaces(&cpu->name);
#if __i386__ || __x86_64__
ffCPUDetectX86Specific(cpu);
#endif
return NULL;
}
+11
View File
@@ -27,9 +27,20 @@ typedef struct FFCPUResult {
FFCPUCore coreTypes[16]; // number of P cores, E cores, etc.
double temperature;
#if __i386__ || __x86_64__
const char* codeName;
const char* technology;
#endif
} FFCPUResult;
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
const char* ffCPUAppleCodeToName(uint32_t code);
const char* ffCPUQualcommCodeToName(uint32_t code);
void ffCPUDetectByCpuid(FFCPUResult* cpu);
#if __i386__ || __x86_64__
bool ffCPUDetectX86Specific(FFCPUResult* cpu);
#endif
+1 -1
View File
@@ -65,7 +65,7 @@ static const char* detectFrequency(FFCPUResult* cpu) {
// voltage-states5-sram stores supported <frequency / voltage> pairs of pcores from the lowest to the highest
// voltage-states1-sram stores ecores'
CFIndex propLength = CFDataGetLength(freqProperty);
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
if (propLength == 0 || propLength % (CFIndex) (sizeof(uint32_t) * 2) != 0) {
return "Invalid \"voltage-states5-sram\" length";
}
+44 -77
View File
@@ -461,7 +461,6 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
char* line = NULL;
size_t len = 0;
uint32_t lastPartId = UINT32_MAX;
uint32_t num = 0;
while (ffStrbufGetline(&line, &len, cpuinfo)) {
if (!ffStrStartsWith(line, "CPU part\t: ")) {
continue;
@@ -529,10 +528,7 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
}
if (lastPartId != partId) {
if (lastPartId != UINT32_MAX) {
if (num > 1) {
ffStrbufAppendF(&cpu->name, "*%u", num);
}
ffStrbufAppendS(&cpu->name, " + ");
ffStrbufAppendC(&cpu->name, '+');
}
if (name) {
ffStrbufAppendS(&cpu->name, name);
@@ -542,14 +538,8 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
ffStrbufAppend(&cpu->name, &cpu->vendor);
}
lastPartId = partId;
num = 1;
} else {
++num;
}
}
if (num > 1) {
ffStrbufAppendF(&cpu->name, "*%u", num);
}
}
#endif
@@ -619,19 +609,14 @@ static const char* parseCpuInfo(
return NULL;
}
static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer) {
uint32_t baseLen = basePath->length;
ffStrbufAppendS(basePath, cpuinfoFileName);
bool ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
static uint32_t getFrequency(int policyFd, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer) {
bool ok = ffReadFileBufferRelative(policyFd, cpuinfoFileName, buffer);
if (ok) {
return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000);
}
if (scalingFileName) {
ffStrbufAppendS(basePath, scalingFileName);
ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
ok = ffReadFileBufferRelative(policyFd, scalingFileName, buffer);
if (ok) {
return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000);
}
@@ -640,55 +625,38 @@ static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, co
return 0;
}
static uint8_t getNumCores(FFstrbuf* basePath, FFstrbuf* buffer) {
uint32_t baseLen = basePath->length;
ffStrbufAppendS(basePath, "/affected_cpus");
bool ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok) {
return (uint8_t) (ffStrbufCountC(buffer, ' ') + 1);
}
ffStrbufAppendS(basePath, "/related_cpus");
ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok) {
return (uint8_t) (ffStrbufCountC(buffer, ' ') + 1);
}
return 0;
}
static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) {
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/cpufreq/");
FF_AUTO_CLOSE_DIR DIR* dir = opendir(path.chars);
const char* basePath = "/sys/devices/system/cpu/cpufreq/";
FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath);
if (!dir) {
return false;
}
int freqFd = dirfd(dir);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
uint32_t baseLen = path.length;
struct dirent* entry;
while ((entry = readdir(dir)) != NULL) {
if (ffStrStartsWith(entry->d_name, "policy") && ffCharIsDigit(entry->d_name[strlen("policy")])) {
ffStrbufAppendS(&path, entry->d_name);
FF_AUTO_CLOSE_FD int policyFd = openat(freqFd, entry->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_PATH);
if (policyFd < 0) {
continue;
}
uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
uint32_t fmax = getFrequency(policyFd, "cpuinfo_max_freq", "scaling_max_freq", &buffer);
if (fmax == 0) {
continue;
}
if (cpu->frequencyMax >= fmax) {
if (!options->showPeCoreCount) {
ffStrbufSubstrBefore(&path, baseLen);
continue;
}
} else {
cpu->frequencyMax = fmax;
}
uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
uint32_t fbase = getFrequency(policyFd, "base_frequency", NULL, &buffer);
if (fbase > 0) {
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
}
@@ -702,9 +670,10 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) {
if (cpu->coreTypes[ifreq].freq == 0) {
cpu->coreTypes[ifreq].freq = freq;
}
cpu->coreTypes[ifreq].count += getNumCores(&path, &buffer);
if (ffReadFileBufferRelative(policyFd, "affected_cpus", &buffer)) {
cpu->coreTypes[ifreq].count += ffStrbufCountC(&buffer, ' ') + 1;
}
}
ffStrbufSubstrBefore(&path, baseLen);
}
}
return true;
@@ -773,6 +742,7 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) {
FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(dfd);
if (!dir) {
close(dfd);
return "fdopendir(dfd) failed";
}
@@ -785,7 +755,7 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) {
continue;
}
FF_AUTO_CLOSE_FD int cpuxfd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_DIRECTORY);
FF_AUTO_CLOSE_FD int cpuxfd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (cpuxfd < 0) {
continue;
}
@@ -798,45 +768,42 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) {
ssize_t len = ffReadFileDataRelative(cpuxfd, "topology/physical_package_id", sizeof(buf) - 1, buf);
if (len > 0) {
buf[len] = '\0';
unsigned long long id = strtoul(buf, NULL, 10);
if (__builtin_expect(id > 64, false)) { // Do 129-socket boards exist?
pkgHigh |= 1ULL << (id - 64);
} else {
pkgLow |= 1ULL << id;
unsigned long long id = strtoull(buf, NULL, 10);
if (__builtin_expect(id < 128, true)) {
// Do 129-socket boards exist?
if (__builtin_expect(id >= 64, false)) {
pkgHigh |= 1ULL << (id - 64);
} else {
pkgLow |= 1ULL << id;
}
}
}
// Check if the directory contains a file named "topology/core_cpus_list"
// that lists the physical cores in the package.
// that lists the logical cores in the same physical core.
len = ffReadFileDataRelative(cpuxfd, "topology/core_cpus_list", sizeof(buf) - 1, buf);
if (len > 0) {
buf[len] = '\0'; // low-high or low
buf[len] = '\0'; // low[-high, low-high, ...]
for (const char* p = buf; *p;) {
char* pend;
uint32_t coreId = (uint32_t) strtoul(p, &pend, 10);
if (pend == p) {
char* pend;
// We assume that the different physical cores exposes different logical core ids,
// so that the first `low` is always different between different physical cores.
uint32_t coreId = (uint32_t) strtoul(buf, &pend, 10);
if (pend == buf) {
break;
}
bool found = false;
FF_LIST_FOR_EACH (uint32_t, id, cpuList) {
if (*id == coreId) {
// This core is already counted
found = true;
break;
}
bool found = false;
FF_LIST_FOR_EACH (uint32_t, id, cpuList) {
if (*id == coreId) {
// This core is already counted
found = true;
break;
}
}
if (!found) {
*FF_LIST_ADD(uint32_t, cpuList) = coreId;
}
p = strchr(pend, ',');
if (!p) {
break;
}
++p;
}
if (!found) {
*FF_LIST_ADD(uint32_t, cpuList) = coreId;
}
}
}
+30 -29
View File
@@ -216,7 +216,21 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) {
return NULL;
}
static const char* detectNCores(FFCPUResult* cpu) {
static uint32_t getNumLogicalCores(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr) {
uint32_t num = 0;
for (uint32_t i = 0; i < ptr->Processor.GroupCount; ++i) {
num += (uint32_t)
#if _WIN64
__builtin_popcountll
#else
__builtin_popcountl
#endif
(ptr->Processor.GroupMask[i].Mask);
}
return num;
}
static const char* detectNCores(const FFCPUOptions* options, FFCPUResult* cpu) {
LOGICAL_PROCESSOR_RELATIONSHIP lpr = RelationAll;
ULONG length = 0;
NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), NULL, 0, &length);
@@ -242,6 +256,19 @@ static const char* detectNCores(FFCPUResult* cpu) {
}
} else if (ptr->Relationship == RelationProcessorCore) {
++cpu->coresPhysical;
if (options->showPeCoreCount) {
for (uint32_t i = 0; i < ARRAY_SIZE(cpu->coreTypes); ++i) {
if (ptr->Processor.EfficiencyClass + 1 == cpu->coreTypes[i].freq) {
cpu->coreTypes[i].count += getNumLogicalCores(ptr);
break;
} else if (cpu->coreTypes[i].freq == 0) {
cpu->coreTypes[i].freq = ptr->Processor.EfficiencyClass + 1;
cpu->coreTypes[i].count += getNumLogicalCores(ptr);
break;
}
}
}
} else if (ptr->Relationship == RelationProcessorPackage) {
++cpu->packages;
} else if (ptr->Relationship == RelationNumaNode) {
@@ -258,7 +285,7 @@ static const char* detectByRegistry(FFCPUResult* cpu) {
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
}
if (ffRegReadValues(hKey, 3, (FFRegValueArg[]) {
if (ffRegReadValues(hKey, 3, (FFRegValueArg[]){
FF_ARG(cpu->name, L"ProcessorNameString"),
FF_ARG(cpu->vendor, L"VendorIdentifier"),
FF_ARG(cpu->frequencyBase, L"~MHz"),
@@ -272,31 +299,8 @@ static const char* detectByRegistry(FFCPUResult* cpu) {
return NULL;
}
static const char* detectCoreTypes(FFCPUResult* cpu) {
FF_AUTO_FREE PROCESSOR_POWER_INFORMATION* pinfo = calloc(cpu->coresLogical, sizeof(PROCESSOR_POWER_INFORMATION));
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical))) {
return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed";
}
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore) {
uint32_t ifreq = 0;
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0) {
++ifreq;
}
if (cpu->coreTypes[ifreq].freq == 0) {
cpu->coreTypes[ifreq].freq = pinfo[icore].MhzLimit;
}
++cpu->coreTypes[ifreq].count;
}
if (cpu->frequencyBase == 0) {
cpu->frequencyBase = pinfo->MaxMhz;
}
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
detectNCores(cpu);
detectNCores(options, cpu);
const char* error = detectByRegistry(cpu);
if (error) {
@@ -304,9 +308,6 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
}
ffCPUDetectByCpuid(cpu);
if (options->showPeCoreCount) {
detectCoreTypes(cpu);
}
if (cpu->frequencyMax == 0) {
detectMaxSpeedBySmbios(cpu);
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -42,7 +42,7 @@ FFDisplayResult* ffdsAppendDisplay(
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
display->manufactureYear = 0;
display->manufactureWeek = 0;
display->serial = 0;
ffStrbufInit(&display->serial);
display->drrStatus = FF_DISPLAY_DRR_STATUS_UNKNOWN;
return display;
+1 -1
View File
@@ -89,7 +89,7 @@ typedef struct FFDisplayResult {
FFDisplayHdrStatus hdrStatus;
uint16_t manufactureYear;
uint16_t manufactureWeek;
uint32_t serial;
FFstrbuf serial;
FFDisplayVrrStatus drrStatus;
} FFDisplayResult;
@@ -9,6 +9,7 @@
#include <assert.h>
#include <CoreGraphics/CGDirectDisplay.h>
#include <CoreVideo/CVDisplayLink.h>
#include <IOKit/IOKitLib.h>
#ifdef MAC_OS_X_VERSION_10_15
extern Boolean CoreDisplay_Display_SupportsHDRMode(CGDirectDisplayID display) FF_A_WEAK_IMPORT;
@@ -28,6 +29,7 @@ static void detectDisplays(FFDisplayServerResult* ds) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
for (uint32_t i = 0; i < screenCount; i++) {
CGDirectDisplayID screen = screens[i];
boolean_t builtin = CGDisplayIsBuiltin(screen);
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen);
if (mode) {
// https://github.com/glfw/glfw/commit/aab08712dd8142b642e2042e7b7ba563acd07a45
@@ -63,20 +65,37 @@ static void detectDisplays(FFDisplayServerResult* ds) {
uint32_t physicalWidth = 0, physicalHeight = 0;
uint32_t preferredWidth = 0, preferredHeight = 0;
double preferredRefreshRate = 0;
FF_STRBUF_AUTO_DESTROY serial = ffStrbufCreate();
if (displayInfo) {
CFDictionaryRef productNames;
if (ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames) == NULL) {
ffCfDictGetString(productNames, CFSTR("en_US"), &buffer);
}
// CGDisplayScreenSize reports invalid result for external displays on old Intel MacBook Pro
CFDataRef edidRef = (CFDataRef) CFDictionaryGetValue(displayInfo, CFSTR(kIODisplayEDIDKey));
if (edidRef && CFGetTypeID(edidRef) == CFDataGetTypeID()) {
const uint8_t* edidData = CFDataGetBytePtr(edidRef);
uint32_t edidLength = (uint32_t) CFDataGetLength(edidRef);
if (edidLength >= 128) {
if (ffEdidIsValid(edidData, edidLength)) {
ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight);
ffEdidGetSerial(edidData, &serial);
}
} else if (!builtin && ffCfDictGetString(displayInfo, CFSTR(kIODisplayLocationKey), &buffer) == NULL) {
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t ioDisplay = IORegistryEntryFromPath(MACH_PORT_NULL, buffer.chars);
ffStrbufClear(&buffer);
if (ioDisplay) {
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef displayAttrRef = IORegistryEntryCreateCFProperty(ioDisplay, CFSTR("DisplayAttributes"), kCFAllocatorDefault, kNilOptions);
if (displayAttrRef && CFGetTypeID(displayAttrRef) == CFDictionaryGetTypeID()) {
CFDictionaryRef productAttrs;
if (ffCfDictGetDict(displayAttrRef, CFSTR("ProductAttributes"), &productAttrs) == NULL) {
ffCfDictGetString(productAttrs, CFSTR("AlphanumericSerialNumber"), &serial);
ffCfDictGetString(productAttrs, CFSTR("ProductName"), &buffer);
}
}
}
}
if (!buffer.length) {
CFDictionaryRef productNames;
if (ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames) == NULL) {
ffCfDictGetString(productNames, CFSTR("en_US"), &buffer);
}
}
@@ -125,7 +144,7 @@ static void detectDisplays(FFDisplayServerResult* ds) {
preferredRefreshRate,
(uint32_t) CGDisplayRotation(screen),
&buffer,
CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL,
builtin ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL,
CGDisplayIsMain(screen),
(uint64_t) screen,
physicalWidth,
@@ -166,7 +185,14 @@ static void detectDisplays(FFDisplayServerResult* ds) {
}
#endif
display->serial = CGDisplaySerialNumber(screen);
if (serial.length) {
ffStrbufInitMove(&display->serial, &serial);
} else {
uint32_t int_serial = CGDisplaySerialNumber(screen);
if (int_serial != 0 && int_serial != 0xFFFFFFFF) {
ffStrbufSetF(&display->serial, "0x%08X", int_serial);
}
}
if (displayInfo) {
int value;
@@ -196,7 +196,8 @@ static void detectDisplays(FFDisplayServerResult* ds) {
}
}
if (edid.length > 0) {
ffEdidGetSerialAndManufactureDate(edid.data, &display->serial, &display->manufactureYear, &display->manufactureWeek);
ffEdidGetManufactureDate(edid.data, &display->manufactureYear, &display->manufactureWeek);
ffEdidGetSerial(edid.data, &display->serial);
}
display->drrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_DRR_STATUS_ENABLED : FF_DISPLAY_DRR_STATUS_DISABLED;
}
+215 -201
View File
@@ -2,6 +2,7 @@
#include "common/io.h"
#include "common/edidHelper.h"
#include "common/strutil.h"
#include "common/mallocHelper.h"
#ifdef __linux__
#include <dirent.h>
@@ -43,8 +44,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) {
}
}
unsigned width = 0, height = 0, physicalWidth = 0, physicalHeight = 0;
double refreshRate = 0;
uint32_t width = 0, height = 0, physicalWidth = 0, physicalHeight = 0, preferredWidth = 0, preferredHeight = 0;
double preferredRefreshRate = 0;
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
@@ -58,33 +59,35 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) {
}
}
uint8_t edidData[512];
ssize_t edidLength = ffReadFileData(drmDir.chars, ARRAY_SIZE(edidData), edidData);
if (edidLength <= 0 || edidLength % 128 != 0) {
edidLength = 0;
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/modes");
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/modes");
char modes[32];
if (ffReadFileData(drmDir.chars, ARRAY_SIZE(modes), modes) >= 3) {
sscanf(modes, "%ux%u", &width, &height);
ffStrbufAppendS(&name, plainName);
}
} else {
char modes[32];
if (ffReadFileData(drmDir.chars, ARRAY_SIZE(modes), modes) >= 3) {
// This is actually preferred resolution
sscanf(modes, "%ux%u", &width, &height);
ffStrbufAppendS(&name, plainName);
}
uint8_t edidData[1024];
ssize_t edidLength = ffReadFileData(drmDir.chars, ARRAY_SIZE(edidData), edidData);
if (edidLength > 0 && ffEdidIsValid(edidData, (uint32_t) edidLength)) {
ffEdidGetName(edidData, &name);
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate);
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &preferredWidth, &preferredHeight, &preferredRefreshRate);
ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight);
} else {
edidLength = 0;
}
FFDisplayResult* item = ffdsAppendDisplay(
result,
width,
height,
refreshRate,
0,
0,
0,
0,
preferredWidth,
preferredHeight,
preferredRefreshRate,
0,
&name,
ffdsGetDisplayType(plainName),
@@ -95,7 +98,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) {
"sysfs-drm");
if (item && edidLength) {
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
ffEdidGetManufactureDate(edidData, &item->manufactureYear, &item->manufactureWeek);
ffEdidGetSerial(edidData, &item->serial);
}
ffStrbufSubstrBefore(&drmDir, drmDirLength);
@@ -105,13 +109,18 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) {
}
#endif
#ifdef FF_HAVE_DRM
#if FF_HAVE_DRM || __has_include(<drm/drm.h>)
#include "common/library.h"
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#if FF_HAVE_DRM
#include <drm.h>
#include <drm_mode.h>
#else
#define FF_HAVE_DRM 1
#include <drm/drm.h>
#include <drm/drm_mode.h>
#endif
// https://gitlab.freedesktop.org/mesa/drm/-/blob/main/xf86drmMode.c#L1785
// It's not supported on Ubuntu 20.04
@@ -207,221 +216,226 @@ FF_A_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edid
}
static const char* drmConnectLibdrm(FFDisplayServerResult* result) {
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetResources)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetConnectorCurrent)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetCrtc)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetEncoder)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetFB)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetProperty)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetPropertyBlob)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeResources)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeCrtc)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeConnector)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeEncoder)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeFB)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeProperty)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreePropertyBlob)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
drmDevice* devices[64];
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
if (nDevices <= 0) {
return "drmGetDevices() failed";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/dri/");
if (dirp == NULL) {
return "opendir(/dev/dri/) failed";
}
int drifd = dirfd(dirp);
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
int nSuccess = 0;
for (int iDev = 0; iDev < nDevices; ++iDev) {
drmDevice* dev = devices[iDev];
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY))) {
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.' || !ffStrStartsWith(entry->d_name, "card")) {
continue;
}
const char* path = dev->nodes[DRM_NODE_PRIMARY];
#if __linux__
ffStrbufSetF(&name, "/sys/class/drm/%s/device/power/runtime_status", strrchr(path, '/') + 1);
char powerStatusBuf[512];
snprintf(powerStatusBuf, ARRAY_SIZE(powerStatusBuf), "/sys/class/drm/%s/device/power/runtime_status", entry->d_name);
char buffer[8] = "";
if (ffReadFileData(name.chars, strlen("suspend"), buffer) > 0 && ffStrStartsWith(buffer, "suspend")) {
if (ffReadFileData(powerStatusBuf, strlen("suspend"), buffer) > 0 && ffStrStartsWith(buffer, "suspend")) {
continue;
}
#endif
FF_AUTO_CLOSE_FD int primaryFd = open(path, O_RDWR | O_CLOEXEC);
FF_AUTO_CLOSE_FD int primaryFd = openat(drifd, entry->d_name, O_RDWR | O_CLOEXEC);
if (primaryFd < 0) {
continue;
}
drmModeRes* res = ffdrmModeGetResources(primaryFd);
if (!res) {
struct drm_mode_card_res res_ = {};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETRESOURCES, &res_) < 0 || res_.count_connectors <= 0) {
continue;
}
for (int iConn = 0; iConn < res->count_connectors; ++iConn) {
drmModeConnector* conn = ffdrmModeGetConnectorCurrent(primaryFd, res->connectors[iConn]);
if (!conn) {
FF_AUTO_FREE uint32_t* connectors = malloc(res_.count_connectors * sizeof(*connectors));
struct drm_mode_card_res res = {
.count_connectors = res_.count_connectors,
.connector_id_ptr = (uintptr_t) connectors,
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETRESOURCES, &res) < 0) {
continue;
}
++nSuccess;
for (uint32_t iConn = 0; iConn < res.count_connectors; ++iConn) {
struct drm_mode_get_connector conn = {
.connector_id = connectors[iConn]
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETCONNECTOR, &conn) < 0) {
continue;
}
if (conn->connection != DRM_MODE_DISCONNECTED) {
drmModeEncoder* encoder = ffdrmModeGetEncoder(primaryFd, conn->encoder_id);
uint32_t width = 0, height = 0, refreshRate = 0;
uint8_t bitDepth = 0;
if (conn.connection == 2 /* connector_status_disconnected */) {
continue;
}
if (encoder) {
drmModeCrtc* crtc = ffdrmModeGetCrtc(primaryFd, encoder->crtc_id);
if (crtc) {
width = crtc->mode.hdisplay;
height = crtc->mode.vdisplay;
refreshRate = crtc->mode.vrefresh;
if (refreshRate == 0) {
// There are weird cases that we can't get the refresh rate from the CRTC but from the modes
for (int iMode = 0; iMode < conn->count_modes; ++iMode) {
drmModeModeInfo* mode = &conn->modes[iMode];
if (mode->clock == crtc->mode.clock && mode->htotal == crtc->mode.htotal) {
refreshRate = mode->vrefresh;
break;
}
uint32_t width = 0, height = 0, refreshRate = 0;
uint8_t bitDepth = 0;
if (conn.encoder_id > 0) {
struct drm_mode_get_encoder enc = {
.encoder_id = conn.encoder_id
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETENCODER, &enc) >= 0 && enc.crtc_id > 0) {
struct drm_mode_crtc crtc = {
.crtc_id = enc.crtc_id,
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETCRTC, &crtc) >= 0) {
width = crtc.mode.hdisplay;
height = crtc.mode.vdisplay;
refreshRate = crtc.mode.vrefresh;
if (crtc.fb_id > 0) {
struct drm_mode_fb_cmd fb = {
.fb_id = crtc.fb_id,
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETFB, &fb) >= 0) {
bitDepth = (uint8_t) (fb.depth / 3);
}
}
drmModeFBPtr fb = ffdrmModeGetFB(primaryFd, crtc->buffer_id);
if (fb) {
bitDepth = (uint8_t) (fb->depth / 3);
ffdrmModeFreeFB(fb);
}
ffdrmModeFreeCrtc(crtc);
}
ffdrmModeFreeEncoder(encoder);
}
uint32_t preferredWidth = 0, preferredHeight = 0, preferredRefreshRate = 0;
for (int iMode = 0; iMode < conn->count_modes; ++iMode) {
drmModeModeInfo* mode = &conn->modes[iMode];
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
preferredWidth = mode->hdisplay;
preferredHeight = mode->vdisplay;
preferredRefreshRate = mode->vrefresh;
break;
}
}
// NVIDIA DRM driver seems incomplete and conn->encoder_id == 0
// Assume preferred resolution is used as what we do in drmParseSys
if (width == 0 || height == 0) {
width = preferredWidth;
height = preferredHeight;
refreshRate = preferredRefreshRate;
}
ffStrbufClear(&name);
uint16_t myear = 0, mweak = 0;
uint32_t serial = 0;
FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
for (int iProp = 0; iProp < conn->count_props; ++iProp) {
drmModePropertyRes* prop = ffdrmModeGetProperty(primaryFd, conn->props[iProp]);
if (!prop) {
continue;
}
uint32_t type = prop->flags & (DRM_MODE_PROP_LEGACY_TYPE | DRM_MODE_PROP_EXTENDED_TYPE);
if (type == DRM_MODE_PROP_BLOB && ffStrEquals(prop->name, "EDID")) {
drmModePropertyBlobPtr blob = NULL;
if (prop->count_blobs > 0 && prop->blob_ids != NULL) {
blob = ffdrmModeGetPropertyBlob(primaryFd, prop->blob_ids[0]);
} else {
blob = ffdrmModeGetPropertyBlob(primaryFd, (uint32_t) conn->prop_values[iProp]);
}
if (blob) {
if (blob->length >= 128) {
ffEdidGetName(blob->data, &name);
hdrStatus = ffEdidGetHdrCompatible(blob->data, blob->length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(blob->data, &serial, &myear, &mweak);
}
ffdrmModeFreePropertyBlob(blob);
}
break;
}
ffdrmModeFreeProperty(prop);
}
#if __linux__
if (name.length == 0) {
uint8_t edidData[512];
ssize_t edidLength = 0;
drmGetEdidByConnId(conn->connector_id, edidData, &edidLength);
if (edidLength > 0 && edidLength % 128 == 0) {
ffEdidGetName(edidData, &name);
hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak);
}
}
#endif
if (name.length == 0) {
const char* connectorTypeName = drmType2Name(conn->connector_type);
if (connectorTypeName == NULL) {
connectorTypeName = "Unknown";
}
ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1);
}
FFDisplayResult* item = ffdsAppendDisplay(result,
width,
height,
refreshRate,
0,
preferredWidth,
preferredHeight,
preferredRefreshRate,
0,
&name,
conn->connector_type == DRM_MODE_CONNECTOR_eDP || conn->connector_type == DRM_MODE_CONNECTOR_LVDS
? FF_DISPLAY_TYPE_BUILTIN
: conn->connector_type == DRM_MODE_CONNECTOR_HDMIA || conn->connector_type == DRM_MODE_CONNECTOR_HDMIB || conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort
? FF_DISPLAY_TYPE_EXTERNAL
: FF_DISPLAY_TYPE_UNKNOWN,
false,
conn->connector_id,
conn->mmWidth,
conn->mmHeight,
"libdrm");
if (item) {
item->hdrStatus = hdrStatus;
item->serial = serial;
item->manufactureYear = myear;
item->manufactureWeek = mweak;
item->bitDepth = bitDepth;
}
}
ffdrmModeFreeConnector(conn);
}
uint32_t preferredWidth = 0, preferredHeight = 0, preferredRefreshRate = 0;
if (conn.count_modes > 0) {
FF_AUTO_FREE struct drm_mode_modeinfo* modes = malloc(conn.count_modes * sizeof(*modes));
struct drm_mode_get_connector connModes = {
.connector_id = connectors[iConn],
.modes_ptr = (uintptr_t) modes,
.count_modes = conn.count_modes
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETCONNECTOR, &connModes) >= 0) {
for (uint32_t iMode = 0; iMode < connModes.count_modes; ++iMode) {
if (modes[iMode].type & DRM_MODE_TYPE_PREFERRED) {
preferredWidth = modes[iMode].hdisplay;
preferredHeight = modes[iMode].vdisplay;
preferredRefreshRate = modes[iMode].vrefresh;
break;
}
}
}
}
ffdrmModeFreeResources(res);
if (width == 0 || height == 0) {
width = preferredWidth;
height = preferredHeight;
refreshRate = preferredRefreshRate;
}
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
uint16_t myear = 0, mweak = 0;
FF_STRBUF_AUTO_DESTROY serial = ffStrbufCreate();
FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
uint32_t* props = malloc(conn.count_props * sizeof(uint32_t));
uint64_t* propValues = malloc(conn.count_props * sizeof(uint64_t));
if (props && propValues && conn.count_props > 0) {
struct drm_mode_get_connector connProps = {
.connector_id = connectors[iConn],
.props_ptr = (uintptr_t) props,
.prop_values_ptr = (uintptr_t) propValues,
.count_props = conn.count_props,
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETCONNECTOR, &connProps) >= 0) {
for (uint32_t iProp = 0; iProp < connProps.count_props; ++iProp) {
struct drm_mode_get_property prop = {
.prop_id = props[iProp],
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETPROPERTY, &prop) < 0) {
continue;
}
uint32_t type = prop.flags & (DRM_MODE_PROP_LEGACY_TYPE | DRM_MODE_PROP_EXTENDED_TYPE);
if (type == DRM_MODE_PROP_BLOB && ffStrEquals(prop.name, "EDID")) {
struct drm_mode_get_blob blob_ = {
.blob_id = (uint32_t) propValues[iProp]
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETPROPBLOB, &blob_) >= 0 && blob_.length > 0) {
FF_AUTO_FREE void* blobData = malloc(blob_.length);
struct drm_mode_get_blob blob = {
.blob_id = blob_.blob_id,
.length = blob_.length,
.data = (uintptr_t) blobData
};
if (ioctl(primaryFd, DRM_IOCTL_MODE_GETPROPBLOB, &blob) >= 0 && ffEdidIsValid(blobData, blob.length)) {
ffEdidGetName(blobData, &name);
hdrStatus = ffEdidGetHdrCompatible(blobData, blob.length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetManufactureDate(blobData, &myear, &mweak);
ffEdidGetSerial(blobData, &serial);
}
}
break;
}
}
}
}
#if __linux__
if (name.length == 0) {
uint8_t edidData[512];
ssize_t edidLength = 0;
drmGetEdidByConnId(conn.connector_id, edidData, &edidLength);
if (edidLength > 0 && ffEdidIsValid(edidData, (uint32_t) edidLength)) {
ffEdidGetName(edidData, &name);
hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetManufactureDate(edidData, &myear, &mweak);
ffEdidGetSerial(edidData, &serial);
}
}
#endif
if (name.length == 0) {
const char* connectorTypeName = drmType2Name(conn.connector_type);
if (connectorTypeName == NULL) {
connectorTypeName = "Unknown";
}
ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1);
}
FFDisplayResult* item = ffdsAppendDisplay(result,
width,
height,
refreshRate,
0,
preferredWidth,
preferredHeight,
preferredRefreshRate,
0,
&name,
conn.connector_type == DRM_MODE_CONNECTOR_eDP || conn.connector_type == DRM_MODE_CONNECTOR_LVDS
? FF_DISPLAY_TYPE_BUILTIN
: conn.connector_type == DRM_MODE_CONNECTOR_HDMIA || conn.connector_type == DRM_MODE_CONNECTOR_HDMIB || conn.connector_type == DRM_MODE_CONNECTOR_DisplayPort
? FF_DISPLAY_TYPE_EXTERNAL
: FF_DISPLAY_TYPE_UNKNOWN,
false,
conn.connector_id,
conn.mm_width,
conn.mm_height,
"libdrm");
if (item) {
item->hdrStatus = hdrStatus;
ffStrbufInitMove(&item->serial, &serial);
item->manufactureYear = myear;
item->manufactureWeek = mweak;
item->bitDepth = bitDepth;
}
}
}
ffdrmFreeDevices(devices, nDevices);
return NULL;
return nSuccess > 0 ? NULL : "No connectors found using libdrm";
}
#endif
const char* ffdsConnectDrm(FF_A_UNUSED FFDisplayServerResult* result) {
#ifdef FF_HAVE_DRM
#if FF_HAVE_DRM
if (instance.config.general.dsForceDrm != FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY) {
if (drmConnectLibdrm(result) == NULL) {
return NULL;
@@ -3,6 +3,7 @@
#include "wayland.h"
#include "common/strutil.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include "wp-color-management-v1-client-protocol.h"
static void waylandOutputModeListener(void* data, FF_A_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate) {
WaylandDisplay* display = data;
@@ -70,10 +71,36 @@ static struct zxdg_output_v1_listener zxdgOutputListener = {
.description = (void*) ffWaylandOutputDescriptionListener,
};
static void handleWpTfNamed(void *data, FF_A_UNUSED struct wp_image_description_info_v1* wp_image_description_info_v1, uint32_t tf) {
// KDE reports `gamma 2.2` even in HDR mode, but it should be handled in KDE specific path
WaylandDisplay* display = data;
switch (tf) {
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ:
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_HLG:
display->hdrInfoAvailable = true;
display->hdrEnabled = true;
break;
}
}
static const struct wp_image_description_info_v1_listener wpImageDescInfoListener = {
.done = (void*) stubListener,
.icc_file = (void*) stubListener,
.primaries = (void*) stubListener,
.primaries_named = (void*) stubListener,
.tf_power = (void*) stubListener,
.tf_named = (void*) handleWpTfNamed,
.luminances = (void*) stubListener,
.target_primaries = (void*) stubListener,
.target_luminance = (void*) stubListener,
.target_max_cll = (void*) stubListener,
.target_max_fall = (void*) stubListener,
};
const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
const char* api = "wayland-global";
const char* api = "wayland-base";
uint32_t bindVersion = min(version, WL_OUTPUT_DESCRIPTION_SINCE_VERSION);
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, bindVersion, name, wldata->ffwl_output_interface->name, bindVersion, NULL);
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &wl_output_interface, bindVersion, name, wl_output_interface.name, bindVersion, NULL);
if (output == NULL) {
return "Failed to create wl_output";
}
@@ -104,7 +131,28 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
wldata->ffwl_proxy_add_listener(zxdgOutput, (void (**)(void)) &zxdgOutputListener, &display);
wldata->ffwl_display_roundtrip(wldata->display);
wldata->ffwl_proxy_destroy(zxdgOutput);
api = "wayland-global-zxdg";
api = "wayland-zxdg";
}
}
if (wldata->wpColorManager) {
uint32_t bindVersion = min(version, WP_COLOR_MANAGER_V1_GET_OUTPUT_SINCE_VERSION);
struct wl_proxy* wpColorOutput = wldata->ffwl_proxy_marshal_constructor_versioned(wldata->wpColorManager, WP_COLOR_MANAGER_V1_GET_OUTPUT, &wp_color_management_output_v1_interface, bindVersion, NULL, output);
if (wpColorOutput) {
struct wl_proxy* wpImageDesc = wldata->ffwl_proxy_marshal_constructor_versioned(wpColorOutput, WP_COLOR_MANAGEMENT_OUTPUT_V1_GET_IMAGE_DESCRIPTION, &wp_image_description_v1_interface, bindVersion, NULL);
if (wpImageDesc) {
struct wl_proxy* wpImageDescInfo = wldata->ffwl_proxy_marshal_constructor_versioned(wpImageDesc, WP_IMAGE_DESCRIPTION_V1_GET_INFORMATION, &wp_image_description_info_v1_interface, bindVersion, NULL);
if (wpImageDescInfo) {
wldata->ffwl_proxy_add_listener(wpImageDescInfo, (void (**)(void)) &wpImageDescInfoListener, &display);
wldata->ffwl_display_roundtrip(wldata->display);
wldata->ffwl_proxy_destroy(wpImageDescInfo);
}
wldata->ffwl_proxy_destroy(wpImageDesc);
}
wldata->ffwl_proxy_destroy(wpColorOutput);
wldata->ffwl_display_roundtrip(wldata->display);
api = api[strlen("wayland-")] == 'z' ? "wayland-zxdg+wpcolor" : "wayland-wpcolor";
}
}
@@ -138,7 +186,9 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
(uint32_t) display.physicalHeight,
api);
if (item) {
if (display.hdrSupported) {
if (display.hdrEnabled) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED;
} else if (display.hdrSupported) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
} else if (display.hdrInfoAvailable) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
@@ -148,7 +198,7 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
item->serial = display.serial;
ffStrbufInitMove(&item->serial, &display.serial);
}
ffStrbufDestroy(&display.description);
@@ -170,4 +220,16 @@ const char* ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* r
return NULL;
}
const char* ffWaylandHandleWpColor(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
uint32_t bindVersion = min(version, WP_COLOR_MANAGER_V1_GET_OUTPUT_SINCE_VERSION);
struct wl_proxy* manager = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &wp_color_manager_v1_interface, bindVersion, name, wp_color_manager_v1_interface.name, bindVersion, NULL);
if (manager == NULL) {
return "Failed to create wp_color_manager_v1";
}
wldata->wpColorManager = manager;
return NULL;
}
#endif
@@ -1,134 +0,0 @@
/* Generated by wayland-scanner 1.22.0 */
#ifndef KDE_OUTPUT_ORDER_V1_CLIENT_PROTOCOL_H
#define KDE_OUTPUT_ORDER_V1_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_kde_output_order_v1 The kde_output_order_v1 protocol
* @section page_ifaces_kde_output_order_v1 Interfaces
* - @subpage page_iface_kde_output_order_v1 - announce order of outputs
* @section page_copyright_kde_output_order_v1 Copyright
* <pre>
*
* SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
*
* SPDX-License-Identifier: MIT-CMU
* </pre>
*/
struct kde_output_order_v1;
#ifndef KDE_OUTPUT_ORDER_V1_INTERFACE
#define KDE_OUTPUT_ORDER_V1_INTERFACE
/**
* @page page_iface_kde_output_order_v1 kde_output_order_v1
* @section page_iface_kde_output_order_v1_desc Description
*
* Announce the order in which desktop environment components should be placed on outputs.
* The compositor will send the list of outputs when the global is bound and whenever there is a change.
* @section page_iface_kde_output_order_v1_api API
* See @ref iface_kde_output_order_v1.
*/
/**
* @defgroup iface_kde_output_order_v1 The kde_output_order_v1 interface
*
* Announce the order in which desktop environment components should be placed on outputs.
* The compositor will send the list of outputs when the global is bound and whenever there is a change.
*/
extern const struct wl_interface kde_output_order_v1_interface;
#endif
/**
* @ingroup iface_kde_output_order_v1
* @struct kde_output_order_v1_listener
*/
struct kde_output_order_v1_listener {
/**
* output name
*
* Specifies the output identified by their wl_output.name.
* @param output_name the name of the output
*/
void (*output)(void* data,
struct kde_output_order_v1* kde_output_order_v1,
const char* output_name);
/**
* done
*
* Specifies that the output list is complete. On the next output
* event, a new list begins.
*/
void (*done)(void* data,
struct kde_output_order_v1* kde_output_order_v1);
};
/**
* @ingroup iface_kde_output_order_v1
*/
static inline int
kde_output_order_v1_add_listener(struct kde_output_order_v1* kde_output_order_v1,
const struct kde_output_order_v1_listener* listener,
void* data) {
return wl_proxy_add_listener((struct wl_proxy*) kde_output_order_v1,
(void (**)(void)) listener,
data);
}
#define KDE_OUTPUT_ORDER_V1_DESTROY 0
/**
* @ingroup iface_kde_output_order_v1
*/
#define KDE_OUTPUT_ORDER_V1_OUTPUT_SINCE_VERSION 1
/**
* @ingroup iface_kde_output_order_v1
*/
#define KDE_OUTPUT_ORDER_V1_DONE_SINCE_VERSION 1
/**
* @ingroup iface_kde_output_order_v1
*/
#define KDE_OUTPUT_ORDER_V1_DESTROY_SINCE_VERSION 1
// /** @ingroup iface_kde_output_order_v1 */
// static inline void
// kde_output_order_v1_set_user_data(struct kde_output_order_v1 *kde_output_order_v1, void *user_data)
// {
// wl_proxy_set_user_data((struct wl_proxy *) kde_output_order_v1, user_data);
// }
// /** @ingroup iface_kde_output_order_v1 */
// static inline void *
// kde_output_order_v1_get_user_data(struct kde_output_order_v1 *kde_output_order_v1)
// {
// return wl_proxy_get_user_data((struct wl_proxy *) kde_output_order_v1);
// }
// static inline uint32_t
// kde_output_order_v1_get_version(struct kde_output_order_v1 *kde_output_order_v1)
// {
// return wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1);
// }
// /**
// * @ingroup iface_kde_output_order_v1
// */
// static inline void
// kde_output_order_v1_destroy(struct kde_output_order_v1 *kde_output_order_v1)
// {
// wl_proxy_marshal_flags((struct wl_proxy *) kde_output_order_v1,
// KDE_OUTPUT_ORDER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1), WL_MARSHAL_FLAG_DESTROY);
// }
#ifdef __cplusplus
}
#endif
#endif
@@ -1,37 +0,0 @@
#ifdef FF_HAVE_WAYLAND
/* Generated by wayland-scanner 1.22.0 */
/*
* SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
*
* SPDX-License-Identifier: MIT-CMU
*/
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
static const struct wl_interface* kde_output_order_v1_types[] = {
NULL,
};
static const struct wl_message kde_output_order_v1_requests[] = {
{ "destroy", "", kde_output_order_v1_types + 0 },
};
static const struct wl_message kde_output_order_v1_events[] = {
{ "output", "s", kde_output_order_v1_types + 0 },
{ "done", "", kde_output_order_v1_types + 0 },
};
WL_EXPORT const struct wl_interface kde_output_order_v1_interface = {
"kde_output_order_v1",
1,
1,
kde_output_order_v1_requests,
2,
kde_output_order_v1_events,
};
#endif
@@ -2,7 +2,6 @@
#include "wayland.h"
#include "kde-output-device-v2-client-protocol.h"
#include "kde-output-order-v1-client-protocol.h"
#include "common/edidHelper.h"
#include "common/base64.h"
@@ -96,7 +95,8 @@ static void waylandKdeEdidListener(void* data, FF_A_UNUSED struct kde_output_dev
}
ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName);
wldata->hdrSupported = ffEdidGetHdrCompatible((const uint8_t*) edid.chars, edid.length);
ffEdidGetSerialAndManufactureDate((const uint8_t*) edid.chars, &wldata->serial, &wldata->myear, &wldata->mweek);
ffEdidGetManufactureDate((const uint8_t*) edid.chars, &wldata->myear, &wldata->mweek);
ffEdidGetSerial((const uint8_t*) edid.chars, &wldata->serial);
wldata->hdrInfoAvailable = true;
}
@@ -142,6 +142,11 @@ static void waylandKdeMaxBitsPerColorListener(void* data, FF_A_UNUSED struct kde
display->bitDepth = (uint8_t) max_bpc;
}
static void waylandKdePriorityListener(void* data, FF_A_UNUSED struct kde_output_device_v2* kde_output_device_v2, uint32_t priority) {
WaylandDisplay* display = data;
display->primary = priority == 1;
}
static struct kde_output_device_v2_listener outputListener = {
.geometry = waylandKdeGeometryListener,
.current_mode = waylandKdeCurrentModeListener,
@@ -176,15 +181,16 @@ static struct kde_output_device_v2_listener outputListener = {
.max_bits_per_color_range = (void*) stubListener,
.automatic_max_bits_per_color_limit = (void*) stubListener,
.edr_policy = (void*) stubListener,
.sharpness = (void*) stubListener,
.priority = waylandKdePriorityListener,
.auto_brightness = (void*) stubListener,
.removed = (void*) stubListener,
.hdr_icc_profile_path = (void*) stubListener,
.hdr_color_profile_source = (void*) stubListener,
.abm_level = (void*) stubListener,
};
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
uint32_t bindVersion = min(version, KDE_OUTPUT_DEVICE_V2_MAX_BITS_PER_COLOR_SINCE_VERSION);
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_v2_interface, bindVersion, name, kde_output_device_v2_interface.name, bindVersion, NULL);
if (output == NULL) {
return "Failed to create kde_output_device_v2";
}
static const char* waylandKdeHandleOutput(WaylandData* wldata, struct wl_proxy* output) {
FF_LIST_AUTO_DESTROY modes = ffListCreate();
WaylandDisplay display = {
.parent = wldata,
@@ -236,7 +242,7 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
? &display.edidName
: &display.name,
display.type,
false,
display.primary,
display.id,
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight,
@@ -254,7 +260,7 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
item->serial = display.serial;
ffStrbufInitMove(&item->serial, &display.serial);
item->bitDepth = display.bitDepth;
}
@@ -265,35 +271,42 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
return NULL;
}
static void waylandKdeOutputOrderListener(void* data, FF_A_UNUSED struct kde_output_order_v1* _, const char* output_name) {
uint64_t* id = (uint64_t*) data;
if (*id == 0) {
*id = ffWaylandGenerateIdFromName(output_name);
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
// TODO: remove this in future versions
uint32_t bindVersion = min(version, KDE_OUTPUT_DEVICE_V2_PRIORITY_SINCE_VERSION);
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_v2_interface, bindVersion, name, kde_output_device_v2_interface.name, bindVersion, NULL);
if (output == NULL) {
return "Failed to create kde_output_device_v2";
}
return waylandKdeHandleOutput(wldata, output);
}
static const struct kde_output_order_v1_listener orderListener = {
.output = waylandKdeOutputOrderListener,
.done = (void*) stubListener,
static void waylandKdeOutputListener(void* data, FF_A_UNUSED struct kde_output_device_registry_v2* kde_output_device_registry_v2, struct kde_output_device_v2* output) {
waylandKdeHandleOutput((WaylandData*) data, (struct wl_proxy*) output);
}
static struct kde_output_device_registry_v2_listener registryListener = {
.output = waylandKdeOutputListener,
.finished = (void*) stubListener,
};
const char* ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
uint32_t bindVersion = min(version, KDE_OUTPUT_ORDER_V1_OUTPUT_SINCE_VERSION);
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_order_v1_interface, bindVersion, name, kde_output_order_v1_interface.name, bindVersion, NULL);
if (output == NULL) {
return "Failed to create kde_output_order_v1";
const char* ffWaylandHandleKdeOutputRegistry(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
uint32_t bindVersion = min(version, KDE_OUTPUT_DEVICE_REGISTRY_V2_OUTPUT_SINCE_VERSION);
struct wl_proxy* outputRegistry = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_registry_v2_interface, bindVersion, name, kde_output_device_registry_v2_interface.name, bindVersion, NULL);
if (outputRegistry == NULL) {
return "Failed to create kde_output_device_registry_v2";
}
if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &orderListener, &wldata->primaryDisplayId) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to add listener to kde_output_order_v1";
if (wldata->ffwl_proxy_add_listener(outputRegistry, (void (**)(void)) &registryListener, wldata) < 0) {
wldata->ffwl_proxy_destroy(outputRegistry);
return "Failed to add listener to kde_output_device_registry_v2";
}
if (wldata->ffwl_display_roundtrip(wldata->display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to roundtrip kde_output_order_v1";
wldata->ffwl_proxy_destroy(outputRegistry);
return "Failed to roundtrip kde_output_device_registry_v2";
}
wldata->ffwl_proxy_destroy(output);
wldata->ffwl_proxy_destroy(outputRegistry);
return NULL;
}
@@ -13,10 +13,9 @@
#include "common/properties.h"
#include "wayland.h"
#include "wlr-output-management-unstable-v1-client-protocol.h"
#include "kde-output-device-v2-client-protocol.h"
#include "kde-output-order-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include "wp-color-management-v1-client-protocol.h"
#if __FreeBSD__
#include <sys/un.h>
@@ -81,25 +80,25 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result) {
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) {
WaylandData* wldata = data;
if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL) && ffStrEquals(interface, wldata->ffwl_output_interface->name)) {
if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL) && ffStrEquals(interface, wl_output_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_GLOBAL;
if (ffWaylandHandleGlobalOutput(wldata, registry, name, version) != NULL) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE;
}
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_ZWLR) && ffStrEquals(interface, zwlr_output_manager_v1_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_ZWLR;
if (ffWaylandHandleZwlrOutput(wldata, registry, name, version) != NULL) {
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, kde_output_device_registry_v2_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE_REGISTRY;
if (ffWaylandHandleKdeOutputRegistry(wldata, registry, name, version) != NULL) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE;
}
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE) && ffStrEquals(interface, kde_output_device_v2_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE;
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE_DEPRECATED) && ffStrEquals(interface, kde_output_device_v2_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE_DEPRECATED;
if (ffWaylandHandleKdeOutput(wldata, registry, name, version) != NULL) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE;
}
} else if (ffStrEquals(interface, kde_output_order_v1_interface.name)) {
ffWaylandHandleKdeOutputOrder(wldata, registry, name, version);
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, zxdg_output_manager_v1_interface.name)) {
ffWaylandHandleZxdgOutput(wldata, registry, name, version);
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, wp_color_manager_v1_interface.name)) {
ffWaylandHandleWpColor(wldata, registry, name, version);
}
}
@@ -128,10 +127,19 @@ static FF_A_UNUSED bool matchDrmConnector(const char* connName, WaylandDisplay*
uint8_t edidData[512];
ssize_t edidLength = ffReadFileData(path.chars, ARRAY_SIZE(edidData), edidData);
if (edidLength > 0 && edidLength % 128 == 0) {
if (edidLength > 0 && ffEdidIsValid(edidData, (uint32_t) edidLength)) {
ffEdidGetName(edidData, &wldata->edidName);
ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
ffEdidGetSerialAndManufactureDate(edidData, &wldata->serial, &wldata->myear, &wldata->mweek);
wldata->hdrSupported = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
ffEdidGetManufactureDate((const uint8_t*) edidData, &wldata->myear, &wldata->mweek);
ffEdidGetSerial((const uint8_t*) edidData, &wldata->serial);
if (wldata->preferredWidth == 0) {
uint32_t preferredWidth = 0, preferredHeight = 0;
double preferredRefreshRate = 0;
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &preferredWidth, &preferredHeight, &preferredRefreshRate);
wldata->preferredWidth = (int32_t) preferredWidth;
wldata->preferredHeight = (int32_t) preferredHeight;
wldata->preferredRefreshRate = (int32_t) (preferredRefreshRate * 1000.);
}
wldata->hdrInfoAvailable = true;
return true;
}
@@ -220,7 +228,6 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) {
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_get_fd)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_proxy_marshal_constructor)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_disconnect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_registry_interface)
WaylandData data = {};
@@ -228,7 +235,6 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) {
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_add_listener)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_destroy)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_display_roundtrip)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_output_interface)
data.display = ffwl_display_connect(NULL);
if (data.display == NULL) {
@@ -237,7 +243,7 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) {
waylandDetectWM(ffwl_display_get_fd(data.display), result);
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, &wl_registry_interface, NULL);
if (registry == NULL) {
ffwl_display_disconnect(data.display);
return "wl_display_get_registry returned NULL";
@@ -257,10 +263,14 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) {
data.ffwl_proxy_destroy(data.zxdgOutputManager);
}
if (data.wpColorManager) {
data.ffwl_proxy_destroy(data.wpColorManager);
}
data.ffwl_proxy_destroy(registry);
ffwl_display_disconnect(data.display);
if (data.primaryDisplayId == 0 && result->wmProcessName.length > 0) {
{
const char* fileName = ffStrbufEqualS(&result->wmProcessName, "gnome-shell")
? "monitors.xml"
: ffStrbufEqualS(&result->wmProcessName, "cinnamon")
@@ -307,7 +317,14 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) {
if (end < monitorsXml.length) {
ffStrbufSubstrBefore(&monitorsXml, end);
const char* name = monitorsXml.chars + start + strlen("<connector>");
data.primaryDisplayId = ffWaylandGenerateIdFromName(name);
uint64_t primaryDisplayId = ffWaylandGenerateIdFromName(name);
FF_LIST_FOR_EACH (FFDisplayResult, d, data.result->displays) {
if (d->id == primaryDisplayId) {
d->primary = true;
break;
}
}
}
}
}
@@ -315,15 +332,6 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) {
}
}
if (data.primaryDisplayId) {
FF_LIST_FOR_EACH (FFDisplayResult, d, data.result->displays) {
if (d->id == data.primaryDisplayId) {
d->primary = true;
break;
}
}
}
// We successfully connected to wayland and detected the display.
// So we can set set the session type to wayland.
// This is used as an indicator that we are running wayland by the x11 backends.
@@ -16,8 +16,8 @@ static inline uint32_t min(uint32_t a, uint32_t b) {
typedef enum FF_A_PACKED WaylandProtocolType {
FF_WAYLAND_PROTOCOL_TYPE_NONE,
FF_WAYLAND_PROTOCOL_TYPE_GLOBAL,
FF_WAYLAND_PROTOCOL_TYPE_ZWLR,
FF_WAYLAND_PROTOCOL_TYPE_KDE,
FF_WAYLAND_PROTOCOL_TYPE_KDE_DEPRECATED,
FF_WAYLAND_PROTOCOL_TYPE_KDE_REGISTRY,
} WaylandProtocolType;
typedef struct WaylandData {
@@ -27,10 +27,9 @@ typedef struct WaylandData {
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
FF_LIBRARY_SYMBOL(wl_display_roundtrip)
struct wl_display* display;
const struct wl_interface* ffwl_output_interface;
WaylandProtocolType protocolType;
uint64_t primaryDisplayId;
struct wl_proxy* zxdgOutputManager;
struct wl_proxy* wpColorManager;
} WaylandData;
typedef struct WaylandDisplay {
@@ -56,8 +55,9 @@ typedef struct WaylandDisplay {
bool hdrEnabled;
uint16_t myear;
uint16_t mweek;
uint32_t serial;
FFstrbuf serial;
uint8_t bitDepth;
bool primary;
} WaylandDisplay;
inline static void stubListener(void* data, ...) {
@@ -81,9 +81,10 @@ void ffWaylandOutputDescriptionListener(void* data, FF_A_UNUSED void* output, co
uint32_t ffWaylandHandleRotation(WaylandDisplay* display);
const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
const char* ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
const char* ffWaylandHandleKdeOutputRegistry(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
const char* ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
const char* ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
const char* ffWaylandHandleWpColor(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
#endif
@@ -0,0 +1,531 @@
#ifdef FF_HAVE_WAYLAND
/* Generated by wayland-scanner 1.24.0 */
/*
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2010-2011 Intel Corporation
* Copyright © 2012-2013 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
extern const struct wl_interface wl_buffer_interface;
extern const struct wl_interface wl_callback_interface;
extern const struct wl_interface wl_data_device_interface;
extern const struct wl_interface wl_data_offer_interface;
extern const struct wl_interface wl_data_source_interface;
extern const struct wl_interface wl_keyboard_interface;
extern const struct wl_interface wl_output_interface;
extern const struct wl_interface wl_pointer_interface;
extern const struct wl_interface wl_region_interface;
extern const struct wl_interface wl_registry_interface;
extern const struct wl_interface wl_seat_interface;
extern const struct wl_interface wl_shell_surface_interface;
extern const struct wl_interface wl_shm_pool_interface;
extern const struct wl_interface wl_subsurface_interface;
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface wl_touch_interface;
static const struct wl_interface *wayland_types[] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&wl_callback_interface,
&wl_registry_interface,
&wl_surface_interface,
&wl_region_interface,
&wl_buffer_interface,
NULL,
NULL,
NULL,
NULL,
NULL,
&wl_shm_pool_interface,
NULL,
NULL,
&wl_data_source_interface,
&wl_surface_interface,
&wl_surface_interface,
NULL,
&wl_data_source_interface,
NULL,
&wl_data_offer_interface,
NULL,
&wl_surface_interface,
NULL,
NULL,
&wl_data_offer_interface,
&wl_data_offer_interface,
&wl_data_source_interface,
&wl_data_device_interface,
&wl_seat_interface,
&wl_shell_surface_interface,
&wl_surface_interface,
&wl_seat_interface,
NULL,
&wl_seat_interface,
NULL,
NULL,
&wl_surface_interface,
NULL,
NULL,
NULL,
NULL,
NULL,
&wl_output_interface,
&wl_seat_interface,
NULL,
&wl_surface_interface,
NULL,
NULL,
NULL,
&wl_output_interface,
&wl_buffer_interface,
NULL,
NULL,
&wl_callback_interface,
&wl_region_interface,
&wl_region_interface,
&wl_output_interface,
&wl_output_interface,
&wl_pointer_interface,
&wl_keyboard_interface,
&wl_touch_interface,
NULL,
&wl_surface_interface,
NULL,
NULL,
NULL,
&wl_surface_interface,
NULL,
NULL,
NULL,
&wl_surface_interface,
NULL,
&wl_surface_interface,
NULL,
NULL,
&wl_surface_interface,
NULL,
NULL,
&wl_surface_interface,
NULL,
NULL,
NULL,
&wl_subsurface_interface,
&wl_surface_interface,
&wl_surface_interface,
&wl_surface_interface,
&wl_surface_interface,
&wl_registry_interface,
};
static const struct wl_message wl_display_requests[] = {
{ "sync", "n", wayland_types + 8 },
{ "get_registry", "n", wayland_types + 9 },
};
static const struct wl_message wl_display_events[] = {
{ "error", "ous", wayland_types + 0 },
{ "delete_id", "u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_display_interface = {
"wl_display", 1,
2, wl_display_requests,
2, wl_display_events,
};
static const struct wl_message wl_registry_requests[] = {
{ "bind", "usun", wayland_types + 0 },
};
static const struct wl_message wl_registry_events[] = {
{ "global", "usu", wayland_types + 0 },
{ "global_remove", "u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_registry_interface = {
"wl_registry", 1,
1, wl_registry_requests,
2, wl_registry_events,
};
static const struct wl_message wl_callback_events[] = {
{ "done", "u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_callback_interface = {
"wl_callback", 1,
0, NULL,
1, wl_callback_events,
};
static const struct wl_message wl_compositor_requests[] = {
{ "create_surface", "n", wayland_types + 10 },
{ "create_region", "n", wayland_types + 11 },
};
WL_EXPORT const struct wl_interface wl_compositor_interface = {
"wl_compositor", 6,
2, wl_compositor_requests,
0, NULL,
};
static const struct wl_message wl_shm_pool_requests[] = {
{ "create_buffer", "niiiiu", wayland_types + 12 },
{ "destroy", "", wayland_types + 0 },
{ "resize", "i", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_shm_pool_interface = {
"wl_shm_pool", 2,
3, wl_shm_pool_requests,
0, NULL,
};
static const struct wl_message wl_shm_requests[] = {
{ "create_pool", "nhi", wayland_types + 18 },
{ "release", "2", wayland_types + 0 },
};
static const struct wl_message wl_shm_events[] = {
{ "format", "u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_shm_interface = {
"wl_shm", 2,
2, wl_shm_requests,
1, wl_shm_events,
};
static const struct wl_message wl_buffer_requests[] = {
{ "destroy", "", wayland_types + 0 },
};
static const struct wl_message wl_buffer_events[] = {
{ "release", "", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_buffer_interface = {
"wl_buffer", 1,
1, wl_buffer_requests,
1, wl_buffer_events,
};
static const struct wl_message wl_data_offer_requests[] = {
{ "accept", "u?s", wayland_types + 0 },
{ "receive", "sh", wayland_types + 0 },
{ "destroy", "", wayland_types + 0 },
{ "finish", "3", wayland_types + 0 },
{ "set_actions", "3uu", wayland_types + 0 },
};
static const struct wl_message wl_data_offer_events[] = {
{ "offer", "s", wayland_types + 0 },
{ "source_actions", "3u", wayland_types + 0 },
{ "action", "3u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_data_offer_interface = {
"wl_data_offer", 3,
5, wl_data_offer_requests,
3, wl_data_offer_events,
};
static const struct wl_message wl_data_source_requests[] = {
{ "offer", "s", wayland_types + 0 },
{ "destroy", "", wayland_types + 0 },
{ "set_actions", "3u", wayland_types + 0 },
};
static const struct wl_message wl_data_source_events[] = {
{ "target", "?s", wayland_types + 0 },
{ "send", "sh", wayland_types + 0 },
{ "cancelled", "", wayland_types + 0 },
{ "dnd_drop_performed", "3", wayland_types + 0 },
{ "dnd_finished", "3", wayland_types + 0 },
{ "action", "3u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_data_source_interface = {
"wl_data_source", 3,
3, wl_data_source_requests,
6, wl_data_source_events,
};
static const struct wl_message wl_data_device_requests[] = {
{ "start_drag", "?oo?ou", wayland_types + 21 },
{ "set_selection", "?ou", wayland_types + 25 },
{ "release", "2", wayland_types + 0 },
};
static const struct wl_message wl_data_device_events[] = {
{ "data_offer", "n", wayland_types + 27 },
{ "enter", "uoff?o", wayland_types + 28 },
{ "leave", "", wayland_types + 0 },
{ "motion", "uff", wayland_types + 0 },
{ "drop", "", wayland_types + 0 },
{ "selection", "?o", wayland_types + 33 },
};
WL_EXPORT const struct wl_interface wl_data_device_interface = {
"wl_data_device", 3,
3, wl_data_device_requests,
6, wl_data_device_events,
};
static const struct wl_message wl_data_device_manager_requests[] = {
{ "create_data_source", "n", wayland_types + 34 },
{ "get_data_device", "no", wayland_types + 35 },
};
WL_EXPORT const struct wl_interface wl_data_device_manager_interface = {
"wl_data_device_manager", 3,
2, wl_data_device_manager_requests,
0, NULL,
};
static const struct wl_message wl_shell_requests[] = {
{ "get_shell_surface", "no", wayland_types + 37 },
};
WL_EXPORT const struct wl_interface wl_shell_interface = {
"wl_shell", 1,
1, wl_shell_requests,
0, NULL,
};
static const struct wl_message wl_shell_surface_requests[] = {
{ "pong", "u", wayland_types + 0 },
{ "move", "ou", wayland_types + 39 },
{ "resize", "ouu", wayland_types + 41 },
{ "set_toplevel", "", wayland_types + 0 },
{ "set_transient", "oiiu", wayland_types + 44 },
{ "set_fullscreen", "uu?o", wayland_types + 48 },
{ "set_popup", "ouoiiu", wayland_types + 51 },
{ "set_maximized", "?o", wayland_types + 57 },
{ "set_title", "s", wayland_types + 0 },
{ "set_class", "s", wayland_types + 0 },
};
static const struct wl_message wl_shell_surface_events[] = {
{ "ping", "u", wayland_types + 0 },
{ "configure", "uii", wayland_types + 0 },
{ "popup_done", "", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_shell_surface_interface = {
"wl_shell_surface", 1,
10, wl_shell_surface_requests,
3, wl_shell_surface_events,
};
static const struct wl_message wl_surface_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "attach", "?oii", wayland_types + 58 },
{ "damage", "iiii", wayland_types + 0 },
{ "frame", "n", wayland_types + 61 },
{ "set_opaque_region", "?o", wayland_types + 62 },
{ "set_input_region", "?o", wayland_types + 63 },
{ "commit", "", wayland_types + 0 },
{ "set_buffer_transform", "2i", wayland_types + 0 },
{ "set_buffer_scale", "3i", wayland_types + 0 },
{ "damage_buffer", "4iiii", wayland_types + 0 },
{ "offset", "5ii", wayland_types + 0 },
};
static const struct wl_message wl_surface_events[] = {
{ "enter", "o", wayland_types + 64 },
{ "leave", "o", wayland_types + 65 },
{ "preferred_buffer_scale", "6i", wayland_types + 0 },
{ "preferred_buffer_transform", "6u", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_surface_interface = {
"wl_surface", 6,
11, wl_surface_requests,
4, wl_surface_events,
};
static const struct wl_message wl_seat_requests[] = {
{ "get_pointer", "n", wayland_types + 66 },
{ "get_keyboard", "n", wayland_types + 67 },
{ "get_touch", "n", wayland_types + 68 },
{ "release", "5", wayland_types + 0 },
};
static const struct wl_message wl_seat_events[] = {
{ "capabilities", "u", wayland_types + 0 },
{ "name", "2s", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_seat_interface = {
"wl_seat", 10,
4, wl_seat_requests,
2, wl_seat_events,
};
static const struct wl_message wl_pointer_requests[] = {
{ "set_cursor", "u?oii", wayland_types + 69 },
{ "release", "3", wayland_types + 0 },
};
static const struct wl_message wl_pointer_events[] = {
{ "enter", "uoff", wayland_types + 73 },
{ "leave", "uo", wayland_types + 77 },
{ "motion", "uff", wayland_types + 0 },
{ "button", "uuuu", wayland_types + 0 },
{ "axis", "uuf", wayland_types + 0 },
{ "frame", "5", wayland_types + 0 },
{ "axis_source", "5u", wayland_types + 0 },
{ "axis_stop", "5uu", wayland_types + 0 },
{ "axis_discrete", "5ui", wayland_types + 0 },
{ "axis_value120", "8ui", wayland_types + 0 },
{ "axis_relative_direction", "9uu", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_pointer_interface = {
"wl_pointer", 10,
2, wl_pointer_requests,
11, wl_pointer_events,
};
static const struct wl_message wl_keyboard_requests[] = {
{ "release", "3", wayland_types + 0 },
};
static const struct wl_message wl_keyboard_events[] = {
{ "keymap", "uhu", wayland_types + 0 },
{ "enter", "uoa", wayland_types + 79 },
{ "leave", "uo", wayland_types + 82 },
{ "key", "uuuu", wayland_types + 0 },
{ "modifiers", "uuuuu", wayland_types + 0 },
{ "repeat_info", "4ii", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_keyboard_interface = {
"wl_keyboard", 10,
1, wl_keyboard_requests,
6, wl_keyboard_events,
};
static const struct wl_message wl_touch_requests[] = {
{ "release", "3", wayland_types + 0 },
};
static const struct wl_message wl_touch_events[] = {
{ "down", "uuoiff", wayland_types + 84 },
{ "up", "uui", wayland_types + 0 },
{ "motion", "uiff", wayland_types + 0 },
{ "frame", "", wayland_types + 0 },
{ "cancel", "", wayland_types + 0 },
{ "shape", "6iff", wayland_types + 0 },
{ "orientation", "6if", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_touch_interface = {
"wl_touch", 10,
1, wl_touch_requests,
7, wl_touch_events,
};
static const struct wl_message wl_output_requests[] = {
{ "release", "3", wayland_types + 0 },
};
static const struct wl_message wl_output_events[] = {
{ "geometry", "iiiiissi", wayland_types + 0 },
{ "mode", "uiii", wayland_types + 0 },
{ "done", "2", wayland_types + 0 },
{ "scale", "2i", wayland_types + 0 },
{ "name", "4s", wayland_types + 0 },
{ "description", "4s", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_output_interface = {
"wl_output", 4,
1, wl_output_requests,
6, wl_output_events,
};
static const struct wl_message wl_region_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "add", "iiii", wayland_types + 0 },
{ "subtract", "iiii", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_region_interface = {
"wl_region", 1,
3, wl_region_requests,
0, NULL,
};
static const struct wl_message wl_subcompositor_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "get_subsurface", "noo", wayland_types + 90 },
};
WL_EXPORT const struct wl_interface wl_subcompositor_interface = {
"wl_subcompositor", 1,
2, wl_subcompositor_requests,
0, NULL,
};
static const struct wl_message wl_subsurface_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "set_position", "ii", wayland_types + 0 },
{ "place_above", "o", wayland_types + 93 },
{ "place_below", "o", wayland_types + 94 },
{ "set_sync", "", wayland_types + 0 },
{ "set_desync", "", wayland_types + 0 },
};
WL_EXPORT const struct wl_interface wl_subsurface_interface = {
"wl_subsurface", 1,
6, wl_subsurface_requests,
0, NULL,
};
static const struct wl_message wl_fixes_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "destroy_registry", "o", wayland_types + 95 },
};
WL_EXPORT const struct wl_interface wl_fixes_interface = {
"wl_fixes", 1,
2, wl_fixes_requests,
0, NULL,
};
#endif
@@ -1,176 +0,0 @@
#ifdef FF_HAVE_WAYLAND
/* Generated by wayland-scanner 1.24.0 */
/*
* Copyright © 2019 Purism SPC
*
* Permission to use, copy, modify, distribute, and sell this
* software and its documentation for any purpose is hereby granted
* without fee, provided that the above copyright notice appear in
* all copies and that both that copyright notice and this permission
* notice appear in supporting documentation, and that the name of
* the copyright holders not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
#ifndef __has_attribute
#define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
#endif
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
#define WL_PRIVATE __attribute__((visibility("hidden")))
#else
#define WL_PRIVATE
#endif
extern const struct wl_interface zwlr_output_configuration_head_v1_interface;
extern const struct wl_interface zwlr_output_configuration_v1_interface;
extern const struct wl_interface zwlr_output_head_v1_interface;
extern const struct wl_interface zwlr_output_mode_v1_interface;
static const struct wl_interface* wlr_output_management_unstable_v1_types[] = {
NULL,
NULL,
NULL,
&zwlr_output_configuration_v1_interface,
NULL,
&zwlr_output_head_v1_interface,
&zwlr_output_mode_v1_interface,
&zwlr_output_mode_v1_interface,
&zwlr_output_configuration_head_v1_interface,
&zwlr_output_head_v1_interface,
&zwlr_output_head_v1_interface,
&zwlr_output_mode_v1_interface,
};
static const struct wl_message zwlr_output_manager_v1_requests[] = {
{ "create_configuration", "nu", wlr_output_management_unstable_v1_types + 3 },
{ "stop", "", wlr_output_management_unstable_v1_types + 0 },
};
static const struct wl_message zwlr_output_manager_v1_events[] = {
{ "head", "n", wlr_output_management_unstable_v1_types + 5 },
{ "done", "u", wlr_output_management_unstable_v1_types + 0 },
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zwlr_output_manager_v1_interface = {
"zwlr_output_manager_v1",
4,
2,
zwlr_output_manager_v1_requests,
3,
zwlr_output_manager_v1_events,
};
static const struct wl_message zwlr_output_head_v1_requests[] = {
{ "release", "3", wlr_output_management_unstable_v1_types + 0 },
};
static const struct wl_message zwlr_output_head_v1_events[] = {
{ "name", "s", wlr_output_management_unstable_v1_types + 0 },
{ "description", "s", wlr_output_management_unstable_v1_types + 0 },
{ "physical_size", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "mode", "n", wlr_output_management_unstable_v1_types + 6 },
{ "enabled", "i", wlr_output_management_unstable_v1_types + 0 },
{ "current_mode", "o", wlr_output_management_unstable_v1_types + 7 },
{ "position", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "transform", "i", wlr_output_management_unstable_v1_types + 0 },
{ "scale", "f", wlr_output_management_unstable_v1_types + 0 },
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
{ "make", "2s", wlr_output_management_unstable_v1_types + 0 },
{ "model", "2s", wlr_output_management_unstable_v1_types + 0 },
{ "serial_number", "2s", wlr_output_management_unstable_v1_types + 0 },
{ "adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zwlr_output_head_v1_interface = {
"zwlr_output_head_v1",
4,
1,
zwlr_output_head_v1_requests,
14,
zwlr_output_head_v1_events,
};
static const struct wl_message zwlr_output_mode_v1_requests[] = {
{ "release", "3", wlr_output_management_unstable_v1_types + 0 },
};
static const struct wl_message zwlr_output_mode_v1_events[] = {
{ "size", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "refresh", "i", wlr_output_management_unstable_v1_types + 0 },
{ "preferred", "", wlr_output_management_unstable_v1_types + 0 },
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zwlr_output_mode_v1_interface = {
"zwlr_output_mode_v1",
3,
1,
zwlr_output_mode_v1_requests,
4,
zwlr_output_mode_v1_events,
};
static const struct wl_message zwlr_output_configuration_v1_requests[] = {
{ "enable_head", "no", wlr_output_management_unstable_v1_types + 8 },
{ "disable_head", "o", wlr_output_management_unstable_v1_types + 10 },
{ "apply", "", wlr_output_management_unstable_v1_types + 0 },
{ "test", "", wlr_output_management_unstable_v1_types + 0 },
{ "destroy", "", wlr_output_management_unstable_v1_types + 0 },
};
static const struct wl_message zwlr_output_configuration_v1_events[] = {
{ "succeeded", "", wlr_output_management_unstable_v1_types + 0 },
{ "failed", "", wlr_output_management_unstable_v1_types + 0 },
{ "cancelled", "", wlr_output_management_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zwlr_output_configuration_v1_interface = {
"zwlr_output_configuration_v1",
4,
5,
zwlr_output_configuration_v1_requests,
3,
zwlr_output_configuration_v1_events,
};
static const struct wl_message zwlr_output_configuration_head_v1_requests[] = {
{ "set_mode", "o", wlr_output_management_unstable_v1_types + 11 },
{ "set_custom_mode", "iii", wlr_output_management_unstable_v1_types + 0 },
{ "set_position", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "set_transform", "i", wlr_output_management_unstable_v1_types + 0 },
{ "set_scale", "f", wlr_output_management_unstable_v1_types + 0 },
{ "set_adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zwlr_output_configuration_head_v1_interface = {
"zwlr_output_configuration_head_v1",
4,
6,
zwlr_output_configuration_head_v1_requests,
0,
NULL,
};
#endif
@@ -0,0 +1,225 @@
#ifdef FF_HAVE_WAYLAND
/* Generated by wayland-scanner 1.24.0 */
/*
* Copyright 2019 Sebastian Wick
* Copyright 2019 Erwin Burema
* Copyright 2020 AMD
* Copyright 2020-2024 Collabora, Ltd.
* Copyright 2024 Xaver Hugl
* Copyright 2022-2025 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
extern const struct wl_interface wl_output_interface;
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface wp_color_management_output_v1_interface;
extern const struct wl_interface wp_color_management_surface_feedback_v1_interface;
extern const struct wl_interface wp_color_management_surface_v1_interface;
extern const struct wl_interface wp_image_description_creator_icc_v1_interface;
extern const struct wl_interface wp_image_description_creator_params_v1_interface;
extern const struct wl_interface wp_image_description_info_v1_interface;
extern const struct wl_interface wp_image_description_reference_v1_interface;
extern const struct wl_interface wp_image_description_v1_interface;
static const struct wl_interface *color_management_v1_types[] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&wp_color_management_output_v1_interface,
&wl_output_interface,
&wp_color_management_surface_v1_interface,
&wl_surface_interface,
&wp_color_management_surface_feedback_v1_interface,
&wl_surface_interface,
&wp_image_description_creator_icc_v1_interface,
&wp_image_description_creator_params_v1_interface,
&wp_image_description_v1_interface,
&wp_image_description_v1_interface,
&wp_image_description_reference_v1_interface,
&wp_image_description_v1_interface,
&wp_image_description_v1_interface,
NULL,
&wp_image_description_v1_interface,
&wp_image_description_v1_interface,
&wp_image_description_v1_interface,
&wp_image_description_v1_interface,
&wp_image_description_info_v1_interface,
};
static const struct wl_message wp_color_manager_v1_requests[] = {
{ "destroy", "", color_management_v1_types + 0 },
{ "get_output", "no", color_management_v1_types + 8 },
{ "get_surface", "no", color_management_v1_types + 10 },
{ "get_surface_feedback", "no", color_management_v1_types + 12 },
{ "create_icc_creator", "n", color_management_v1_types + 14 },
{ "create_parametric_creator", "n", color_management_v1_types + 15 },
{ "create_windows_scrgb", "n", color_management_v1_types + 16 },
{ "get_image_description", "2no", color_management_v1_types + 17 },
};
static const struct wl_message wp_color_manager_v1_events[] = {
{ "supported_intent", "u", color_management_v1_types + 0 },
{ "supported_feature", "u", color_management_v1_types + 0 },
{ "supported_tf_named", "u", color_management_v1_types + 0 },
{ "supported_primaries_named", "u", color_management_v1_types + 0 },
{ "done", "", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_color_manager_v1_interface = {
"wp_color_manager_v1", 2,
8, wp_color_manager_v1_requests,
5, wp_color_manager_v1_events,
};
static const struct wl_message wp_color_management_output_v1_requests[] = {
{ "destroy", "", color_management_v1_types + 0 },
{ "get_image_description", "n", color_management_v1_types + 19 },
};
static const struct wl_message wp_color_management_output_v1_events[] = {
{ "image_description_changed", "", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_color_management_output_v1_interface = {
"wp_color_management_output_v1", 2,
2, wp_color_management_output_v1_requests,
1, wp_color_management_output_v1_events,
};
static const struct wl_message wp_color_management_surface_v1_requests[] = {
{ "destroy", "", color_management_v1_types + 0 },
{ "set_image_description", "ou", color_management_v1_types + 20 },
{ "unset_image_description", "", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_color_management_surface_v1_interface = {
"wp_color_management_surface_v1", 2,
3, wp_color_management_surface_v1_requests,
0, NULL,
};
static const struct wl_message wp_color_management_surface_feedback_v1_requests[] = {
{ "destroy", "", color_management_v1_types + 0 },
{ "get_preferred", "n", color_management_v1_types + 22 },
{ "get_preferred_parametric", "n", color_management_v1_types + 23 },
};
static const struct wl_message wp_color_management_surface_feedback_v1_events[] = {
{ "preferred_changed", "u", color_management_v1_types + 0 },
{ "preferred_changed2", "2uu", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_color_management_surface_feedback_v1_interface = {
"wp_color_management_surface_feedback_v1", 2,
3, wp_color_management_surface_feedback_v1_requests,
2, wp_color_management_surface_feedback_v1_events,
};
static const struct wl_message wp_image_description_creator_icc_v1_requests[] = {
{ "create", "n", color_management_v1_types + 24 },
{ "set_icc_file", "huu", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_image_description_creator_icc_v1_interface = {
"wp_image_description_creator_icc_v1", 2,
2, wp_image_description_creator_icc_v1_requests,
0, NULL,
};
static const struct wl_message wp_image_description_creator_params_v1_requests[] = {
{ "create", "n", color_management_v1_types + 25 },
{ "set_tf_named", "u", color_management_v1_types + 0 },
{ "set_tf_power", "u", color_management_v1_types + 0 },
{ "set_primaries_named", "u", color_management_v1_types + 0 },
{ "set_primaries", "iiiiiiii", color_management_v1_types + 0 },
{ "set_luminances", "uuu", color_management_v1_types + 0 },
{ "set_mastering_display_primaries", "iiiiiiii", color_management_v1_types + 0 },
{ "set_mastering_luminance", "uu", color_management_v1_types + 0 },
{ "set_max_cll", "u", color_management_v1_types + 0 },
{ "set_max_fall", "u", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_image_description_creator_params_v1_interface = {
"wp_image_description_creator_params_v1", 2,
10, wp_image_description_creator_params_v1_requests,
0, NULL,
};
static const struct wl_message wp_image_description_v1_requests[] = {
{ "destroy", "", color_management_v1_types + 0 },
{ "get_information", "n", color_management_v1_types + 26 },
};
static const struct wl_message wp_image_description_v1_events[] = {
{ "failed", "us", color_management_v1_types + 0 },
{ "ready", "u", color_management_v1_types + 0 },
{ "ready2", "2uu", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_image_description_v1_interface = {
"wp_image_description_v1", 2,
2, wp_image_description_v1_requests,
3, wp_image_description_v1_events,
};
static const struct wl_message wp_image_description_info_v1_events[] = {
{ "done", "", color_management_v1_types + 0 },
{ "icc_file", "hu", color_management_v1_types + 0 },
{ "primaries", "iiiiiiii", color_management_v1_types + 0 },
{ "primaries_named", "u", color_management_v1_types + 0 },
{ "tf_power", "u", color_management_v1_types + 0 },
{ "tf_named", "u", color_management_v1_types + 0 },
{ "luminances", "uuu", color_management_v1_types + 0 },
{ "target_primaries", "iiiiiiii", color_management_v1_types + 0 },
{ "target_luminance", "uu", color_management_v1_types + 0 },
{ "target_max_cll", "u", color_management_v1_types + 0 },
{ "target_max_fall", "u", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_image_description_info_v1_interface = {
"wp_image_description_info_v1", 2,
0, NULL,
11, wp_image_description_info_v1_events,
};
static const struct wl_message wp_image_description_reference_v1_requests[] = {
{ "destroy", "", color_management_v1_types + 0 },
};
WL_EXPORT const struct wl_interface wp_image_description_reference_v1_interface = {
"wp_image_description_reference_v1", 1,
1, wp_image_description_reference_v1_requests,
0, NULL,
};
#endif
@@ -35,7 +35,7 @@ static const struct wl_interface* xdg_output_unstable_v1_types[] = {
NULL,
NULL,
&zxdg_output_v1_interface,
NULL, // &wl_output_interface,
&wl_output_interface,
};
static const struct wl_message zxdg_output_manager_v1_requests[] = {
@@ -1,212 +0,0 @@
#ifdef FF_HAVE_WAYLAND
#include "wayland.h"
#include "wlr-output-management-unstable-v1-client-protocol.h"
static void waylandZwlrTransformListener(void* data, FF_A_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, int32_t transform) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->transform = (enum wl_output_transform) transform;
}
static void waylandZwlrScaleListener(void* data, FF_A_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, wl_fixed_t scale) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->dpi = (uint32_t) scale * 3 / 8; // wl_fixed_to_double(scale) * 96;
}
typedef struct WaylandZwlrMode {
int32_t width;
int32_t height;
int32_t refreshRate;
bool preferred;
struct zwlr_output_mode_v1* pMode;
} WaylandZwlrMode;
static void waylandZwlrModeSizeListener(void* data, FF_A_UNUSED struct zwlr_output_mode_v1* zwlr_output_mode_v1, int32_t width, int32_t height) {
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
mode->width = width;
mode->height = height;
}
static void waylandZwlrModeRefreshListener(void* data, FF_A_UNUSED struct zwlr_output_mode_v1* zwlr_output_mode_v1, int32_t rate) {
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
mode->refreshRate = rate;
}
static void waylandZwlrModePreferredListener(void* data, FF_A_UNUSED struct zwlr_output_mode_v1* zwlr_output_mode_v1) {
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
mode->preferred = true;
}
static const struct zwlr_output_mode_v1_listener modeListener = {
.size = waylandZwlrModeSizeListener,
.refresh = waylandZwlrModeRefreshListener,
.preferred = waylandZwlrModePreferredListener,
.finished = (void*) stubListener,
};
static void waylandZwlrModeListener(void* data, FF_A_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, struct zwlr_output_mode_v1* mode) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!wldata->internal) {
return;
}
WaylandZwlrMode* newMode = FF_LIST_ADD(WaylandZwlrMode, *(FFlist*) wldata->internal);
*newMode = (WaylandZwlrMode) { .pMode = mode };
// Strangely, the listener is called only in this function, but not in `waylandZwlrCurrentModeListener`
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy*) mode, (void (**)(void)) &modeListener, newMode);
}
static void waylandZwlrCurrentModeListener(void* data, FF_A_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, struct zwlr_output_mode_v1* mode) {
// waylandZwlrModeListener is always run before this
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!wldata->internal) {
return;
}
int set = 0;
FF_LIST_FOR_EACH (WaylandZwlrMode, m, *(FFlist*) wldata->internal) {
if (m->pMode == mode) {
wldata->width = m->width;
wldata->height = m->height;
wldata->refreshRate = m->refreshRate;
if (++set == 2) {
break;
}
}
if (m->preferred) {
wldata->preferredWidth = m->width;
wldata->preferredHeight = m->height;
wldata->preferredRefreshRate = m->refreshRate;
if (++set == 2) {
break;
}
}
}
}
static void waylandZwlrPhysicalSizeListener(void* data, FF_A_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, int32_t width, int32_t height) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->physicalWidth = width;
wldata->physicalHeight = height;
}
static void waylandZwlrEnabledListener(void* data, FF_A_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, bool enabled) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!enabled) {
wldata->internal = NULL;
}
}
static const struct zwlr_output_head_v1_listener headListener = {
.name = (void*) ffWaylandOutputNameListener,
.description = (void*) ffWaylandOutputDescriptionListener,
.physical_size = waylandZwlrPhysicalSizeListener,
.mode = waylandZwlrModeListener,
.enabled = (void*) waylandZwlrEnabledListener,
.current_mode = waylandZwlrCurrentModeListener,
.position = (void*) stubListener,
.transform = waylandZwlrTransformListener,
.scale = waylandZwlrScaleListener,
.finished = (void*) stubListener,
.make = (void*) stubListener,
.model = (void*) stubListener,
.serial_number = (void*) stubListener,
.adaptive_sync = (void*) stubListener,
};
static void waylandHandleZwlrHead(void* data, FF_A_UNUSED struct zwlr_output_manager_v1* zwlr_output_manager_v1, struct zwlr_output_head_v1* head) {
WaylandData* wldata = data;
FF_LIST_AUTO_DESTROY modes = ffListCreate();
WaylandDisplay display = {
.parent = wldata,
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
.type = FF_DISPLAY_TYPE_UNKNOWN,
.name = ffStrbufCreate(),
.description = ffStrbufCreate(),
.edidName = ffStrbufCreate(),
.internal = &modes,
};
wldata->ffwl_proxy_add_listener((struct wl_proxy*) head, (void (**)(void)) &headListener, &display);
wldata->ffwl_display_roundtrip(wldata->display);
if (display.width <= 0 || display.height <= 0 || !display.internal) {
return;
}
uint32_t rotation = ffWaylandHandleRotation(&display);
FFDisplayResult* item = ffdsAppendDisplay(wldata->result,
(uint32_t) display.width,
(uint32_t) display.height,
display.refreshRate / 1000.0,
(uint32_t) display.dpi,
(uint32_t) display.preferredWidth,
(uint32_t) display.preferredHeight,
display.preferredRefreshRate / 1000.0,
rotation,
display.edidName.length
? &display.edidName
: display.description.length && !ffStrbufContain(&display.description, &display.name)
? &display.description
: &display.name,
display.type,
false,
display.id,
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight,
"wayland-zwlr");
if (item) {
if (display.hdrSupported) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
} else if (display.hdrInfoAvailable) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
} else {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
}
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
item->serial = display.serial;
}
ffStrbufDestroy(&display.description);
ffStrbufDestroy(&display.name);
ffStrbufDestroy(&display.edidName);
// These must be released manually
FF_LIST_FOR_EACH (WaylandZwlrMode, m, modes) {
wldata->ffwl_proxy_destroy((void*) m->pMode);
}
wldata->ffwl_proxy_destroy((void*) head);
}
static const struct zwlr_output_manager_v1_listener outputListener = {
.head = waylandHandleZwlrHead,
.done = (void*) stubListener,
.finished = (void*) stubListener,
};
const char* ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
uint32_t bindVersion = min(version, ZWLR_OUTPUT_MANAGER_V1_HEAD_SINCE_VERSION);
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &zwlr_output_manager_v1_interface, bindVersion, name, zwlr_output_manager_v1_interface.name, bindVersion, NULL);
if (output == NULL) {
return "Failed to bind zwlr_output_manager_v1";
}
if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &outputListener, wldata) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to add listener to zwlr_output_manager_v1";
}
if (wldata->ffwl_display_roundtrip(wldata->display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to roundtrip display";
}
wldata->ffwl_proxy_destroy(output);
return NULL;
}
#endif
+2 -1
View File
@@ -227,7 +227,8 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
if (item) {
if (edidData && edidLength >= 128) {
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
ffEdidGetManufactureDate(edidData, &item->manufactureYear, &item->manufactureWeek);
ffEdidGetSerial(edidData, &item->serial);
}
item->bitDepth = bitDepth;
if ((rotation == 90 || rotation == 180) && !randrEmulation) {
+2 -1
View File
@@ -161,7 +161,8 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
if (item) {
if (edidLength) {
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
ffEdidGetManufactureDate(edidData, &item->manufactureYear, &item->manufactureWeek);
ffEdidGetSerial(edidData, &item->serial);
}
item->bitDepth = bitDepth;
if ((rotation == 90 || rotation == 180) && !randrEmulation) {
+3
View File
@@ -26,6 +26,9 @@ extern int ADL2_Adapter_DedicatedVRAMUsage_Get(ADL_CONTEXT_HANDLE context, int i
// Function to get the ASICFamilyType from the adapter.
extern int ADL2_Adapter_ASICFamilyType_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpAsicTypes, int* lpValids);
// This function retrieves the chipset information for a specified adapter.
extern int ADL2_Adapter_ChipSetInfo_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLChipSetInfo* lpChipSetInfo);
// Function to retrieve current power management capabilities.
extern int ADL2_Overdrive_Caps(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iSupported, int* iEnabled, int* iVersion);
+5 -1
View File
@@ -7,7 +7,11 @@
#ifndef _ASAHI_DRM_H_
#define _ASAHI_DRM_H_
#include <drm.h>
#if __has_include(<drm.h>)
#include <drm.h>
#else
#include <drm/drm.h>
#endif
#if defined(__cplusplus)
extern "C" {
+13
View File
@@ -152,6 +152,18 @@ typedef struct _D3DKMT_QUERY_DEVICE_IDS {
D3DKMT_DEVICE_IDS DeviceIds; // out:
} D3DKMT_QUERY_DEVICE_IDS;
typedef enum _D3DKMT_PNP_KEY_TYPE {
D3DKMT_PNP_KEY_HARDWARE,
D3DKMT_PNP_KEY_SOFTWARE
} D3DKMT_PNP_KEY_TYPE;
typedef struct _D3DKMT_QUERY_PHYSICAL_ADAPTER_PNP_KEY {
UINT PhysicalAdapterIndex;
D3DKMT_PNP_KEY_TYPE PnPKeyType;
WCHAR* pDest;
UINT* pCchDest;
} D3DKMT_QUERY_PHYSICAL_ADAPTER_PNP_KEY;
typedef enum _QAI_DRIVERVERSION {
KMT_DRIVERVERSION_WDDM_1_0 = 1000, // Windows Vista
KMT_DRIVERVERSION_WDDM_1_1_PRERELEASE = 1102, // Windows Vista with prereleased Win7 features
@@ -187,6 +199,7 @@ typedef enum _KMTQUERYADAPTERINFOTYPE {
KMTQAITYPE_UMD_DRIVER_VERSION = 18,
KMTQAITYPE_NODEMETADATA = 25, // WDDM 2.0, Windows 10
KMTQAITYPE_PHYSICALADAPTERDEVICEIDS = 31,
KMTQAITYPE_PHYSICALADAPTERPNPKEY = 41, // WDDM 2.2, Windows 10 (1703)
KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID = 60, // WDDM 2.4, Windows 10 (1803)
KMTQAITYPE_NODEPERFDATA = 61,
KMTQAITYPE_ADAPTERPERFDATA = 62,
+159 -12
View File
@@ -77,6 +77,25 @@ const char* ffGPUGetVendorString(unsigned vendorId) {
}
}
static bool normalizeVendorName(FFGPUResult* gpu) {
if (ffStrbufContainS(&gpu->name, "Apple")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
gpu->type = FF_GPU_TYPE_INTEGRATED;
} else if (ffStrbufContainS(&gpu->name, "Intel")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
} else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
} else if (ffStrbufContainS(&gpu->name, "NVIDIA")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
} else if (ffStrbufContainS(&gpu->name, "MTT")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
} else {
return false;
}
return true;
}
const char* detectByOpenGL(FFlist* gpus) {
FF_DEBUG("Starting OpenGL GPU detection fallback");
@@ -107,24 +126,14 @@ const char* detectByOpenGL(FFlist* gpus) {
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->dedicated = gpu->shared = (FFGPUMemory) { 0, 0 };
gpu->deviceId = 0;
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
FF_DEBUG("OpenGL reported renderer='%s', vendor='%s', version='%s'",
gpu->name.chars,
gpu->vendor.chars,
result.version.chars);
if (ffStrbufContainS(&gpu->name, "Apple")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
gpu->type = FF_GPU_TYPE_INTEGRATED;
} else if (ffStrbufContainS(&gpu->name, "Intel")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
} else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
} else if (ffStrbufContainS(&gpu->name, "NVIDIA")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
} else if (ffStrbufContainS(&gpu->name, "MTT")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
}
normalizeVendorName(gpu);
FF_DEBUG("OpenGL fallback produced GPU: name='%s', vendor='%s', type=%u",
gpu->name.chars,
@@ -140,6 +149,98 @@ const char* detectByOpenGL(FFlist* gpus) {
return error;
}
#if defined(FF_HAVE_EGL) || __has_include(<EGL/egl.h>)
#include <EGL/egl.h>
#include <EGL/eglext.h>
#if EGL_EXT_device_base && EGL_EXT_device_persistent_id && EGL_EXT_device_query_name
#define FF_HAVE_EGL_EXT 1
#include <inttypes.h>
#include "common/library.h"
#include "common/strutil.h"
#include "common/io.h"
const char* detectByEglext(FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(egl, "libEGL" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(egl, eglGetProcAddress);
PFNEGLQUERYDEVICESEXTPROC ffeglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC) ffeglGetProcAddress("eglQueryDevicesEXT");
if (!ffeglQueryDevicesEXT) {
return "eglQueryDevicesEXT is unavailable";
}
PFNEGLQUERYDEVICESTRINGEXTPROC ffeglQueryDeviceStringEXT = (PFNEGLQUERYDEVICESTRINGEXTPROC) ffeglGetProcAddress("eglQueryDeviceStringEXT");
if (!ffeglQueryDeviceStringEXT) {
return "eglQueryDeviceStringEXT is unavailable";
}
PFNEGLQUERYDEVICEBINARYEXTPROC ffeglQueryDeviceBinaryEXT = (PFNEGLQUERYDEVICEBINARYEXTPROC) ffeglGetProcAddress("eglQueryDeviceBinaryEXT");
if (!ffeglQueryDeviceBinaryEXT) {
return "eglQueryDeviceBinaryEXT is unavailable";
}
FF_DEBUG("Loaded EGL library and required symbols");
FF_SUPPRESS_IO();
EGLDeviceEXT devices[16];
EGLint numDevices;
if (ffeglQueryDevicesEXT(ARRAY_SIZE(devices), devices, &numDevices) == EGL_TRUE) {
FF_DEBUG("eglQueryDevicesEXT() returned %d device(s)", numDevices);
for (EGLint i = 0; i < numDevices; i++) {
const EGLDeviceEXT device = devices[i];
if (device == (EGLDeviceEXT) EGL_NO_DEVICE_EXT || device == (EGLDeviceEXT) EGL_BAD_DEVICE_EXT) {
FF_DEBUG("eglQueryDevicesEXT() returned invalid device at index %d", i);
continue;
}
const char* exts = (const char*) ffeglQueryDeviceStringEXT(device, EGL_EXTENSIONS);
FF_DEBUG("eglQueryDeviceStringEXT() returned extensions for device %d: %s", i, exts);
if (exts && ffStrContains(exts, "EGL_MESA_device_software")) {
FF_DEBUG("eglQueryDeviceStringEXT() returned software device at index %d, skipping", i);
continue;
}
const char* name = ffeglQueryDeviceStringEXT(device, EGL_RENDERER_EXT);
if (!name) {
FF_DEBUG("eglQueryDeviceStringEXT() returned NULL name for device %d, skipping", i);
continue;
}
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *result);
ffStrbufInitS(&gpu->name, name);
ffStrbufInit(&gpu->vendor);
ffStrbufInitS(&gpu->driver, ffeglQueryDeviceStringEXT(device, EGL_DRIVER_NAME_EXT));
ffStrbufInitF(&gpu->platformApi, "egl-ext");
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
ffeglQueryDeviceBinaryEXT(device, EGL_DEVICE_UUID_EXT, sizeof(gpu->deviceId), &gpu->deviceId, NULL);
if (!normalizeVendorName(gpu)) {
ffStrbufSetS(&gpu->vendor, ffeglQueryDeviceStringEXT(device, EGL_VENDOR));
}
FF_DEBUG("Detected GPU %d: vendor='%s', name='%s', driver='%s', id='%16" PRIX64 "'", i, gpu->vendor.chars, gpu->name.chars, gpu->driver.chars, gpu->deviceId);
}
} else {
FF_DEBUG("eglQueryDevicesEXT() returned EGL_FALSE");
}
return NULL;
}
#endif
#endif
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) {
FF_DEBUG("Starting GPU detection with method=%d", (int) options->detectionMethod);
@@ -192,6 +293,22 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) {
opencl->error ?: "none",
opencl->gpus.length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_EGL_EXT) {
#if FF_HAVE_EGL_EXT
FF_DEBUG("Trying EGL_EXT GPU detection fallback");
const char* error = detectByEglext(result);
if (!error && result->length > 0) {
FF_DEBUG("EGL_EXT GPU detection succeeded with %u GPU(s)", result->length);
return NULL;
}
FF_DEBUG("EGL_EXT GPU detection did not produce results (error=%s, gpuCount=%u)",
error ?: "none",
result->length);
#else
FF_DEBUG("EGL_EXT GPU detection is unavailable");
#endif
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL) {
FF_DEBUG("Trying OpenGL GPU detection fallback");
const char* error = detectByOpenGL(result);
@@ -206,3 +323,33 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) {
FF_DEBUG("GPU detection failed in all enabled backends");
return "GPU detection failed";
}
bool ffGPUDetectTypeByVendorAndName(FFGPUResult* gpu) {
if (gpu->type != FF_GPU_TYPE_UNKNOWN) {
return true;
}
FF_DEBUG("Using fallback GPU type detection");
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) { gpu->type = FF_GPU_TYPE_DISCRETE; }
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) {
// 0000:00:02.0 is reserved for Intel integrated graphics
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_VMWARE || gpu->vendor.chars == FF_GPU_VENDOR_NAME_PARALLELS) {
// Virtualized GPUs
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
if (gpu->type != FF_GPU_TYPE_UNKNOWN) {
FF_DEBUG("Determined GPU type based on vendor (%s) and name: %u", gpu->vendor.chars, gpu->type);
return true;
}
return false;
}
+23 -2
View File
@@ -7,6 +7,7 @@
#define FF_GPU_CORE_COUNT_UNSET -1
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t) -1)
#define FF_GPU_FREQUENCY_UNSET 0
#define FF_GPU_PCIE_SPEED_UNSET 0
#define FF_GPU_CORE_USAGE_UNSET (-DBL_MAX)
#define FF_GPU_INDEX_UNSET ((uint32_t) -1)
@@ -34,6 +35,11 @@ typedef struct FFGPUMemory {
uint64_t used;
} FFGPUMemory;
typedef struct FFGPUPcieSpeed {
uint16_t gen;
uint16_t lanes;
} FFGPUPcieSpeed;
typedef struct FFGPUResult {
uint32_t index;
FFGPUType type;
@@ -46,11 +52,21 @@ typedef struct FFGPUResult {
double coreUsage;
int32_t coreCount;
uint32_t frequency; // Maximum time clock frequency in MHz
union {
struct {
FFGPUPcieSpeed psMax;
FFGPUPcieSpeed psCurr;
};
uint64_t pcieSpeed;
};
FFGPUMemory dedicated;
FFGPUMemory shared;
uint64_t deviceId;
} FFGPUResult;
static_assert(sizeof(((FFGPUResult*) NULL)->pcieSpeed) == 8, "pcieSpeed is not 8 bytes");
static_assert(sizeof(((FFGPUResult*) NULL)->psMax) == 4, "psMax has padding");
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
@@ -67,14 +83,17 @@ typedef struct FFGpuDriverPciBusId {
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
#if FF_HAVE_DRM
#if FF_HAVE_DRM || __has_include(<drm/drm.h>)
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd);
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd);
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd);
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd);
#endif // FF_HAVE_DRM
#if __FreeBSD__ || __OpenBSD__ // DRM is not available on NetBSD
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus);
#endif
#endif // FF_HAVE_DRM || __has_include(<drm/drm.h>)
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
#endif // defined(XXX)
@@ -87,3 +106,5 @@ static inline uint64_t ffGPUGeneral2Id(uint64_t originalId) {
// Note: originalId may already have the MSB set
return (1ULL << 63) | originalId;
}
bool ffGPUDetectTypeByVendorAndName(FFGPUResult* gpu);
+36
View File
@@ -52,6 +52,7 @@ struct FFAdlData {
FF_LIBRARY_SYMBOL(ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_ChipSetInfo_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive_Caps)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_CapabilitiesX2_Get)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_SystemClocksX2_Get)
@@ -89,6 +90,7 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ChipSetInfo_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive_Caps)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_CapabilitiesX2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_SystemClocksX2_Get)
@@ -233,6 +235,40 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
FF_DEBUG("Setting adapter name: %s; UDID: %s, Present: %d, Exist: %d", device->strAdapterName, device->strUDID, device->iPresent, device->iExist);
}
if (result.psMax || result.psCurr) {
ADLChipSetInfo chipSetInfo;
int status = adlData.ffADL2_Adapter_ChipSetInfo_Get(adlData.apiHandle, device->iAdapterIndex, &chipSetInfo);
FF_DEBUG("ADL2_Adapter_ChipSetInfo_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK) {
FF_DEBUG("Chipset info - iBusSpeedType: %d, iMaxPCIELaneWidth: %d", chipSetInfo.iBusSpeedType, chipSetInfo.iMaxPCIELaneWidth);
if (result.psMax) {
if (chipSetInfo.iBusSpeedType >= 2) {
result.psMax->gen = (uint16_t) (chipSetInfo.iBusSpeedType - 2);
FF_DEBUG("Got PCIe Max Gen: %u", result.psMax->gen);
}
if (chipSetInfo.iMaxPCIELaneWidth > 0) {
result.psMax->lanes = (uint16_t) chipSetInfo.iMaxPCIELaneWidth;
FF_DEBUG("Got PCIe Max Lanes: %u", result.psMax->lanes);
}
}
FF_DEBUG("Chipset info - iBusType: %d, iCurrentPCIELaneWidth: %d", chipSetInfo.iBusType, chipSetInfo.iCurrentPCIELaneWidth);
if (result.psCurr) {
if (chipSetInfo.iBusType >= 2) {
result.psCurr->gen = (uint16_t) (chipSetInfo.iBusType - 2);
FF_DEBUG("Got PCIe Current Gen: %u", result.psCurr->gen);
}
if (chipSetInfo.iCurrentPCIELaneWidth > 0) {
result.psCurr->lanes = (uint16_t) chipSetInfo.iCurrentPCIELaneWidth;
FF_DEBUG("Got PCIe Current Lanes: %u", result.psCurr->lanes);
}
}
} else {
FF_DEBUG("Failed to get chipset information");
}
}
int odVersion = 0;
{
+2 -3
View File
@@ -48,8 +48,6 @@ static double detectGpuTemp(const FFstrbuf* gpuName) {
}
#ifdef __aarch64__
#include "common/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
static const char* detectFrequency(FFGPUResult* gpu) {
@@ -71,7 +69,7 @@ static const char* detectFrequency(FFGPUResult* gpu) {
// voltage-states9-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
CFIndex propLength = CFDataGetLength(freqProperty);
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
if (propLength == 0 || propLength % (CFIndex) (sizeof(uint32_t) * 2) != 0) {
return "Invalid \"voltage-states9-sram\" length";
}
@@ -118,6 +116,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId);
ffStrbufInitStatic(&gpu->platformApi, "IOKit");
+4 -137
View File
@@ -1,7 +1,7 @@
#include "gpu.h"
#include "gpu_driver_specific.h"
#include "common/io.h"
#include "common/mallocHelper.h"
#include <sys/pciio.h>
#include <fcntl.h>
@@ -11,140 +11,6 @@
#include <bus/pci/pcireg.h> // DragonFly
#endif
static void fillGPUTypeGeneric(FFGPUResult* gpu) {
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) {
// 0000:00:02.0 is reserved for Intel integrated graphics
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
}
}
}
#if FF_HAVE_DRM
#include "common/library.h"
#include "common/strutil.h"
#include <xf86drm.h>
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus) {
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
drmDevicePtr devices[64];
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
if (nDevices < 0) {
return "drmGetDevices() failed";
}
for (int iDev = 0; iDev < nDevices; ++iDev) {
drmDevice* dev = devices[iDev];
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY))) {
continue;
}
const char* path = dev->nodes[DRM_NODE_PRIMARY];
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitS(&gpu->platformApi, path);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
switch (dev->bustype) {
case DRM_BUS_PCI:
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
gpu->deviceId = ffGPUPciAddr2Id(dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func);
break;
case DRM_BUS_HOST1X:
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_PLATFORM:
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_USB:
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
gpu->type = FF_GPU_TYPE_DISCRETE;
break;
}
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
continue;
}
char driverName[64];
driverName[0] = '\0';
struct drm_version ver = {
.name = driverName,
.name_len = ARRAY_SIZE(driverName),
};
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0) {
driverName[ver.name_len] = '\0';
ffStrbufSetF(&gpu->driver, "%s %d.%d.%d", ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
}
if (ffStrStartsWith(driverName, "i915")) {
ffDrmDetectI915(gpu, fd);
} else if (ffStrStartsWith(driverName, "amdgpu")) {
ffDrmDetectAmdgpu(options, gpu, dev->nodes[DRM_NODE_RENDER]);
} else if (ffStrStartsWith(driverName, "radeon")) {
ffDrmDetectRadeon(options, gpu, dev->nodes[DRM_NODE_RENDER]);
} else if (ffStrStartsWith(driverName, "xe")) {
ffDrmDetectXe(gpu, fd);
} else if (ffStrStartsWith(driverName, "asahi")) {
ffDrmDetectAsahi(gpu, fd);
} else if (ffStrStartsWith(driverName, "nouveau")) {
ffDrmDetectNouveau(gpu, fd);
} else if (dev->bustype == DRM_BUS_PCI) {
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = (uint32_t) dev->businfo.pci->domain,
.bus = dev->businfo.pci->bus,
.device = dev->businfo.pci->dev,
.func = dev->businfo.pci->func,
});
}
if (gpu->name.length == 0) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(dev->deviceinfo.pci->device_id, dev->deviceinfo.pci->revision_id, gpu);
}
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, gpu);
}
}
fillGPUTypeGeneric(gpu);
}
ffdrmFreeDevices(devices, nDevices);
return NULL;
}
#endif
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
@@ -193,6 +59,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(pc->pc_sel.pc_domain, pc->pc_sel.pc_bus, pc->pc_sel.pc_dev, pc->pc_sel.pc_func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = (uint32_t) pc->pc_sel.pc_domain,
@@ -210,7 +77,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
}
}
fillGPUTypeGeneric(gpu);
ffGPUDetectTypeByVendorAndName(gpu);
}
return NULL;
@@ -219,7 +86,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
#if FF_HAVE_DRM
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO) {
detectByDrm(options, gpus);
ffGPUDetectByDrmBSD(options, gpus);
if (gpus->length > 0) {
return NULL;
}
+204
View File
@@ -0,0 +1,204 @@
#include "gpu.h"
#if FF_HAVE_DRM
#include "common/strutil.h"
#include "common/io.h"
#include <drm.h>
#include <sys/ioctl.h>
#if __FreeBSD__
#include <sys/sysctl.h>
#include <inttypes.h>
#include <sys/pciio.h>
#include <fcntl.h>
#if __has_include(<dev/pci/pcireg.h>)
#include <dev/pci/pcireg.h> // FreeBSD
#else
#include <bus/pci/pcireg.h> // DragonFly
#endif
#endif
// https://github.com/freebsd/drm-kmod/blob/8fea1f06b3ac3fa24217e24ba7b2133abad705a9/include/uapi/drm/drm.h#L1095
struct drm_pciinfo {
uint16_t domain;
uint8_t bus;
uint8_t dev;
uint8_t func;
uint16_t vendor_id;
uint16_t device_id;
uint16_t subvendor_id;
uint16_t subdevice_id;
uint8_t revision_id;
};
#define DRM_IOCTL_GET_PCIINFO DRM_IOR(0x15, struct drm_pciinfo)
static const char* drmGetPciinfo(int drmfd, const char* drmId, struct drm_pciinfo* result) {
#if !__FreeBSD__
FF_UNUSED(drmId);
if (ioctl(drmfd, DRM_IOCTL_GET_PCIINFO, result) < 0) {
return "ioctl(DRM_IOCTL_GET_PCIINFO) failed";
}
#else
FF_UNUSED(drmfd);
char requestBuf[64];
snprintf(requestBuf, ARRAY_SIZE(requestBuf), "hw.dri.%s.busid", drmId);
char pciidBuf[64];
size_t pciidLen = ARRAY_SIZE(pciidBuf);
if (sysctlbyname(requestBuf, pciidBuf, &pciidLen, NULL, 0) < 0) {
return "sysctlbyname(hw.dri.%s.busid) failed";
}
// hw.dri.0.busid: pci:0000:01:00.0
struct pci_match_conf match = {
.pc_class = PCIC_DISPLAY,
.flags = PCI_GETCONF_MATCH_CLASS | PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC,
};
if (sscanf(pciidBuf, "pci:%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8, &match.pc_sel.pc_domain, &match.pc_sel.pc_bus, &match.pc_sel.pc_dev, &match.pc_sel.pc_func) != 4) {
return "Invalid PCI busid found";
}
FF_AUTO_CLOSE_FD int pcifd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
if (pcifd < 0) {
return "open(\"/dev/pci\", O_RDONLY | O_CLOEXEC, 0) failed";
}
struct pci_conf conf;
struct pci_conf_io pcio = {
.pat_buf_len = sizeof(match),
.num_patterns = 1,
.patterns = &match,
.match_buf_len = sizeof(conf),
.matches = &conf,
};
if (ioctl(pcifd, PCIOCGETCONF, &pcio) < 0) {
return "ioctl(pcifd, PCIOCGETCONF, &pc) failed";
}
if (pcio.status == PCI_GETCONF_ERROR) {
return "ioctl(pcifd, PCIOCGETCONF, &pc) returned error";
}
if (pcio.num_matches != 1) {
return "ioctl(pcifd, PCIOCGETCONF, &pc) returned no results";
}
*result = (struct drm_pciinfo){
.domain = (uint16_t) conf.pc_sel.pc_domain,
.bus = conf.pc_sel.pc_bus,
.dev = conf.pc_sel.pc_dev,
.func = conf.pc_sel.pc_func,
.vendor_id = conf.pc_vendor,
.device_id = conf.pc_device,
.subvendor_id = conf.pc_subvendor,
.subdevice_id = conf.pc_subdevice,
.revision_id = conf.pc_revid,
};
// This sysctl can also be useful
// dev.drm.0.PCI_ID: 10de:2782
#endif
return NULL;
}
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/dri/");
if (dirp == NULL) {
return "opendir(/dev/dri/) failed";
}
int drifd = dirfd(dirp);
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.' || !ffStrStartsWith(entry->d_name, "card")) {
continue;
}
FF_AUTO_CLOSE_FD int fd = openat(drifd, entry->d_name, O_RDWR | O_CLOEXEC);
if (fd < 0) {
continue;
}
// Currently, DRM_BUS_PCI is the only bus type supported by drm-kmod on BSD (hard-coded in libdrm source tree)
struct drm_pciinfo pciInfo;
if (drmGetPciinfo(fd, entry->d_name + strlen("card"), &pciInfo) != NULL) {
continue;
}
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pciInfo.vendor_id));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitF(&gpu->platformApi, "/dev/dri/%s", entry->d_name);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(pciInfo.domain, pciInfo.bus, pciInfo.dev, pciInfo.func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
char driverName[64];
driverName[0] = '\0';
struct drm_version ver = {
.name = driverName,
.name_len = ARRAY_SIZE(driverName) - 1,
};
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0) {
driverName[ver.name_len] = '\0';
ffStrbufSetF(&gpu->driver, "%s %d.%d.%d", ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
}
if (ffStrStartsWith(driverName, "i915")) {
ffDrmDetectI915(gpu, fd);
} else if (ffStrStartsWith(driverName, "amdgpu")) {
uint32_t primaryNodeId = (uint32_t) strtoul(entry->d_name + strlen("card"), NULL, 10);
FF_STRBUF_AUTO_DESTROY renderNode = ffStrbufCreateF("/dev/dri/renderD%d", primaryNodeId + 128);
ffDrmDetectAmdgpu(options, gpu, renderNode.chars);
} else if (ffStrStartsWith(driverName, "radeon")) {
uint32_t primaryNodeId = (uint32_t) strtoul(entry->d_name + strlen("card"), NULL, 10);
FF_STRBUF_AUTO_DESTROY renderNode = ffStrbufCreateF("/dev/dri/renderD%d", primaryNodeId + 128);
ffDrmDetectRadeon(options, gpu, renderNode.chars);
} else if (ffStrStartsWith(driverName, "xe")) {
ffDrmDetectXe(gpu, fd);
} else if (ffStrStartsWith(driverName, "asahi")) {
ffDrmDetectAsahi(gpu, fd);
} else if (ffStrStartsWith(driverName, "nouveau")) {
ffDrmDetectNouveau(gpu, fd);
} else {
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId){
.domain = pciInfo.domain,
.bus = pciInfo.bus,
.device = pciInfo.dev,
.func = pciInfo.func,
});
}
if (gpu->name.length == 0) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(pciInfo.device_id, pciInfo.revision_id, gpu);
}
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(0, pciInfo.vendor_id, pciInfo.device_id, gpu);
}
}
ffGPUDetectTypeByVendorAndName(gpu);
}
return NULL;
}
#else
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) {
FF_UNUSED(options, gpus);
return "Fastfetch was built without libdrm support";
}
#endif // FF_HAVE_DRM
+2
View File
@@ -36,6 +36,8 @@ typedef struct FFGpuDriverResult {
FFGPUType* type;
uint32_t* frequency;
FFstrbuf* name;
FFGPUPcieSpeed* psMax;
FFGPUPcieSpeed* psCurr;
} FFGpuDriverResult;
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
+80 -60
View File
@@ -1,19 +1,26 @@
#include "gpu.h"
#if FF_HAVE_DRM
#include <drm.h>
#if FF_HAVE_DRM || __has_include(<drm/drm.h>)
#include <fcntl.h>
#include <sys/ioctl.h>
#include "common/io.h"
#include "common/library.h"
#include "common/mallocHelper.h"
#include "common/strutil.h"
#if FF_HAVE_DRM
#include <drm.h>
#include <radeon_drm.h>
#include <nouveau_drm.h>
#include <amdgpu_drm.h>
#else
#define FF_HAVE_DRM 1
#include <drm/drm.h>
#include <drm/radeon_drm.h>
#include <drm/nouveau_drm.h>
#include <drm/amdgpu_drm.h>
#endif
#include "intel_drm.h"
#include "asahi_drm.h"
#include <radeon_drm.h>
#include <nouveau_drm.h>
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath) {
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
@@ -43,7 +50,7 @@ const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, con
}
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_MAX_SCLK, // MHz
.request = RADEON_INFO_MAX_SCLK, // KHz
.value = (uintptr_t) &value,
}) >= 0) {
gpu->frequency = (uint32_t) (value / 1000u);
@@ -52,7 +59,7 @@ const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, con
if (options->driverSpecific) {
struct drm_radeon_gem_info gemInfo;
if (ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &gemInfo) >= 0) {
// vram_usage can be bigger than vram_usage, so we use vram_size here
// vram_usage can be bigger than vram_size, so we use vram_size here
gpu->dedicated.total = gemInfo.vram_size;
gpu->shared.total = gemInfo.gart_size;
@@ -76,52 +83,50 @@ const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, con
return NULL;
}
#ifdef FF_HAVE_DRM_AMDGPU
#include <amdgpu.h>
#include <amdgpu_drm.h>
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath) {
#if FF_HAVE_DRM_AMDGPU
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return "Failed to open DRM render device";
}
amdgpu_device_handle handle;
uint32_t majorVersion, minorVersion;
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0) {
return "Failed to initialize AMDGPU device";
}
uint32_t value;
if (options->temp) {
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0) {
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
&(struct drm_amdgpu_info) {
.return_pointer = (uintptr_t) &value,
.return_size = sizeof(value),
.query = AMDGPU_INFO_SENSOR,
.query_hw_ip.type = AMDGPU_INFO_SENSOR_GPU_TEMP,
}) >= 0 && value != 0) {
gpu->temperature = value / 1000.;
}
}
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
struct amdgpu_gpu_info gpuInfo;
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0) {
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
struct drm_amdgpu_info_device devInfo;
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
&(struct drm_amdgpu_info) {
.return_pointer = (uintptr_t) &devInfo,
.return_size = sizeof(devInfo),
.query = AMDGPU_INFO_DEV_INFO,
}) >= 0) {
gpu->coreCount = (int32_t) devInfo.cu_active_number;
gpu->frequency = (uint32_t) (devInfo.max_engine_clock / 1000u);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#define FF_VRAM_CASE(name, value) \
case value /* AMDGPU_VRAM_TYPE_ ## name */: \
gpu->type = devInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
// Was `_pad`. Introduced in commit https://github.com/sailfishos-mirror/drm/commit/22b698a5990292bce0eeb2782754d1eba3fe7a2e
#ifdef AMDGPU_FAMILY_GC_11_0_0
gpu->psMax.gen = (uint16_t) devInfo.pcie_gen;
gpu->psMax.lanes = (uint16_t) devInfo.pcie_num_lanes;
#else
gpu->psMax.gen = (uint16_t) devInfo._pad;
gpu->psMax.lanes = (uint16_t) devInfo._pad1;
#endif
#define FF_VRAM_CASE(name, value) \
case value /* AMDGPU_VRAM_TYPE_ ## name */: \
ffStrbufSetStatic(&gpu->memoryType, #name); \
break
switch (gpuInfo.vram_type) {
switch (devInfo.vram_type) {
FF_VRAM_CASE(UNKNOWN, 0);
FF_VRAM_CASE(GDDR1, 1);
FF_VRAM_CASE(DDR2, 2);
@@ -135,35 +140,40 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
FF_VRAM_CASE(DDR5, 10);
FF_VRAM_CASE(LPDDR4, 11);
FF_VRAM_CASE(LPDDR5, 12);
FF_VRAM_CASE(HBM3E, 13);
FF_VRAM_CASE(HBM4, 14);
default:
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", devInfo.vram_type);
break;
}
struct amdgpu_heap_info heapInfo;
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0) {
gpu->dedicated.total = heapInfo.heap_size;
gpu->dedicated.used = heapInfo.heap_usage;
}
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_GTT, 0, &heapInfo) >= 0) {
gpu->shared.total = heapInfo.heap_size;
gpu->shared.used = heapInfo.heap_usage;
}
#undef FF_VRAM_CASE
}
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0) {
struct drm_amdgpu_memory_info memInfo;
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
&(struct drm_amdgpu_info) {
.return_pointer = (uintptr_t) &memInfo,
.return_size = sizeof(memInfo),
.query = AMDGPU_INFO_MEMORY,
}) >= 0) {
gpu->dedicated.total = memInfo.vram.total_heap_size;
gpu->dedicated.used = memInfo.vram.heap_usage;
gpu->shared.total = memInfo.gtt.total_heap_size;
gpu->shared.used = memInfo.gtt.heap_usage;
}
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
&(struct drm_amdgpu_info) {
.return_pointer = (uintptr_t) &value,
.return_size = sizeof(value),
.query = AMDGPU_INFO_SENSOR,
.query_hw_ip.type = AMDGPU_INFO_SENSOR_GPU_LOAD,
}) >= 0) {
gpu->coreUsage = value;
}
ffamdgpu_device_deinitialize(handle);
return NULL;
#else
FF_UNUSED(options, gpu, renderPath);
return "Fastfetch is compiled without libdrm support";
#endif
}
#endif
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd) {
{
@@ -219,12 +229,12 @@ static inline int popcountBytes(uint8_t* bytes, uint32_t length) {
length -= 4;
}
if (length >= 2) {
count += __builtin_popcountl(*(uint16_t*) bytes);
count += __builtin_popcount(*(uint16_t*) bytes);
bytes += 2;
length -= 2;
}
if (length) {
count += __builtin_popcountl(*(uint8_t*) bytes);
count += __builtin_popcount(*(uint8_t*) bytes);
}
return count;
}
@@ -297,7 +307,11 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd) {
.size = sizeof(paramsGlobal),
}) >= 0) {
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
assert(paramsGlobal.num_clusters_total <= DRM_ASAHI_MAX_CLUSTERS);
gpu->coreCount = 0;
for (uint32_t i = 0; i < paramsGlobal.num_clusters_total; i++) {
gpu->coreCount += __builtin_popcountll(paramsGlobal.core_masks[i]);
}
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = ffGPUGeneral2Id(paramsGlobal.chip_id);
@@ -356,6 +370,7 @@ const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd) {
#include "gpu_driver_specific.h"
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId) {
#if !__OpenBSD__
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* soName;
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific)) {
@@ -367,14 +382,19 @@ const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult*
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.sharedMemory = options->driverSpecific ? &gpu->shared : NULL,
.memoryType = options->driverSpecific ? &gpu->memoryType : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
.psCurr = options->driverSpecific ? &gpu->psCurr : NULL,
.psMax = options->driverSpecific ? &gpu->psMax : NULL,
},
soName);
}
#endif
return "No driver-specific detection function found for the GPU vendor";
}

Some files were not shown because too many files have changed in this diff Show More