mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
166 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0869809857 | |||
| c31779e99d | |||
| 89ad35d8a1 | |||
| d651f3de43 | |||
| c34c3e5aae | |||
| c5c61584d9 | |||
| 48c3b4f980 | |||
| 93bca8d480 | |||
| c690fe5aa9 | |||
| 55e674e1cb | |||
| 0495c47909 | |||
| 2f79c39f62 | |||
| 44056f1c85 | |||
| 6358bd7844 | |||
| 11d77e0d09 | |||
| ec25659503 | |||
| 35dbcb2588 | |||
| 8b6a74f2ec | |||
| 2ea6c3767e | |||
| 827bc26b0a | |||
| e12f3631d4 | |||
| 52c9730542 | |||
| 225d9e7771 | |||
| d031d6c20f | |||
| 35af768d92 | |||
| 22c4620345 | |||
| 81738aa303 | |||
| 113f7d34d8 | |||
| 62513004c8 | |||
| 1b36c3cd5f | |||
| 78874ae583 | |||
| a447928853 | |||
| 9f446bdad7 | |||
| 4cf060eb27 | |||
| 08d419d75c | |||
| 3ae1bfdc24 | |||
| 0e257f25c2 | |||
| 195e148cc1 | |||
| 5ab192ee05 | |||
| 4897152af6 | |||
| 69418cb527 | |||
| 0e90f3a7d4 | |||
| 1a663e72da | |||
| e0ae1ac1a2 | |||
| e0d141ecf6 | |||
| 29eb8bb57d | |||
| bc1f240558 | |||
| 3e15a2591a | |||
| 0ec9443de5 | |||
| 4a4ca9a4a8 | |||
| acf76e565a | |||
| 778aa21192 | |||
| dfdc7284a2 | |||
| 231d7fcd4d | |||
| a3184601dc | |||
| e3dfeeb8db | |||
| ccdcd6ab6f | |||
| 64d205628e | |||
| ff13adf1b4 | |||
| c38fd9ec10 | |||
| 96793ec604 | |||
| 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 | |||
| 021ece1681 | |||
| 9787b56460 | |||
| 54792e61ff | |||
| b34e2a4055 | |||
| 3b56200ee4 | |||
| de95a62e2f | |||
| 72cb64a500 |
+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
|
||||
|
||||
@@ -3,35 +3,58 @@ name: Reusable DragonFly amd64
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/dragonflybsd-vm@v1
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
usesh: yes
|
||||
envs: 'CMAKE_BUILD_TYPE'
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf lua54 libva libvdpau
|
||||
operating_system: dragonflybsd
|
||||
version: '6.4.2'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
run: |
|
||||
env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
pkg --version
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg update
|
||||
sudo pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf lua54 libva libvdpau
|
||||
|
||||
- name: CMake configuration
|
||||
run: env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -3,37 +3,59 @@ name: Reusable FreeBSD amd64
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: freebsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
version: '15.1'
|
||||
shell: bash
|
||||
version: '15.0'
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa lua54 libva libvdpau
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
freebsd-version
|
||||
pkg -v
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa lua54 libva libvdpau
|
||||
|
||||
- name: CMake configuration
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -3,35 +3,52 @@ name: Reusable Haiku amd64
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 lua
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ctest --output-on-failure
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: uname -a
|
||||
|
||||
- name: Install dependencies
|
||||
shell: cpa.sh {0} --reboot
|
||||
run: pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake llvm22_clang ninja pkgconfig python3.10 lua || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake llvm22_clang ninja pkgconfig python3.10 lua
|
||||
|
||||
- name: CMake configuration
|
||||
run: CC=clang CXX=clang++ cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
|
||||
@@ -3,36 +3,57 @@ name: Reusable NetBSD amd64
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: netbsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '10.1'
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick libva libvdpau
|
||||
CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
pkgin -v
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick libva libvdpau
|
||||
|
||||
- name: CMake configuration
|
||||
run: CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
@@ -3,37 +3,62 @@ name: Reusable OmniOS amd64
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/omnios-vm@v1
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
usesh: true
|
||||
envs: 'CMAKE_BUILD_TYPE'
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update --accept || true
|
||||
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
|
||||
operating_system: omnios
|
||||
version: 'r151058'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
|
||||
cmake --build . --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg update --accept || true
|
||||
sudo pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
|
||||
|
||||
- name: CMake configuration
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -3,37 +3,57 @@ name: Reusable OpenBSD amd64
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: openbsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
version: '7.9'
|
||||
shell: bash
|
||||
version: '7.8'
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -u
|
||||
sudo pkg_add -r llvm-21.1.2p0 cmake git wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa lua-5.4.7 # pkg-config is preinstalled
|
||||
CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg_add -u
|
||||
sudo pkg_add -r llvm-21.1.8p4 cmake git wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa lua-5.4.8p0 # pkg-config is preinstalled
|
||||
|
||||
- name: CMake configuration
|
||||
run: CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/solaris-vm@v1
|
||||
|
||||
@@ -3,22 +3,19 @@ name: Reusable Spellcheck
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y codespell
|
||||
pip3 install codespell
|
||||
codespell --version
|
||||
|
||||
- name: Run Spellchecker
|
||||
run: codespell
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
|
||||
@@ -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
|
||||
|
||||
+109
@@ -1,3 +1,112 @@
|
||||
# 2.66.0
|
||||
|
||||
Changes:
|
||||
* CPU package count is no longer reported in the default output.
|
||||
* Users can still print it in custom formats via `{packages}`
|
||||
|
||||
Bugfixes:
|
||||
* Fixed compatibility with WSL 2.9.3 (#2433, WM, Linux)
|
||||
* Fixed accurate AMD GPU names are not queried in `driverSpecific` mode (GPU, Linux)
|
||||
* Fixed GPU core counting for Apple Silicon GPU on Asahi Linux (GPU, Linux)
|
||||
* Some internal cleanups and optimizations
|
||||
|
||||
Features:
|
||||
* Added Astra Linux version detection (OS, Linux)
|
||||
* Improved performance of Windows PowerShell version detection (Shell, Windows)
|
||||
* Improved performance of Media module on macOS (Media, macOS)
|
||||
* Added proxmox backup server detection (#2443, OS, Linux)
|
||||
|
||||
Logos:
|
||||
* Added Flatcar, Azure Linux
|
||||
* Added Chimera_small, Chimera2, Parabola2_small, PostmarketOS2, Qubes_small
|
||||
* Updated linuxmint_small
|
||||
* Cleaned up distro names
|
||||
|
||||
# 2.65.2
|
||||
|
||||
Changes:
|
||||
* Memory usage calculations now exclude the ZFS ARC cache on Linux, FreeBSD, NetBSD, and SunOS. (#1995 / #2418, Memory)
|
||||
* This prevents the Memory module from reporting artificially high memory usage on systems with the ZFS kmod enabled.
|
||||
|
||||
Bugfixes:
|
||||
* The GPU module no longer pings sleeping dedicated GPUs on dual-GPU laptops. (#2419, GPU)
|
||||
* As a result, PCIe link speed detection (introduced in v2.65.0) is now only enabled in `driverSpecific` mode.
|
||||
* Fixed a crash when detecting hardware codec support with the `amdgpu` driver on Linux. (#2419, Codec, Linux)
|
||||
|
||||
Logos:
|
||||
* Updated CachyOS_small; fixed CachyOS logo colors to match the official logo better
|
||||
* Added Turkish
|
||||
|
||||
# 2.65.1
|
||||
|
||||
No changes
|
||||
|
||||
# 2.65.0
|
||||
|
||||
Changes:
|
||||
* `display.disableLinewrap` now defaults to `false`.
|
||||
* This allows long lines to wrap instead of being truncated, preventing confusion for new users.
|
||||
* Wrapped lines may overlap with the image logo. Users who prefer the old behavior can set `display.disableLinewrap: true` in their config file or use `--disable-linewrap true` on the command line.
|
||||
* Reorders package manager variables in custom format strings, moving aggregate variables (e.g., `all`, `brew-all`, `flatpak-all`) to the end. (Packages)
|
||||
* This is a breaking change for users relying on numeric placeholders (e.g., `{1}`). Numeric placeholders are a long-deprecated feature; named placeholders (e.g., `{pacman}`) are always preferred and future-proof.
|
||||
* Enables `showPeCoreCount` by default to better display hybrid-architecture core counts. (CPU)
|
||||
* No longer accepts `chafa` options in config files if `chafa` support was disabled at compile time. (Logo)
|
||||
* This may affect users who generated their config files using `fastfetch --gen-full-config`. To resolve this, simply remove the `chafa` section from the config file.
|
||||
|
||||
Features:
|
||||
* Adds detection for CPU code names (e.g., "Alder Lake", "Zen 4") and manufacturing technologies (e.g., "Intel 7", "TSMC N4") on x86 processors. (#1501, CPU, X86)
|
||||
* These can be used in custom formats via `{code-name}` and `{technology}`.
|
||||
* Adds PCIe link speed detection (current and max generation & lanes) for GPUs on Linux and Windows.
|
||||
* These can be used in custom formats via `{pcie-max-speed}` and `{pcie-curr-speed}`.
|
||||
* Adds HDR display detection via the `wp-color-management-v1` Wayland protocol. (#2356, Display, Linux)
|
||||
* Previously, HDR detection was only supported on KDE Plasma.
|
||||
* Adds the `egl-ext` detection method, which uses `EGL_EXT_device_enumeration` for GPU enumeration. (GPU)
|
||||
* Adds terminal version and font detection for `kmscon`. (#2393, Terminal / TerminalFont, Linux)
|
||||
* Adds the currently-in-beta code name "Golden Gate" for macOS 27. (OS, macOS)
|
||||
* Adds WPA version detection on FreeBSD. (Wifi, FreeBSD)
|
||||
* Adds package manager support for `porg` (#2405) and `install-release` (#2342). (Packages, Linux)
|
||||
* Adds Weston version detection. (WM, Linux)
|
||||
* Improves the core type (P-Core/E-Core) fetching mechanism on Windows by using `EfficiencyClass` instead of legacy frequency inference. (CPU, Windows)
|
||||
* Improves display detection compatibility with KDE 6.7. (Display, Linux)
|
||||
* Improves display serial number detection, now preferring alphanumeric serial numbers when available. (Display)
|
||||
* This can be used in custom formats via `{serial}`.
|
||||
* Improves the performance of `emerge` package manager detection. (#2406, Packages, Linux)
|
||||
* Improves error messages for config file parsing errors.
|
||||
* Improves reliability of the `Codec` module on Linux (Codec, Linux)
|
||||
* Adds `va-x11` backend for VA-API and VDPAU, which is used if `va-drm` backend fails to initialize.
|
||||
* Fixes an issue where the Codec module incorrectly reports no results when the `codec.showType` option is set.
|
||||
|
||||
Bugfixes:
|
||||
* Fixes physical core detection on non-x86 architectures and simplifies the frequency detection code. (CPU, Linux)
|
||||
* Fixes console mode and output code page initialization issues when running `fastfetch` in `Conhost`. (#2383, Windows)
|
||||
* Fixes public IP detection randomly failing on Linux. (#2401, PublicIP, Linux)
|
||||
* Fixes several memory leaks.
|
||||
|
||||
Logos:
|
||||
* Adds Zerene OS. (#2404)
|
||||
|
||||
# 2.64.2
|
||||
|
||||
Bugfixes:
|
||||
* Fixes image rendering being wiped quickly (#2374)
|
||||
* Regression from v2.64.0
|
||||
* Fixes ASCII logo being overwritten in `--dynamic-interval` mode
|
||||
* Regression from v2.64.0
|
||||
|
||||
Logos:
|
||||
* Updates OpenWrt and adds a small variant (#2376)
|
||||
* The old one is renamed to `openwrt_old`
|
||||
|
||||
# 2.64.1
|
||||
|
||||
Features:
|
||||
* Adds a CMake option `-DPACKAGES_REMOVE_DISABLED` to remove detection code of disabled packages (`-DPACKAGES_DISABLE_<PACKAGE_NAME>`) for slightly smaller binary size (Packages)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes compatibility issues with Lua 5.3
|
||||
* Avoid possible infinite recursion in `encode_json` when encoding deeply nested tables or circular references
|
||||
* Fixes compilation issues when building with old macOS SDKs
|
||||
|
||||
# 2.64.0
|
||||
|
||||
New **optional build** dependencies:
|
||||
|
||||
+91
-54
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.64.0
|
||||
VERSION 2.66.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -63,6 +63,13 @@ endif()
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
if(LINUX)
|
||||
CHECK_INCLUDE_FILE("linux/version.h" HAVE_LINUX_VERSION_H)
|
||||
if(NOT HAVE_LINUX_VERSION_H)
|
||||
message(FATAL_ERROR "Linux headers (linux/version.h) not found! Please install linux-headers package.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#####################
|
||||
# Configure options #
|
||||
#####################
|
||||
@@ -70,13 +77,13 @@ include(CheckIncludeFile)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_VA "Enable libva" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_VADRM "Enable libva-drm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_VAX11 "Enable libva-x11" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_VDPAU "Enable vdpau" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_EET "Enable eet" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
@@ -98,6 +105,7 @@ cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND"
|
||||
option(ENABLE_ZLIB "Enable zlib" ON)
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
option(ENABLE_TRACER "Build fastfetch with function tracing" OFF)
|
||||
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
|
||||
option(BUILD_FLASHFETCH "Build flashfetch" ON) # Also build the flashfetch binary
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
@@ -134,7 +142,10 @@ if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
|
||||
message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
|
||||
endif()
|
||||
|
||||
set(PACKAGE_MANAGERS AM APPIMAGE APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SOAR SORCERY WINGET XBPS)
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/packages/option.h" PACKAGE_MANAGERS)
|
||||
string(REGEX MATCHALL "FF_PACKAGES_FLAG_[A-Z]+_BIT" PACKAGE_MANAGERS "${PACKAGE_MANAGERS}")
|
||||
string(REGEX REPLACE "FF_PACKAGES_FLAG_([A-Z]+)_BIT" "\\1" PACKAGE_MANAGERS "${PACKAGE_MANAGERS}")
|
||||
list(SORT PACKAGE_MANAGERS)
|
||||
foreach(package_manager ${PACKAGE_MANAGERS})
|
||||
if(package_manager STREQUAL "WINGET")
|
||||
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
|
||||
@@ -142,6 +153,7 @@ foreach(package_manager ${PACKAGE_MANAGERS})
|
||||
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" OFF)
|
||||
endif()
|
||||
endforeach()
|
||||
option(PACKAGES_REMOVE_DISABLED "Remove disabled package managers from the build entirely, instead of just skipping them at runtime" OFF)
|
||||
|
||||
if (LINUX)
|
||||
set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
|
||||
@@ -308,7 +320,7 @@ if(Python_FOUND)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Python3 is not found, 'help.json' will not be minified")
|
||||
file(READ "doc/help.json" DATATEXT_JSON_HELP)
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/doc/help.json" DATATEXT_JSON_HELP)
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
|
||||
@@ -428,6 +440,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/codec/codec.c
|
||||
src/detection/codec/codec_vulkan.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpu/cpu_x86.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
src/detection/command/command.c
|
||||
src/detection/disk/disk.c
|
||||
@@ -572,11 +585,10 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/wl-output-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
@@ -733,11 +745,10 @@ elseif(FreeBSD)
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wl-output-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
@@ -746,6 +757,7 @@ elseif(FreeBSD)
|
||||
src/detection/gpu/gpu_bsd.c
|
||||
src/detection/gpu/gpu_drm.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gpu/gpu_bsddrm.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/lm/lm_linux.c
|
||||
@@ -828,11 +840,10 @@ elseif(NetBSD)
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wl-output-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
@@ -913,11 +924,10 @@ elseif(OpenBSD)
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wl-output-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
@@ -925,6 +935,8 @@ elseif(OpenBSD)
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gpu/gpu_obsd.c
|
||||
src/detection/gpu/gpu_drm.c
|
||||
src/detection/gpu/gpu_bsddrm.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_obsd.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
@@ -1156,11 +1168,10 @@ elseif(SunOS)
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wl-output-protocol.c
|
||||
src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
@@ -1306,12 +1317,9 @@ elseif(GNU)
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
src/detection/diskio/diskio_nosupport.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
@@ -1358,6 +1366,22 @@ elseif(GNU)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TRACER)
|
||||
message(STATUS "Tracer is enabled")
|
||||
list(APPEND LIBFASTFETCH_SRC src/common/impl/tracer.c)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions-after-inlining")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions -Dinline=\"__attribute__((no_instrument_function)) inline\"")
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gcodeview -fuse-ld=lld")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--pdb=${CMAKE_BINARY_DIR}/fastfetch.pdb")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Proprietary GPU driver APIs
|
||||
if(LINUX OR FreeBSD OR WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
|
||||
@@ -1557,24 +1581,24 @@ endif()
|
||||
|
||||
if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
|
||||
endif()
|
||||
if(NOT "${CUSTOM_AMDGPU_IDS_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of amdgpu.ids: ${CUSTOM_AMDGPU_IDS_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
|
||||
endif()
|
||||
if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
|
||||
endif()
|
||||
if(NOT "${CUSTOM_LSB_RELEASE_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of lsb_release: ${CUSTOM_LSB_RELEASE_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_LSB_RELEASE_PATH=${CUSTOM_LSB_RELEASE_PATH})
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_LSB_RELEASE_PATH=${CUSTOM_LSB_RELEASE_PATH})
|
||||
endif()
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
message(STATUS "Enabling custom link type: ${BINARY_LINK_TYPE}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_DISABLE_DLOPEN=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_DISABLE_DLOPEN=1)
|
||||
if(NOT WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--copy-dt-needed-entries")
|
||||
endif()
|
||||
@@ -1619,6 +1643,11 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME) # [CMAKE_TARGET_NAME]
|
||||
set(${VARNAME}_LIBRARIES ${_FF_CMAKE_TARGET})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
# INTERFACE_LINK_LIBRARIES doesn't expose libvarname.a
|
||||
target_link_libraries(libfastfetch PRIVATE ${_FF_CMAKE_TARGET})
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(${VARNAME}_INCLUDE_DIRS ${${CMAKE_NAME}_INCLUDE_DIRS})
|
||||
@@ -1635,18 +1664,18 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME) # [CMAKE_TARGET_NAME]
|
||||
|
||||
message(STATUS "Library: found ${VARNAME} by ${${VARNAME}_FOUND}")
|
||||
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_${VARNAME}=1)
|
||||
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_link_directories(libfastfetch PUBLIC ${${VARNAME}_LIBRARY_DIRS})
|
||||
target_link_directories(libfastfetch PRIVATE ${${VARNAME}_LIBRARY_DIRS})
|
||||
target_link_libraries(libfastfetch PRIVATE ${${VARNAME}_LIBRARIES})
|
||||
endif()
|
||||
|
||||
foreach(FLAG ${${VARNAME}_CFLAGS_OTHER})
|
||||
if(FLAG MATCHES "-D.*")
|
||||
string(SUBSTRING ${FLAG} 2 -1 FLAG)
|
||||
target_compile_definitions(libfastfetch PRIVATE ${FLAG})
|
||||
target_compile_definitions(libfastfetch PUBLIC ${FLAG})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
@@ -1671,18 +1700,18 @@ ff_lib_enable(DRM
|
||||
"libdrm"
|
||||
"Libdrm"
|
||||
)
|
||||
ff_lib_enable(VA
|
||||
"libva"
|
||||
"Libva"
|
||||
ff_lib_enable(VADRM
|
||||
"libva-drm"
|
||||
"Libva-drm"
|
||||
)
|
||||
ff_lib_enable(VAX11
|
||||
"libva-x11"
|
||||
"Libva-x11"
|
||||
)
|
||||
ff_lib_enable(VDPAU
|
||||
"vdpau"
|
||||
"vdpau"
|
||||
)
|
||||
ff_lib_enable(DRM_AMDGPU
|
||||
"libdrm_amdgpu"
|
||||
"Libdrm_Amdgpu"
|
||||
)
|
||||
ff_lib_enable(GIO
|
||||
"gio-2.0"
|
||||
"GIO"
|
||||
@@ -1776,8 +1805,8 @@ if(ENABLE_LUA)
|
||||
message(STATUS "Library: Lua version ${Lua_VERSION} is not supported, requires 5.3-5.5")
|
||||
unset(Lua_FOUND)
|
||||
else()
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LUA=1)
|
||||
target_include_directories(libfastfetch PRIVATE ${LUA_INCLUDE_DIR})
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LUA=1)
|
||||
target_include_directories(libfastfetch PUBLIC ${LUA_INCLUDE_DIR})
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_link_libraries(libfastfetch PRIVATE ${LUA_LIBRARIES})
|
||||
@@ -1790,20 +1819,20 @@ if(ENABLE_LUA)
|
||||
endif()
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_THREADS=1)
|
||||
if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
|
||||
target_link_libraries(libfastfetch PRIVATE Threads::Threads)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMBEDDED_PCIIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_EMBEDDED_PCIIDS=1)
|
||||
endif()
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
endif()
|
||||
if(ENABLE_LIBZFS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LIBZFS=1)
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1877,6 +1906,11 @@ elseif(WIN32)
|
||||
PRIVATE "runtimeobject"
|
||||
)
|
||||
endif()
|
||||
if(ENABLE_TRACER)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "dbghelp"
|
||||
)
|
||||
endif()
|
||||
elseif(FreeBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
@@ -1960,7 +1994,7 @@ target_link_libraries(libfastfetch
|
||||
PRIVATE ${CMAKE_DL_LIBS}
|
||||
)
|
||||
|
||||
target_compile_options(libfastfetch PRIVATE
|
||||
target_compile_options(libfastfetch PUBLIC
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti>)
|
||||
|
||||
if(FreeBSD)
|
||||
@@ -1969,18 +2003,18 @@ endif()
|
||||
if(LINUX OR FreeBSD OR OpenBSD OR NetBSD)
|
||||
CHECK_INCLUDE_FILE("linux/videodev2.h" HAVE_LINUX_VIDEODEV2)
|
||||
if(HAVE_LINUX_VIDEODEV2)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LINUX_VIDEODEV2=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LINUX_VIDEODEV2=1)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX)
|
||||
if(HAVE_UTMPX)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_UTMPX=1)
|
||||
endif()
|
||||
if(ENABLE_WORDEXP)
|
||||
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
|
||||
if(HAVE_WORDEXP)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WORDEXP=1)
|
||||
message(STATUS "wordexp.h found, wordexp support enabled")
|
||||
else()
|
||||
set(ENABLE_WORDEXP OFF)
|
||||
@@ -1992,19 +2026,19 @@ if(NOT WIN32)
|
||||
if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
|
||||
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
|
||||
if(HAVE_PTHREAD_NP)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_PTHREAD_NP=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PTHREAD_NP=1)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} pthread_np.h)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} Threads::Threads)
|
||||
check_function_exists("pthread_timedjoin_np" HAVE_TIMEDJOIN_NP)
|
||||
if(HAVE_TIMEDJOIN_NP)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_TIMEDJOIN_NP=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_TIMEDJOIN_NP=1)
|
||||
else()
|
||||
message(WARNING "pthread_timedjoin_np was not found; networking timeout will not work")
|
||||
endif()
|
||||
endif()
|
||||
elseif(HAVE_WINRT)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WINRT=1)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WINRT=1)
|
||||
endif()
|
||||
|
||||
set(PACKAGES_DISABLE_LIST "")
|
||||
@@ -2021,7 +2055,10 @@ else()
|
||||
list(TRANSFORM PACKAGES_DISABLE_LIST APPEND "_BIT")
|
||||
list(JOIN PACKAGES_DISABLE_LIST " | " PACKAGES_DISABLE_LIST)
|
||||
endif()
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_PACKAGES_DISABLE_LIST=${PACKAGES_DISABLE_LIST})
|
||||
target_compile_definitions(libfastfetch PUBLIC "FF_PACKAGES_DISABLE_LIST=${PACKAGES_DISABLE_LIST}")
|
||||
if(PACKAGES_REMOVE_DISABLED)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_PACKAGES_REMOVE_DISABLED=1)
|
||||
endif()
|
||||
|
||||
######################
|
||||
# Executable targets #
|
||||
|
||||
Vendored
+18
@@ -1,3 +1,21 @@
|
||||
fastfetch (2.65.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.65.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 29 Jun 2026 10:05:47 +0800
|
||||
|
||||
fastfetch (2.65.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.65.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 24 Jun 2026 14:21:06 +0800
|
||||
|
||||
fastfetch (2.64.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.64.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Jun 2026 15:45:11 +0800
|
||||
|
||||
fastfetch (2.63.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.63.1
|
||||
|
||||
Vendored
+1
-1
@@ -10,7 +10,7 @@ SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
|
||||
OUT_DIR="$(dirname "$ROOT_DIR")"
|
||||
PPA="ppa:zhangsongcui3371/fastfetch"
|
||||
CODENAMES=( jammy noble plucky questing resolute )
|
||||
CODENAMES=( jammy noble plucky questing resolute stonking )
|
||||
DRY_RUN=0
|
||||
|
||||
if [[ -d "$OUT_DIR/build" ]]; then
|
||||
|
||||
@@ -322,7 +322,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cpuFormat": {
|
||||
"description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count",
|
||||
"description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count\n 13. {code-name}: CPU code name\n 14. {technology}: CPU technology",
|
||||
"type": "string"
|
||||
},
|
||||
"cpucacheFormat": {
|
||||
@@ -374,7 +374,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"gpuFormat": {
|
||||
"description": "Output format for the `GPU` module. See Wiki for formatting syntax\n 1. {vendor}: GPU vendor\n 2. {name}: GPU name\n 3. {driver}: GPU driver\n 4. {temperature}: GPU temperature\n 5. {core-count}: GPU core count\n 6. {type}: GPU type\n 7. {dedicated-total}: GPU total dedicated memory\n 8. {dedicated-used}: GPU used dedicated memory\n 9. {shared-total}: GPU total shared memory\n 10. {shared-used}: GPU used shared memory\n 11. {platform-api}: The platform API used when detecting the GPU\n 12. {frequency}: Current frequency in GHz\n 13. {index}: GPU vendor specific index\n 14. {dedicated-percentage-num}: Dedicated memory usage percentage num\n 15. {dedicated-percentage-bar}: Dedicated memory usage percentage bar\n 16. {shared-percentage-num}: Shared memory usage percentage num\n 17. {shared-percentage-bar}: Shared memory usage percentage bar\n 18. {core-usage-num}: Core usage percentage num\n 19. {core-usage-bar}: Core usage percentage bar\n 20. {memory-type}: Memory type (Windows only)",
|
||||
"description": "Output format for the `GPU` module. See Wiki for formatting syntax\n 1. {vendor}: GPU vendor\n 2. {name}: GPU name\n 3. {driver}: GPU driver\n 4. {temperature}: GPU temperature\n 5. {core-count}: GPU core count\n 6. {type}: GPU type\n 7. {dedicated-total}: GPU total dedicated memory\n 8. {dedicated-used}: GPU used dedicated memory\n 9. {shared-total}: GPU total shared memory\n 10. {shared-used}: GPU used shared memory\n 11. {platform-api}: The platform API used when detecting the GPU\n 12. {frequency}: Current frequency in GHz\n 13. {index}: GPU vendor specific index\n 14. {dedicated-percentage-num}: Dedicated memory usage percentage num\n 15. {dedicated-percentage-bar}: Dedicated memory usage percentage bar\n 16. {shared-percentage-num}: Shared memory usage percentage num\n 17. {shared-percentage-bar}: Shared memory usage percentage bar\n 18. {core-usage-num}: Core usage percentage num\n 19. {core-usage-bar}: Core usage percentage bar\n 20. {memory-type}: Memory type (Windows only)\n 21. {pcie-max-speed}: PCIe maximum speed in gen and lanes\n 22. {pcie-curr-speed}: PCIe current speed in gen and lanes",
|
||||
"type": "string"
|
||||
},
|
||||
"hostFormat": {
|
||||
@@ -446,7 +446,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"packagesFormat": {
|
||||
"description": "Output format for the `Packages` module. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {am-system}: Number of am-system packages\n 3. {am-user}: Number of am-user (aka appman) packages\n 4. {appimage}: Number of appimage packages\n 5. {apk}: Number of apk packages\n 6. {brew}: Number of brew packages\n 7. {brew-all}: Total number of all brew packages\n 8. {brew-cask}: Number of brew-cask packages\n 9. {cards}: Number of cards packages\n 10. {choco}: Number of choco packages\n 11. {dpkg}: Number of dpkg packages\n 12. {emerge}: Number of emerge packages\n 13. {eopkg}: Number of eopkg packages\n 14. {flatpak-all}: Total number of all flatpak app packages\n 15. {flatpak-system}: Number of flatpak-system app packages\n 16. {flatpak-user}: Number of flatpak-user app packages\n 17. {guix-all}: Total number of all guix packages\n 18. {guix-home}: Number of guix-home packages\n 19. {guix-system}: Number of guix-system packages\n 20. {guix-user}: Number of guix-user packages\n 21. {hpkg-all}: Total number of all hpkg packages\n 22. {hpkg-system}: Number of hpkg-system packages\n 23. {hpkg-user}: Number of hpkg-user packages\n 24. {kiss}: Number of kiss packages\n 25. {linglong}: Number of linglong packages\n 26. {lpkg}: Number of lpkg packages\n 27. {lpkgbuild}: Number of lpkgbuild packages\n 28. {macports}: Number of macports packages\n 29. {mport}: Number of mport packages\n 30. {moss}: Number of moss packages\n 31. {nix-all}: Total number of all nix packages\n 32. {nix-default}: Number of nix-default packages\n 33. {nix-system}: Number of nix-system packages\n 34. {nix-user}: Number of nix-user packages\n 35. {opkg}: Number of opkg packages\n 36. {pacman}: Number of pacman packages\n 37. {pacman-branch}: Pacman branch on manjaro\n 38. {pacstall}: Number of pacstall packages\n 39. {paludis}: Number of paludis packages\n 40. {pisi}: Number of pisi packages\n 41. {pkg}: Number of pkg packages\n 42. {pkgsrc}: Number of pkgsrc packages\n 43. {pkgtool}: Number of pkgtool packages\n 44. {rpm}: Number of rpm packages\n 45. {scoop-global}: Number of scoop-global packages\n 46. {scoop-user}: Number of scoop-user packages\n 47. {snap}: Number of snap packages\n 48. {soar}: Number of soar packages\n 49. {sorcery}: Number of sorcery packages\n 50. {winget}: Number of winget packages\n 51. {xbps}: Number of xbps packages",
|
||||
"description": "Output format for the `Packages` module. See Wiki for formatting syntax\n 1. {am-system}: Number of am-system packages\n 2. {am-user}: Number of am-user (aka appman) packages\n 3. {appimage}: Number of appimage packages\n 4. {apk}: Number of apk packages\n 5. {brew}: Number of brew packages\n 6. {brew-cask}: Number of brew-cask packages\n 7. {cards}: Number of cards packages\n 8. {choco}: Number of choco packages\n 9. {dpkg}: Number of dpkg packages\n 10. {emerge}: Number of emerge packages\n 11. {eopkg}: Number of eopkg packages\n 12. {flatpak-system}: Number of flatpak-system app packages\n 13. {flatpak-user}: Number of flatpak-user app packages\n 14. {guix-home}: Number of guix-home packages\n 15. {guix-system}: Number of guix-system packages\n 16. {guix-user}: Number of guix-user packages\n 17. {hpkg-system}: Number of hpkg-system packages\n 18. {hpkg-user}: Number of hpkg-user packages\n 19. {install-release}: Number of install-release packages\n 20. {kiss}: Number of kiss packages\n 21. {linglong}: Number of linglong packages\n 22. {lpkg}: Number of lpkg packages\n 23. {lpkgbuild}: Number of lpkgbuild packages\n 24. {macports}: Number of macports packages\n 25. {mport}: Number of mport packages\n 26. {moss}: Number of moss packages\n 27. {nix-default}: Number of nix-default packages\n 28. {nix-system}: Number of nix-system packages\n 29. {nix-user}: Number of nix-user packages\n 30. {opkg}: Number of opkg packages\n 31. {pacman}: Number of pacman packages\n 32. {pacman-branch}: Pacman branch on manjaro\n 33. {pacstall}: Number of pacstall packages\n 34. {paludis}: Number of paludis packages\n 35. {pisi}: Number of pisi packages\n 36. {pkg}: Number of pkg packages\n 37. {pkgsrc}: Number of pkgsrc packages\n 38. {pkgtool}: Number of pkgtool packages\n 39. {porg}: Number of porg packages\n 40. {rpm}: Number of rpm packages\n 41. {scoop-global}: Number of scoop-global packages\n 42. {scoop-user}: Number of scoop-user packages\n 43. {snap}: Number of snap packages\n 44. {soar}: Number of soar packages\n 45. {sorcery}: Number of sorcery packages\n 46. {winget}: Number of winget packages\n 47. {xbps}: Number of xbps packages\n 48. {brew-all}: Total number of all brew packages\n 49. {flatpak-all}: Total number of all flatpak app packages\n 50. {guix-all}: Total number of all guix packages\n 51. {hpkg-all}: Total number of all hpkg packages\n 52. {nix-all}: Total number of all nix packages\n 53. {all}: Number of all packages",
|
||||
"type": "string"
|
||||
},
|
||||
"physicaldiskFormat": {
|
||||
@@ -2850,6 +2850,10 @@
|
||||
"const": "opencl",
|
||||
"description": "Use OpenCL API.\nSlow and requires proper OpenCL drivers to be installed"
|
||||
},
|
||||
{
|
||||
"const": "egl-ext",
|
||||
"description": "Use EGL_EXT_device_enumeration and EGL_EXT_device_query APIs.\nSlow and only detects GPUs that support these extensions"
|
||||
},
|
||||
{
|
||||
"const": "opengl",
|
||||
"description": "Use OpenGL API.\nSlow and only detects one GPU.\nUsed for OpenBSD"
|
||||
|
||||
+13
-13
@@ -42,12 +42,12 @@
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
@@ -62,22 +62,22 @@
|
||||
},
|
||||
{
|
||||
"type": "lm",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "wmtheme",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "icons",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
@@ -92,32 +92,32 @@
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
@@ -132,7 +132,7 @@
|
||||
},
|
||||
{
|
||||
"type": "player",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
+9
-2
@@ -15,8 +15,6 @@ typedef struct FFlist {
|
||||
uint32_t capacity;
|
||||
} FFlist;
|
||||
|
||||
void* ffListAdd(FFlist* list, uint32_t elementSize);
|
||||
|
||||
// Removes the first element, and copy its value to `*result`
|
||||
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result);
|
||||
// Removes the last element, and copy its value to `*result`
|
||||
@@ -105,6 +103,15 @@ static inline void ffListReserve(FFlist* list, uint32_t elementSize, uint32_t ne
|
||||
list->capacity = newCapacity;
|
||||
}
|
||||
|
||||
static inline void* ffListAdd(FFlist* list, uint32_t elementSize) {
|
||||
if (__builtin_expect(list->length == list->capacity, false)) {
|
||||
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
|
||||
}
|
||||
|
||||
++list->length;
|
||||
return ffListGet(list, elementSize, list->length - 1);
|
||||
}
|
||||
|
||||
#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
|
||||
for (itemType* itemVarName = (itemType*) (listVar).data; \
|
||||
itemVarName - (itemType*) (listVar).data < (intptr_t) (listVar).length; \
|
||||
|
||||
+100
-46
@@ -37,16 +37,13 @@ static inline void ffStrbufInit(FFstrbuf* strbuf);
|
||||
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
|
||||
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments);
|
||||
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr);
|
||||
FF_A_PRINTF(2, 3) void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...);
|
||||
FF_A_PRINTF(1, 2) FF_A_NODISCARD FFstrbuf ffStrbufCreateF(const char* format, ...);
|
||||
|
||||
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);
|
||||
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free);
|
||||
|
||||
void ffStrbufClear(FFstrbuf* strbuf);
|
||||
void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free);
|
||||
|
||||
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value);
|
||||
void ffStrbufAppendC(FFstrbuf* strbuf, char c);
|
||||
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c);
|
||||
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int));
|
||||
FF_A_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
|
||||
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
|
||||
@@ -88,13 +85,6 @@ bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end);
|
||||
|
||||
bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c);
|
||||
|
||||
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file);
|
||||
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file);
|
||||
|
||||
FF_A_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue);
|
||||
FF_A_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue);
|
||||
FF_A_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue);
|
||||
|
||||
void ffStrbufUpperCase(FFstrbuf* strbuf);
|
||||
void ffStrbufLowerCase(FFstrbuf* strbuf);
|
||||
|
||||
@@ -182,31 +172,6 @@ FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateMove(FFstrbuf* src) {
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateVF(const char* format, va_list arguments) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitVF(&strbuf, format, arguments);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
FF_A_PRINTF(2, 3) static inline void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
ffStrbufInitVF(strbuf, format, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
FF_A_PRINTF(1, 2) FF_A_NODISCARD static inline FFstrbuf
|
||||
ffStrbufCreateF(const char* format, ...) {
|
||||
FFstrbuf strbuf;
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
ffStrbufInitVF(&strbuf, format, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitMoveS(FFstrbuf* strbuf, char* heapStr) {
|
||||
ffStrbufInitMoveNS(strbuf, (uint32_t) strlen(heapStr), heapStr);
|
||||
}
|
||||
@@ -229,6 +194,76 @@ FF_A_NODISCARD static inline uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) {
|
||||
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
|
||||
}
|
||||
|
||||
static inline void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
|
||||
if (__builtin_expect(free == 0, false)) {
|
||||
if (__builtin_expect(!(strbuf->allocated == 0 && strbuf->length > 0), true)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (__builtin_expect(ffStrbufGetFree(strbuf) >= free, true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufEnsureFreeNoCheck(strbuf, free);
|
||||
}
|
||||
|
||||
|
||||
static inline void ffStrbufClear(FFstrbuf* strbuf) {
|
||||
assert(strbuf != NULL);
|
||||
extern char* CHAR_NULL_PTR;
|
||||
|
||||
if (strbuf->allocated == 0) {
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
} else {
|
||||
strbuf->chars[0] = '\0';
|
||||
}
|
||||
|
||||
strbuf->length = 0;
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
|
||||
if (__builtin_expect(ffStrbufGetFree(strbuf) == 0, false)) {
|
||||
ffStrbufEnsureFreeNoCheck(strbuf, 1);
|
||||
}
|
||||
strbuf->chars[strbuf->length++] = c;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
|
||||
if (__builtin_expect(num == 0, false)) {
|
||||
return;
|
||||
}
|
||||
if (__builtin_expect(ffStrbufGetFree(strbuf) < num, false)) {
|
||||
ffStrbufEnsureFreeNoCheck(strbuf, num);
|
||||
}
|
||||
|
||||
memset(&strbuf->chars[strbuf->length], c, num);
|
||||
strbuf->length += num;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
|
||||
if (__builtin_expect(value == NULL || length == 0, false)) {
|
||||
return;
|
||||
}
|
||||
if (__builtin_expect(ffStrbufGetFree(strbuf) < length, false)) {
|
||||
ffStrbufEnsureFreeNoCheck(strbuf, length);
|
||||
}
|
||||
|
||||
memcpy(&strbuf->chars[strbuf->length], value, length);
|
||||
strbuf->length += length;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
|
||||
assert(value != strbuf);
|
||||
if (value == NULL) {
|
||||
return;
|
||||
}
|
||||
ffStrbufAppendNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) {
|
||||
strbuf->length = (uint32_t) strlen(strbuf->chars);
|
||||
}
|
||||
@@ -338,14 +373,6 @@ FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateS(const char* str) {
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
|
||||
assert(value != strbuf);
|
||||
if (value == NULL) {
|
||||
return;
|
||||
}
|
||||
ffStrbufAppendNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufPrepend(FFstrbuf* strbuf, FFstrbuf* value) {
|
||||
if (value == NULL) {
|
||||
return;
|
||||
@@ -578,6 +605,33 @@ static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const
|
||||
return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
|
||||
}
|
||||
|
||||
static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
ffStrbufWriteTo(strbuf, file);
|
||||
fputc('\n', file);
|
||||
}
|
||||
|
||||
FF_A_NODISCARD static inline double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
|
||||
char* str_end;
|
||||
double result = strtod(strbuf->chars, &str_end);
|
||||
return str_end == strbuf->chars ? defaultValue : result;
|
||||
}
|
||||
|
||||
FF_A_NODISCARD static inline uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
|
||||
char* str_end;
|
||||
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
|
||||
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
|
||||
}
|
||||
|
||||
FF_A_NODISCARD static inline int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
|
||||
char* str_end;
|
||||
long long result = strtoll(strbuf->chars, &str_end, 10);
|
||||
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
|
||||
}
|
||||
|
||||
// Returns true if the strbuf is modified
|
||||
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf);
|
||||
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -236,54 +236,38 @@ static void getSystemPageSize(FFPlatformSysinfo* info) {
|
||||
}
|
||||
|
||||
static void getSystemArchitecture(FFPlatformSysinfo* info) {
|
||||
SYSTEM_PROCESSOR_INFORMATION spi;
|
||||
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorInformation, &spi, sizeof(spi), NULL))) {
|
||||
switch (spi.ProcessorArchitecture) {
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
ffStrbufSetStatic(&info->architecture, "x86_64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
ffStrbufSetStatic(&info->architecture, "ia64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
switch (spi.ProcessorLevel) {
|
||||
case 4:
|
||||
ffStrbufSetStatic(&info->architecture, "i486");
|
||||
break;
|
||||
case 5:
|
||||
ffStrbufSetStatic(&info->architecture, "i586");
|
||||
break;
|
||||
case 6:
|
||||
ffStrbufSetStatic(&info->architecture, "i686");
|
||||
break;
|
||||
default:
|
||||
ffStrbufSetStatic(&info->architecture, "i386");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ARM64:
|
||||
ffStrbufSetStatic(&info->architecture, "aarch64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ARM:
|
||||
ffStrbufSetStatic(&info->architecture, "arm");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_PPC:
|
||||
ffStrbufSetStatic(&info->architecture, "ppc");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_MIPS:
|
||||
ffStrbufSetStatic(&info->architecture, "mips");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA:
|
||||
ffStrbufSetStatic(&info->architecture, "alpha");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA64:
|
||||
ffStrbufSetStatic(&info->architecture, "alpha64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_UNKNOWN:
|
||||
default:
|
||||
ffStrbufSetStatic(&info->architecture, "unknown");
|
||||
break;
|
||||
}
|
||||
switch (SharedUserData->NativeProcessorArchitecture) {
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
ffStrbufSetStatic(&info->architecture, "x86_64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
ffStrbufSetStatic(&info->architecture, "ia64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
ffStrbufSetStatic(&info->architecture, "i686");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ARM64:
|
||||
ffStrbufSetStatic(&info->architecture, "aarch64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ARM:
|
||||
ffStrbufSetStatic(&info->architecture, "arm");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_PPC:
|
||||
ffStrbufSetStatic(&info->architecture, "ppc");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_MIPS:
|
||||
ffStrbufSetStatic(&info->architecture, "mips");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA:
|
||||
ffStrbufSetStatic(&info->architecture, "alpha");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA64:
|
||||
ffStrbufSetStatic(&info->architecture, "alpha64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_UNKNOWN:
|
||||
default:
|
||||
ffStrbufSetStatic(&info->architecture, "unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void* ffListAdd(FFlist* list, uint32_t elementSize) {
|
||||
if (list->length == list->capacity) {
|
||||
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
|
||||
}
|
||||
|
||||
++list->length;
|
||||
return ffListGet(list, elementSize, list->length - 1);
|
||||
}
|
||||
|
||||
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result) {
|
||||
if (list->length == 0) {
|
||||
return false;
|
||||
|
||||
+26
-78
@@ -45,18 +45,33 @@ void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr) {
|
||||
strbuf->chars = heapStr;
|
||||
}
|
||||
|
||||
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
|
||||
if (ffStrbufGetFree(strbuf) >= free && !(strbuf->allocated == 0 && strbuf->length > 0)) {
|
||||
return;
|
||||
}
|
||||
void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
ffStrbufInitVF(strbuf, format, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
uint32_t allocate = strbuf->allocated;
|
||||
if (allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) {
|
||||
FFstrbuf ffStrbufCreateF(const char* format, ...) {
|
||||
FFstrbuf strbuf;
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
ffStrbufInitVF(&strbuf, format, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free) {
|
||||
uint32_t allocate = strbuf->length + free;
|
||||
if (allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) { // `<` for null terminator
|
||||
allocate = FASTFETCH_STRBUF_DEFAULT_ALLOC;
|
||||
}
|
||||
|
||||
while ((strbuf->length + free + 1) > allocate) { // + 1 for the null byte
|
||||
allocate *= 2;
|
||||
} else {
|
||||
// Round up to the next power of 2.
|
||||
// If the value is already a power of 2, it will be rounded up to the next power of 2.
|
||||
assert(allocate < (UINT32_MAX >> 1));
|
||||
allocate = 1U << (32 - __builtin_clz(allocate));
|
||||
}
|
||||
|
||||
if (strbuf->allocated == 0) {
|
||||
@@ -100,46 +115,6 @@ void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) {
|
||||
strbuf->allocated = newCap;
|
||||
}
|
||||
|
||||
void ffStrbufClear(FFstrbuf* strbuf) {
|
||||
assert(strbuf != NULL);
|
||||
|
||||
if (strbuf->allocated == 0) {
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
} else {
|
||||
strbuf->chars[0] = '\0';
|
||||
}
|
||||
|
||||
strbuf->length = 0;
|
||||
}
|
||||
|
||||
void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
|
||||
ffStrbufEnsureFree(strbuf, 1);
|
||||
strbuf->chars[strbuf->length++] = c;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
|
||||
if (num == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFree(strbuf, num);
|
||||
memset(&strbuf->chars[strbuf->length], c, num);
|
||||
strbuf->length += num;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
|
||||
if (value == NULL || length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFree(strbuf, length);
|
||||
memcpy(&strbuf->chars[strbuf->length], value, length);
|
||||
strbuf->length += length;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int)) {
|
||||
if (value == NULL) {
|
||||
return;
|
||||
@@ -168,7 +143,7 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) {
|
||||
int written = vsnprintf(strbuf->chars + strbuf->length, strbuf->allocated > 0 ? free + 1 : 0, format, arguments);
|
||||
|
||||
if (written > 0 && (uint32_t) written > free) {
|
||||
ffStrbufEnsureFree(strbuf, (uint32_t) written);
|
||||
ffStrbufEnsureFreeNoCheck(strbuf, (uint32_t) written);
|
||||
written = vsnprintf(strbuf->chars + strbuf->length, (uint32_t) written + 1, format, copy);
|
||||
}
|
||||
|
||||
@@ -550,33 +525,6 @@ bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
|
||||
}
|
||||
|
||||
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
ffStrbufWriteTo(strbuf, file);
|
||||
fputc('\n', file);
|
||||
}
|
||||
|
||||
double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
|
||||
char* str_end;
|
||||
double result = strtod(strbuf->chars, &str_end);
|
||||
return str_end == strbuf->chars ? defaultValue : result;
|
||||
}
|
||||
|
||||
uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
|
||||
char* str_end;
|
||||
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
|
||||
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
|
||||
}
|
||||
|
||||
int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
|
||||
char* str_end;
|
||||
long long result = strtoll(strbuf->chars, &str_end, 10);
|
||||
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
|
||||
}
|
||||
|
||||
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value) {
|
||||
ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number
|
||||
char* start = strbuf->chars + strbuf->length;
|
||||
|
||||
@@ -34,7 +34,7 @@ void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char*
|
||||
|
||||
static uint8_t decode_table[256];
|
||||
|
||||
void init_decode_table() {
|
||||
static void init_decode_table() {
|
||||
uint8_t ch = 0;
|
||||
do {
|
||||
int32_t code = -1;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -191,7 +191,7 @@ static bool parseLuaString(FFstrbuf* buffer, const char* script, uint32_t script
|
||||
lua_pushboolean(L, *(bool*) arg->value);
|
||||
break;
|
||||
case FF_ARG_TYPE_STRING:
|
||||
lua_pushstring(L, (const char*) arg->value);
|
||||
lua_pushlstring(L, (const char*) arg->value, strlen((const char*) arg->value));
|
||||
break;
|
||||
case FF_ARG_TYPE_STRBUF: {
|
||||
const FFstrbuf* sb = (const FFstrbuf*) arg->value;
|
||||
@@ -232,7 +232,6 @@ static bool parseLuaString(FFstrbuf* buffer, const char* script, uint32_t script
|
||||
if (res) {
|
||||
ffStrbufAppendS(buffer, res);
|
||||
} else {
|
||||
// Fallback: use luaL_tolstring to get a reasonable representation
|
||||
luaL_tolstring(L, 1, NULL);
|
||||
const char* sval = lua_tolstring(L, -1, NULL);
|
||||
if (sval) {
|
||||
|
||||
+32
-23
@@ -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"
|
||||
|
||||
@@ -177,7 +177,7 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) {
|
||||
}
|
||||
|
||||
static inline void readWithLength(HANDLE handle, FFstrbuf* buffer, uint32_t length) {
|
||||
ffStrbufEnsureFree(buffer, length);
|
||||
ffStrbufEnsureFixedLengthFree(buffer, length);
|
||||
DWORD bytesRead = 0;
|
||||
while (
|
||||
length > 0 &&
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void* libraryLoad(const char* path, int maxVersion) {
|
||||
void* ffLibraryLoadSingle(const char* path, int maxVersion) {
|
||||
void* result = dlopen(path, FF_DLOPEN_FLAGS);
|
||||
|
||||
#if _WIN32
|
||||
@@ -81,8 +81,8 @@ static void* libraryLoad(const char* path, int maxVersion) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void* ffLibraryLoad(const char* path, int maxVersion, ...) {
|
||||
void* result = libraryLoad(path, maxVersion);
|
||||
void* ffLibraryLoadMulti(const char* path, int maxVersion, ...) {
|
||||
void* result = ffLibraryLoadSingle(path, maxVersion);
|
||||
|
||||
if (!result) {
|
||||
va_list defaultNames;
|
||||
@@ -95,7 +95,7 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...) {
|
||||
}
|
||||
|
||||
int maxVersionRest = va_arg(defaultNames, int);
|
||||
result = libraryLoad(pathRest, maxVersionRest);
|
||||
result = ffLibraryLoadSingle(pathRest, maxVersionRest);
|
||||
} while (!result);
|
||||
|
||||
va_end(defaultNames);
|
||||
|
||||
+44
-27
@@ -5,7 +5,15 @@
|
||||
|
||||
struct FFLuaData luaData;
|
||||
|
||||
static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc) {
|
||||
static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc, int depth) {
|
||||
if (__builtin_expect(depth > 15, false)) {
|
||||
yyjson_mut_doc_free(doc);
|
||||
lua_pushlstring(
|
||||
L, "yyjson: recursion depth exceeded; possible circular reference", strlen("yyjson: recursion depth exceeded; possible circular reference"));
|
||||
lua_error(L); // noreturn
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
if (idx < 0) {
|
||||
idx = lua_gettop(L) + idx + 1;
|
||||
}
|
||||
@@ -66,7 +74,7 @@ static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc) {
|
||||
yyjson_mut_val* arr = yyjson_mut_arr(doc);
|
||||
for (lua_Unsigned i = 1; i <= len; i++) {
|
||||
lua_rawgeti(L, idx, (lua_Integer) i);
|
||||
yyjson_mut_val* val = lua2yyjson(L, -1, doc);
|
||||
yyjson_mut_val* val = lua2yyjson(L, -1, doc, depth + 1);
|
||||
yyjson_mut_arr_append(arr, val);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
@@ -80,7 +88,7 @@ static yyjson_mut_val* lua2yyjson(lua_State* L, int idx, yyjson_mut_doc* doc) {
|
||||
yyjson_mut_val* key = yyjson_mut_strncpy(doc, key_str, klen);
|
||||
lua_pop(L, 1);
|
||||
|
||||
yyjson_mut_val* val = lua2yyjson(L, -1, doc);
|
||||
yyjson_mut_val* val = lua2yyjson(L, -1, doc, depth + 1);
|
||||
yyjson_mut_obj_add(obj, key, val);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
@@ -102,28 +110,35 @@ static int yyjsonEncode(lua_State* L) {
|
||||
}
|
||||
|
||||
yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL);
|
||||
if (!doc) {
|
||||
return luaL_error(L, "failed to create yyjson document");
|
||||
if (__builtin_expect(!doc, false)) {
|
||||
lua_pushlstring(L, "yyjson: yyjson_mut_doc_new() failed", strlen("yyjson: yyjson_mut_doc_new() failed"));
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
yyjson_mut_val* root = lua2yyjson(L, 1, doc);
|
||||
yyjson_mut_val* root = lua2yyjson(L, 1, doc, 0);
|
||||
yyjson_mut_doc_set_root(doc, root);
|
||||
|
||||
size_t jsonLen;
|
||||
yyjson_write_err err = {};
|
||||
FF_AUTO_FREE const char* jsonStr = yyjson_mut_write_opts(doc, YYJSON_WRITE_ALLOW_INF_AND_NAN | (pretty ? YYJSON_WRITE_PRETTY_TWO_SPACES : 0), NULL, &jsonLen, &err);
|
||||
|
||||
if (jsonStr) {
|
||||
if (__builtin_expect(jsonStr != NULL, true)) {
|
||||
lua_pushlstring(L, jsonStr, jsonLen);
|
||||
yyjson_mut_doc_free(doc);
|
||||
return 1;
|
||||
} else {
|
||||
yyjson_mut_doc_free(doc);
|
||||
return luaL_error(L, "failed to encode JSON: %s", err.msg);
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY errBuf = ffStrbufCreateStatic("yyjson: yyjson_mut_write_opts() failed: ");
|
||||
ffStrbufAppendS(&errBuf, err.msg);
|
||||
lua_pushlstring(L, errBuf.chars, errBuf.length);
|
||||
}
|
||||
|
||||
return lua_error(L); // longjmp
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffLuaLoadState() {
|
||||
const char* ffLuaLoadState(void) {
|
||||
if (luaData.inited) {
|
||||
if (luaData.L == NULL) {
|
||||
return "Lua library is not available";
|
||||
@@ -163,35 +178,37 @@ const char* ffLuaLoadState() {
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(liblua, luaopen_string)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(liblua, luaopen_table)
|
||||
#endif
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_settop)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_loadbufferx)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tolstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_createtable)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushinteger)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnumber)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushboolean)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushlstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushvalue)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_seti)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnil)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_setfield)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pcallk)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_gettop)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_tolstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_error)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushcclosure)
|
||||
|
||||
#if !FF_DISABLE_DLOPEN
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_checkany)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_loadbufferx)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, luaL_tolstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_callk)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_createtable)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_error)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_gettop)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_isinteger)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_next)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pcallk)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushboolean)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushcclosure)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushinteger)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushlstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnil)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushnumber)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_pushvalue)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_rawgeti)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_rawlen)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_setfield)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_setglobal)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_seti)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_settop)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_toboolean)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tointegerx)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tolstring)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_tonumberx)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(liblua, luaData, lua_type)
|
||||
#endif
|
||||
|
||||
lua_State* L = ffluaL_newstate();
|
||||
if (L == NULL) {
|
||||
|
||||
@@ -1,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;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ int ffSettingsGetSQLite3Int(const char* dbPath, const char* query) {
|
||||
}
|
||||
|
||||
sqlite3* db;
|
||||
if (data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) {
|
||||
if (data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
// DON'T CALL ANY FASTFETCH FUNCTION IN THIS FILE (to avoid recursion when -finstrument-functions is enabled)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#if !_WIN32
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
static LARGE_INTEGER freq;
|
||||
#define NtCurrentProcess() ((HANDLE) (-1))
|
||||
#endif
|
||||
|
||||
static struct trace_event {
|
||||
uint64_t ts;
|
||||
uint64_t tid;
|
||||
void* func;
|
||||
} events[4 * 1024 * 1024]; // 4M events, 96 MiB memory usage
|
||||
static _Atomic uint32_t event_count;
|
||||
|
||||
__attribute__((no_instrument_function, always_inline)) static inline uint64_t get_time_us() {
|
||||
#if !_WIN32
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
|
||||
#else
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
return (uint64_t) (now.QuadPart * 1000000 / freq.QuadPart);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
__attribute__((constructor, no_instrument_function)) void trace_init() {
|
||||
QueryPerformanceFrequency(&freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((destructor, no_instrument_function)) void trace_fini() {
|
||||
#if _WIN32
|
||||
uint32_t pid = (uint32_t) GetCurrentProcessId();
|
||||
#else
|
||||
uint32_t pid = (uint32_t) getpid();
|
||||
#endif
|
||||
|
||||
char fileName[64];
|
||||
snprintf(fileName, sizeof(fileName), "trace_%d.json", pid);
|
||||
FILE* trace_file = fopen(fileName, "wb");
|
||||
if (!trace_file) {
|
||||
fprintf(stderr, "Failed to open trace file %s for writing\n", fileName);
|
||||
abort();
|
||||
}
|
||||
|
||||
fputs("[\n", trace_file);
|
||||
|
||||
#if _WIN32
|
||||
SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
|
||||
SymInitialize(NtCurrentProcess(), NULL, TRUE);
|
||||
#endif
|
||||
|
||||
const char* fnName = NULL;
|
||||
|
||||
uint32_t count = atomic_load_explicit(&event_count, memory_order_acquire);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
void* fn = events[i].func;
|
||||
uint64_t ts = events[i].ts;
|
||||
bool is_exit = (ts >> 63) != 0;
|
||||
ts &= ~(1ULL << 63); // clear the highest bit
|
||||
uint64_t tid = events[i].tid;
|
||||
|
||||
#if _WIN32
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 displacement = 0;
|
||||
if (SymFromAddr(NtCurrentProcess(), (DWORD64) fn, &displacement, pSymbol)) {
|
||||
fnName = pSymbol->Name;
|
||||
}
|
||||
#else
|
||||
char buffer[32];
|
||||
Dl_info info;
|
||||
if (dladdr(fn, &info) && info.dli_sname) {
|
||||
fnName = info.dli_sname;
|
||||
}
|
||||
#endif
|
||||
|
||||
else {
|
||||
snprintf(buffer, sizeof(buffer), "%p", fn);
|
||||
fnName = buffer;
|
||||
}
|
||||
|
||||
fprintf(trace_file, "{\"name\":\"%s\",\"ph\":\"%c\",\"pid\":%" PRIu32 ",\"tid\":%" PRIu64 ",\"ts\":%" PRIu64 "}%c\n", fnName, is_exit ? 'E' : 'B', pid, tid, ts, i < count - 1 ? ',' : ' ');
|
||||
}
|
||||
|
||||
fputc(']', trace_file);
|
||||
fclose(trace_file);
|
||||
fprintf(stderr, "Trace written to trace_%d.json with %u events. Use https://ui.perfetto.dev/ to view it.\n", pid, count);
|
||||
|
||||
#if _WIN32
|
||||
SymCleanup(NtCurrentProcess());
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((no_instrument_function)) static void write_event(void* this_fn, bool is_exit) {
|
||||
uint32_t idx = atomic_fetch_add_explicit(&event_count, 1, memory_order_relaxed);
|
||||
if (__builtin_expect(idx >= sizeof(events) / sizeof(events[0]), false)) {
|
||||
abort();
|
||||
}
|
||||
|
||||
events[idx].ts = get_time_us();
|
||||
#if ENABLE_THREADS
|
||||
#if _WIN32
|
||||
events[idx].tid = (uint64_t) GetCurrentThreadId();
|
||||
#else
|
||||
events[idx].tid = (uint64_t) (uintptr_t) pthread_self();
|
||||
#endif
|
||||
#else
|
||||
events[idx].tid = 0;
|
||||
#endif
|
||||
events[idx].func = this_fn;
|
||||
if (is_exit) {
|
||||
events[idx].ts |= (1ULL << 63); // set the highest bit to indicate function exit
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((no_instrument_function)) void __cyg_profile_func_enter(void* this_fn, void* call_site) {
|
||||
(void) call_site;
|
||||
write_event(this_fn, false);
|
||||
}
|
||||
|
||||
__attribute__((no_instrument_function)) void __cyg_profile_func_exit(void* this_fn, void* call_site) {
|
||||
(void) call_site;
|
||||
write_event(this_fn, true);
|
||||
}
|
||||
+17
-25
@@ -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)
|
||||
|
||||
@@ -35,9 +35,10 @@ static inline void ffLibraryUnload(void** handle) {
|
||||
#define FF_LIBRARY_SYMBOL(symbolName) \
|
||||
__typeof__(&symbolName) ff##symbolName;
|
||||
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...) \
|
||||
void* FF_A_CLEANUP(ffLibraryUnload) libraryObjectName = ffLibraryLoad(__VA_ARGS__, NULL); \
|
||||
if (libraryObjectName == NULL) \
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, returnValue, libraryFileName, maxVersion, ...) \
|
||||
void* FF_A_CLEANUP(ffLibraryUnload) libraryObjectName = ffLibraryLoadSingle(libraryFileName, maxVersion); \
|
||||
__VA_OPT__(if (__builtin_expect(libraryObjectName == NULL, false)) libraryObjectName = ffLibraryLoadMulti(__VA_ARGS__, NULL);) \
|
||||
if (__builtin_expect(libraryObjectName == NULL, false)) \
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
|
||||
@@ -45,7 +46,7 @@ static inline void ffLibraryUnload(void** handle) {
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
|
||||
symbolMapping = (__typeof__(&symbolName)) dlsym(library, #symbolName); \
|
||||
if (symbolMapping == NULL) \
|
||||
if (__builtin_expect(symbolMapping == NULL, false)) \
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
|
||||
@@ -66,7 +67,8 @@ static inline void ffLibraryUnload(void** handle) {
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff##symbolName, symbolName, returnValue);
|
||||
|
||||
void* ffLibraryLoad(const char* path, int maxVersion, ...);
|
||||
void* ffLibraryLoadSingle(const char* path, int maxVersion);
|
||||
void* ffLibraryLoadMulti(const char* path, int maxVersion, ...);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
+45
-41
@@ -3,16 +3,19 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#if FF_HAVE_LUA
|
||||
// Hack. LUA_API is defined as extern which prevents us from implementing the functions ourselves.
|
||||
#include <luaconf.h>
|
||||
#undef LUA_API
|
||||
#undef LUALIB_API
|
||||
#undef LUAMOD_API
|
||||
#define LUA_API static inline
|
||||
#define LUALIB_API LUA_API
|
||||
#define LUAMOD_API LUA_API
|
||||
#if !FF_DISABLE_DLOPEN
|
||||
// Hack. LUA_API is defined as extern which prevents us from implementing the functions ourselves.
|
||||
#include <luaconf.h>
|
||||
#undef LUA_API
|
||||
#undef LUALIB_API
|
||||
#undef LUAMOD_API
|
||||
#define LUA_API static inline
|
||||
#define LUALIB_API LUA_API
|
||||
#define LUAMOD_API LUA_API
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
@@ -24,48 +27,42 @@
|
||||
#include "common/library.h"
|
||||
|
||||
extern struct FFLuaData {
|
||||
FF_LIBRARY_SYMBOL(luaL_newstate)
|
||||
#if LUA_VERSION_NUM >= 505
|
||||
FF_LIBRARY_SYMBOL(luaL_openselectedlibs)
|
||||
#else
|
||||
FF_LIBRARY_SYMBOL(luaL_openlibs)
|
||||
#endif
|
||||
FF_LIBRARY_SYMBOL(lua_settop)
|
||||
FF_LIBRARY_SYMBOL(luaL_loadbufferx)
|
||||
FF_LIBRARY_SYMBOL(lua_tolstring)
|
||||
FF_LIBRARY_SYMBOL(lua_createtable)
|
||||
FF_LIBRARY_SYMBOL(lua_pushinteger)
|
||||
FF_LIBRARY_SYMBOL(lua_pushnumber)
|
||||
FF_LIBRARY_SYMBOL(lua_pushboolean)
|
||||
FF_LIBRARY_SYMBOL(lua_pushstring)
|
||||
FF_LIBRARY_SYMBOL(lua_pushlstring)
|
||||
FF_LIBRARY_SYMBOL(lua_pushvalue)
|
||||
FF_LIBRARY_SYMBOL(lua_seti)
|
||||
FF_LIBRARY_SYMBOL(lua_pushnil)
|
||||
FF_LIBRARY_SYMBOL(lua_setfield)
|
||||
FF_LIBRARY_SYMBOL(lua_pcallk)
|
||||
FF_LIBRARY_SYMBOL(lua_gettop)
|
||||
FF_LIBRARY_SYMBOL(luaL_tolstring)
|
||||
FF_LIBRARY_SYMBOL(luaL_error)
|
||||
FF_LIBRARY_SYMBOL(lua_pushcclosure)
|
||||
#if !FF_DISABLE_DLOPEN
|
||||
FF_LIBRARY_SYMBOL(luaL_checkany)
|
||||
FF_LIBRARY_SYMBOL(luaL_loadbufferx)
|
||||
FF_LIBRARY_SYMBOL(luaL_tolstring)
|
||||
FF_LIBRARY_SYMBOL(lua_callk)
|
||||
FF_LIBRARY_SYMBOL(lua_createtable)
|
||||
FF_LIBRARY_SYMBOL(lua_error)
|
||||
FF_LIBRARY_SYMBOL(lua_gettop)
|
||||
FF_LIBRARY_SYMBOL(lua_isinteger)
|
||||
FF_LIBRARY_SYMBOL(lua_next)
|
||||
FF_LIBRARY_SYMBOL(lua_pcallk)
|
||||
FF_LIBRARY_SYMBOL(lua_pushboolean)
|
||||
FF_LIBRARY_SYMBOL(lua_pushcclosure)
|
||||
FF_LIBRARY_SYMBOL(lua_pushinteger)
|
||||
FF_LIBRARY_SYMBOL(lua_pushlstring)
|
||||
FF_LIBRARY_SYMBOL(lua_pushnil)
|
||||
FF_LIBRARY_SYMBOL(lua_pushnumber)
|
||||
FF_LIBRARY_SYMBOL(lua_pushvalue)
|
||||
FF_LIBRARY_SYMBOL(lua_rawgeti)
|
||||
FF_LIBRARY_SYMBOL(lua_rawlen)
|
||||
FF_LIBRARY_SYMBOL(lua_setfield)
|
||||
FF_LIBRARY_SYMBOL(lua_setglobal)
|
||||
FF_LIBRARY_SYMBOL(lua_seti)
|
||||
FF_LIBRARY_SYMBOL(lua_settop)
|
||||
FF_LIBRARY_SYMBOL(lua_toboolean)
|
||||
FF_LIBRARY_SYMBOL(lua_tointegerx)
|
||||
FF_LIBRARY_SYMBOL(lua_tolstring)
|
||||
FF_LIBRARY_SYMBOL(lua_tonumberx)
|
||||
FF_LIBRARY_SYMBOL(lua_type)
|
||||
#endif
|
||||
|
||||
lua_State* L;
|
||||
bool inited;
|
||||
} luaData;
|
||||
|
||||
const char* ffLuaLoadState();
|
||||
|
||||
#if !FF_DISABLE_DLOPEN
|
||||
FF_A_ALWAYS_INLINE void(lua_settop)(lua_State* L, int idx) {
|
||||
return luaData.fflua_settop(L, idx);
|
||||
}
|
||||
@@ -94,10 +91,6 @@ FF_A_ALWAYS_INLINE void(lua_pushboolean)(lua_State* L, int b) {
|
||||
return luaData.fflua_pushboolean(L, b);
|
||||
}
|
||||
|
||||
FF_A_ALWAYS_INLINE const char*(lua_pushstring) (lua_State * L, const char* s) {
|
||||
return luaData.fflua_pushstring(L, s);
|
||||
}
|
||||
|
||||
FF_A_ALWAYS_INLINE const char*(lua_pushlstring) (lua_State * L, const char* s, size_t len) {
|
||||
return luaData.fflua_pushlstring(L, s, len);
|
||||
}
|
||||
@@ -130,7 +123,9 @@ FF_A_ALWAYS_INLINE const char*(luaL_tolstring) (lua_State * L, int idx, size_t*
|
||||
return luaData.ffluaL_tolstring(L, idx, len);
|
||||
}
|
||||
|
||||
#define luaL_error(L, fmt, ...) luaData.ffluaL_error(L, fmt, ##__VA_ARGS__)
|
||||
FF_A_ALWAYS_INLINE int(lua_error)(lua_State* L) {
|
||||
return luaData.fflua_error(L);
|
||||
}
|
||||
|
||||
FF_A_ALWAYS_INLINE void(lua_pushcclosure)(lua_State* L, lua_CFunction fn, int n) {
|
||||
return luaData.fflua_pushcclosure(L, fn, n);
|
||||
@@ -156,7 +151,13 @@ FF_A_ALWAYS_INLINE int(lua_rawgeti)(lua_State* L, int idx, lua_Integer n) {
|
||||
return luaData.fflua_rawgeti(L, idx, n);
|
||||
}
|
||||
|
||||
FF_A_ALWAYS_INLINE lua_Unsigned(lua_rawlen)(lua_State* L, int idx) {
|
||||
FF_A_ALWAYS_INLINE
|
||||
#if LUA_VERSION_NUM > 503
|
||||
lua_Unsigned
|
||||
#else
|
||||
size_t
|
||||
#endif
|
||||
(lua_rawlen)(lua_State* L, int idx) {
|
||||
return luaData.fflua_rawlen(L, idx);
|
||||
}
|
||||
|
||||
@@ -179,5 +180,8 @@ FF_A_ALWAYS_INLINE lua_Number(lua_tonumberx)(lua_State* L, int idx, int* isnum)
|
||||
FF_A_ALWAYS_INLINE int(lua_type)(lua_State* L, int idx) {
|
||||
return luaData.fflua_type(L, idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffLuaLoadState(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,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');
|
||||
}
|
||||
|
||||
+7
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
#if defined(_WIN32)
|
||||
#include <winternl.h>
|
||||
#include "common/windows/nt.h"
|
||||
#include <synchapi.h>
|
||||
#include <process.h>
|
||||
#include <processthreadsapi.h>
|
||||
@@ -41,6 +41,9 @@ static inline bool ffThreadJoin(FFThreadType thread, uint32_t timeout) {
|
||||
}
|
||||
NtClose(thread);
|
||||
return true;
|
||||
}
|
||||
static inline uintptr_t ffThreadGetCurrentId() {
|
||||
return (uintptr_t) ffGetTeb()->ClientId.UniqueThread;
|
||||
}
|
||||
#else
|
||||
#include <pthread.h>
|
||||
@@ -104,6 +107,9 @@ static inline bool ffThreadJoin(FFThreadType thread, FF_A_UNUSED uint32_t timeou
|
||||
#endif
|
||||
pthread_join(thread, NULL);
|
||||
return true;
|
||||
}
|
||||
static inline uintptr_t ffThreadGetCurrentId() {
|
||||
return (uintptr_t) pthread_self();
|
||||
}
|
||||
#endif
|
||||
#else // FF_HAVE_THREADS
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ typedef enum FF_A_PACKED FFCodecType {
|
||||
FF_CODEC_TYPE_DOLBY_VISION_HEVC = UINT32_C(1) << 16,
|
||||
FF_CODEC_TYPE_PRORES = UINT32_C(1) << 17,
|
||||
FF_CODEC_TYPE_PRORES_RAW = UINT32_C(1) << 18,
|
||||
FF_CODEC_TYPE_JPEG_XL = UINT32_C(1) << 19,
|
||||
FF_CODEC_TYPE_MAX = FF_CODEC_TYPE_JPEG_XL,
|
||||
FF_CODEC_TYPE_MAX = FF_CODEC_TYPE_PRORES_RAW,
|
||||
FF_CODEC_TYPE_FORCE_UNSIGNED = UINT32_MAX,
|
||||
} FFCodecType;
|
||||
|
||||
|
||||
@@ -7,28 +7,28 @@ static const struct {
|
||||
CMVideoCodecType codec;
|
||||
FFCodecType type;
|
||||
} FF_CODEC_CODECS[] = {
|
||||
{ kCMVideoCodecType_H263, FF_CODEC_TYPE_H263 },
|
||||
{ kCMVideoCodecType_JPEG, FF_CODEC_TYPE_MJPEG },
|
||||
{ kCMVideoCodecType_JPEG_XL, FF_CODEC_TYPE_JPEG_XL },
|
||||
{ kCMVideoCodecType_MPEG1Video, FF_CODEC_TYPE_MPEG1 },
|
||||
{ kCMVideoCodecType_MPEG2Video, FF_CODEC_TYPE_MPEG2 },
|
||||
{ kCMVideoCodecType_MPEG4Video, FF_CODEC_TYPE_DIVX_XVID },
|
||||
{ kCMVideoCodecType_H264, FF_CODEC_TYPE_H264 },
|
||||
{ kCMVideoCodecType_HEVC, FF_CODEC_TYPE_HEVC },
|
||||
{ kCMVideoCodecType_HEVCWithAlpha, FF_CODEC_TYPE_HEVC },
|
||||
{ kCMVideoCodecType_DolbyVisionHEVC, FF_CODEC_TYPE_DOLBY_VISION_HEVC },
|
||||
{ kCMVideoCodecType_DisparityHEVC, FF_CODEC_TYPE_HEVC },
|
||||
{ kCMVideoCodecType_DepthHEVC, FF_CODEC_TYPE_HEVC },
|
||||
{ kCMVideoCodecType_VP9, FF_CODEC_TYPE_VP9 },
|
||||
{ kCMVideoCodecType_AV1, FF_CODEC_TYPE_AV1 },
|
||||
{ kCMVideoCodecType_AppleProRes4444XQ, FF_CODEC_TYPE_PRORES },
|
||||
{ kCMVideoCodecType_AppleProRes4444, FF_CODEC_TYPE_PRORES },
|
||||
{ kCMVideoCodecType_AppleProRes422HQ, FF_CODEC_TYPE_PRORES },
|
||||
{ kCMVideoCodecType_AppleProRes422, FF_CODEC_TYPE_PRORES },
|
||||
{ kCMVideoCodecType_AppleProRes422LT, FF_CODEC_TYPE_PRORES },
|
||||
{ kCMVideoCodecType_AppleProRes422Proxy, FF_CODEC_TYPE_PRORES },
|
||||
{ kCMVideoCodecType_AppleProResRAW, FF_CODEC_TYPE_PRORES_RAW },
|
||||
{ kCMVideoCodecType_AppleProResRAWHQ, FF_CODEC_TYPE_PRORES_RAW },
|
||||
{ 'h263', FF_CODEC_TYPE_H263 }, // kCMVideoCodecType_H263
|
||||
{ 'jpeg', FF_CODEC_TYPE_MJPEG }, // kCMVideoCodecType_JPEG
|
||||
{ 'dmb1', FF_CODEC_TYPE_MJPEG }, // kCMVideoCodecType_JPEG_OpenDML
|
||||
{ 'mp1v', FF_CODEC_TYPE_MPEG1 }, // kCMVideoCodecType_MPEG1Video
|
||||
{ 'mp2v', FF_CODEC_TYPE_MPEG2 }, // kCMVideoCodecType_MPEG2Video
|
||||
{ 'mp4v', FF_CODEC_TYPE_DIVX_XVID }, // kCMVideoCodecType_MPEG4Video
|
||||
{ 'avc1', FF_CODEC_TYPE_H264 }, // kCMVideoCodecType_H264
|
||||
{ 'hvc1', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_HEVC
|
||||
{ 'muxa', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_HEVCWithAlpha
|
||||
{ 'dvh1', FF_CODEC_TYPE_DOLBY_VISION_HEVC }, // kCMVideoCodecType_DolbyVisionHEVC
|
||||
{ 'dish', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_DisparityHEVC
|
||||
{ 'deph', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_DepthHEVC
|
||||
{ 'vp09', FF_CODEC_TYPE_VP9 }, // kCMVideoCodecType_VP9
|
||||
{ 'av01', FF_CODEC_TYPE_AV1 }, // kCMVideoCodecType_AV1
|
||||
{ 'ap4x', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes4444XQ
|
||||
{ 'ap4h', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes4444
|
||||
{ 'apch', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422HQ
|
||||
{ 'apcn', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422
|
||||
{ 'apcs', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422LT
|
||||
{ 'apco', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422Proxy
|
||||
{ 'aprn', FF_CODEC_TYPE_PRORES_RAW }, // kCMVideoCodecType_AppleProResRAW
|
||||
{ 'aprh', FF_CODEC_TYPE_PRORES_RAW }, // kCMVideoCodecType_AppleProResRAWHQ
|
||||
};
|
||||
|
||||
static FFCodecType ffCodecCodecToType(CMVideoCodecType codec) {
|
||||
|
||||
+188
-186
@@ -1,35 +1,33 @@
|
||||
#include "codec.h"
|
||||
|
||||
#if (FF_HAVE_DRM && FF_HAVE_VA) || FF_HAVE_VDPAU
|
||||
#if FF_HAVE_VADRM || FF_HAVE_VAX11
|
||||
#define FF_HAVE_VA 1
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_VA || FF_HAVE_VDPAU
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/strutil.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#if FF_HAVE_DRM && FF_HAVE_VA
|
||||
#include "detection/gpu/gpu.h"
|
||||
#if FF_HAVE_VA
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <va/va.h>
|
||||
#include <va/va_drm.h>
|
||||
#include <xf86drm.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
typedef struct FFVAData {
|
||||
FF_LIBRARY_SYMBOL(vaInitialize)
|
||||
FF_LIBRARY_SYMBOL(vaTerminate)
|
||||
FF_LIBRARY_SYMBOL(vaMaxNumProfiles)
|
||||
FF_LIBRARY_SYMBOL(vaMaxNumEntrypoints)
|
||||
FF_LIBRARY_SYMBOL(vaQueryConfigProfiles)
|
||||
FF_LIBRARY_SYMBOL(vaQueryConfigEntrypoints)
|
||||
FF_LIBRARY_SYMBOL(vaQueryVendorString)
|
||||
FF_LIBRARY_SYMBOL(vaGetConfigAttributes)
|
||||
} FFVAData;
|
||||
|
||||
#if FF_HAVE_VDPAU
|
||||
#include <stdlib.h>
|
||||
#include <vdpau/vdpau.h>
|
||||
|
||||
VdpStatus vdp_device_create_x11(void* display, int screen, VdpDevice* device, VdpGetProcAddress** get_proc_address);
|
||||
void* XOpenDisplay(const char* display_name);
|
||||
int XCloseDisplay(void* display);
|
||||
int XDefaultScreen(void* display);
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_DRM && FF_HAVE_VA
|
||||
|
||||
static FFCodecType ffCodecProfileToType(VAProfile profile) {
|
||||
static FFCodecType vaProfileToType(VAProfile profile) {
|
||||
switch (profile) {
|
||||
case 11: // VAProfileH263Baseline
|
||||
return FF_CODEC_TYPE_H263;
|
||||
@@ -98,7 +96,7 @@ static FFCodecType ffCodecProfileToType(VAProfile profile) {
|
||||
}
|
||||
}
|
||||
|
||||
static FFCodecShowType ffCodecGetEntrypointType(VAEntrypoint entrypoint) {
|
||||
static FFCodecShowType vaGetEntrypointType(VAEntrypoint entrypoint) {
|
||||
switch (entrypoint) {
|
||||
case VAEntrypointVLD:
|
||||
case VAEntrypointIDCT:
|
||||
@@ -113,21 +111,20 @@ static FFCodecShowType ffCodecGetEntrypointType(VAEntrypoint entrypoint) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool ffCodecProfileHasOutput(
|
||||
static bool vaProfileHasOutput(
|
||||
FFVAData* vaData,
|
||||
VADisplay display,
|
||||
__typeof__(vaQueryConfigEntrypoints)* ffvaQueryConfigEntrypoints,
|
||||
__typeof__(vaGetConfigAttributes)* ffvaGetConfigAttributes,
|
||||
int maxEntrypoints,
|
||||
VAEntrypoint* entrypoints,
|
||||
VAProfile profile,
|
||||
FFCodecShowType entrypointType) {
|
||||
int numEntrypoints = maxEntrypoints;
|
||||
if (ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
|
||||
if (vaData->ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numEntrypoints; ++i) {
|
||||
if (ffCodecGetEntrypointType(entrypoints[i]) != entrypointType) {
|
||||
if (vaGetEntrypointType(entrypoints[i]) != entrypointType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -136,7 +133,7 @@ static bool ffCodecProfileHasOutput(
|
||||
.value = 0,
|
||||
};
|
||||
|
||||
if (ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
|
||||
if (vaData->ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
|
||||
attrib.value != VA_ATTRIB_NOT_SUPPORTED &&
|
||||
attrib.value != 0) {
|
||||
return true;
|
||||
@@ -146,91 +143,101 @@ static bool ffCodecProfileHasOutput(
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ffCodecFillGpuName(const drmDevice* dev, const char* path, FFstrbuf* name) {
|
||||
ffStrbufInit(name);
|
||||
|
||||
switch (dev->bustype) {
|
||||
case DRM_BUS_PCI: {
|
||||
FFGPUResult gpu = {
|
||||
.vendor = ffStrbufCreateStatic(ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id)),
|
||||
.name = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, &gpu);
|
||||
ffStrbufSetF(name, "%s %s", gpu.vendor.chars, gpu.name.chars);
|
||||
|
||||
ffStrbufDestroy(&gpu.vendor);
|
||||
ffStrbufDestroy(&gpu.name);
|
||||
break;
|
||||
}
|
||||
case DRM_BUS_PLATFORM:
|
||||
ffStrbufSetS(name, dev->deviceinfo.platform->compatible[0]);
|
||||
return;
|
||||
case DRM_BUS_HOST1X:
|
||||
ffStrbufSetS(name, dev->deviceinfo.host1x->compatible[0]);
|
||||
return;
|
||||
case DRM_BUS_USB:
|
||||
ffStrbufSetF(name, "0x%04X 0x%04X", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
|
||||
return;
|
||||
default:
|
||||
ffStrbufSetStatic(name, "Unknown GPU");
|
||||
return;
|
||||
static bool vaDetectDisplay(VADisplay display, FFVAData* vaData, FFCodecOptions* options, FFlist* result, const char* api) {
|
||||
int major = 0, minor = 0;
|
||||
if (vaData->ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
|
||||
vaData->ffvaTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!name->length && path && *path) {
|
||||
const char* base = strrchr(path, '/');
|
||||
ffStrbufSetS(name, base ? base + 1 : path);
|
||||
int maxProfiles = vaData->ffvaMaxNumProfiles(display);
|
||||
int maxEntrypoints = vaData->ffvaMaxNumEntrypoints(display);
|
||||
if (maxProfiles <= 0 || maxEntrypoints <= 0) {
|
||||
vaData->ffvaTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!name->length) {
|
||||
ffStrbufSetStatic(name, "Unknown GPU");
|
||||
}
|
||||
}
|
||||
FF_AUTO_FREE VAProfile* profiles = (VAProfile*) malloc(sizeof(VAProfile) * (size_t) maxProfiles);
|
||||
FF_AUTO_FREE VAEntrypoint* entrypoints = (VAEntrypoint*) malloc(sizeof(VAEntrypoint) * (size_t) maxEntrypoints);
|
||||
|
||||
static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result) {
|
||||
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
|
||||
|
||||
FF_LIBRARY_LOAD_MESSAGE(libva, "libva" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaInitialize)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaTerminate)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaMaxNumProfiles)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaMaxNumEntrypoints)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryConfigProfiles)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryConfigEntrypoints)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaGetConfigAttributes)
|
||||
|
||||
FF_LIBRARY_LOAD_MESSAGE(libvaDrm, "libva-drm" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaDrm, vaGetDisplayDRM)
|
||||
|
||||
drmDevicePtr devices[64];
|
||||
int numDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
|
||||
if (numDevices < 0) {
|
||||
return "drmGetDevices() failed";
|
||||
}
|
||||
if (numDevices == 0) {
|
||||
return "No DRM devices found";
|
||||
int numProfiles = maxProfiles;
|
||||
if (vaData->ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
|
||||
vaData->ffvaTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* error = "No DRM device could initialize VA-API";
|
||||
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
|
||||
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
|
||||
for (int j = 0; j < numProfiles; ++j) {
|
||||
FFCodecType type = vaProfileToType(profiles[j]);
|
||||
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
drmDevice* dev = devices[i];
|
||||
bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) &&
|
||||
!(decoderTypes & type) &&
|
||||
vaProfileHasOutput(
|
||||
vaData,
|
||||
display,
|
||||
maxEntrypoints,
|
||||
entrypoints,
|
||||
profiles[j],
|
||||
FF_CODEC_SHOW_TYPE_DECODER);
|
||||
|
||||
const char* path = NULL;
|
||||
if (dev->available_nodes & (1 << DRM_NODE_RENDER)) {
|
||||
path = dev->nodes[DRM_NODE_RENDER];
|
||||
} else if (dev->available_nodes & (1 << DRM_NODE_PRIMARY)) {
|
||||
path = dev->nodes[DRM_NODE_PRIMARY];
|
||||
} else {
|
||||
bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) &&
|
||||
!(encoderTypes & type) &&
|
||||
vaProfileHasOutput(
|
||||
vaData,
|
||||
display,
|
||||
maxEntrypoints,
|
||||
entrypoints,
|
||||
profiles[j],
|
||||
FF_CODEC_SHOW_TYPE_ENCODER);
|
||||
|
||||
if (!hasDecoder && !hasEncoder) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (hasDecoder) {
|
||||
decoderTypes |= type;
|
||||
}
|
||||
if (hasEncoder) {
|
||||
encoderTypes |= type;
|
||||
}
|
||||
}
|
||||
|
||||
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
|
||||
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
|
||||
ffStrbufInitS(&item->gpu, vaData->ffvaQueryVendorString(display));
|
||||
item->decoders = decoderTypes;
|
||||
item->encoders = encoderTypes;
|
||||
item->platformApi = api;
|
||||
}
|
||||
|
||||
vaData->ffvaTerminate(display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if FF_HAVE_VADRM
|
||||
#include <va/va_drm.h>
|
||||
|
||||
static const char* detectCodecByVaDrm(FFVAData* vaData, FFCodecOptions* options, FFlist* result) {
|
||||
FF_LIBRARY_LOAD_MESSAGE(libvaDrm, "libva-drm" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaDrm, vaGetDisplayDRM)
|
||||
|
||||
const char* error = "No DRM device could initialize VA-API";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/dri/");
|
||||
if (dirp == NULL) {
|
||||
return "opendir(/dev/dri/) failed";
|
||||
}
|
||||
int drifd = dirfd(dirp);
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL) {
|
||||
if (entry->d_name[0] == '.' || !ffStrStartsWith(entry->d_name, "renderD")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = openat(drifd, entry->d_name, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -240,84 +247,77 @@ static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int major = 0, minor = 0;
|
||||
if (ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
|
||||
continue;
|
||||
if (vaDetectDisplay(display, vaData, options, result, "VA-API (DRM)")) {
|
||||
error = NULL;
|
||||
}
|
||||
error = NULL;
|
||||
|
||||
int maxProfiles = ffvaMaxNumProfiles(display);
|
||||
int maxEntrypoints = ffvaMaxNumEntrypoints(display);
|
||||
if (maxProfiles <= 0 || maxEntrypoints <= 0) {
|
||||
ffvaTerminate(display);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_FREE VAProfile* profiles = (VAProfile*) malloc(sizeof(VAProfile) * (size_t) maxProfiles);
|
||||
FF_AUTO_FREE VAEntrypoint* entrypoints = (VAEntrypoint*) malloc(sizeof(VAEntrypoint) * (size_t) maxEntrypoints);
|
||||
|
||||
int numProfiles = maxProfiles;
|
||||
if (ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
|
||||
ffvaTerminate(display);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
|
||||
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
|
||||
for (int j = 0; j < numProfiles; ++j) {
|
||||
FFCodecType type = ffCodecProfileToType(profiles[j]);
|
||||
|
||||
bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) &&
|
||||
!(decoderTypes & type) &&
|
||||
ffCodecProfileHasOutput(
|
||||
display,
|
||||
ffvaQueryConfigEntrypoints,
|
||||
ffvaGetConfigAttributes,
|
||||
maxEntrypoints,
|
||||
entrypoints,
|
||||
profiles[j],
|
||||
FF_CODEC_SHOW_TYPE_DECODER);
|
||||
|
||||
bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) &&
|
||||
!(encoderTypes & type) &&
|
||||
ffCodecProfileHasOutput(
|
||||
display,
|
||||
ffvaQueryConfigEntrypoints,
|
||||
ffvaGetConfigAttributes,
|
||||
maxEntrypoints,
|
||||
entrypoints,
|
||||
profiles[j],
|
||||
FF_CODEC_SHOW_TYPE_ENCODER);
|
||||
|
||||
if (!hasDecoder && !hasEncoder) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasDecoder) {
|
||||
decoderTypes |= type;
|
||||
}
|
||||
if (hasEncoder) {
|
||||
encoderTypes |= type;
|
||||
}
|
||||
}
|
||||
|
||||
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
|
||||
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
|
||||
ffCodecFillGpuName(dev, path, &item->gpu);
|
||||
item->decoders = decoderTypes;
|
||||
item->encoders = encoderTypes;
|
||||
item->platformApi = "VA-API";
|
||||
}
|
||||
|
||||
ffvaTerminate(display);
|
||||
}
|
||||
|
||||
ffdrmFreeDevices(devices, numDevices);
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
#if FF_HAVE_VAX11
|
||||
#include <va/va_x11.h>
|
||||
|
||||
static const char* detectCodecByVaX11(FFVAData* vaData, FFCodecOptions* options, FFlist* result) {
|
||||
FF_LIBRARY_LOAD_MESSAGE(libX11, "libX11" FF_LIBRARY_EXTENSION, 6)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XOpenDisplay)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XCloseDisplay)
|
||||
|
||||
FF_LIBRARY_LOAD_MESSAGE(libvaX11, "libva-x11" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaX11, vaGetDisplay)
|
||||
|
||||
Display* x11Display = ffXOpenDisplay(NULL);
|
||||
if (!x11Display) {
|
||||
return "XOpenDisplay() failed";
|
||||
}
|
||||
|
||||
VADisplay display = ffvaGetDisplay(x11Display);
|
||||
if (!display) {
|
||||
ffXCloseDisplay(x11Display);
|
||||
return "vaGetDisplay() failed";
|
||||
}
|
||||
|
||||
if (!vaDetectDisplay(display, vaData, options, result, "VA-API (X11)")) {
|
||||
ffXCloseDisplay(x11Display);
|
||||
return "VA-API could not detect any supported codec via X11";
|
||||
}
|
||||
ffXCloseDisplay(x11Display);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* detectCodecByVa(FFCodecOptions* options, FFlist* result) {
|
||||
FFVAData vaData = {};
|
||||
|
||||
FF_LIBRARY_LOAD_MESSAGE(libva, "libva" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaInitialize)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaTerminate)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaMaxNumProfiles)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaMaxNumEntrypoints)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryConfigProfiles)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryConfigEntrypoints)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryVendorString)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaGetConfigAttributes)
|
||||
|
||||
#if FF_HAVE_VADRM
|
||||
if (detectCodecByVaDrm(&vaData, options, result) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_VAX11
|
||||
if (detectCodecByVaX11(&vaData, options, result) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return "VA-API could not detect any supported codec via DRM or X11";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_VDPAU
|
||||
#include <vdpau/vdpau_x11.h>
|
||||
|
||||
static const struct FFCodecVdpauCodec {
|
||||
VdpDecoderProfile profile;
|
||||
@@ -326,6 +326,13 @@ static const struct FFCodecVdpauCodec {
|
||||
{ 0, FF_CODEC_TYPE_MPEG1 }, // VDP_DECODER_PROFILE_MPEG1
|
||||
{ 1, FF_CODEC_TYPE_MPEG2 }, // VDP_DECODER_PROFILE_MPEG2_SIMPLE
|
||||
{ 2, FF_CODEC_TYPE_MPEG2 }, // VDP_DECODER_PROFILE_MPEG2_MAIN
|
||||
|
||||
{ 6, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_BASELINE
|
||||
{ 7, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_MAIN
|
||||
{ 8, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH
|
||||
{ 9, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_SIMPLE
|
||||
{ 10, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_MAIN
|
||||
{ 11, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_ADVANCED
|
||||
{ 12, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_MPEG4_PART2_SP
|
||||
{ 13, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_MPEG4_PART2_ASP
|
||||
{ 14, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX4_QMOBILE
|
||||
@@ -336,17 +343,16 @@ static const struct FFCodecVdpauCodec {
|
||||
{ 19, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_MOBILE
|
||||
{ 20, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_HOME_THEATER
|
||||
{ 21, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_HD_1080P
|
||||
{ 6, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_BASELINE
|
||||
{ 7, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_MAIN
|
||||
{ 8, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH
|
||||
{ 22, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
|
||||
{ 23, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_EXTENDED
|
||||
{ 24, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_PROGRESSIVE_HIGH
|
||||
{ 25, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH
|
||||
{ 26, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
|
||||
{ 9, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_SIMPLE
|
||||
{ 10, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_MAIN
|
||||
{ 11, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_ADVANCED
|
||||
{ 27, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_0
|
||||
{ 28, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_1
|
||||
{ 29, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_2
|
||||
{ 30, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_3
|
||||
|
||||
{ 100, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN
|
||||
{ 101, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_10
|
||||
{ 102, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_STILL
|
||||
@@ -354,17 +360,13 @@ static const struct FFCodecVdpauCodec {
|
||||
{ 104, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444
|
||||
{ 105, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444_10
|
||||
{ 106, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444_12
|
||||
{ 27, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_0
|
||||
{ 28, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_1
|
||||
{ 29, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_2
|
||||
{ 30, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_3
|
||||
{ 107, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_MAIN
|
||||
{ 108, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_HIGH
|
||||
{ 109, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_PROFESSIONAL
|
||||
};
|
||||
|
||||
static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result) {
|
||||
if (options->showType == FF_CODEC_SHOW_TYPE_DECODER) {
|
||||
static const char* detectCodecByVdpau(FFCodecOptions* options, FFlist* result) {
|
||||
if (!(options->showType & FF_CODEC_SHOW_TYPE_DECODER)) {
|
||||
return "VDPAU only supports decoding";
|
||||
}
|
||||
|
||||
@@ -376,7 +378,7 @@ static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result)
|
||||
FF_LIBRARY_LOAD_MESSAGE(libvdpau, "libvdpau" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvdpau, vdp_device_create_x11)
|
||||
|
||||
void* x11Display = ffXOpenDisplay(NULL);
|
||||
Display* x11Display = ffXOpenDisplay(NULL);
|
||||
if (!x11Display) {
|
||||
return "XOpenDisplay() failed";
|
||||
}
|
||||
@@ -446,13 +448,13 @@ static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result)
|
||||
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
#if FF_HAVE_DRM && FF_HAVE_VA
|
||||
if (ffDetectCodecByVa(options, result) == NULL) {
|
||||
#if FF_HAVE_VA
|
||||
if (detectCodecByVa(options, result) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if FF_HAVE_VDPAU
|
||||
if (ffDetectCodecByVdpau(options, result) == NULL) {
|
||||
if (detectCodecByVdpau(options, result) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -464,7 +466,7 @@ const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list
|
||||
|
||||
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
FF_UNUSED(options, result);
|
||||
return "Fastfetch was built without DRM / VA-API / VDPAU headers";
|
||||
return "Fastfetch was built without VA-API / VDPAU headers";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -65,7 +65,7 @@ static const char* detectFrequency(FFCPUResult* cpu) {
|
||||
// voltage-states5-sram stores supported <frequency / voltage> pairs of pcores from the lowest to the highest
|
||||
// voltage-states1-sram stores ecores'
|
||||
CFIndex propLength = CFDataGetLength(freqProperty);
|
||||
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
|
||||
if (propLength == 0 || propLength % (CFIndex) (sizeof(uint32_t) * 2) != 0) {
|
||||
return "Invalid \"voltage-states5-sram\" length";
|
||||
}
|
||||
|
||||
|
||||
@@ -461,7 +461,6 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
uint32_t lastPartId = UINT32_MAX;
|
||||
uint32_t num = 0;
|
||||
while (ffStrbufGetline(&line, &len, cpuinfo)) {
|
||||
if (!ffStrStartsWith(line, "CPU part\t: ")) {
|
||||
continue;
|
||||
@@ -529,10 +528,7 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
|
||||
}
|
||||
if (lastPartId != partId) {
|
||||
if (lastPartId != UINT32_MAX) {
|
||||
if (num > 1) {
|
||||
ffStrbufAppendF(&cpu->name, "*%u", num);
|
||||
}
|
||||
ffStrbufAppendS(&cpu->name, " + ");
|
||||
ffStrbufAppendC(&cpu->name, '+');
|
||||
}
|
||||
if (name) {
|
||||
ffStrbufAppendS(&cpu->name, name);
|
||||
@@ -542,14 +538,8 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
|
||||
ffStrbufAppend(&cpu->name, &cpu->vendor);
|
||||
}
|
||||
lastPartId = partId;
|
||||
num = 1;
|
||||
} else {
|
||||
++num;
|
||||
}
|
||||
}
|
||||
if (num > 1) {
|
||||
ffStrbufAppendF(&cpu->name, "*%u", num);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -619,19 +609,14 @@ static const char* parseCpuInfo(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer) {
|
||||
uint32_t baseLen = basePath->length;
|
||||
ffStrbufAppendS(basePath, cpuinfoFileName);
|
||||
bool ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
static uint32_t getFrequency(int policyFd, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer) {
|
||||
bool ok = ffReadFileBufferRelative(policyFd, cpuinfoFileName, buffer);
|
||||
if (ok) {
|
||||
return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000);
|
||||
}
|
||||
|
||||
if (scalingFileName) {
|
||||
ffStrbufAppendS(basePath, scalingFileName);
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
ok = ffReadFileBufferRelative(policyFd, scalingFileName, buffer);
|
||||
if (ok) {
|
||||
return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000);
|
||||
}
|
||||
@@ -640,55 +625,38 @@ static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, co
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t getNumCores(FFstrbuf* basePath, FFstrbuf* buffer) {
|
||||
uint32_t baseLen = basePath->length;
|
||||
ffStrbufAppendS(basePath, "/affected_cpus");
|
||||
bool ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok) {
|
||||
return (uint8_t) (ffStrbufCountC(buffer, ' ') + 1);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(basePath, "/related_cpus");
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok) {
|
||||
return (uint8_t) (ffStrbufCountC(buffer, ' ') + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) {
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/cpufreq/");
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(path.chars);
|
||||
const char* basePath = "/sys/devices/system/cpu/cpufreq/";
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath);
|
||||
if (!dir) {
|
||||
return false;
|
||||
}
|
||||
int freqFd = dirfd(dir);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (ffStrStartsWith(entry->d_name, "policy") && ffCharIsDigit(entry->d_name[strlen("policy")])) {
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
FF_AUTO_CLOSE_FD int policyFd = openat(freqFd, entry->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_PATH);
|
||||
if (policyFd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
|
||||
uint32_t fmax = getFrequency(policyFd, "cpuinfo_max_freq", "scaling_max_freq", &buffer);
|
||||
if (fmax == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cpu->frequencyMax >= fmax) {
|
||||
if (!options->showPeCoreCount) {
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
cpu->frequencyMax = fmax;
|
||||
}
|
||||
|
||||
uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
|
||||
uint32_t fbase = getFrequency(policyFd, "base_frequency", NULL, &buffer);
|
||||
if (fbase > 0) {
|
||||
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
|
||||
}
|
||||
@@ -702,9 +670,10 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) {
|
||||
if (cpu->coreTypes[ifreq].freq == 0) {
|
||||
cpu->coreTypes[ifreq].freq = freq;
|
||||
}
|
||||
cpu->coreTypes[ifreq].count += getNumCores(&path, &buffer);
|
||||
if (ffReadFileBufferRelative(policyFd, "affected_cpus", &buffer)) {
|
||||
cpu->coreTypes[ifreq].count += ffStrbufCountC(&buffer, ' ') + 1;
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -773,6 +742,7 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) {
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(dfd);
|
||||
if (!dir) {
|
||||
close(dfd);
|
||||
return "fdopendir(dfd) failed";
|
||||
}
|
||||
|
||||
@@ -785,7 +755,7 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int cpuxfd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_DIRECTORY);
|
||||
FF_AUTO_CLOSE_FD int cpuxfd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (cpuxfd < 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -798,45 +768,42 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) {
|
||||
ssize_t len = ffReadFileDataRelative(cpuxfd, "topology/physical_package_id", sizeof(buf) - 1, buf);
|
||||
if (len > 0) {
|
||||
buf[len] = '\0';
|
||||
unsigned long long id = strtoul(buf, NULL, 10);
|
||||
if (__builtin_expect(id > 64, false)) { // Do 129-socket boards exist?
|
||||
pkgHigh |= 1ULL << (id - 64);
|
||||
} else {
|
||||
pkgLow |= 1ULL << id;
|
||||
unsigned long long id = strtoull(buf, NULL, 10);
|
||||
if (__builtin_expect(id < 128, true)) {
|
||||
// Do 129-socket boards exist?
|
||||
if (__builtin_expect(id >= 64, false)) {
|
||||
pkgHigh |= 1ULL << (id - 64);
|
||||
} else {
|
||||
pkgLow |= 1ULL << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the directory contains a file named "topology/core_cpus_list"
|
||||
// that lists the physical cores in the package.
|
||||
// that lists the logical cores in the same physical core.
|
||||
|
||||
len = ffReadFileDataRelative(cpuxfd, "topology/core_cpus_list", sizeof(buf) - 1, buf);
|
||||
if (len > 0) {
|
||||
buf[len] = '\0'; // low-high or low
|
||||
buf[len] = '\0'; // low[-high, low-high, ...]
|
||||
|
||||
for (const char* p = buf; *p;) {
|
||||
char* pend;
|
||||
uint32_t coreId = (uint32_t) strtoul(p, &pend, 10);
|
||||
if (pend == p) {
|
||||
char* pend;
|
||||
// We assume that the different physical cores exposes different logical core ids,
|
||||
// so that the first `low` is always different between different physical cores.
|
||||
uint32_t coreId = (uint32_t) strtoul(buf, &pend, 10);
|
||||
if (pend == buf) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
FF_LIST_FOR_EACH (uint32_t, id, cpuList) {
|
||||
if (*id == coreId) {
|
||||
// This core is already counted
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
FF_LIST_FOR_EACH (uint32_t, id, cpuList) {
|
||||
if (*id == coreId) {
|
||||
// This core is already counted
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
*FF_LIST_ADD(uint32_t, cpuList) = coreId;
|
||||
}
|
||||
|
||||
p = strchr(pend, ',');
|
||||
if (!p) {
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
if (!found) {
|
||||
*FF_LIST_ADD(uint32_t, cpuList) = coreId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ffGPUDetectTypeByVendorAndName(FFGPUResult* gpu) {
|
||||
if (gpu->type != FF_GPU_TYPE_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_DEBUG("Using fallback GPU type detection");
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) { gpu->type = FF_GPU_TYPE_DISCRETE; }
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) {
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_VMWARE || gpu->vendor.chars == FF_GPU_VENDOR_NAME_PARALLELS) {
|
||||
// Virtualized GPUs
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
|
||||
if (gpu->type != FF_GPU_TYPE_UNKNOWN) {
|
||||
FF_DEBUG("Determined GPU type based on vendor (%s) and name: %u", gpu->vendor.chars, gpu->type);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+23
-2
@@ -7,6 +7,7 @@
|
||||
#define FF_GPU_CORE_COUNT_UNSET -1
|
||||
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t) -1)
|
||||
#define FF_GPU_FREQUENCY_UNSET 0
|
||||
#define FF_GPU_PCIE_SPEED_UNSET 0
|
||||
#define FF_GPU_CORE_USAGE_UNSET (-DBL_MAX)
|
||||
#define FF_GPU_INDEX_UNSET ((uint32_t) -1)
|
||||
|
||||
@@ -34,6 +35,11 @@ typedef struct FFGPUMemory {
|
||||
uint64_t used;
|
||||
} FFGPUMemory;
|
||||
|
||||
typedef struct FFGPUPcieSpeed {
|
||||
uint16_t gen;
|
||||
uint16_t lanes;
|
||||
} FFGPUPcieSpeed;
|
||||
|
||||
typedef struct FFGPUResult {
|
||||
uint32_t index;
|
||||
FFGPUType type;
|
||||
@@ -46,11 +52,21 @@ typedef struct FFGPUResult {
|
||||
double coreUsage;
|
||||
int32_t coreCount;
|
||||
uint32_t frequency; // Maximum time clock frequency in MHz
|
||||
union {
|
||||
struct {
|
||||
FFGPUPcieSpeed psMax;
|
||||
FFGPUPcieSpeed psCurr;
|
||||
};
|
||||
uint64_t pcieSpeed;
|
||||
};
|
||||
FFGPUMemory dedicated;
|
||||
FFGPUMemory shared;
|
||||
uint64_t deviceId;
|
||||
} FFGPUResult;
|
||||
|
||||
static_assert(sizeof(((FFGPUResult*) NULL)->pcieSpeed) == 8, "pcieSpeed is not 8 bytes");
|
||||
static_assert(sizeof(((FFGPUResult*) NULL)->psMax) == 4, "psMax has padding");
|
||||
|
||||
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
|
||||
|
||||
@@ -67,14 +83,17 @@ typedef struct FFGpuDriverPciBusId {
|
||||
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
|
||||
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
#if FF_HAVE_DRM || __has_include(<drm/drm.h>)
|
||||
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
|
||||
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
|
||||
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd);
|
||||
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd);
|
||||
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd);
|
||||
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd);
|
||||
#endif // FF_HAVE_DRM
|
||||
#if __FreeBSD__ || __OpenBSD__ // DRM is not available on NetBSD
|
||||
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus);
|
||||
#endif
|
||||
#endif // FF_HAVE_DRM || __has_include(<drm/drm.h>)
|
||||
|
||||
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
|
||||
#endif // defined(XXX)
|
||||
@@ -87,3 +106,5 @@ static inline uint64_t ffGPUGeneral2Id(uint64_t originalId) {
|
||||
// Note: originalId may already have the MSB set
|
||||
return (1ULL << 63) | originalId;
|
||||
}
|
||||
|
||||
bool ffGPUDetectTypeByVendorAndName(FFGPUResult* gpu);
|
||||
|
||||
@@ -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;
|
||||
|
||||
{
|
||||
|
||||
@@ -48,8 +48,6 @@ static double detectGpuTemp(const FFstrbuf* gpuName) {
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
#include "common/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static const char* detectFrequency(FFGPUResult* gpu) {
|
||||
@@ -71,7 +69,7 @@ static const char* detectFrequency(FFGPUResult* gpu) {
|
||||
|
||||
// voltage-states9-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
|
||||
CFIndex propLength = CFDataGetLength(freqProperty);
|
||||
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
|
||||
if (propLength == 0 || propLength % (CFIndex) (sizeof(uint32_t) * 2) != 0) {
|
||||
return "Invalid \"voltage-states9-sram\" length";
|
||||
}
|
||||
|
||||
@@ -118,6 +116,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId);
|
||||
ffStrbufInitStatic(&gpu->platformApi, "IOKit");
|
||||
|
||||
|
||||
+4
-137
@@ -1,7 +1,7 @@
|
||||
#include "gpu.h"
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
@@ -11,140 +11,6 @@
|
||||
#include <bus/pci/pcireg.h> // DragonFly
|
||||
#endif
|
||||
|
||||
static void fillGPUTypeGeneric(FFGPUResult* gpu) {
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) {
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
#include "common/library.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus) {
|
||||
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
|
||||
|
||||
drmDevicePtr devices[64];
|
||||
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
|
||||
if (nDevices < 0) {
|
||||
return "drmGetDevices() failed";
|
||||
}
|
||||
|
||||
for (int iDev = 0; iDev < nDevices; ++iDev) {
|
||||
drmDevice* dev = devices[iDev];
|
||||
|
||||
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* path = dev->nodes[DRM_NODE_PRIMARY];
|
||||
|
||||
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitS(&gpu->platformApi, path);
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = 0;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
switch (dev->bustype) {
|
||||
case DRM_BUS_PCI:
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
|
||||
gpu->deviceId = ffGPUPciAddr2Id(dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func);
|
||||
break;
|
||||
case DRM_BUS_HOST1X:
|
||||
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
break;
|
||||
case DRM_BUS_PLATFORM:
|
||||
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
break;
|
||||
case DRM_BUS_USB:
|
||||
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
break;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char driverName[64];
|
||||
driverName[0] = '\0';
|
||||
struct drm_version ver = {
|
||||
.name = driverName,
|
||||
.name_len = ARRAY_SIZE(driverName),
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0) {
|
||||
driverName[ver.name_len] = '\0';
|
||||
ffStrbufSetF(&gpu->driver, "%s %d.%d.%d", ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
|
||||
}
|
||||
|
||||
if (ffStrStartsWith(driverName, "i915")) {
|
||||
ffDrmDetectI915(gpu, fd);
|
||||
} else if (ffStrStartsWith(driverName, "amdgpu")) {
|
||||
ffDrmDetectAmdgpu(options, gpu, dev->nodes[DRM_NODE_RENDER]);
|
||||
} else if (ffStrStartsWith(driverName, "radeon")) {
|
||||
ffDrmDetectRadeon(options, gpu, dev->nodes[DRM_NODE_RENDER]);
|
||||
} else if (ffStrStartsWith(driverName, "xe")) {
|
||||
ffDrmDetectXe(gpu, fd);
|
||||
} else if (ffStrStartsWith(driverName, "asahi")) {
|
||||
ffDrmDetectAsahi(gpu, fd);
|
||||
} else if (ffStrStartsWith(driverName, "nouveau")) {
|
||||
ffDrmDetectNouveau(gpu, fd);
|
||||
} else if (dev->bustype == DRM_BUS_PCI) {
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
.domain = (uint32_t) dev->businfo.pci->domain,
|
||||
.bus = dev->businfo.pci->bus,
|
||||
.device = dev->businfo.pci->dev,
|
||||
.func = dev->businfo.pci->func,
|
||||
});
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0) {
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
ffGPUQueryAmdGpuName(dev->deviceinfo.pci->device_id, dev->deviceinfo.pci->revision_id, gpu);
|
||||
}
|
||||
if (gpu->name.length == 0) {
|
||||
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, gpu);
|
||||
}
|
||||
}
|
||||
|
||||
fillGPUTypeGeneric(gpu);
|
||||
}
|
||||
|
||||
ffdrmFreeDevices(devices, nDevices);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
@@ -193,6 +59,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(pc->pc_sel.pc_domain, pc->pc_sel.pc_bus, pc->pc_sel.pc_dev, pc->pc_sel.pc_func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
.domain = (uint32_t) pc->pc_sel.pc_domain,
|
||||
@@ -210,7 +77,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
|
||||
}
|
||||
}
|
||||
|
||||
fillGPUTypeGeneric(gpu);
|
||||
ffGPUDetectTypeByVendorAndName(gpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -219,7 +86,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
|
||||
#if FF_HAVE_DRM
|
||||
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO) {
|
||||
detectByDrm(options, gpus);
|
||||
ffGPUDetectByDrmBSD(options, gpus);
|
||||
if (gpus->length > 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
#include "gpu.h"
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
|
||||
#include "common/strutil.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <drm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if __FreeBSD__
|
||||
#include <sys/sysctl.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
#if __has_include(<dev/pci/pcireg.h>)
|
||||
#include <dev/pci/pcireg.h> // FreeBSD
|
||||
#else
|
||||
#include <bus/pci/pcireg.h> // DragonFly
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// https://github.com/freebsd/drm-kmod/blob/8fea1f06b3ac3fa24217e24ba7b2133abad705a9/include/uapi/drm/drm.h#L1095
|
||||
struct drm_pciinfo {
|
||||
uint16_t domain;
|
||||
uint8_t bus;
|
||||
uint8_t dev;
|
||||
uint8_t func;
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint16_t subvendor_id;
|
||||
uint16_t subdevice_id;
|
||||
uint8_t revision_id;
|
||||
};
|
||||
|
||||
#define DRM_IOCTL_GET_PCIINFO DRM_IOR(0x15, struct drm_pciinfo)
|
||||
|
||||
static const char* drmGetPciinfo(int drmfd, const char* drmId, struct drm_pciinfo* result) {
|
||||
#if !__FreeBSD__
|
||||
FF_UNUSED(drmId);
|
||||
if (ioctl(drmfd, DRM_IOCTL_GET_PCIINFO, result) < 0) {
|
||||
return "ioctl(DRM_IOCTL_GET_PCIINFO) failed";
|
||||
}
|
||||
#else
|
||||
FF_UNUSED(drmfd);
|
||||
char requestBuf[64];
|
||||
snprintf(requestBuf, ARRAY_SIZE(requestBuf), "hw.dri.%s.busid", drmId);
|
||||
char pciidBuf[64];
|
||||
size_t pciidLen = ARRAY_SIZE(pciidBuf);
|
||||
if (sysctlbyname(requestBuf, pciidBuf, &pciidLen, NULL, 0) < 0) {
|
||||
return "sysctlbyname(hw.dri.%s.busid) failed";
|
||||
}
|
||||
// hw.dri.0.busid: pci:0000:01:00.0
|
||||
struct pci_match_conf match = {
|
||||
.pc_class = PCIC_DISPLAY,
|
||||
.flags = PCI_GETCONF_MATCH_CLASS | PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC,
|
||||
};
|
||||
if (sscanf(pciidBuf, "pci:%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8, &match.pc_sel.pc_domain, &match.pc_sel.pc_bus, &match.pc_sel.pc_dev, &match.pc_sel.pc_func) != 4) {
|
||||
return "Invalid PCI busid found";
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int pcifd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
|
||||
if (pcifd < 0) {
|
||||
return "open(\"/dev/pci\", O_RDONLY | O_CLOEXEC, 0) failed";
|
||||
}
|
||||
|
||||
struct pci_conf conf;
|
||||
struct pci_conf_io pcio = {
|
||||
.pat_buf_len = sizeof(match),
|
||||
.num_patterns = 1,
|
||||
.patterns = &match,
|
||||
.match_buf_len = sizeof(conf),
|
||||
.matches = &conf,
|
||||
};
|
||||
|
||||
if (ioctl(pcifd, PCIOCGETCONF, &pcio) < 0) {
|
||||
return "ioctl(pcifd, PCIOCGETCONF, &pc) failed";
|
||||
}
|
||||
|
||||
if (pcio.status == PCI_GETCONF_ERROR) {
|
||||
return "ioctl(pcifd, PCIOCGETCONF, &pc) returned error";
|
||||
}
|
||||
|
||||
if (pcio.num_matches != 1) {
|
||||
return "ioctl(pcifd, PCIOCGETCONF, &pc) returned no results";
|
||||
}
|
||||
|
||||
*result = (struct drm_pciinfo){
|
||||
.domain = (uint16_t) conf.pc_sel.pc_domain,
|
||||
.bus = conf.pc_sel.pc_bus,
|
||||
.dev = conf.pc_sel.pc_dev,
|
||||
.func = conf.pc_sel.pc_func,
|
||||
.vendor_id = conf.pc_vendor,
|
||||
.device_id = conf.pc_device,
|
||||
.subvendor_id = conf.pc_subvendor,
|
||||
.subdevice_id = conf.pc_subdevice,
|
||||
.revision_id = conf.pc_revid,
|
||||
};
|
||||
|
||||
// This sysctl can also be useful
|
||||
// dev.drm.0.PCI_ID: 10de:2782
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) {
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/dri/");
|
||||
if (dirp == NULL) {
|
||||
return "opendir(/dev/dri/) failed";
|
||||
}
|
||||
int drifd = dirfd(dirp);
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL) {
|
||||
if (entry->d_name[0] == '.' || !ffStrStartsWith(entry->d_name, "card")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = openat(drifd, entry->d_name, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Currently, DRM_BUS_PCI is the only bus type supported by drm-kmod on BSD (hard-coded in libdrm source tree)
|
||||
struct drm_pciinfo pciInfo;
|
||||
if (drmGetPciinfo(fd, entry->d_name + strlen("card"), &pciInfo) != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pciInfo.vendor_id));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitF(&gpu->platformApi, "/dev/dri/%s", entry->d_name);
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(pciInfo.domain, pciInfo.bus, pciInfo.dev, pciInfo.func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
|
||||
|
||||
char driverName[64];
|
||||
driverName[0] = '\0';
|
||||
struct drm_version ver = {
|
||||
.name = driverName,
|
||||
.name_len = ARRAY_SIZE(driverName) - 1,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0) {
|
||||
driverName[ver.name_len] = '\0';
|
||||
ffStrbufSetF(&gpu->driver, "%s %d.%d.%d", ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
|
||||
}
|
||||
|
||||
if (ffStrStartsWith(driverName, "i915")) {
|
||||
ffDrmDetectI915(gpu, fd);
|
||||
} else if (ffStrStartsWith(driverName, "amdgpu")) {
|
||||
uint32_t primaryNodeId = (uint32_t) strtoul(entry->d_name + strlen("card"), NULL, 10);
|
||||
FF_STRBUF_AUTO_DESTROY renderNode = ffStrbufCreateF("/dev/dri/renderD%d", primaryNodeId + 128);
|
||||
ffDrmDetectAmdgpu(options, gpu, renderNode.chars);
|
||||
} else if (ffStrStartsWith(driverName, "radeon")) {
|
||||
uint32_t primaryNodeId = (uint32_t) strtoul(entry->d_name + strlen("card"), NULL, 10);
|
||||
FF_STRBUF_AUTO_DESTROY renderNode = ffStrbufCreateF("/dev/dri/renderD%d", primaryNodeId + 128);
|
||||
ffDrmDetectRadeon(options, gpu, renderNode.chars);
|
||||
} else if (ffStrStartsWith(driverName, "xe")) {
|
||||
ffDrmDetectXe(gpu, fd);
|
||||
} else if (ffStrStartsWith(driverName, "asahi")) {
|
||||
ffDrmDetectAsahi(gpu, fd);
|
||||
} else if (ffStrStartsWith(driverName, "nouveau")) {
|
||||
ffDrmDetectNouveau(gpu, fd);
|
||||
} else {
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId){
|
||||
.domain = pciInfo.domain,
|
||||
.bus = pciInfo.bus,
|
||||
.device = pciInfo.dev,
|
||||
.func = pciInfo.func,
|
||||
});
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0) {
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
|
||||
ffGPUQueryAmdGpuName(pciInfo.device_id, pciInfo.revision_id, gpu);
|
||||
}
|
||||
if (gpu->name.length == 0) {
|
||||
ffGPUFillVendorAndName(0, pciInfo.vendor_id, pciInfo.device_id, gpu);
|
||||
}
|
||||
}
|
||||
|
||||
ffGPUDetectTypeByVendorAndName(gpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) {
|
||||
FF_UNUSED(options, gpus);
|
||||
return "Fastfetch was built without libdrm support";
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_DRM
|
||||
@@ -36,6 +36,8 @@ typedef struct FFGpuDriverResult {
|
||||
FFGPUType* type;
|
||||
uint32_t* frequency;
|
||||
FFstrbuf* name;
|
||||
FFGPUPcieSpeed* psMax;
|
||||
FFGPUPcieSpeed* psCurr;
|
||||
} FFGpuDriverResult;
|
||||
|
||||
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
|
||||
|
||||
+80
-60
@@ -1,19 +1,26 @@
|
||||
#include "gpu.h"
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
#include <drm.h>
|
||||
#if FF_HAVE_DRM || __has_include(<drm/drm.h>)
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "common/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
#include <drm.h>
|
||||
#include <radeon_drm.h>
|
||||
#include <nouveau_drm.h>
|
||||
#include <amdgpu_drm.h>
|
||||
#else
|
||||
#define FF_HAVE_DRM 1
|
||||
#include <drm/drm.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
#include <drm/nouveau_drm.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#endif
|
||||
#include "intel_drm.h"
|
||||
#include "asahi_drm.h"
|
||||
#include <radeon_drm.h>
|
||||
#include <nouveau_drm.h>
|
||||
|
||||
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath) {
|
||||
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
|
||||
@@ -43,7 +50,7 @@ const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, con
|
||||
}
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
|
||||
.request = RADEON_INFO_MAX_SCLK, // MHz
|
||||
.request = RADEON_INFO_MAX_SCLK, // KHz
|
||||
.value = (uintptr_t) &value,
|
||||
}) >= 0) {
|
||||
gpu->frequency = (uint32_t) (value / 1000u);
|
||||
@@ -52,7 +59,7 @@ const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, con
|
||||
if (options->driverSpecific) {
|
||||
struct drm_radeon_gem_info gemInfo;
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &gemInfo) >= 0) {
|
||||
// vram_usage can be bigger than vram_usage, so we use vram_size here
|
||||
// vram_usage can be bigger than vram_size, so we use vram_size here
|
||||
gpu->dedicated.total = gemInfo.vram_size;
|
||||
gpu->shared.total = gemInfo.gart_size;
|
||||
|
||||
@@ -76,52 +83,50 @@ const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, con
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_DRM_AMDGPU
|
||||
#include <amdgpu.h>
|
||||
#include <amdgpu_drm.h>
|
||||
|
||||
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath) {
|
||||
#if FF_HAVE_DRM_AMDGPU
|
||||
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
return "Failed to open DRM render device";
|
||||
}
|
||||
|
||||
amdgpu_device_handle handle;
|
||||
uint32_t majorVersion, minorVersion;
|
||||
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0) {
|
||||
return "Failed to initialize AMDGPU device";
|
||||
}
|
||||
|
||||
uint32_t value;
|
||||
|
||||
if (options->temp) {
|
||||
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0) {
|
||||
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
|
||||
&(struct drm_amdgpu_info) {
|
||||
.return_pointer = (uintptr_t) &value,
|
||||
.return_size = sizeof(value),
|
||||
.query = AMDGPU_INFO_SENSOR,
|
||||
.query_hw_ip.type = AMDGPU_INFO_SENSOR_GPU_TEMP,
|
||||
}) >= 0 && value != 0) {
|
||||
gpu->temperature = value / 1000.;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
|
||||
|
||||
struct amdgpu_gpu_info gpuInfo;
|
||||
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0) {
|
||||
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
|
||||
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
|
||||
struct drm_amdgpu_info_device devInfo;
|
||||
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
|
||||
&(struct drm_amdgpu_info) {
|
||||
.return_pointer = (uintptr_t) &devInfo,
|
||||
.return_size = sizeof(devInfo),
|
||||
.query = AMDGPU_INFO_DEV_INFO,
|
||||
}) >= 0) {
|
||||
gpu->coreCount = (int32_t) devInfo.cu_active_number;
|
||||
gpu->frequency = (uint32_t) (devInfo.max_engine_clock / 1000u);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
#define FF_VRAM_CASE(name, value) \
|
||||
case value /* AMDGPU_VRAM_TYPE_ ## name */: \
|
||||
gpu->type = devInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
// Was `_pad`. Introduced in commit https://github.com/sailfishos-mirror/drm/commit/22b698a5990292bce0eeb2782754d1eba3fe7a2e
|
||||
#ifdef AMDGPU_FAMILY_GC_11_0_0
|
||||
gpu->psMax.gen = (uint16_t) devInfo.pcie_gen;
|
||||
gpu->psMax.lanes = (uint16_t) devInfo.pcie_num_lanes;
|
||||
#else
|
||||
gpu->psMax.gen = (uint16_t) devInfo._pad;
|
||||
gpu->psMax.lanes = (uint16_t) devInfo._pad1;
|
||||
#endif
|
||||
#define FF_VRAM_CASE(name, value) \
|
||||
case value /* AMDGPU_VRAM_TYPE_ ## name */: \
|
||||
ffStrbufSetStatic(&gpu->memoryType, #name); \
|
||||
break
|
||||
switch (gpuInfo.vram_type) {
|
||||
switch (devInfo.vram_type) {
|
||||
FF_VRAM_CASE(UNKNOWN, 0);
|
||||
FF_VRAM_CASE(GDDR1, 1);
|
||||
FF_VRAM_CASE(DDR2, 2);
|
||||
@@ -135,35 +140,40 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
|
||||
FF_VRAM_CASE(DDR5, 10);
|
||||
FF_VRAM_CASE(LPDDR4, 11);
|
||||
FF_VRAM_CASE(LPDDR5, 12);
|
||||
FF_VRAM_CASE(HBM3E, 13);
|
||||
FF_VRAM_CASE(HBM4, 14);
|
||||
default:
|
||||
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
|
||||
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", devInfo.vram_type);
|
||||
break;
|
||||
}
|
||||
|
||||
struct amdgpu_heap_info heapInfo;
|
||||
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0) {
|
||||
gpu->dedicated.total = heapInfo.heap_size;
|
||||
gpu->dedicated.used = heapInfo.heap_usage;
|
||||
}
|
||||
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_GTT, 0, &heapInfo) >= 0) {
|
||||
gpu->shared.total = heapInfo.heap_size;
|
||||
gpu->shared.used = heapInfo.heap_usage;
|
||||
}
|
||||
#undef FF_VRAM_CASE
|
||||
}
|
||||
|
||||
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0) {
|
||||
struct drm_amdgpu_memory_info memInfo;
|
||||
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
|
||||
&(struct drm_amdgpu_info) {
|
||||
.return_pointer = (uintptr_t) &memInfo,
|
||||
.return_size = sizeof(memInfo),
|
||||
.query = AMDGPU_INFO_MEMORY,
|
||||
}) >= 0) {
|
||||
gpu->dedicated.total = memInfo.vram.total_heap_size;
|
||||
gpu->dedicated.used = memInfo.vram.heap_usage;
|
||||
gpu->shared.total = memInfo.gtt.total_heap_size;
|
||||
gpu->shared.used = memInfo.gtt.heap_usage;
|
||||
}
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_AMDGPU_INFO,
|
||||
&(struct drm_amdgpu_info) {
|
||||
.return_pointer = (uintptr_t) &value,
|
||||
.return_size = sizeof(value),
|
||||
.query = AMDGPU_INFO_SENSOR,
|
||||
.query_hw_ip.type = AMDGPU_INFO_SENSOR_GPU_LOAD,
|
||||
}) >= 0) {
|
||||
gpu->coreUsage = value;
|
||||
}
|
||||
|
||||
ffamdgpu_device_deinitialize(handle);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(options, gpu, renderPath);
|
||||
return "Fastfetch is compiled without libdrm support";
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd) {
|
||||
{
|
||||
@@ -219,12 +229,12 @@ static inline int popcountBytes(uint8_t* bytes, uint32_t length) {
|
||||
length -= 4;
|
||||
}
|
||||
if (length >= 2) {
|
||||
count += __builtin_popcountl(*(uint16_t*) bytes);
|
||||
count += __builtin_popcount(*(uint16_t*) bytes);
|
||||
bytes += 2;
|
||||
length -= 2;
|
||||
}
|
||||
if (length) {
|
||||
count += __builtin_popcountl(*(uint8_t*) bytes);
|
||||
count += __builtin_popcount(*(uint8_t*) bytes);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -297,7 +307,11 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd) {
|
||||
.size = sizeof(paramsGlobal),
|
||||
}) >= 0) {
|
||||
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
|
||||
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
|
||||
assert(paramsGlobal.num_clusters_total <= DRM_ASAHI_MAX_CLUSTERS);
|
||||
gpu->coreCount = 0;
|
||||
for (uint32_t i = 0; i < paramsGlobal.num_clusters_total; i++) {
|
||||
gpu->coreCount += __builtin_popcountll(paramsGlobal.core_masks[i]);
|
||||
}
|
||||
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
|
||||
gpu->deviceId = ffGPUGeneral2Id(paramsGlobal.chip_id);
|
||||
|
||||
@@ -356,6 +370,7 @@ const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd) {
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId) {
|
||||
#if !__OpenBSD__
|
||||
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
||||
const char* soName;
|
||||
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific)) {
|
||||
@@ -367,14 +382,19 @@ const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult*
|
||||
.index = &gpu->index,
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.sharedMemory = options->driverSpecific ? &gpu->shared : NULL,
|
||||
.memoryType = options->driverSpecific ? &gpu->memoryType : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
|
||||
.type = &gpu->type,
|
||||
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
|
||||
.name = &gpu->name,
|
||||
.psCurr = options->driverSpecific ? &gpu->psCurr : NULL,
|
||||
.psMax = options->driverSpecific ? &gpu->psMax : NULL,
|
||||
},
|
||||
soName);
|
||||
}
|
||||
#endif
|
||||
|
||||
return "No driver-specific detection function found for the GPU vendor";
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user