mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 09:58:03 +02:00
Decoder (Linux): adds *nix support
This commit is contained in:
@@ -74,6 +74,7 @@ cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeB
|
||||
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_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)
|
||||
@@ -553,6 +554,7 @@ if(LINUX)
|
||||
src/detection/cpucache/cpucache_linux.c
|
||||
src/detection/cpuusage/cpuusage_linux.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/bluetoothradio/bluetoothradio_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
@@ -714,6 +716,7 @@ elseif(FreeBSD)
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_bsd.c
|
||||
@@ -808,6 +811,7 @@ elseif(NetBSD)
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nbsd.c
|
||||
@@ -892,6 +896,7 @@ elseif(OpenBSD)
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_obsd.c
|
||||
@@ -1133,6 +1138,7 @@ elseif(SunOS)
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/disk/disk_sunos.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_sunos.c
|
||||
@@ -1216,6 +1222,7 @@ elseif(Haiku)
|
||||
src/detection/cursor/cursor_nosupport.c
|
||||
src/detection/bluetooth/bluetooth_haiku.cpp
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/disk/disk_haiku.cpp
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_haiku.c
|
||||
@@ -1286,6 +1293,7 @@ elseif(GNU)
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/bluetoothradio/bluetoothradio_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/decoder/decoder_linux.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
@@ -1656,6 +1664,10 @@ ff_lib_enable(DRM
|
||||
"libdrm"
|
||||
"Libdrm"
|
||||
)
|
||||
ff_lib_enable(VA
|
||||
"libva"
|
||||
"Libva"
|
||||
)
|
||||
ff_lib_enable(DRM_AMDGPU
|
||||
"libdrm_amdgpu"
|
||||
"Libdrm_Amdgpu"
|
||||
|
||||
@@ -20,7 +20,8 @@ typedef enum FF_A_PACKED FFDecoderType {
|
||||
FF_DECODER_TYPE_HEVC = UINT32_C(1) << 12,
|
||||
FF_DECODER_TYPE_VP9 = UINT32_C(1) << 13,
|
||||
FF_DECODER_TYPE_AV1 = UINT32_C(1) << 14,
|
||||
FF_DECODER_TYPE_MAX = FF_DECODER_TYPE_AV1,
|
||||
FF_DECODER_TYPE_VVC = UINT32_C(1) << 15,
|
||||
FF_DECODER_TYPE_MAX = FF_DECODER_TYPE_VVC,
|
||||
FF_DECODER_TYPE_FORCE_UNSIGNED = UINT32_MAX,
|
||||
} FFDecoderType;
|
||||
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
#include "decoder.h"
|
||||
|
||||
#if FF_HAVE_DRM && FF_HAVE_VA
|
||||
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "common/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <va/va.h>
|
||||
#include <va/va_drm.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
static FFDecoderType ffDecoderProfileToType(VAProfile profile) {
|
||||
switch (profile) {
|
||||
case 11: // VAProfileH263Baseline
|
||||
return FF_DECODER_TYPE_H263;
|
||||
|
||||
case 12: // VAProfileJPEGBaseline
|
||||
return FF_DECODER_TYPE_MJPEG;
|
||||
|
||||
case 0: // VAProfileMPEG2Simple
|
||||
case 1: // VAProfileMPEG2Main
|
||||
return FF_DECODER_TYPE_MPEG2;
|
||||
|
||||
case 2: // VAProfileMPEG4Simple
|
||||
case 3: // VAProfileMPEG4AdvancedSimple
|
||||
case 4: // VAProfileMPEG4Main
|
||||
return FF_DECODER_TYPE_DIVX_XVID;
|
||||
|
||||
case 5: // VAProfileH264Baseline
|
||||
case 6: // VAProfileH264Main
|
||||
case 7: // VAProfileH264High
|
||||
case 13: // VAProfileH264ConstrainedBaseline
|
||||
case 15: // VAProfileH264MultiviewHigh
|
||||
case 16: // VAProfileH264StereoHigh
|
||||
case 36: // VAProfileH264High10
|
||||
case 40: // VAProfileH264High422
|
||||
return FF_DECODER_TYPE_H264;
|
||||
|
||||
case 8: // VAProfileVC1Simple
|
||||
case 9: // VAProfileVC1Main
|
||||
case 10: // VAProfileVC1Advanced
|
||||
return FF_DECODER_TYPE_VC1;
|
||||
|
||||
case 14: // VAProfileVP8Version0_3
|
||||
return FF_DECODER_TYPE_VP8;
|
||||
|
||||
case 17: // VAProfileHEVCMain
|
||||
case 18: // VAProfileHEVCMain10
|
||||
case 23: // VAProfileHEVCMain12
|
||||
case 24: // VAProfileHEVCMain422_10
|
||||
case 25: // VAProfileHEVCMain422_12
|
||||
case 26: // VAProfileHEVCMain444
|
||||
case 27: // VAProfileHEVCMain444_10
|
||||
case 28: // VAProfileHEVCMain444_12
|
||||
case 29: // VAProfileHEVCSccMain
|
||||
case 30: // VAProfileHEVCSccMain10
|
||||
case 31: // VAProfileHEVCSccMain444
|
||||
case 34: // VAProfileHEVCSccMain444_10
|
||||
return FF_DECODER_TYPE_HEVC;
|
||||
|
||||
case 19: // VAProfileVP9Profile0
|
||||
case 20: // VAProfileVP9Profile1
|
||||
case 21: // VAProfileVP9Profile2
|
||||
case 22: // VAProfileVP9Profile3
|
||||
return FF_DECODER_TYPE_VP9;
|
||||
|
||||
case 32: // VAProfileAV1Profile0
|
||||
case 33: // VAProfileAV1Profile1
|
||||
case 39: // VAProfileAV1Profile2
|
||||
return FF_DECODER_TYPE_AV1;
|
||||
|
||||
case 37: // VAProfileVVCMain10
|
||||
case 38: // VAProfileVVCMultilayerMain10
|
||||
return FF_DECODER_TYPE_VVC;
|
||||
|
||||
default:
|
||||
return FF_DECODER_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ffDecoderEntrypointIsDecode(VAEntrypoint entrypoint) {
|
||||
switch (entrypoint) {
|
||||
case VAEntrypointVLD:
|
||||
case VAEntrypointIDCT:
|
||||
case VAEntrypointMoComp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ffDecoderProfileHasOutput(
|
||||
VADisplay display,
|
||||
__typeof__(vaQueryConfigEntrypoints)* ffvaQueryConfigEntrypoints,
|
||||
__typeof__(vaGetConfigAttributes)* ffvaGetConfigAttributes,
|
||||
int maxEntrypoints,
|
||||
VAEntrypoint* entrypoints,
|
||||
VAProfile profile
|
||||
) {
|
||||
int numEntrypoints = maxEntrypoints;
|
||||
if (ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numEntrypoints; ++i) {
|
||||
if (!ffDecoderEntrypointIsDecode(entrypoints[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VAConfigAttrib attrib = {
|
||||
.type = VAConfigAttribRTFormat,
|
||||
.value = 0,
|
||||
};
|
||||
|
||||
if (ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
|
||||
attrib.value != VA_ATTRIB_NOT_SUPPORTED &&
|
||||
attrib.value != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ffDecoderFillGpuName(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;
|
||||
}
|
||||
|
||||
if (!name->length && path && *path) {
|
||||
const char* base = strrchr(path, '/');
|
||||
ffStrbufSetS(name, base ? base + 1 : path);
|
||||
}
|
||||
|
||||
if (!name->length) {
|
||||
ffStrbufSetStatic(name, "Unknown GPU");
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* result /* list of FFDecoderResult */) {
|
||||
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 NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
drmDevice* dev = devices[i];
|
||||
|
||||
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 {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VADisplay display = ffvaGetDisplayDRM(fd);
|
||||
if (!display) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int major = 0, minor = 0;
|
||||
if (ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
if (!profiles || !entrypoints) {
|
||||
ffvaTerminate(display);
|
||||
return "malloc() failed";
|
||||
}
|
||||
|
||||
int numProfiles = maxProfiles;
|
||||
if (ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
|
||||
ffvaTerminate(display);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFDecoderType types = FF_DECODER_TYPE_NONE;
|
||||
for (int j = 0; j < numProfiles; ++j) {
|
||||
if (!ffDecoderProfileHasOutput(
|
||||
display,
|
||||
ffvaQueryConfigEntrypoints,
|
||||
ffvaGetConfigAttributes,
|
||||
maxEntrypoints,
|
||||
entrypoints,
|
||||
profiles[j])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFDecoderType type = ffDecoderProfileToType(profiles[j]);
|
||||
types = (FFDecoderType) ((uint32_t) types | (uint32_t) type);
|
||||
}
|
||||
|
||||
if (types != FF_DECODER_TYPE_NONE) {
|
||||
FFDecoderResult* item = FF_LIST_ADD(FFDecoderResult, *result);
|
||||
ffDecoderFillGpuName(dev, path, &item->gpu);
|
||||
item->types = types;
|
||||
}
|
||||
|
||||
ffvaTerminate(display);
|
||||
}
|
||||
|
||||
ffdrmFreeDevices(devices, numDevices);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffDetectDecoder(FFDecoderOptions* options, FFlist* result /* list of FFDecoderResult */) {
|
||||
FF_UNUSED(options, result);
|
||||
return "Fastfetch was built without DRM / VA-API headers";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -33,6 +33,8 @@ static const char* ffDecoderTypeToString(FFDecoderType type) {
|
||||
return "VP9";
|
||||
case FF_DECODER_TYPE_AV1:
|
||||
return "AV1";
|
||||
case FF_DECODER_TYPE_VVC:
|
||||
return "VVC / H.266";
|
||||
case FF_DECODER_TYPE_UNKNOWN:
|
||||
default:
|
||||
return "Unknown";
|
||||
|
||||
Reference in New Issue
Block a user