From 76424950e373d3b04ac3dd13019151bfba3e8423 Mon Sep 17 00:00:00 2001 From: sumuel Date: Mon, 17 Aug 2026 20:44:55 +0000 Subject: Add the files --- src/detection/gpu/gpu_bsd.c | 230 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/detection/gpu/gpu_bsd.c (limited to 'src/detection/gpu/gpu_bsd.c') diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c new file mode 100644 index 0000000..ae29f46 --- /dev/null +++ b/src/detection/gpu/gpu_bsd.c @@ -0,0 +1,230 @@ +#include "gpu_driver_specific.h" + +#include "common/io.h" +#include "common/mallocHelper.h" + +#include +#include +#if __has_include() + #include // FreeBSD +#else + #include // 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 + +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) { + return "open(\"/dev/pci\", O_RDONLY | O_CLOEXEC, 0) failed"; + } + + struct pci_conf confs[128]; + struct pci_match_conf match = { + .pc_class = PCIC_DISPLAY, + .flags = PCI_GETCONF_MATCH_CLASS, + }; + struct pci_conf_io pcio = { + .pat_buf_len = sizeof(match), + .num_patterns = 1, + .patterns = &match, + .match_buf_len = sizeof(confs), + .matches = confs, + }; + + if (ioctl(fd, PCIOCGETCONF, &pcio) < 0) { + return "ioctl(fd, PCIOCGETCONF, &pc) failed"; + } + + if (pcio.status == PCI_GETCONF_ERROR) { + return "ioctl(fd, PCIOCGETCONF, &pc) returned error"; + } + + for (uint32_t i = 0; i < pcio.num_matches; ++i) { + struct pci_conf* pc = &confs[i]; + + if (pc->pc_sel.pc_func > 0 && pc->pc_subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) { + continue; // Likely an auxiliary display controller (#2034) + } + + FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus); + ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor)); + ffStrbufInit(&gpu->name); + ffStrbufInitS(&gpu->driver, pc->pd_name); + ffStrbufInitStatic(&gpu->platformApi, "/dev/pci"); + 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(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; + + ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) { + .domain = (uint32_t) pc->pc_sel.pc_domain, + .bus = pc->pc_sel.pc_bus, + .device = pc->pc_sel.pc_dev, + .func = pc->pc_sel.pc_func, + }); + + if (gpu->name.length == 0) { + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { + ffGPUQueryAmdGpuName(pc->pc_device, pc->pc_revid, gpu); + } + if (gpu->name.length == 0) { + ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); + } + } + + fillGPUTypeGeneric(gpu); + } + + return NULL; +} + +const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { +#if FF_HAVE_DRM + if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO) { + detectByDrm(options, gpus); + if (gpus->length > 0) { + return NULL; + } + } +#endif + + return detectByPci(options, gpus); +} -- cgit v1.2.3