mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
98 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b79a336576 | |||
| d36e3a793b | |||
| d48bb48e4f | |||
| 835001eb2f | |||
| 5647703e4d | |||
| eff0108bb5 | |||
| 31c1431ac6 | |||
| fa2c56cb9f | |||
| 104b33c1f7 | |||
| cb4502dacc | |||
| 3dc86391ab | |||
| f5a67b25f4 | |||
| d8be61411e | |||
| 61968ca95c | |||
| 9f190b46c9 | |||
| a6aac70a5e | |||
| 3aa43212ff | |||
| 7c39b64fb4 | |||
| e1963e41be | |||
| a1d4cbf67f | |||
| f5b9e09d91 | |||
| 9742dda795 | |||
| 677c213397 | |||
| 8f0a12323b | |||
| b49f0b3d9c | |||
| bc686b2c84 | |||
| 7c2f7fa4f2 | |||
| 5fd059827d | |||
| 240928138e | |||
| 508a50f803 | |||
| bd40d8756e | |||
| b732e0c6d7 | |||
| 96685b7ebe | |||
| 49a1e42efd | |||
| b0fd11fcbd | |||
| b6127ff2c9 | |||
| f3babe3187 | |||
| e9c0d886d1 | |||
| d6a4946511 | |||
| 43e0cc22ff | |||
| c42ea6eeea | |||
| fe7962d5d2 | |||
| e84195bca0 | |||
| bf0133fe60 | |||
| 942c15b7b0 | |||
| 61a0bbcc8d | |||
| 8b3673eb38 | |||
| 22f9948497 | |||
| 107f39eb15 | |||
| 4e44c0520b | |||
| 55eb3c59d4 | |||
| 878ccf1375 | |||
| ebb0cf77bd | |||
| 17914dc29e | |||
| 14dfe171fb | |||
| 265c334399 | |||
| fc303c58db | |||
| 01e7503263 | |||
| ffd0455fe3 | |||
| 7df2ed2251 | |||
| 2edc41dd9a | |||
| cada77163e | |||
| 7cecdb0e6d | |||
| 420a9e9d7b | |||
| b96d8ad00b | |||
| 52970e2d13 | |||
| 4594734b66 | |||
| eb54c89b4a | |||
| 43301afc47 | |||
| 09e28451ec | |||
| 35c2f8c924 | |||
| 3ec7e94b47 | |||
| a720e1f945 | |||
| 70061625f7 | |||
| 5cd4316f98 | |||
| e946861eb0 | |||
| f09aebecd5 | |||
| 8f266eb2a7 | |||
| 8ee08d0067 | |||
| e936ddef6b | |||
| c706201282 | |||
| e24e3b6b29 | |||
| 135547fd50 | |||
| da05bed32f | |||
| 636471c366 | |||
| cbc84fda6c | |||
| fc7a0a8484 | |||
| 4d3b6c3b1b | |||
| 70e67177fe | |||
| 9fe7d6dbfa | |||
| a139a8c4a5 | |||
| da568c986e | |||
| 727fbc0276 | |||
| 20aabdfd78 | |||
| e79aaf5ce1 | |||
| 53c2d07161 | |||
| 6b9f594620 | |||
| ba3968784f |
+2
-2
@@ -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
|
||||
|
||||
@@ -20,12 +20,12 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.8'
|
||||
version: '7.9'
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
@@ -3,9 +3,6 @@ name: Reusable Spellcheck
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -17,8 +14,8 @@ jobs:
|
||||
- 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
|
||||
|
||||
@@ -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
@@ -1,8 +1,10 @@
|
||||
build/
|
||||
.vs/
|
||||
.vscode/
|
||||
.cache/
|
||||
.kdev4/
|
||||
/build/
|
||||
/build_*/
|
||||
/build-*/
|
||||
/.vs/
|
||||
/.vscode/
|
||||
/.cache/
|
||||
/.kdev4/
|
||||
.DS_Store
|
||||
cscope.*
|
||||
tags
|
||||
|
||||
@@ -1,3 +1,59 @@
|
||||
# 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:
|
||||
|
||||
+66
-73
@@ -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.1
|
||||
VERSION 2.65.1
|
||||
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)
|
||||
@@ -134,25 +141,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 APK APPIMAGE
|
||||
BREW
|
||||
CARDS CHOCO
|
||||
DPKG
|
||||
EMERGE EOPKG
|
||||
FLATPAK
|
||||
GUIX
|
||||
HPKG
|
||||
KISS
|
||||
LINGLONG LPKG LPKGBUILD
|
||||
MACPORTS MOSS MPORT
|
||||
NIX
|
||||
OPKG
|
||||
PACMAN PACSTALL PALUDIS PISI PKG PKGSRC 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)
|
||||
@@ -327,7 +319,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")
|
||||
@@ -447,6 +439,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
|
||||
@@ -591,11 +584,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
|
||||
@@ -752,11 +744,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
|
||||
@@ -765,6 +756,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
|
||||
@@ -847,11 +839,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
|
||||
@@ -932,11 +923,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
|
||||
@@ -944,6 +934,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
|
||||
@@ -1175,11 +1167,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
|
||||
@@ -1325,12 +1316,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
|
||||
@@ -1576,24 +1564,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()
|
||||
@@ -1638,6 +1626,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})
|
||||
@@ -1654,18 +1647,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()
|
||||
@@ -1690,18 +1683,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"
|
||||
@@ -1795,8 +1788,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})
|
||||
@@ -1809,20 +1802,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
|
||||
@@ -1979,7 +1972,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)
|
||||
@@ -1988,18 +1981,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)
|
||||
@@ -2011,19 +2004,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 "")
|
||||
@@ -2040,9 +2033,9 @@ 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 PRIVATE FF_PACKAGES_REMOVE_DISABLED=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_PACKAGES_REMOVE_DISABLED=1)
|
||||
endif()
|
||||
|
||||
######################
|
||||
|
||||
Vendored
+6
@@ -1,3 +1,9 @@
|
||||
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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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__))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+32
-23
@@ -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"
|
||||
|
||||
@@ -9,9 +9,7 @@ static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc, in
|
||||
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")
|
||||
);
|
||||
L, "yyjson: recursion depth exceeded; possible circular reference", strlen("yyjson: recursion depth exceeded; possible circular reference"));
|
||||
lua_error(L); // noreturn
|
||||
__builtin_unreachable();
|
||||
}
|
||||
@@ -140,7 +138,7 @@ static int yyjsonEncode(lua_State* L) {
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffLuaLoadState() {
|
||||
const char* ffLuaLoadState(void) {
|
||||
if (luaData.inited) {
|
||||
if (luaData.L == NULL) {
|
||||
return "Lua library is not available";
|
||||
@@ -180,6 +178,8 @@ const char* ffLuaLoadState() {
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(liblua, luaopen_string)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(liblua, luaopen_table)
|
||||
#endif
|
||||
|
||||
#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)
|
||||
@@ -208,6 +208,7 @@ const char* ffLuaLoadState() {
|
||||
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,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");
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+17
-25
@@ -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)
|
||||
|
||||
+21
-14
@@ -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,6 +27,7 @@
|
||||
#include "common/library.h"
|
||||
|
||||
extern struct FFLuaData {
|
||||
#if !FF_DISABLE_DLOPEN
|
||||
FF_LIBRARY_SYMBOL(luaL_checkany)
|
||||
FF_LIBRARY_SYMBOL(luaL_loadbufferx)
|
||||
FF_LIBRARY_SYMBOL(luaL_tolstring)
|
||||
@@ -52,13 +56,13 @@ extern struct FFLuaData {
|
||||
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);
|
||||
}
|
||||
@@ -148,11 +152,11 @@ FF_A_ALWAYS_INLINE int(lua_rawgeti)(lua_State* L, int idx, lua_Integer n) {
|
||||
}
|
||||
|
||||
FF_A_ALWAYS_INLINE
|
||||
#if LUA_VERSION_NUM > 503
|
||||
#if LUA_VERSION_NUM > 503
|
||||
lua_Unsigned
|
||||
#else
|
||||
#else
|
||||
size_t
|
||||
#endif
|
||||
#endif
|
||||
(lua_rawlen)(lua_State* L, int idx) {
|
||||
return luaData.fflua_rawlen(L, idx);
|
||||
}
|
||||
@@ -176,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,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) {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+188
-186
@@ -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_RDONLY | 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -619,19 +619,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 +635,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 +680,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 +752,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 +765,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 +778,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)) ®istryListener, 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
|
||||
-1292
File diff suppressed because it is too large
Load Diff
-176
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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
@@ -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 ffGPUFillVendorByDeviceName(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;
|
||||
}
|
||||
|
||||
+20
-2
@@ -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,6 +52,13 @@ 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;
|
||||
@@ -67,14 +80,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 +103,5 @@ static inline uint64_t ffGPUGeneral2Id(uint64_t originalId) {
|
||||
// Note: originalId may already have the MSB set
|
||||
return (1ULL << 63) | originalId;
|
||||
}
|
||||
|
||||
bool ffGPUFillVendorByDeviceName(FFGPUResult* gpu);
|
||||
|
||||
@@ -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;
|
||||
|
||||
{
|
||||
|
||||
@@ -118,6 +118,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
@@ -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);
|
||||
ffGPUFillVendorByDeviceName(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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
#if FF_HAVE_DRM
|
||||
|
||||
#include "gpu.h"
|
||||
#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) {
|
||||
perror("ioctl");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ffGPUFillVendorByDeviceName(gpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) {
|
||||
FF_UNUSED(options, gpus);
|
||||
return "Fastfetch was built without libdrm support";
|
||||
}
|
||||
|
||||
#endif // __FreeBSD__ || __OpenBSD__
|
||||
@@ -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);
|
||||
|
||||
+70
-55
@@ -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);
|
||||
@@ -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,39 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
{
|
||||
@@ -356,6 +365,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 +377,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";
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
ffGPUQueryAmdGpuName(deviceId, revision, gpu);
|
||||
|
||||
@@ -37,6 +37,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, dev.bus, dev.device, dev.function);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
ffGPUQueryAmdGpuName(dev.device_id, dev.revision, gpu);
|
||||
|
||||
@@ -16,6 +16,8 @@ struct FFIgclData {
|
||||
FF_LIBRARY_SYMBOL(ctlMemoryGetState)
|
||||
FF_LIBRARY_SYMBOL(ctlEnumFrequencyDomains)
|
||||
FF_LIBRARY_SYMBOL(ctlFrequencyGetProperties)
|
||||
FF_LIBRARY_SYMBOL(ctlPciGetProperties)
|
||||
FF_LIBRARY_SYMBOL(ctlPciGetState)
|
||||
|
||||
bool inited;
|
||||
ctl_api_handle_t apiHandle;
|
||||
@@ -43,6 +45,8 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumFrequencyDomains)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetProperties)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlPciGetProperties)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlPciGetState)
|
||||
|
||||
if (ffctlInit(&(ctl_init_args_t) {
|
||||
.AppVersion = CTL_IMPL_VERSION,
|
||||
@@ -227,5 +231,28 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
|
||||
ffStrbufSetS(result.name, properties.name);
|
||||
}
|
||||
|
||||
if (result.psMax) {
|
||||
ctl_pci_properties_t pciProps = { .Size = sizeof(pciProps), .Version = 0 };
|
||||
if (igclData.ffctlPciGetProperties(device, &pciProps) == CTL_RESULT_SUCCESS) {
|
||||
if (pciProps.maxSpeed.gen > 0) {
|
||||
result.psMax->gen = (uint16_t) pciProps.maxSpeed.gen;
|
||||
}
|
||||
if (pciProps.maxSpeed.width > 0) {
|
||||
result.psMax->lanes = (uint16_t) pciProps.maxSpeed.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.psCurr) {
|
||||
ctl_pci_state_t pciState = { .Size = sizeof(pciState), .Version = 0 };
|
||||
if (igclData.ffctlPciGetState(device, &pciState) == CTL_RESULT_SUCCESS) {
|
||||
if (pciState.speed.gen > 0) {
|
||||
result.psCurr->gen = (uint16_t) pciState.speed.gen;
|
||||
}
|
||||
if (pciState.speed.width > 0) {
|
||||
result.psCurr->lanes = (uint16_t) pciState.speed.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,40 +1,12 @@
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
#include "detection/cpu/cpu.h"
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "common/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/strutil.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "modules/gpu/option.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FF_HAVE_DRM_AMDGPU
|
||||
#include <amdgpu.h>
|
||||
#include <amdgpu_drm.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_DRM
|
||||
#include "intel_drm.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(FF_HAVE_DRM) && defined(__aarch64__)
|
||||
// https://github.com/alyssarosenzweig/linux/blob/agx-uapi-v7/include/uapi/drm/asahi_drm.h
|
||||
// Found in kernel-headers-6.14.4-400.asahi.fc42.aarch64
|
||||
#if __has_include(<drm/asahi_drm.h>)
|
||||
#include <drm/asahi_drm.h>
|
||||
#else
|
||||
#include "asahi_drm.h"
|
||||
#endif
|
||||
#define FF_HAVE_DRM_ASAHI 1
|
||||
#endif
|
||||
|
||||
static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_A_UNUSED const char* drmKey) {
|
||||
uint32_t pciDirLength = pciDir->length;
|
||||
ffStrbufAppendS(pciDir, "/driver");
|
||||
@@ -100,7 +72,6 @@ FF_A_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey, FFs
|
||||
}
|
||||
|
||||
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) {
|
||||
#if FF_HAVE_DRM
|
||||
const char* error = drmFindRenderFromCard(drmKey, buffer);
|
||||
if (error) {
|
||||
return error;
|
||||
@@ -108,17 +79,8 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult
|
||||
if (ffStrbufEqualS(&gpu->driver, "radeon")) {
|
||||
return ffDrmDetectRadeon(options, gpu, buffer->chars);
|
||||
} else {
|
||||
#if FF_HAVE_DRM_AMDGPU
|
||||
return ffDrmDetectAmdgpu(options, gpu, buffer->chars);
|
||||
#else
|
||||
FF_UNUSED(options, gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with libdrm_amdgpu support";
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
FF_UNUSED(options, gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) {
|
||||
@@ -246,7 +208,6 @@ static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu
|
||||
}
|
||||
|
||||
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) {
|
||||
#if FF_HAVE_DRM
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
|
||||
@@ -260,10 +221,6 @@ static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey,
|
||||
return ffDrmDetectI915(gpu, fd);
|
||||
}
|
||||
return "Unknown Intel GPU driver";
|
||||
#else
|
||||
FF_UNUSED(gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) {
|
||||
@@ -294,7 +251,6 @@ static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult
|
||||
}
|
||||
|
||||
static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) {
|
||||
#if FF_HAVE_DRM
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
|
||||
@@ -303,10 +259,6 @@ static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey
|
||||
}
|
||||
|
||||
return ffDrmDetectNouveau(gpu, fd);
|
||||
#else
|
||||
FF_UNUSED(gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) {
|
||||
@@ -351,6 +303,32 @@ static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult*
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline uint16_t pcieLinkSpeedToGen(const FFstrbuf* buffer) {
|
||||
int64_t speed = ffStrbufToSInt(buffer, FF_GPU_PCIE_SPEED_UNSET);
|
||||
if (speed >= 64) {
|
||||
return 6;
|
||||
} else if (speed >= 32) {
|
||||
return 5;
|
||||
} else if (speed >= 16) {
|
||||
return 4;
|
||||
} else if (speed >= 8) {
|
||||
return 3;
|
||||
} else if (speed >= 5) {
|
||||
return 2;
|
||||
} else if (speed >= 2) { // 2.5
|
||||
return 1;
|
||||
}
|
||||
return FF_GPU_PCIE_SPEED_UNSET;
|
||||
}
|
||||
|
||||
static inline uint16_t pcieWidthToLanes(const FFstrbuf* buffer) {
|
||||
int64_t width = ffStrbufToSInt(buffer, FF_GPU_PCIE_SPEED_UNSET);
|
||||
if (width > 0 && width < 255) { // kernel returns 255 if the value is unknown
|
||||
return (uint16_t) width;
|
||||
}
|
||||
return FF_GPU_PCIE_SPEED_UNSET;
|
||||
}
|
||||
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) {
|
||||
const uint32_t drmDirPathLength = deviceDir->length;
|
||||
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
|
||||
@@ -406,6 +384,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(pciDomain, pciBus, pciDevice, pciFunc);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
char drmKeyBuffer[8];
|
||||
if (!drmKey) {
|
||||
@@ -431,6 +410,34 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey);
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
|
||||
ffStrbufAppendS(deviceDir, "/max_link_speed");
|
||||
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
|
||||
gpu->psMax.gen = pcieLinkSpeedToGen(buffer);
|
||||
}
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
|
||||
if (gpu->psMax.gen != FF_GPU_PCIE_SPEED_UNSET) {
|
||||
ffStrbufAppendS(deviceDir, "/max_link_width");
|
||||
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
|
||||
gpu->psMax.lanes = pcieWidthToLanes(buffer);
|
||||
}
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(deviceDir, "/current_link_speed");
|
||||
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
|
||||
gpu->psCurr.gen = pcieLinkSpeedToGen(buffer);
|
||||
}
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
|
||||
if (gpu->psCurr.gen != FF_GPU_PCIE_SPEED_UNSET) {
|
||||
ffStrbufAppendS(deviceDir, "/current_link_width");
|
||||
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
|
||||
gpu->psCurr.lanes = pcieWidthToLanes(buffer);
|
||||
}
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
}
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
bool ok = false;
|
||||
if (drmKey && options->driverSpecific) {
|
||||
@@ -478,24 +485,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
ffGPUFillVendorByDeviceName(gpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if __aarch64__
|
||||
#include "detection/cpu/cpu.h"
|
||||
|
||||
FF_A_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FF_A_UNUSED FFstrbuf* buffer, FF_A_UNUSED const char* drmKey) {
|
||||
if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1) {
|
||||
@@ -503,14 +499,12 @@ FF_A_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const ch
|
||||
}
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
|
||||
#if FF_HAVE_DRM_ASAHI
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
return ffDrmDetectAsahi(gpu, fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -542,6 +536,7 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey);
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
|
||||
|
||||
@@ -8,12 +8,16 @@ struct FFNvmlData {
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByIndex_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByPciBusId_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetPciInfo_v3)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperatureV)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxPcieLinkGeneration)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxPcieLinkWidth)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetCurrPcieLinkGeneration)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetCurrPcieLinkWidth)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetIndex)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetName)
|
||||
@@ -154,11 +158,15 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByIndex_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByPciBusId_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetPciInfo_v3)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperatureV)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxPcieLinkGeneration)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxPcieLinkWidth)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCurrPcieLinkGeneration)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCurrPcieLinkWidth)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetIndex)
|
||||
@@ -246,9 +254,12 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
}
|
||||
|
||||
if (result.temp) {
|
||||
uint32_t value;
|
||||
if (nvmlData.ffnvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &value) == NVML_SUCCESS) {
|
||||
*result.temp = value;
|
||||
nvmlTemperature_v1_t temp = {
|
||||
.version = nvmlTemperature_v1,
|
||||
.sensorType = NVML_TEMPERATURE_GPU,
|
||||
};
|
||||
if (nvmlData.ffnvmlDeviceGetTemperatureV(device, &temp) == NVML_SUCCESS) {
|
||||
*result.temp = temp.temperature;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,6 +299,26 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
}
|
||||
}
|
||||
|
||||
if (result.psMax) {
|
||||
unsigned int value;
|
||||
if (nvmlData.ffnvmlDeviceGetMaxPcieLinkGeneration(device, &value) == NVML_SUCCESS) {
|
||||
result.psMax->gen = (uint16_t) value;
|
||||
}
|
||||
if (nvmlData.ffnvmlDeviceGetMaxPcieLinkWidth(device, &value) == NVML_SUCCESS) {
|
||||
result.psMax->lanes = (uint16_t) value;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.psCurr) {
|
||||
unsigned int value;
|
||||
if (nvmlData.ffnvmlDeviceGetCurrPcieLinkGeneration(device, &value) == NVML_SUCCESS) {
|
||||
result.psCurr->gen = (uint16_t) value;
|
||||
}
|
||||
if (nvmlData.ffnvmlDeviceGetCurrPcieLinkWidth(device, &value) == NVML_SUCCESS) {
|
||||
result.psCurr->lanes = (uint16_t) value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
#else
|
||||
|
||||
@@ -27,7 +27,7 @@ static inline int pciReadConf(int fd, uint8_t bus, uint8_t device, uint8_t func,
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpus) {
|
||||
const char* detectByPci(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpus) {
|
||||
char pciDevPath[] = "/dev/pci0";
|
||||
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
|
||||
if (pcifd < 0) {
|
||||
@@ -86,6 +86,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
|
||||
@@ -99,3 +100,16 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
|
||||
#if FF_HAVE_DRM
|
||||
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO) {
|
||||
ffGPUDetectByDrmBSD(options, gpus);
|
||||
if (gpus->length > 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return detectByPci(options, gpus);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/memrchr.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef __FreeBSD__
|
||||
@@ -22,9 +23,6 @@
|
||||
#include "fastfetch_amdgpuids.c.inc"
|
||||
#endif
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
static const FFstrbuf* loadPciIds() {
|
||||
static FFstrbuf pciids;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ static int walkDevTree(di_node_t node, FF_A_UNUSED di_minor_t minor, FFlist* gpu
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = strtoul(di_bus_addr(node), NULL, 16);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
int* revId;
|
||||
|
||||
@@ -11,31 +11,28 @@
|
||||
#if _WIN32
|
||||
#include "common/windows/unicode.h"
|
||||
#include "common/windows/registry.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#if FF_WIN81_COMPAT
|
||||
#include "common/mallocHelper.h"
|
||||
#include <windows.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <devguid.h>
|
||||
#define INITGUID
|
||||
#include <windows.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <devguid.h>
|
||||
#include <pciprop.h>
|
||||
|
||||
#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in <devguid.h>
|
||||
#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in <devguid.h>
|
||||
|
||||
static bool queryDeviceIdsFallback(D3DKMT_ADAPTERADDRESS adapterAddress, D3DKMT_DEVICE_IDS* outDeviceIds) {
|
||||
FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS failed. Attempting queryDeviceIdsFallback: bus=%u device=%u function=%u",
|
||||
adapterAddress.BusNumber,
|
||||
adapterAddress.DeviceNumber,
|
||||
adapterAddress.FunctionNumber);
|
||||
|
||||
if (adapterAddress.BusNumber == -1u) {
|
||||
FF_DEBUG("Invalid adapter address, cannot query device IDs");
|
||||
return false;
|
||||
}
|
||||
static bool queryPciDeviceInfo(FFGPUResult* gpu, D3DKMT_DEVICE_IDS* outDeviceIds) {
|
||||
FF_DEBUG("Query PCI device info: %08llX", gpu->deviceId);
|
||||
|
||||
static FFlist deviceIdsCache;
|
||||
static bool initialized;
|
||||
typedef struct {
|
||||
uint32_t currentLinkSpeed;
|
||||
uint32_t currentLinkWidth;
|
||||
uint32_t maxLinkSpeed;
|
||||
uint32_t maxLinkWidth;
|
||||
D3DKMT_DEVICE_IDS deviceIds;
|
||||
D3DKMT_ADAPTERADDRESS adapterAddress;
|
||||
uint64_t adapterAddress;
|
||||
} CacheEntry;
|
||||
|
||||
if (!initialized) {
|
||||
@@ -79,34 +76,29 @@ static bool queryDeviceIdsFallback(D3DKMT_ADAPTERADDRESS adapterAddress, D3DKMT_
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t pciBus = 0;
|
||||
CacheEntry* entry = FF_LIST_ADD(CacheEntry, deviceIdsCache);
|
||||
*entry = (CacheEntry) {};
|
||||
|
||||
// L"PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1\\4&3674a6b9&0&0008"
|
||||
if (swscanf(devId + 4, L"VEN_%x&DEV_%x&SUBSYS_%4x%4x&REV_%x", &entry->deviceIds.VendorID, &entry->deviceIds.DeviceID, &entry->deviceIds.SubSystemID, &entry->deviceIds.SubVendorID, &entry->deviceIds.RevisionID) >= 2) {
|
||||
FF_DEBUG("Parsed PCI IDs - Vendor: 0x%04x, Device: 0x%04x, SubVendor: 0x%04x, SubSystem: 0x%04x, Rev: 0x%04x", entry->deviceIds.VendorID, entry->deviceIds.DeviceID, entry->deviceIds.SubVendorID, entry->deviceIds.SubSystemID, entry->deviceIds.RevisionID);
|
||||
// I thought it was DXGKMDT_OPM_BUS_TYPE_PCI, but it turns out to be false
|
||||
// Who TF knows what 1 actually means. It's just reported by most graphic cards
|
||||
// And yeah, DXGKMDT_OPM_BUS_TYPE_PCIEXPRESS (3) exists
|
||||
entry->deviceIds.BusType = 1;
|
||||
} else {
|
||||
FF_DEBUG("Failed to parse PCI IDs from device ID string");
|
||||
deviceIdsCache.length--; // remove the cache entry since it's not valid
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t pciBus = 0;
|
||||
ULONG pciBufLen = sizeof(pciBus);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_BUSNUMBER, NULL, &pciBus, &pciBufLen, 0) == CR_SUCCESS) {
|
||||
uint32_t pciAddr = 0;
|
||||
pciBufLen = sizeof(pciAddr);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_ADDRESS, NULL, &pciAddr, &pciBufLen, 0) == CR_SUCCESS) {
|
||||
CacheEntry* entry = FF_LIST_ADD(CacheEntry, deviceIdsCache);
|
||||
|
||||
entry->deviceIds = (D3DKMT_DEVICE_IDS) {};
|
||||
// L"PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1\\4&3674a6b9&0&0008"
|
||||
if (swscanf(devId + 4, L"VEN_%x&DEV_%x&SUBSYS_%4x%4x&REV_%x", &entry->deviceIds.VendorID, &entry->deviceIds.DeviceID, &entry->deviceIds.SubSystemID, &entry->deviceIds.SubVendorID, &entry->deviceIds.RevisionID) >= 2) {
|
||||
FF_DEBUG("Parsed PCI IDs - Vendor: 0x%04x, Device: 0x%04x, SubVendor: 0x%04x, SubSystem: 0x%04x, Rev: 0x%04x", entry->deviceIds.VendorID, entry->deviceIds.DeviceID, entry->deviceIds.SubVendorID, entry->deviceIds.SubSystemID, entry->deviceIds.RevisionID);
|
||||
// I thought it was DXGKMDT_OPM_BUS_TYPE_PCI, but it turns out to be false
|
||||
// Who TF knows what 1 actually means. It's just reported by most graphic cards
|
||||
// And yeah, DXGKMDT_OPM_BUS_TYPE_PCIEXPRESS (3) exists
|
||||
entry->deviceIds.BusType = 1;
|
||||
} else {
|
||||
FF_DEBUG("Failed to parse PCI IDs from device ID string");
|
||||
deviceIdsCache.length--; // remove the cache entry since it's not valid
|
||||
continue;
|
||||
}
|
||||
|
||||
entry->adapterAddress = (D3DKMT_ADAPTERADDRESS) {
|
||||
.BusNumber = pciBus,
|
||||
.DeviceNumber = (pciAddr >> 16) & 0xFFFF,
|
||||
.FunctionNumber = pciAddr & 0xFFFF,
|
||||
};
|
||||
entry->adapterAddress = ffGPUPciAddr2Id(0, pciBus, (pciAddr >> 16) & 0xFFFF, pciAddr & 0xFFFF);
|
||||
FF_DEBUG("Cached device IDs for PCI bus %u: vendor=0x%04x device=0x%04x", pciBus, entry->deviceIds.VendorID, entry->deviceIds.DeviceID);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCI address");
|
||||
@@ -114,21 +106,65 @@ static bool queryDeviceIdsFallback(D3DKMT_ADAPTERADDRESS adapterAddress, D3DKMT_
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCI bus number");
|
||||
}
|
||||
|
||||
DEVPROPTYPE propType;
|
||||
|
||||
pciBufLen = sizeof(entry->maxLinkSpeed);
|
||||
// Reports PCEe gen despite the PKEY name
|
||||
CONFIGRET ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_MaxLinkSpeed, &propType, (PBYTE) &entry->maxLinkSpeed, &pciBufLen, 0);
|
||||
if (ret == CR_SUCCESS) {
|
||||
FF_DEBUG("PCIe max GEN: %u", entry->maxLinkSpeed);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCIe max GEN: %s", ffDebugConfigRet(ret));
|
||||
}
|
||||
|
||||
if (entry->maxLinkSpeed != FF_GPU_PCIE_SPEED_UNSET) {
|
||||
pciBufLen = sizeof(entry->maxLinkWidth);
|
||||
ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_MaxLinkWidth, &propType, (PBYTE) &entry->maxLinkWidth, &pciBufLen, 0);
|
||||
if (ret == CR_SUCCESS) {
|
||||
FF_DEBUG("PCIe max link width: %u", entry->maxLinkWidth);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCIe max link width: %s", ffDebugConfigRet(ret));
|
||||
}
|
||||
}
|
||||
|
||||
pciBufLen = sizeof(entry->currentLinkSpeed);
|
||||
ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_CurrentLinkSpeed, &propType, (PBYTE) &entry->currentLinkSpeed, &pciBufLen, 0);
|
||||
if (ret == CR_SUCCESS) {
|
||||
FF_DEBUG("PCIe GEN: %u", entry->currentLinkSpeed);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCIe GEN: %s", ffDebugConfigRet(ret));
|
||||
}
|
||||
|
||||
if (entry->currentLinkSpeed != FF_GPU_PCIE_SPEED_UNSET) {
|
||||
pciBufLen = sizeof(entry->currentLinkWidth);
|
||||
ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_CurrentLinkWidth, &propType, (PBYTE) &entry->currentLinkWidth, &pciBufLen, 0);
|
||||
if (ret == CR_SUCCESS) {
|
||||
FF_DEBUG("PCIe current link width: %u", entry->currentLinkWidth);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCIe current link width: %s", ffDebugConfigRet(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH (CacheEntry, entry, deviceIdsCache) {
|
||||
if (memcmp(&entry->adapterAddress, &adapterAddress, sizeof(adapterAddress)) == 0) {
|
||||
FF_DEBUG("Cache hit for adapter address: bus=%u device=%u function=%u", adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber);
|
||||
*outDeviceIds = entry->deviceIds;
|
||||
if (gpu->deviceId == entry->adapterAddress) {
|
||||
FF_DEBUG("Cache hit for adapter address: %08llX", gpu->deviceId);
|
||||
if (outDeviceIds->VendorID != -1u) {
|
||||
*outDeviceIds = entry->deviceIds;
|
||||
}
|
||||
gpu->psMax.gen = (uint16_t) entry->maxLinkSpeed;
|
||||
gpu->psMax.lanes = (uint16_t) entry->maxLinkWidth;
|
||||
gpu->psCurr.gen = (uint16_t) entry->currentLinkSpeed;
|
||||
gpu->psCurr.lanes = (uint16_t) entry->currentLinkWidth;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FF_DEBUG("Cache miss for adapter address: bus=%u device=%u function=%u", adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber);
|
||||
FF_DEBUG("Cache miss for adapter address: %08llX", gpu->deviceId);
|
||||
return false;
|
||||
}
|
||||
#endif // FF_WIN81_COMPAT
|
||||
|
||||
static bool queryVendorNameViaRegistry(FFstrbuf* vendor, D3DKMT_HANDLE hAdapter) {
|
||||
// `KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID` reports the GUID value used by the adapter's registry key (DirectX and Video)
|
||||
@@ -278,6 +314,7 @@ ffGPUDetectWsl2
|
||||
: adapterType.HybridDiscrete
|
||||
? FF_GPU_TYPE_DISCRETE
|
||||
: FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
D3DKMT_DRIVERVERSION wddmVersion = KMT_DRIVERVERSION_WDDM_2_0;
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
@@ -323,11 +360,7 @@ ffGPUDetectWsl2
|
||||
.pPrivateDriverData = &deviceIds,
|
||||
.PrivateDriverDataSize = sizeof(deviceIds),
|
||||
});
|
||||
if (NT_SUCCESS(status)
|
||||
#if FF_WIN81_COMPAT
|
||||
|| queryDeviceIdsFallback(adapterAddress, &deviceIds.DeviceIds)
|
||||
#endif
|
||||
) {
|
||||
if (NT_SUCCESS(status)) {
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(deviceIds.DeviceIds.VendorID));
|
||||
FF_DEBUG("Adapter #%u vendor/device IDs: vendor=0x%04x device=0x%04x",
|
||||
i,
|
||||
@@ -338,6 +371,14 @@ ffGPUDetectWsl2
|
||||
FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS query failed for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
if (adapterAddress.BusNumber != -1u) {
|
||||
if (queryPciDeviceInfo(gpu, &deviceIds.DeviceIds) && gpu->vendor.length == 0) {
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(deviceIds.DeviceIds.VendorID));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
D3DKMT_UMD_DRIVER_VERSION umdDriverVersion;
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
@@ -389,8 +430,10 @@ ffGPUDetectWsl2
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
|
||||
.type = &gpu->type,
|
||||
.name = &gpu->name,
|
||||
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
|
||||
.name = &gpu->name,
|
||||
.psCurr = options->driverSpecific ? &gpu->psCurr : NULL,
|
||||
.psMax = options->driverSpecific ? &gpu->psMax : NULL,
|
||||
},
|
||||
dllName);
|
||||
FF_DEBUG("Driver-specific detection completed: %s", error ?: "Success");
|
||||
@@ -553,25 +596,8 @@ ffGPUDetectWsl2
|
||||
}
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
|
||||
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);
|
||||
if (ffGPUFillVendorByDeviceName(gpu)) {
|
||||
// OK
|
||||
}
|
||||
#if _WIN32
|
||||
else if (ffIsWindows10OrGreater()) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv412ctl_result_t
|
||||
typedef enum ctl_result_t {
|
||||
@@ -73,7 +74,7 @@ typedef struct ctl_adapter_bdf_t {
|
||||
} ctl_adapter_bdf_t;
|
||||
|
||||
#define IGCL_CTL_MAX_DEVICE_NAME_LEN 100
|
||||
#define IGCL_CTL_MAX_RESERVED_SIZE 112
|
||||
#define IGCL_CTL_MAX_RESERVED_SIZE 108
|
||||
|
||||
typedef enum ctl_adapter_properties_flag_t {
|
||||
CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED = 1,
|
||||
@@ -101,6 +102,7 @@ typedef struct ctl_device_adapter_properties_t {
|
||||
uint16_t pci_subsys_id;
|
||||
uint16_t pci_subsys_vendor_id;
|
||||
ctl_adapter_bdf_t adapter_bdf;
|
||||
uint32_t num_xe_cores;
|
||||
char reserved[IGCL_CTL_MAX_RESERVED_SIZE];
|
||||
} ctl_device_adapter_properties_t;
|
||||
|
||||
@@ -214,3 +216,45 @@ typedef struct ctl_freq_properties_t {
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv425ctlFrequencyGetProperties17ctl_freq_handle_tP21ctl_freq_properties_t
|
||||
extern ctl_result_t ctlFrequencyGetProperties(ctl_freq_handle_t hFrequency, ctl_freq_properties_t* pProperties);
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv415ctl_pci_speed_t
|
||||
typedef struct ctl_pci_speed_t {
|
||||
uint32_t Size;
|
||||
uint8_t Version;
|
||||
int32_t gen;
|
||||
int32_t width;
|
||||
int64_t maxBandwidth;
|
||||
} ctl_pci_speed_t;
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctl_pci_address_t
|
||||
typedef struct ctl_pci_address_t {
|
||||
uint32_t Size;
|
||||
uint8_t Version;
|
||||
uint32_t domain;
|
||||
uint32_t bus;
|
||||
uint32_t device;
|
||||
uint32_t function;
|
||||
} ctl_pci_address_t;
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctl_pci_properties_t
|
||||
typedef struct ctl_pci_properties_t {
|
||||
uint32_t Size;
|
||||
uint8_t Version;
|
||||
ctl_pci_address_t address;
|
||||
ctl_pci_speed_t maxSpeed;
|
||||
bool resizable_bar_supported;
|
||||
bool resizable_bar_enabled;
|
||||
} ctl_pci_properties_t;
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlpcigetproperties
|
||||
extern ctl_result_t ctlPciGetProperties(ctl_device_adapter_handle_t hDAhandle, ctl_pci_properties_t* pProperties);
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctl-pci-state-t
|
||||
typedef struct _ctl_pci_state_t {
|
||||
uint32_t Size;
|
||||
uint8_t Version;
|
||||
ctl_pci_speed_t speed;
|
||||
} ctl_pci_state_t;
|
||||
|
||||
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlpcigetstate
|
||||
extern ctl_result_t ctlPciGetState(ctl_device_adapter_handle_t hDAhandle, ctl_pci_state_t* pState);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
#include <drm.h>
|
||||
#if __has_include(<drm.h>)
|
||||
#include <drm.h>
|
||||
#else
|
||||
#include <drm/drm.h>
|
||||
#endif
|
||||
|
||||
// xe_drm.h
|
||||
|
||||
|
||||
+60
-21
@@ -4,6 +4,8 @@
|
||||
// THIS FILE IS CREATED FROM SCRATCH, BY READING THE OFFICIAL NVML API
|
||||
// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT.
|
||||
|
||||
// https://docs.nvidia.com/deploy/pdf/NVML_API_Reference_Guide.pdf
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceStructs.html
|
||||
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE 32
|
||||
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE 16
|
||||
@@ -11,6 +13,7 @@
|
||||
|
||||
typedef enum { NVML_SUCCESS = 0 } nvmlReturn_t;
|
||||
typedef struct nvmlDevice_t* nvmlDevice_t;
|
||||
#define NVML_STRUCT_VERSION(data, ver) (unsigned int)(sizeof(nvml##data##_v##ver##_t) | (ver << 24U))
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/structnvmlPciInfo__t.html
|
||||
// PCI information about a GPU device
|
||||
@@ -54,7 +57,6 @@ typedef struct {
|
||||
unsigned long long used;
|
||||
} nvmlMemory_v2_t;
|
||||
// https://github.com/NVIDIA/nvidia-settings/issues/78#issuecomment-1012837988
|
||||
enum { nvmlMemory_v2 = (unsigned int) (sizeof(nvmlMemory_v2_t) | (2 << 24U)) };
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/structnvmlMemory__t.html#structnvmlMemory__t
|
||||
// Memory allocation information for a device (v1)
|
||||
@@ -117,36 +119,73 @@ typedef struct
|
||||
unsigned int memory;
|
||||
} nvmlUtilization_t;
|
||||
|
||||
typedef struct {
|
||||
// v1
|
||||
unsigned int version;
|
||||
// input
|
||||
nvmlTemperatureSensors_t sensorType;
|
||||
// output
|
||||
int temperature;
|
||||
} nvmlTemperature_v1_t;
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlInitializationAndCleanup.html#group__nvmlInitializationAndCleanup
|
||||
// Initialize NVML, but don't initialize any GPUs yet
|
||||
nvmlReturn_t nvmlInit_v2(void);
|
||||
extern nvmlReturn_t nvmlInit_v2(void);
|
||||
// Shut down NVML by releasing all GPU resources previously allocated with nvmlInit_v2()
|
||||
nvmlReturn_t nvmlShutdown(void);
|
||||
extern nvmlReturn_t nvmlShutdown(void);
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceQueries.html
|
||||
|
||||
// v545
|
||||
// Retrieves the PCI attributes of this device
|
||||
extern nvmlReturn_t nvmlDeviceGetPciInfo_v3(nvmlDevice_t device, nvmlPciInfo_t* pci);
|
||||
|
||||
// v510
|
||||
// Gets the device's core count
|
||||
extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores);
|
||||
// Retrieves the amount of used, free, reserved and total memory available on the device, in bytes. The reserved amount is supported on version 2 only
|
||||
extern nvmlReturn_t nvmlDeviceGetMemoryInfo_v2(nvmlDevice_t device, nvmlMemory_v2_t* memory);
|
||||
|
||||
// v361
|
||||
// Retrieves the maximum clock speeds for the device
|
||||
extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int* clock);
|
||||
|
||||
// v340
|
||||
// Retrieves the brand of this device
|
||||
extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type);
|
||||
|
||||
// v5.319 RC
|
||||
// Retrieves the number of compute devices in the system. A compute device is a single GPU
|
||||
extern nvmlReturn_t nvmlDeviceGetCount_v2(unsigned int* deviceCount);
|
||||
// Acquire the handle for a particular device, based on its index
|
||||
extern nvmlReturn_t nvmlDeviceGetHandleByIndex_v2(unsigned int index, nvmlDevice_t* device);
|
||||
// Acquire the handle for a particular device, based on its PCI bus id
|
||||
extern nvmlReturn_t nvmlDeviceGetHandleByPciBusId_v2(const char* pciBusId, nvmlDevice_t* device);
|
||||
// Retrieves the PCI attributes of this device
|
||||
extern nvmlReturn_t nvmlDeviceGetPciInfo_v3(nvmlDevice_t device, nvmlPciInfo_t* pci);
|
||||
// Retrieves the current temperature readings for the device, in degrees C
|
||||
extern nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int* temp);
|
||||
// Retrieves the amount of used, free, reserved and total memory available on the device, in bytes. The reserved amount is supported on version 2 only
|
||||
extern nvmlReturn_t nvmlDeviceGetMemoryInfo_v2(nvmlDevice_t device, nvmlMemory_v2_t* memory);
|
||||
// Retrieves the amount of used, free, total memory available on the device, in bytes.
|
||||
extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t* memory);
|
||||
// Gets the device's core count
|
||||
extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores);
|
||||
// Retrieves the maximum clock speeds for the device
|
||||
extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int* clock);
|
||||
// Retrieves the brand of this device
|
||||
extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type);
|
||||
// Retrieves the current utilization rates for the device
|
||||
extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t* utilization);
|
||||
// Retrieves the globally unique immutable UUID associated with this device, as a 5 part hexadecimal string, that augments the immutable, board serial identifier.
|
||||
extern nvmlReturn_t nvmlDeviceGetIndex(nvmlDevice_t device, unsigned int* index);
|
||||
|
||||
// v3.295
|
||||
// Retrieves the maximum PCIe link generation possible with this device and system
|
||||
extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkGeneration(nvmlDevice_t device, unsigned int* maxLinkGen);
|
||||
// Retrieves the maximum PCIe link width possible with this device and system
|
||||
extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkWidth(nvmlDevice_t device, unsigned int* maxLinkWidth);
|
||||
// Retrieves the current PCIe link generation
|
||||
extern nvmlReturn_t nvmlDeviceGetCurrPcieLinkGeneration(nvmlDevice_t device, unsigned int* currLinkGen);
|
||||
// Retrieves the current PCIe link width
|
||||
extern nvmlReturn_t nvmlDeviceGetCurrPcieLinkWidth(nvmlDevice_t device, unsigned int* currLinkWidth);
|
||||
|
||||
// v0
|
||||
// Acquire the handle for a particular device, based on its PCI bus id
|
||||
extern nvmlReturn_t nvmlDeviceGetHandleByPciBusId_v2(const char* pciBusId, nvmlDevice_t* device);
|
||||
// Retrieves the amount of used, free, total memory available on the device, in bytes.
|
||||
extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t* memory);
|
||||
// Retrieves the current utilization rates for the device
|
||||
extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t* utilization);
|
||||
// Retrieves the name of this device.
|
||||
extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char* name, unsigned int length);
|
||||
// Retrieves the current temperature readings (in degrees C) for the given device
|
||||
extern nvmlReturn_t nvmlDeviceGetTemperatureV(nvmlDevice_t device, nvmlTemperature_v1_t* temperature);
|
||||
|
||||
|
||||
enum {
|
||||
nvmlMemory_v2 = NVML_STRUCT_VERSION(Memory, 2),
|
||||
nvmlTemperature_v1 = NVML_STRUCT_VERSION(Temperature, 1),
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "libc.h"
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <features.h>
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "libc.h"
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <features.h>
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) {
|
||||
gpu->deviceId = (size_t) deviceID;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) {
|
||||
ffStrbufSetS(&gpu->platformApi, buffer);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "opengl.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/library.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#if __has_include(<GL/gl.h>)
|
||||
#include <GL/gl.h>
|
||||
@@ -34,8 +35,6 @@ void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglG
|
||||
|
||||
typedef struct EGLData {
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
FF_LIBRARY_SYMBOL(eglGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(eglGetDisplay)
|
||||
FF_LIBRARY_SYMBOL(eglQueryString)
|
||||
FF_LIBRARY_SYMBOL(eglInitialize)
|
||||
FF_LIBRARY_SYMBOL(eglBindAPI)
|
||||
@@ -132,38 +131,7 @@ static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data) {
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleData(FFOpenGLResult* result, EGLData* data) {
|
||||
FF_DEBUG("Resolving glGetString via eglGetProcAddress()");
|
||||
data->ffglGetString = (__typeof__(&glGetString)) data->ffeglGetProcAddress("glGetString");
|
||||
if (!data->ffglGetString) {
|
||||
FF_DEBUG("eglGetProcAddress('glGetString') returned NULL");
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
}
|
||||
|
||||
#if EGL_VERSION_1_5
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC ffeglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC) data->ffeglGetProcAddress("eglGetPlatformDisplay");
|
||||
if (ffeglGetPlatformDisplay) {
|
||||
FF_DEBUG("Trying eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA)");
|
||||
data->display = ffeglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, NULL, NULL);
|
||||
FF_DEBUG("eglGetPlatformDisplay() %s", data->display == EGL_NO_DISPLAY ? "failed" : "succeeded");
|
||||
} else {
|
||||
FF_DEBUG("eglGetPlatformDisplay is unavailable, falling back to eglGetDisplay");
|
||||
}
|
||||
|
||||
if (!ffeglGetPlatformDisplay || data->display == EGL_NO_DISPLAY)
|
||||
#endif
|
||||
|
||||
{
|
||||
FF_DEBUG("Trying eglGetDisplay(EGL_DEFAULT_DISPLAY)");
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (data->display == EGL_NO_DISPLAY) {
|
||||
FF_DEBUG("eglGetDisplay() returned EGL_NO_DISPLAY");
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
}
|
||||
|
||||
FF_DEBUG("eglGetDisplay() succeeded");
|
||||
}
|
||||
|
||||
static const char* eglHandlePreDisplay(FFOpenGLResult* result, EGLData* data) {
|
||||
EGLint major, minor;
|
||||
if (data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE) {
|
||||
FF_DEBUG("eglInitialize() returned EGL_FALSE");
|
||||
@@ -185,8 +153,7 @@ const char* ffOpenGLDetectByEGL(FFOpenGLResult* result) {
|
||||
EGLData eglData;
|
||||
|
||||
FF_LIBRARY_LOAD_MESSAGE(egl, "libEGL" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(egl, eglGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglQueryString);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglBindAPI);
|
||||
@@ -198,12 +165,50 @@ const char* ffOpenGLDetectByEGL(FFOpenGLResult* result) {
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
|
||||
|
||||
FF_DEBUG("Resolving glGetString via eglGetProcAddress()");
|
||||
eglData.ffglGetString = (__typeof__(&glGetString)) ffeglGetProcAddress("glGetString");
|
||||
if (!eglData.ffglGetString) {
|
||||
FF_DEBUG("eglGetProcAddress('glGetString') returned NULL");
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
}
|
||||
|
||||
FF_DEBUG("Loaded EGL library and required symbols");
|
||||
|
||||
FF_SUPPRESS_IO();
|
||||
FF_DEBUG("Suppressed stdout/stderr during EGL probing");
|
||||
|
||||
const char* error = eglHandleData(result, &eglData);
|
||||
EGLDisplay display = EGL_NO_DISPLAY;
|
||||
#if EGL_VERSION_1_5
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC ffeglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC) ffeglGetProcAddress("eglGetPlatformDisplay");
|
||||
if (!ffeglGetPlatformDisplay) {
|
||||
ffeglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC) ffeglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||
}
|
||||
if (ffeglGetPlatformDisplay) {
|
||||
FF_DEBUG("Trying eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA)");
|
||||
display = ffeglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, NULL);
|
||||
FF_DEBUG("eglGetPlatformDisplay() %s", display == EGL_NO_DISPLAY ? "failed" : "succeeded");
|
||||
} else {
|
||||
FF_DEBUG("eglGetPlatformDisplay is unavailable, falling back to eglGetDisplay");
|
||||
}
|
||||
|
||||
if (display == EGL_NO_DISPLAY)
|
||||
#endif
|
||||
|
||||
{
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(egl, eglGetDisplay);
|
||||
|
||||
FF_DEBUG("Trying eglGetDisplay(EGL_DEFAULT_DISPLAY)");
|
||||
display = ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
FF_DEBUG("eglGetDisplay() returned EGL_NO_DISPLAY");
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
}
|
||||
|
||||
FF_DEBUG("eglGetDisplay() succeeded");
|
||||
}
|
||||
eglData.display = display;
|
||||
|
||||
const char* error = eglHandlePreDisplay(result, &eglData);
|
||||
|
||||
FF_DEBUG("OpenGL detection via EGL returns: %s", error ?: "success");
|
||||
|
||||
return error;
|
||||
|
||||
@@ -44,6 +44,7 @@ static bool detectOSCodeName(FFOSResult* os)
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 27: ffStrbufSetStatic(&os->codename, "Golden Gate"); return true;
|
||||
case 26:
|
||||
case 16: ffStrbufSetStatic(&os->codename, "Tahoe"); return true;
|
||||
case 15: ffStrbufSetStatic(&os->codename, "Sequoia"); return true;
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
static bool parseLsbRelease(const char* fileName, FFOSResult* result) {
|
||||
return ffParsePropFileValues(fileName, 4, (FFpropquery[]) {
|
||||
{ "DISTRIB_ID =", &result->id },
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef struct FFPackagesResult {
|
||||
uint32_t guixUser;
|
||||
uint32_t hpkgSystem;
|
||||
uint32_t hpkgUser;
|
||||
uint32_t installrelease;
|
||||
uint32_t kiss;
|
||||
uint32_t linglong;
|
||||
uint32_t lpkg;
|
||||
@@ -40,6 +41,7 @@ typedef struct FFPackagesResult {
|
||||
uint32_t pkg;
|
||||
uint32_t pkgsrc;
|
||||
uint32_t pkgtool;
|
||||
uint32_t porg;
|
||||
uint32_t rpm;
|
||||
uint32_t scoopGlobal;
|
||||
uint32_t scoopUser;
|
||||
|
||||
@@ -84,7 +84,7 @@ static uint32_t countFilesRecursiveImpl(FFstrbuf* baseDirPath, const char* filen
|
||||
return 1;
|
||||
}
|
||||
|
||||
DIR* dirp = opendir(baseDirPath->chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDirPath->chars);
|
||||
if (dirp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -106,7 +106,6 @@ static uint32_t countFilesRecursiveImpl(FFstrbuf* baseDirPath, const char* filen
|
||||
ffStrbufSubstrBefore(baseDirPath, baseDirPathLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
return sum;
|
||||
}
|
||||
|
||||
@@ -138,7 +137,7 @@ static uint32_t getNumElementsBySuffix(FFstrbuf* baseDir, const char* dirname, c
|
||||
}
|
||||
|
||||
static uint32_t getXBPSImpl(FFstrbuf* baseDir) {
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(baseDir->chars);
|
||||
if (dir == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -157,7 +156,6 @@ static uint32_t getXBPSImpl(FFstrbuf* baseDir) {
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -458,6 +456,33 @@ static uint32_t getPacmanPackages(FFstrbuf* baseDir) {
|
||||
return getNumElements(baseDir, dbPath.chars, true);
|
||||
}
|
||||
|
||||
static uint32_t getEmergePackagesImpl(FFstrbuf* baseDir) {
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
|
||||
if (dirp == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_type != DT_DIR || entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
result += getNumElements(baseDir, entry->d_name, true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t getEmergePackages(FFstrbuf* baseDir, const char* dirname) {
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
ffStrbufAppendS(baseDir, dirname);
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
uint32_t result = getEmergePackagesImpl(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) {
|
||||
if (FF_PACKAGES_IS_ENABLED(options, APK)) {
|
||||
packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q", "apk");
|
||||
@@ -469,7 +494,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
packageCounts->lpkg += getNumStrings(baseDir, "/opt/Loc-OS-LPKG/installed-lpkg/Listinstalled-lpkg.list", "\n", "lpkg");
|
||||
}
|
||||
if (FF_PACKAGES_IS_ENABLED(options, EMERGE)) {
|
||||
packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE");
|
||||
packageCounts->emerge += getEmergePackages(baseDir, "/var/db/pkg");
|
||||
}
|
||||
if (FF_PACKAGES_IS_ENABLED(options, EOPKG)) {
|
||||
packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", true);
|
||||
@@ -493,6 +518,9 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
if (FF_PACKAGES_IS_ENABLED(options, PKGTOOL)) {
|
||||
packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", false);
|
||||
}
|
||||
if (FF_PACKAGES_IS_ENABLED(options, PORG)) {
|
||||
packageCounts->porg += getNumElements(baseDir, "/var/log/porg", false);
|
||||
}
|
||||
if (FF_PACKAGES_IS_ENABLED(options, RPM)) {
|
||||
// `Sigmd5` is the only table that doesn't contain the virtual `gpg-pubkey` package
|
||||
packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Sigmd5", "rpm");
|
||||
@@ -586,6 +614,25 @@ static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* package
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
static uint32_t getInstallReleasePackages(FFstrbuf* baseDir) {
|
||||
uint32_t result = 0;
|
||||
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
ffStrbufAppendS(baseDir, ".config/install_release/state.json");
|
||||
if (ffPathExists(baseDir->chars, FF_PATHTYPE_ANY)) {
|
||||
yyjson_doc* doc = yyjson_read_file(baseDir->chars, YYJSON_READ_NOFLAG, NULL, NULL);
|
||||
if (doc != NULL) {
|
||||
yyjson_val* root = yyjson_doc_get_root(doc);
|
||||
if (yyjson_is_obj(root)) {
|
||||
result = (uint32_t) yyjson_obj_size(root);
|
||||
}
|
||||
yyjson_doc_free(doc);
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) {
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(512);
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
|
||||
@@ -648,4 +695,8 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
result->appimage += getNumElementsBySuffix(&baseDir, "/AppImages", ".appimage");
|
||||
result->appimage += getNumElementsBySuffix(&baseDir, "/Applications", ".appimage");
|
||||
}
|
||||
|
||||
if (FF_PACKAGES_IS_ENABLED(options, INSTALLRELEASE)) {
|
||||
result->installrelease = getInstallReleasePackages(&baseDir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,6 +401,24 @@ static void detectWestonTerminal(FFTerminalFontResult* terminalFont) {
|
||||
ffFontInitValues(&terminalFont->font, font.chars, size.chars);
|
||||
}
|
||||
|
||||
static void detectKmscon(FFTerminalFontResult* terminalFont) {
|
||||
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
|
||||
|
||||
ffParsePropFileConfigValues("kmscon/kmscon.conf", 2, (FFpropquery[]){
|
||||
{ "font-size=", &fontSize },
|
||||
{ "font-name=", &fontName },
|
||||
});
|
||||
|
||||
if (fontName.length == 0) {
|
||||
ffStrbufSetStatic(&fontName, "Hack Nerd Font");
|
||||
}
|
||||
if (fontSize.length == 0) {
|
||||
ffStrbufSetStatic(&fontSize, "18");
|
||||
}
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
}
|
||||
|
||||
static void detectUrxvt(FFTerminalFontResult* terminalFont) {
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
@@ -522,6 +540,8 @@ ffDetectTerminalFontPlatform
|
||||
detectWarp(terminalFont);
|
||||
} else if (ffStrbufIgnCaseEqualS(&terminal->processName, "weston-terminal")) {
|
||||
detectWestonTerminal(terminalFont);
|
||||
} else if (ffStrbufIgnCaseEqualS(&terminal->processName, "kmscon")) {
|
||||
detectKmscon(terminalFont);
|
||||
} else if (ffStrbufStartsWithIgnCaseS(&terminal->processName, "terminator")) {
|
||||
detectTerminator(terminalFont);
|
||||
} else if (ffStrbufStartsWithIgnCaseS(&terminal->processName, "sakura")) {
|
||||
|
||||
@@ -503,6 +503,36 @@ FF_A_UNUSED static bool getTerminalVersionWeston(FF_A_UNUSED FFstrbuf* exe, FFst
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
FF_A_UNUSED static bool extractKmsconVersion(const char* str, FF_A_UNUSED uint32_t len, void* userdata) {
|
||||
if (!ffStrStartsWith(str, "v")) {
|
||||
return true;
|
||||
}
|
||||
int count = 0;
|
||||
sscanf(str, "v%*d.%*d.%*d%n", &count);
|
||||
if (count == 0) {
|
||||
return true;
|
||||
}
|
||||
ffStrbufSetNS((FFstrbuf*) userdata, (uint32_t) count - 1, str + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
FF_A_UNUSED static bool getTerminalVersionKmscon(FFstrbuf* exe, FFstrbuf* version) {
|
||||
if (ffIsAbsolutePath(exe->chars)) {
|
||||
ffBinaryExtractStrings(exe->chars, extractKmsconVersion, version, (uint32_t) strlen("v0.0.0"));
|
||||
if (version->length) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!getExeVersionRaw(exe, version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// kmscon version v10.0.0
|
||||
ffStrbufSubstrAfterLastC(version, ' ');
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version) {
|
||||
const char* env = getenv("TERMINAL_VERSION_STRING");
|
||||
if (env) {
|
||||
@@ -840,6 +870,14 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_A_UNUSED FFstrbuf* exe, FF
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
if (ffStrbufIgnCaseEqualS(processName, "kmscon")) {
|
||||
return getTerminalVersionKmscon(exe, version);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
if (ffStrbufIgnCaseEqualS(processName, "WindowsTerminal.exe")) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "version.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define FF_ARCHITECTURE "x86_64"
|
||||
@@ -62,9 +63,6 @@
|
||||
#define FF_SYSNAME "Unknown"
|
||||
#endif
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
FFVersionResult ffVersionResult = {
|
||||
.projectName = FASTFETCH_PROJECT_NAME,
|
||||
.sysName = FF_SYSNAME,
|
||||
|
||||
@@ -280,6 +280,7 @@ static const char* detectVulkan(FFVulkanResult* result) {
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
next:
|
||||
continue;
|
||||
|
||||
@@ -133,14 +133,24 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
ffStrbufSetStatic(&item->conn.security, "Shared");
|
||||
break;
|
||||
case IEEE80211_AUTH_8021X:
|
||||
ffStrbufSetStatic(&item->conn.security, "8021X");
|
||||
ffStrbufSetStatic(&item->conn.security, "802.1x");
|
||||
break;
|
||||
case IEEE80211_AUTH_AUTO:
|
||||
ffStrbufSetStatic(&item->conn.security, "Auto");
|
||||
break;
|
||||
case IEEE80211_AUTH_WPA:
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
case IEEE80211_AUTH_WPA: {
|
||||
ireq.i_type = IEEE80211_IOC_WPA;
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
switch (ireq.i_val) {
|
||||
case 2: ffStrbufSetStatic(&item->conn.security, "WPA2"); break;
|
||||
case 3: ffStrbufSetStatic(&item->conn.security, "WPA1+2"); break;
|
||||
default: ffStrbufSetStatic(&item->conn.security, "WPA"); break;
|
||||
}
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val);
|
||||
break;
|
||||
|
||||
@@ -169,6 +169,22 @@ static const char* getNiri(FFstrbuf* result) {
|
||||
return "Failed to run command `niri --version`";
|
||||
}
|
||||
|
||||
static const char* getWeston(FFstrbuf* result) {
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
const char* error = ffFindExecutableInPath("weston", &path);
|
||||
if (error) {
|
||||
return "Failed to find weston executable path";
|
||||
}
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]) { path.chars, "--version", NULL }) == NULL) { // weston 8.0.0\n...
|
||||
ffStrbufSubstrBeforeFirstC(result, '\n');
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Failed to run command `weston --version`";
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static const char* getWslg(FFstrbuf* result) {
|
||||
if (!ffAppendFileBuffer("/mnt/wslg/versions.txt", result)) {
|
||||
@@ -307,6 +323,10 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_A_UNU
|
||||
return getNiri(result);
|
||||
}
|
||||
|
||||
if (ffStrbufEqualS(wmName, "weston")) {
|
||||
return getWeston(result);
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
if (ffStrbufEqualS(wmName, "WSLg")) {
|
||||
return getWslg(result);
|
||||
|
||||
+31
-10
@@ -15,6 +15,7 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
FF_A_COLD
|
||||
static void printCommandFormatHelpJson(void) {
|
||||
yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL);
|
||||
yyjson_mut_val* root = yyjson_mut_obj(doc);
|
||||
@@ -49,6 +50,7 @@ static void printCommandFormatHelpJson(void) {
|
||||
yyjson_mut_doc_free(doc);
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void printCommandFormatHelp(const char* command) {
|
||||
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateNS((uint32_t) (strlen(command) - strlen("-format")), command);
|
||||
ffStrbufLowerCase(&type);
|
||||
@@ -85,6 +87,7 @@ static void printCommandFormatHelp(const char* command) {
|
||||
fprintf(stderr, "Error: Module '%s' is not supported\n", type.chars);
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void printFullHelp() {
|
||||
fputs("Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way\n\n", stdout);
|
||||
if (!instance.config.display.pipe) {
|
||||
@@ -191,6 +194,7 @@ For detailed information on logo options, module configuration, and formatting,
|
||||
https://github.com/fastfetch-cli/fastfetch/wiki/Configuration");
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static bool printSpecificCommandHelp(const char* command) {
|
||||
yyjson_doc* doc = yyjson_read(FASTFETCH_DATATEXT_JSON_HELP, strlen(FASTFETCH_DATATEXT_JSON_HELP), YYJSON_READ_NOFLAG);
|
||||
assert(doc);
|
||||
@@ -301,6 +305,7 @@ static bool printSpecificCommandHelp(const char* command) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void printCommandHelp(const char* command) {
|
||||
if (command == NULL) {
|
||||
printFullHelp();
|
||||
@@ -313,6 +318,7 @@ static void printCommandHelp(const char* command) {
|
||||
}
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void listAvailablePresets(bool pretty) {
|
||||
FF_LIST_FOR_EACH (FFstrbuf, path, instance.state.platform.dataDirs) {
|
||||
ffStrbufAppendS(path, "fastfetch/presets/");
|
||||
@@ -327,6 +333,7 @@ static void listAvailablePresets(bool pretty) {
|
||||
}
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void listAvailableLogos(void) {
|
||||
FF_LIST_FOR_EACH (FFstrbuf, path, instance.state.platform.dataDirs) {
|
||||
ffStrbufAppendS(path, "fastfetch/logos/");
|
||||
@@ -334,6 +341,7 @@ static void listAvailableLogos(void) {
|
||||
}
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void listConfigPaths(void) {
|
||||
FF_LIST_FOR_EACH (FFstrbuf, folder, instance.state.platform.configDirs) {
|
||||
bool exists = false;
|
||||
@@ -345,6 +353,7 @@ static void listConfigPaths(void) {
|
||||
}
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void listDataPaths(void) {
|
||||
FF_LIST_FOR_EACH (FFstrbuf, folder, instance.state.platform.dataDirs) {
|
||||
ffStrbufAppendS(folder, "fastfetch/");
|
||||
@@ -352,6 +361,7 @@ static void listDataPaths(void) {
|
||||
}
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void listModules(bool pretty) {
|
||||
unsigned count = 0;
|
||||
for (int i = 0; i <= 'Z' - 'A'; ++i) {
|
||||
@@ -394,20 +404,26 @@ static bool parseJsoncFile(FFdata* data, const char* path, yyjson_read_flag flg)
|
||||
}
|
||||
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(data->configDoc);
|
||||
if (!yyjson_is_obj(root)) {
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
fputs("JsonConfig Error: Invalid JSON config format. Root value must be an object", stderr);
|
||||
exit(477);
|
||||
}
|
||||
|
||||
yyjson_val* problematicKey = NULL;
|
||||
const char* error = NULL;
|
||||
const char* problematicModule = NULL;
|
||||
if (
|
||||
error ||
|
||||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
|
||||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
|
||||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
|
||||
((error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root, &problematicKey)) && (problematicModule = "logo")) ||
|
||||
((error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root, &problematicKey)) && (problematicModule = "general")) ||
|
||||
((error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root, &problematicKey)) && (problematicModule = "display")) ||
|
||||
false) {
|
||||
fprintf(stderr, "JsonConfig Error: %s\n", error);
|
||||
if (problematicKey) {
|
||||
fprintf(stderr, "JsonConfig Error (%s.%s): %s\n", problematicModule, unsafe_yyjson_get_str(problematicKey), error);
|
||||
} else {
|
||||
fprintf(stderr, "JsonConfig Error (%s): %s\n", problematicModule, error);
|
||||
}
|
||||
exit(477);
|
||||
}
|
||||
}
|
||||
@@ -415,6 +431,7 @@ static bool parseJsoncFile(FFdata* data, const char* path, yyjson_read_flag flg)
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void generateConfigFile(FFdata* data, bool force, const char* filePath, bool fullConfig) {
|
||||
if (data->resultDoc) {
|
||||
fprintf(stderr, "Error: duplicated `--gen-config` or `--format json` flags found\n");
|
||||
@@ -552,6 +569,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
exit(414);
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void printVersion() {
|
||||
FFVersionResult* result = &ffVersionResult;
|
||||
printf("%s %s%s%s (%s)\n", result->projectName, result->version, result->versionTweak, result->debugMode ? "-debug" : "", result->architecture);
|
||||
@@ -572,8 +590,7 @@ static void parseCommand(FFdata* data, char* key, char* value) {
|
||||
if (ffStrEqualsIgnCase(key, "-h") || ffStrEqualsIgnCase(key, "--help")) {
|
||||
printCommandHelp(value);
|
||||
exit(0);
|
||||
}
|
||||
if (ffStrEqualsIgnCase(key, "--help-raw")) {
|
||||
} else if (ffStrEqualsIgnCase(key, "--help-raw")) {
|
||||
puts(FASTFETCH_DATATEXT_JSON_HELP);
|
||||
exit(0);
|
||||
} else if (ffStrEqualsIgnCase(key, "-v") || ffStrEqualsIgnCase(key, "--version")) {
|
||||
@@ -765,9 +782,12 @@ static void run(FFdata* data) {
|
||||
}
|
||||
|
||||
if (instance.state.dynamicInterval > 0) {
|
||||
ffLogoPrintRemaining(); // `logoLineCacheClear` inside so that ffLogoPrintLine will use `\e[nC` to move the cursor to the right position instead of reprinting the logo
|
||||
fputs("\e[J", stdout); // Clear from cursor to the end of the screen to prevent artifacts when the new output is shorter than the previous one
|
||||
fflush(stdout);
|
||||
ffTimeSleep(instance.state.dynamicInterval);
|
||||
fputs("\e[H", stdout);
|
||||
fputs("\e[H", stdout); // Move cursor to the top left corner to overwrite the previous output
|
||||
instance.state.keysHeight = 0; // Reset keysHeight so `ffLogoPrintRemaining` will recalculate it
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -789,6 +809,7 @@ static void run(FFdata* data) {
|
||||
}
|
||||
}
|
||||
|
||||
FF_A_COLD
|
||||
static void writeConfigFile(FFdata* data) {
|
||||
const FFstrbuf* filename = &data->genConfigPath;
|
||||
|
||||
|
||||
@@ -291,6 +291,34 @@ static const FFlogo O[] = {
|
||||
{
|
||||
.names = { "openwrt" },
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OPENWRT,
|
||||
.colors = {
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
#endif
|
||||
#ifdef FASTFETCH_DATATEXT_LOGO_OPENWRT_SMALL
|
||||
// OpenWrtSmall
|
||||
{
|
||||
.names = { "openwrt_small" },
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OPENWRT_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
#endif
|
||||
#ifdef FASTFETCH_DATATEXT_LOGO_OPENWRT_OLD
|
||||
// OpenWrtOld
|
||||
{
|
||||
.names = { "openwrt_old" },
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OPENWRT_OLD,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
_______
|
||||
| |.-----.-----.-----.
|
||||
| - || _ | -__| |
|
||||
|_______|| __|_____|__|__|
|
||||
|__|
|
||||
________ __
|
||||
| | | |.----.| |_
|
||||
| | | || _|| _|
|
||||
|________||__| |____|
|
||||
..,,..
|
||||
,;odOMMMMMMMMObo:.
|
||||
,odOMMMMMO""''""OMMMMMObo.
|
||||
.dMMMM" .,,. "OMMMb,
|
||||
'0" ,;ddMMMMMMMMbb:. "0'
|
||||
oOMMMMO""''""OMMMMOo
|
||||
$2;. $1'0" .,,. "0' $2.:
|
||||
.OMM* $1.odMMMMMMbo. $2*MMO.
|
||||
MMMO $1"0"````"0" $2OMMM
|
||||
iOMM $1.oo. $2MMMi
|
||||
OMMl $1:MMMM: $2lMMO
|
||||
iMMM $1'oo' $2MMMi
|
||||
OMMb $2dMMO
|
||||
'OMMO. ,OMMO'
|
||||
"MMMb. ,dMMM"
|
||||
"MMMMbgo-,,-ogdMMMM"
|
||||
"*MMMMMMMMMM*"
|
||||
`'""'`
|
||||
@@ -0,0 +1,9 @@
|
||||
_______
|
||||
| |.-----.-----.-----.
|
||||
| - || _ | -__| |
|
||||
|_______|| __|_____|__|__|
|
||||
|__|
|
||||
________ __
|
||||
| | | |.----.| |_
|
||||
| | | || _|| _|
|
||||
|________||__| |____|
|
||||
@@ -0,0 +1,9 @@
|
||||
..,..
|
||||
,odM"""""Mbo,
|
||||
`.odMMMMMbo.`
|
||||
$2d,$1" ,mmm, "$2,b
|
||||
iM $1" . " $2Mi
|
||||
Ml $1dMb $2lM
|
||||
'M, $1' $2.M'
|
||||
"0b. ,d0"
|
||||
`"WWWWW"`
|
||||
@@ -3,6 +3,18 @@
|
||||
#include "common/color.h"
|
||||
|
||||
static const FFlogo Z[] = {
|
||||
#ifdef FASTFETCH_DATATEXT_LOGO_ZERENE
|
||||
// Zerene
|
||||
{
|
||||
.names = { "Zerene" },
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ZERENE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
#endif
|
||||
#ifdef FASTFETCH_DATATEXT_LOGO_ZORIN
|
||||
// Zorin
|
||||
{
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
MMM
|
||||
MMMM
|
||||
MMMMM
|
||||
MMMMMM
|
||||
MMMMMMa
|
||||
MMMMMMMa
|
||||
MMMMMMM
|
||||
MMMMMM
|
||||
MMMM
|
||||
M
|
||||
oxdo aMa
|
||||
aMd aMMMMMMMMM
|
||||
aMMMMM MMMMMMMMMMMMMMa
|
||||
MMMMMMMa MMMMMMMMMMMMMMMa
|
||||
MMMMMMMMa
|
||||
MMMMMMMMa
|
||||
MMMMMMM
|
||||
MMMM
|
||||
+13
-19
@@ -727,7 +727,7 @@ FFLogoImageResult ffLogoPrintImageImpl(FFLogoRequestData* requestData, const FFI
|
||||
|
||||
bool printSuccessful = false;
|
||||
if (requestData->type == FF_LOGO_TYPE_IMAGE_CHAFA) {
|
||||
#ifdef FF_HAVE_CHAFA
|
||||
#if FF_HAVE_CHAFA
|
||||
printSuccessful = printImageChafa(requestData, &imageData);
|
||||
#endif
|
||||
} else if (requestData->type == FF_LOGO_TYPE_IMAGE_KITTY) {
|
||||
@@ -782,12 +782,9 @@ static uint32_t readCachedUint32(FFLogoRequestData* requestData, const char* cac
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool printCachedChars(FFLogoRequestData* requestData) {
|
||||
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreateA(32768);
|
||||
|
||||
if (requestData->type == FF_LOGO_TYPE_IMAGE_CHAFA) {
|
||||
readCachedStrbuf(requestData, &content, FF_CACHE_FILE_CHAFA);
|
||||
}
|
||||
static bool printCachedChars(FFLogoRequestData* requestData, const char* cacheFileName) {
|
||||
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
|
||||
readCachedStrbuf(requestData, &content, cacheFileName);
|
||||
|
||||
if (content.length == 0) {
|
||||
return false;
|
||||
@@ -876,14 +873,6 @@ static bool printCachedPixel(FFLogoRequestData* requestData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool printCached(FFLogoRequestData* requestData) {
|
||||
if (requestData->type == FF_LOGO_TYPE_IMAGE_CHAFA) {
|
||||
return printCachedChars(requestData);
|
||||
} else {
|
||||
return printCachedPixel(requestData);
|
||||
}
|
||||
}
|
||||
|
||||
static bool getCharacterPixelDimensions(FFLogoRequestData* requestData) {
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -947,9 +936,14 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError) {
|
||||
ffStrbufEnsureEndsWithC(&requestData.cacheDir, '/');
|
||||
ffStrbufAppendF(&requestData.cacheDir, "%u*%u/", requestData.logoPixelWidth, requestData.logoPixelHeight);
|
||||
|
||||
if (!instance.config.logo.recache && printCached(&requestData)) {
|
||||
ffStrbufDestroy(&requestData.cacheDir);
|
||||
return true;
|
||||
if (!instance.config.logo.recache) {
|
||||
bool cacheValid = requestData.type == FF_LOGO_TYPE_IMAGE_CHAFA
|
||||
? printCachedChars(&requestData, FF_CACHE_FILE_CHAFA)
|
||||
: printCachedPixel(&requestData);
|
||||
if (cacheValid) {
|
||||
ffStrbufDestroy(&requestData.cacheDir);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FFLogoImageResult result = FF_LOGO_IMAGE_RESULT_INIT_ERROR;
|
||||
@@ -1018,7 +1012,7 @@ bool ffLogoPrintImageIfExists(FFLogoType type, bool printError) {
|
||||
return printImageKittyIcat(printError);
|
||||
}
|
||||
|
||||
#if !defined(FF_HAVE_CHAFA)
|
||||
#if !FF_HAVE_CHAFA
|
||||
if (type == FF_LOGO_TYPE_IMAGE_CHAFA) {
|
||||
if (printError) {
|
||||
fputs("Logo: Chafa support is not compiled in\n", stderr);
|
||||
|
||||
+33
-31
@@ -461,7 +461,7 @@ static bool updateLogoPath(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !FF_MODULE_DISABLE_MEDIA
|
||||
#if !FF_MODULE_DISABLE_MEDIA
|
||||
if (ffStrbufIgnCaseEqualS(&options->source, "media-cover")) {
|
||||
const FFMediaResult* media = ffDetectMedia(true);
|
||||
if (media->cover.length == 0) {
|
||||
@@ -470,7 +470,7 @@ static bool updateLogoPath(void) {
|
||||
ffStrbufSet(&options->source, &media->cover);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreateA(128);
|
||||
if (ffPathExpandEnv(options->source.chars, &fullPath) && ffPathExists(fullPath.chars, FF_PATHTYPE_FILE)) {
|
||||
@@ -639,7 +639,7 @@ void ffLogoPrint(void) {
|
||||
}
|
||||
|
||||
if (!ffStrbufEndsWithIgnCaseS(&options->source, ".txt")) {
|
||||
#if !FF_MODULE_DISABLE_TERMINAL
|
||||
#if !FF_MODULE_DISABLE_TERMINAL
|
||||
const FFTerminalResult* terminal = ffDetectTerminal();
|
||||
|
||||
bool supportsIterm2 = ffStrbufEqualS(&terminal->prettyName, "iTerm");
|
||||
@@ -655,15 +655,15 @@ void ffLogoPrint(void) {
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "wezterm") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "ghostty") ||
|
||||
#ifdef __APPLE__
|
||||
#ifdef __APPLE__
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "WarpTerminal") ||
|
||||
#else
|
||||
#else
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "warp") ||
|
||||
#endif
|
||||
#endif
|
||||
false;
|
||||
#else
|
||||
#else
|
||||
bool supportsKitty = false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Try to load the logo as an image. If it succeeds, print it and return.
|
||||
if (logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false)) {
|
||||
@@ -685,37 +685,39 @@ void ffLogoPrint(void) {
|
||||
}
|
||||
|
||||
void ffLogoPrintLine(void) {
|
||||
uint32_t printedLineWidth = 0;
|
||||
FFLogoLineCacheState* cache = &instance.state.logoLineCache;
|
||||
FFOptionsLogo* logo = &instance.config.logo;
|
||||
|
||||
if (cache->lines.length > 0 && (logo->position == FF_LOGO_POSITION_LEFT || logo->position == FF_LOGO_POSITION_RIGHT) && cache->nextLine < cache->lines.length) {
|
||||
FFLogoCachedLine* line = FF_LIST_GET(FFLogoCachedLine, cache->lines, cache->nextLine);
|
||||
if (cache->lines.length > 0) {
|
||||
// Line cache is enabled. Always move cursor with whitespaces to make lolcat happy
|
||||
if (cache->nextLine < cache->lines.length) {
|
||||
// Print logo line and move cursor
|
||||
FFLogoCachedLine* line = FF_LIST_GET(FFLogoCachedLine, cache->lines, cache->nextLine);
|
||||
|
||||
if (logo->position == FF_LOGO_POSITION_RIGHT && line->chars.length > 0) {
|
||||
printf("\033[9999999C\033[%uD", cache->rightOffset);
|
||||
ffStrbufWriteTo(&line->chars, stdout);
|
||||
fputs("\033[G", stdout);
|
||||
} else {
|
||||
ffStrbufWriteTo(&line->chars, stdout);
|
||||
printedLineWidth = line->width;
|
||||
if (logo->position == FF_LOGO_POSITION_RIGHT) {
|
||||
printf("\033[9999999C\033[%uD", cache->rightOffset);
|
||||
ffStrbufWriteTo(&line->chars, stdout);
|
||||
|
||||
fputs("\033[G", stdout);
|
||||
} else {
|
||||
ffStrbufWriteTo(&line->chars, stdout);
|
||||
|
||||
uint32_t remaining = instance.state.logoWidth;
|
||||
remaining = line->width < remaining ? remaining - line->width : 0;
|
||||
ffPrintCharTimes(' ', remaining);
|
||||
}
|
||||
++cache->nextLine;
|
||||
} else if (logo->position == FF_LOGO_POSITION_LEFT) {
|
||||
// Move cursor to the start position
|
||||
ffPrintCharTimes(' ', instance.state.logoWidth);
|
||||
}
|
||||
|
||||
++cache->nextLine;
|
||||
} else if (instance.state.logoWidth > 0) {
|
||||
printf("\033[%uC", instance.state.logoWidth);
|
||||
}
|
||||
|
||||
if (instance.state.logoWidth > 0) {
|
||||
if (instance.config.logo.position == FF_LOGO_POSITION_LEFT) {
|
||||
uint32_t remaining = instance.state.logoWidth;
|
||||
remaining = printedLineWidth < remaining ? remaining - printedLineWidth : 0;
|
||||
ffPrintCharTimes(' ', remaining);
|
||||
} else {
|
||||
printf("\033[%uC", instance.state.logoWidth);
|
||||
}
|
||||
}
|
||||
|
||||
if (instance.state.dynamicInterval > 0) {
|
||||
if (instance.state.dynamicInterval > 0 && logo->position == FF_LOGO_POSITION_LEFT) {
|
||||
fputs("\033[K", stdout); // Clear to the end of the line
|
||||
// Note that we don't clear the line when the logo is on the right, as it will also clear the logo itself
|
||||
}
|
||||
|
||||
++instance.state.keysHeight;
|
||||
|
||||
@@ -66,6 +66,7 @@ bool ffPrintBluetooth(FFBluetoothOptions* options) {
|
||||
|
||||
if (devices.length == 0) {
|
||||
ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t i = 1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user