diff options
Diffstat (limited to 'src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp')
-rw-r--r-- | src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp new file mode 100644 index 0000000000..07c72872ad --- /dev/null +++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp @@ -0,0 +1,132 @@ +// +// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SystemInfo_libpci.cpp: implementation of the libPCI-specific parts of SystemInfo.h + +#include "gpu_info_util/SystemInfo_internal.h" + +#include <dlfcn.h> +#include <pci/pci.h> +#include <unistd.h> + +#include "common/angleutils.h" +#include "common/debug.h" + +#if !defined(GPU_INFO_USE_LIBPCI) +#error SystemInfo_libpci.cpp compiled without GPU_INFO_USE_LIBPCI +#endif + +namespace angle +{ + +namespace +{ + +struct LibPCI : private angle::NonCopyable +{ + LibPCI() + { + if (access("/sys/bus/pci/", F_OK) != 0 && access("/sys/bs/pci_express/", F_OK) != 0) + { + return; + } + + mHandle = dlopen("libpci.so.3", RTLD_LAZY); + + if (mHandle == nullptr) + { + mHandle = dlopen("libpci.so", RTLD_LAZY); + } + + if (mHandle == nullptr) + { + return; + } + + mValid = + (Alloc = reinterpret_cast<decltype(Alloc)>(dlsym(mHandle, "pci_alloc"))) != nullptr && + (Init = reinterpret_cast<decltype(Init)>(dlsym(mHandle, "pci_init"))) != nullptr && + (Cleanup = reinterpret_cast<decltype(Cleanup)>(dlsym(mHandle, "pci_cleanup"))) != + nullptr && + (ScanBus = reinterpret_cast<decltype(ScanBus)>(dlsym(mHandle, "pci_scan_bus"))) != + nullptr && + (FillInfo = reinterpret_cast<decltype(FillInfo)>(dlsym(mHandle, "pci_fill_info"))) != + nullptr && + (LookupName = reinterpret_cast<decltype(LookupName)>( + dlsym(mHandle, "pci_lookup_name"))) != nullptr; + } + + bool IsValid() const { return mValid; } + + ~LibPCI() + { + if (mHandle != nullptr) + { + dlclose(mHandle); + } + } + + decltype(&::pci_alloc) Alloc = nullptr; + decltype(&::pci_init) Init = nullptr; + decltype(&::pci_cleanup) Cleanup = nullptr; + decltype(&::pci_scan_bus) ScanBus = nullptr; + decltype(&::pci_fill_info) FillInfo = nullptr; + decltype(&::pci_lookup_name) LookupName = nullptr; + + private: + void *mHandle = nullptr; + bool mValid = false; +}; + +} // anonymous namespace + +// Adds an entry per PCI GPU found and fills the device and vendor ID. +bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices) +{ + LibPCI pci; + if (!pci.IsValid()) + { + return false; + } + + pci_access *access = pci.Alloc(); + ASSERT(access != nullptr); + pci.Init(access); + pci.ScanBus(access); + + for (pci_dev *device = access->devices; device != nullptr; device = device->next) + { + pci.FillInfo(device, PCI_FILL_IDENT | PCI_FILL_CLASS); + + // Skip non-GPU devices + switch (device->device_class) + { + case PCI_CLASS_DISPLAY_VGA: + case PCI_CLASS_DISPLAY_XGA: + case PCI_CLASS_DISPLAY_3D: + break; + default: + continue; + } + + // Skip unknown devices + if (device->vendor_id == 0 || device->device_id == 0) + { + continue; + } + + GPUDeviceInfo info; + info.vendorId = device->vendor_id; + info.deviceId = device->device_id; + + devices->push_back(info); + } + + pci.Cleanup(access); + + return true; +} +} |