diff options
Diffstat (limited to 'src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm')
-rw-r--r-- | src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm new file mode 100644 index 0000000000..7a7a62d170 --- /dev/null +++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm @@ -0,0 +1,170 @@ +// +// Copyright (c) 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_mac.cpp: implementation of the Mac-specific parts of SystemInfo.h + +#include "gpu_info_util/SystemInfo_internal.h" + +#import <Cocoa/Cocoa.h> +#import <IOKit/IOKitLib.h> + +namespace angle +{ + +namespace +{ + +std::string GetMachineModel() +{ + io_service_t platformExpert = IOServiceGetMatchingService( + kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); + + if (platformExpert == IO_OBJECT_NULL) + { + return ""; + } + + CFDataRef modelData = static_cast<CFDataRef>( + IORegistryEntryCreateCFProperty(platformExpert, CFSTR("model"), kCFAllocatorDefault, 0)); + if (modelData == nullptr) + { + IOObjectRelease(platformExpert); + return ""; + } + + std::string result = reinterpret_cast<const char *>(CFDataGetBytePtr(modelData)); + + IOObjectRelease(platformExpert); + CFRelease(modelData); + + return result; +} + +// Extracts one integer property from a registry entry. +bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *value) +{ + *value = 0; + + CFDataRef data = static_cast<CFDataRef>( + IORegistryEntrySearchCFProperty(entry, kIOServicePlane, name, kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents)); + + if (data == nullptr) + { + return false; + } + + const uint32_t *valuePtr = reinterpret_cast<const uint32_t *>(CFDataGetBytePtr(data)); + + if (valuePtr == nullptr) + { + CFRelease(data); + return false; + } + + *value = *valuePtr; + CFRelease(data); + return true; +} + +// CGDisplayIOServicePort is deprecated as of macOS 10.9, but has no replacement, see +// https://crbug.com/650837 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +// Find the info of the current GPU. +bool GetActiveGPU(VendorID *vendorId, DeviceID *deviceId) +{ + io_registry_entry_t port = CGDisplayIOServicePort(kCGDirectMainDisplay); + + return GetEntryProperty(port, CFSTR("vendor-id"), vendorId) && + GetEntryProperty(port, CFSTR("device-id"), deviceId); +} + +#pragma clang diagnostic pop + +// Gathers the vendor and device IDs for the PCI GPUs +bool GetPCIDevices(std::vector<GPUDeviceInfo> *devices) +{ + // matchDictionary will be consumed by IOServiceGetMatchingServices, no need to release it. + CFMutableDictionaryRef matchDictionary = IOServiceMatching("IOPCIDevice"); + + io_iterator_t entryIterator; + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchDictionary, &entryIterator) != + kIOReturnSuccess) + { + return false; + } + + io_registry_entry_t entry = IO_OBJECT_NULL; + + while ((entry = IOIteratorNext(entryIterator)) != IO_OBJECT_NULL) + { + constexpr uint32_t kClassCodeDisplayVGA = 0x30000; + uint32_t classCode; + GPUDeviceInfo info; + + if (GetEntryProperty(entry, CFSTR("class-code"), &classCode) && + classCode == kClassCodeDisplayVGA && + GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId) && + GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId)) + { + devices->push_back(info); + } + + IOObjectRelease(entry); + } + IOObjectRelease(entryIterator); + + return true; +} + +} // anonymous namespace + +bool GetSystemInfo(SystemInfo *info) +{ + { + int32_t major = 0; + int32_t minor = 0; + ParseMacMachineModel(GetMachineModel(), &info->machineModelName, &major, &minor); + info->machineModelVersion = std::to_string(major) + "." + std::to_string(minor); + } + + if (!GetPCIDevices(&(info->gpus))) + { + return false; + } + + if (info->gpus.empty()) + { + return false; + } + + // Find the active GPU + { + VendorID activeVendor; + DeviceID activeDevice; + if (!GetActiveGPU(&activeVendor, &activeDevice)) + { + return false; + } + + for (size_t i = 0; i < info->gpus.size(); ++i) + { + if (info->gpus[i].vendorId == activeVendor && info->gpus[i].deviceId == activeDevice) + { + info->activeGPUIndex = i; + break; + } + } + } + + FindPrimaryGPU(info); + + return true; +} + +} // namespace angle |